Call the key transformation function for hv_exists()/hv_fetch()/
Nicholas Clark [Wed, 19 Sep 2007 15:53:43 +0000 (15:53 +0000)]
hv_store(). (And test this)

p4raw-id: //depot/perl@31912

ext/XS/APItest/APItest.xs
ext/XS/APItest/t/hash.t
hv.c

index 96efd9b..5bb0d9d 100644 (file)
@@ -230,6 +230,17 @@ exists(hash, key_sv)
         OUTPUT:
         RETVAL
 
+bool
+exists_ent(hash, key_sv)
+       PREINIT:
+       INPUT:
+       HV *hash
+       SV *key_sv
+       CODE:
+       RETVAL = hv_exists_ent(hash, key_sv, 0);
+        OUTPUT:
+        RETVAL
+
 SV *
 delete(hash, key_sv, flags = 0)
        PREINIT:
@@ -282,7 +293,6 @@ store_ent(hash, key, value)
         OUTPUT:
         RETVAL
 
-
 SV *
 store(hash, key_sv, value)
        PREINIT:
@@ -309,6 +319,22 @@ store(hash, key_sv, value)
         OUTPUT:
         RETVAL
 
+SV *
+fetch_ent(hash, key_sv)
+       PREINIT:
+       HE *result;
+       INPUT:
+       HV *hash
+       SV *key_sv
+       CODE:
+       result = hv_fetch_ent(hash, key_sv, 0, 0);
+       if (!result) {
+           XSRETURN_EMPTY;
+       }
+       /* Force mg_get  */
+       RETVAL = newSVsv(HeVAL(result));
+        OUTPUT:
+        RETVAL
 
 SV *
 fetch(hash, key_sv)
index 949f175..28441c5 100644 (file)
@@ -133,6 +133,36 @@ if ($] > 5.009) {
     is(keys %hash, 1);
     @keys = sort keys %hash;
     is("@keys", join(' ', sort(rot13(qw(e)))));
+
+    $hash{f} = 9;
+    is(keys %hash, 2);
+    @keys = sort keys %hash;
+    is("@keys", join(' ', sort(rot13(qw(e f)))));
+
+    is (XS::APItest::Hash::store_ent(\%hash, 'g', 10), 10, "store_ent");
+    is(keys %hash, 3);
+    @keys = sort keys %hash;
+    is("@keys", join(' ', sort(rot13(qw(e f g)))));
+
+    is (XS::APItest::Hash::store(\%hash, 'h', 11), 11, "store");
+    is(keys %hash, 4);
+    @keys = sort keys %hash;
+    is("@keys", join(' ', sort(rot13(qw(e f g h)))));
+
+    is (XS::APItest::Hash::fetch_ent(\%hash, 'g'), 10, "fetch_ent");
+    is (XS::APItest::Hash::fetch_ent(\%hash, rot13('g')), undef,
+       "fetch_ent (missing)");
+
+    is (XS::APItest::Hash::fetch(\%hash, 'h'), 11, "fetch");
+    is (XS::APItest::Hash::fetch(\%hash, rot13('h')), undef,
+       "fetch (missing)");
+
+    ok (XS::APItest::Hash::exists_ent(\%hash, 'e'), "exists_ent");
+    ok (!XS::APItest::Hash::exists_ent(\%hash, rot13('e')),
+       "exists_ent (missing)");
+
+    ok (XS::APItest::Hash::exists(\%hash, 'f'), "exists");
+    ok (!XS::APItest::Hash::exists(\%hash, rot13('f')), "exists (missing)");
 }
 
 exit;
diff --git a/hv.c b/hv.c
index 8394a0e..6d7c25a 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -423,17 +423,16 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
     if (!hv)
        return NULL;
 
+    if (SvSMAGICAL(hv) && SvGMAGICAL(hv) && !(action & HV_DISABLE_UVAR_XKEY)) {
+       keysv = hv_magic_uvar_xkey(hv, keysv, key, klen, flags, action);
+       /* If a fetch-as-store fails on the fetch, then the action is to
+          recurse once into "hv_store". If we didn't do this, then that
+          recursive call would call the key conversion routine again.
+          However, as we replace the original key with the converted
+          key, this would result in a double conversion, which would show
+          up as a bug if the conversion routine is not idempotent.  */
+    }
     if (keysv) {
-       if (SvSMAGICAL(hv) && SvGMAGICAL(hv)
-           && !(action & HV_DISABLE_UVAR_XKEY)) {
-           keysv = hv_magic_uvar_xkey(hv, keysv, 0, 0, 0, action);
-           /* If a fetch-as-store fails on the fetch, then the action is to
-              recurse once into "hv_store". If we didn't do this, then that
-              recursive call would call the key conversion routine again.
-              However, as we replace the original key with the converted
-              key, this would result in a double conversion, which would show
-              up as a bug if the conversion routine is not idempotent.  */
-       }
        if (flags & HVhek_FREEKEY)
            Safefree(key);
        key = SvPV_const(keysv, klen);