From bdee33e435b03e47d573fcaecde743ced828beef Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Wed, 19 Sep 2007 15:53:43 +0000 Subject: [PATCH] Call the key transformation function for hv_exists()/hv_fetch()/ hv_store(). (And test this) p4raw-id: //depot/perl@31912 --- ext/XS/APItest/APItest.xs | 28 +++++++++++++++++++++++++++- ext/XS/APItest/t/hash.t | 30 ++++++++++++++++++++++++++++++ hv.c | 19 +++++++++---------- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/ext/XS/APItest/APItest.xs b/ext/XS/APItest/APItest.xs index 96efd9b..5bb0d9d 100644 --- a/ext/XS/APItest/APItest.xs +++ b/ext/XS/APItest/APItest.xs @@ -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) diff --git a/ext/XS/APItest/t/hash.t b/ext/XS/APItest/t/hash.t index 949f175..28441c5 100644 --- a/ext/XS/APItest/t/hash.t +++ b/ext/XS/APItest/t/hash.t @@ -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 --- 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); -- 2.7.4