You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2012/03/27 02:01:17 UTC

[lucy-commits] svn commit: r1305682 - /lucy/trunk/perl/xs/XSBind.c

Author: marvin
Date: Tue Mar 27 00:01:16 2012
New Revision: 1305682

URL: http://svn.apache.org/viewvc?rev=1305682&view=rev
Log:
Ignore params hashes in allot_params().

Change the implementation of XSBind_allot_params() to ignore the supplied
PARAMs hash names, and instead validate param labels using the param names
from the allotments.

Modified:
    lucy/trunk/perl/xs/XSBind.c

Modified: lucy/trunk/perl/xs/XSBind.c
URL: http://svn.apache.org/viewvc/lucy/trunk/perl/xs/XSBind.c?rev=1305682&r1=1305681&r2=1305682&view=diff
==============================================================================
--- lucy/trunk/perl/xs/XSBind.c (original)
+++ lucy/trunk/perl/xs/XSBind.c Tue Mar 27 00:01:16 2012
@@ -18,6 +18,7 @@
 #define NEED_newRV_noinc
 #include "XSBind.h"
 #include "Lucy/Util/StringHelper.h"
+#include "Lucy/Util/NumberUtils.h"
 
 // Convert a Perl hash into a Clownfish Hash.  Caller takes responsibility for
 // a refcount.
@@ -472,18 +473,10 @@ S_extract_from_sv(SV *value, void *targe
 
 chy_bool_t
 XSBind_allot_params(SV** stack, int32_t start, int32_t num_stack_elems,
-                    char* params_hash_name, ...) {
+                    char *unused, ...) {
     va_list args;
-    HV *params_hash = get_hv(params_hash_name, 0);
     int32_t args_left = (num_stack_elems - start) / 2;
-
-    // Retrieve the params hash, which must be a package global.
-    if (params_hash == NULL) {
-        cfish_CharBuf *mess = CFISH_MAKE_MESS("Can't find hash named %s",
-                                              params_hash_name);
-        cfish_Err_set_error(cfish_Err_new(mess));
-        return false;
-    }
+    void *verified_labels = alloca(sizeof(int64_t) + num_stack_elems / 64);
 
     // Verify that our args come in pairs. Return success if there are no
     // args.
@@ -495,21 +488,8 @@ XSBind_allot_params(SV** stack, int32_t 
         return false;
     }
 
-    // Validate param names.
-    for (int32_t i = start; i < num_stack_elems; i += 2) {
-        SV *const key_sv = stack[i];
-        STRLEN key_len;
-        const char *key = SvPV(key_sv, key_len); // assume ASCII labels
-        if (!hv_exists(params_hash, key, key_len)) {
-            cfish_CharBuf *mess
-                = CFISH_MAKE_MESS("Invalid parameter: '%s'", key);
-            cfish_Err_set_error(cfish_Err_new(mess));
-            return false;
-        }
-    }
-
     void *target;
-    va_start(args, params_hash_name);
+    va_start(args, unused);
     while (NULL != (target = va_arg(args, void*))) {
         char *label     = va_arg(args, char*);
         int   label_len = va_arg(args, int);
@@ -518,36 +498,56 @@ XSBind_allot_params(SV** stack, int32_t 
         cfish_VTable *vtable = va_arg(args, cfish_VTable*);
         void *allocation = va_arg(args, void*);
 
-        // Iterate through stack looking for a label match. Work backwards so
-        // that if the label is doubled up we get the last one.
-        chy_bool_t got_arg = false;
-        for (int32_t i = num_stack_elems; i >= start + 2; i -= 2) {
-            int32_t tick = i - 2;
+        // Iterate through the stack looking for labels which match this param
+        // name.  If the label appears more than once, keep track of where it
+        // appears *last*, as the last time a param appears overrides all
+        // previous appearances.
+        int32_t found_arg = -1;
+        for (int32_t tick = start; tick < num_stack_elems; tick += 2) {
             SV *const key_sv = stack[tick];
             if (SvCUR(key_sv) == (STRLEN)label_len) {
                 if (memcmp(SvPVX(key_sv), label, label_len) == 0) {
-                    SV *value = stack[tick + 1];
-                    got_arg = S_extract_from_sv(value, target, label,
-                                                required, type, vtable,
-                                                allocation);
-                    if (!got_arg) {
-                        CFISH_ERR_ADD_FRAME(cfish_Err_get_error());
-                        return false;
-                    }
-                    break;
+                    found_arg = tick;
+                    lucy_NumUtil_u1set(verified_labels, tick);
                 }
             }
         }
 
-        // Enforce required params.
-        if (required && !got_arg) {
+        if (found_arg == -1) {
+            // Didn't find this parameter. Throw an error if it was required.
+            if (required) {
+                cfish_CharBuf *mess
+                    = CFISH_MAKE_MESS("Missing required parameter: '%s'",
+                                      label);
+                cfish_Err_set_error(cfish_Err_new(mess));
+                return false;
+            }
+        }
+        else {
+            // Found the arg.  Extract the value.
+            SV *value = stack[found_arg + 1];
+            chy_bool_t got_arg = S_extract_from_sv(value, target, label,
+                                                   required, type, vtable,
+                                                   allocation);
+            if (!got_arg) {
+                CFISH_ERR_ADD_FRAME(cfish_Err_get_error());
+                return false;
+            }
+        }
+    }
+    va_end(args);
+
+    // Ensure that all parameter labels were valid.
+    for (int32_t tick = start; tick < num_stack_elems; tick += 2) {
+        if (!lucy_NumUtil_u1get(verified_labels, tick)) {
+            SV *const key_sv = stack[tick];
+            char *key = SvPV_nolen(key_sv);
             cfish_CharBuf *mess
-                = CFISH_MAKE_MESS("Missing required parameter: '%s'", label);
+                = CFISH_MAKE_MESS("Invalid parameter: '%s'", key);
             cfish_Err_set_error(cfish_Err_new(mess));
             return false;
         }
     }
-    va_end(args);
 
     return true;
 }