X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=f25aea2d99d1ee1b946056868cfd00bd09506471;hb=d81966ff01fcaf0e13cf1b40d512739033a43e42;hp=f5aa4a8d7f35cdd0fe7ac558b616771c0339ef94;hpb=c3654f1afb5dff5b62753314bd22e2270ff9f009;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index f5aa4a8..f25aea2 100644 --- a/hv.c +++ b/hv.c @@ -1,6 +1,6 @@ /* hv.c * - * Copyright (c) 1991-2000, Larry Wall + * Copyright (c) 1991-2001, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -152,6 +152,7 @@ Perl_hv_fetch(pTHX_ HV *hv, const char *key, I32 klen, I32 lval) register HE *entry; SV *sv; bool is_utf8 = FALSE; + const char *keysave = key; if (!hv) return 0; @@ -196,6 +197,14 @@ Perl_hv_fetch(pTHX_ HV *hv, const char *key, I32 klen, I32 lval) return 0; } + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) { + STRLEN tmplen = klen; + /* Just casting the &klen to (STRLEN) won't work well + * if STRLEN and I32 are of different widths. --jhi */ + key = (char*)bytes_from_utf8((U8*)key, &tmplen, &is_utf8); + klen = tmplen; + } + PERL_HASH(hash, key, klen); entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; @@ -208,6 +217,8 @@ Perl_hv_fetch(pTHX_ HV *hv, const char *key, I32 klen, I32 lval) continue; if (HeKUTF8(entry) != (char)is_utf8) continue; + if (key != keysave) + Safefree(key); return &HeVAL(entry); } #ifdef DYNAMIC_ENV_FETCH /* %ENV lookup? If so, try to fetch the value now */ @@ -217,14 +228,24 @@ Perl_hv_fetch(pTHX_ HV *hv, const char *key, I32 klen, I32 lval) if (env) { sv = newSVpvn(env,len); SvTAINTED_on(sv); + if (key != keysave) + Safefree(key); return hv_store(hv,key,klen,sv,hash); } } #endif if (lval) { /* gonna assign to this, so it better be there */ sv = NEWSV(61,0); - return hv_store(hv,key,is_utf8?-klen:klen,sv,hash); + if (key != keysave) { /* must be is_utf8 == 0 */ + SV **ret = hv_store(hv,key,klen,sv,hash); + Safefree(key); + return ret; + } + else + return hv_store(hv,key,is_utf8?-klen:klen,sv,hash); } + if (key != keysave) + Safefree(key); return 0; } @@ -256,6 +277,7 @@ Perl_hv_fetch_ent(pTHX_ HV *hv, SV *keysv, I32 lval, register U32 hash) register HE *entry; SV *sv; bool is_utf8; + char *keysave; if (!hv) return 0; @@ -304,9 +326,12 @@ Perl_hv_fetch_ent(pTHX_ HV *hv, SV *keysv, I32 lval, register U32 hash) return 0; } - key = SvPV(keysv, klen); + keysave = key = SvPV(keysv, klen); is_utf8 = (SvUTF8(keysv)!=0); + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) + key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8); + if (!hash) PERL_HASH(hash, key, klen); @@ -320,6 +345,8 @@ Perl_hv_fetch_ent(pTHX_ HV *hv, SV *keysv, I32 lval, register U32 hash) continue; if (HeKUTF8(entry) != (char)is_utf8) continue; + if (key != keysave) + Safefree(key); return entry; } #ifdef DYNAMIC_ENV_FETCH /* %ENV lookup? If so, try to fetch the value now */ @@ -333,6 +360,8 @@ Perl_hv_fetch_ent(pTHX_ HV *hv, SV *keysv, I32 lval, register U32 hash) } } #endif + if (key != keysave) + Safefree(key); if (lval) { /* gonna assign to this, so it better be there */ sv = NEWSV(61,0); return hv_store_ent(hv,keysv,sv,hash); @@ -385,6 +414,7 @@ Perl_hv_store(pTHX_ HV *hv, const char *key, I32 klen, SV *val, register U32 has register HE *entry; register HE **oentry; bool is_utf8 = FALSE; + const char *keysave = key; if (!hv) return 0; @@ -405,13 +435,20 @@ Perl_hv_store(pTHX_ HV *hv, const char *key, I32 klen, SV *val, register U32 has return 0; #ifdef ENV_IS_CASELESS else if (mg_find((SV*)hv,'E')) { - SV *sv = sv_2mortal(newSVpvn(key,klen)); - key = strupr(SvPVX(sv)); + key = savepvn(key,klen); + key = strupr(key); hash = 0; } #endif } } + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) { + STRLEN tmplen = klen; + /* See the note in hv_fetch(). --jhi */ + key = (char*)bytes_from_utf8((U8*)key, &tmplen, &is_utf8); + klen = tmplen; + } + if (!hash) PERL_HASH(hash, key, klen); @@ -433,6 +470,8 @@ Perl_hv_store(pTHX_ HV *hv, const char *key, I32 klen, SV *val, register U32 has continue; SvREFCNT_dec(HeVAL(entry)); HeVAL(entry) = val; + if (key != keysave) + Safefree(key); return &HeVAL(entry); } @@ -441,6 +480,8 @@ Perl_hv_store(pTHX_ HV *hv, const char *key, I32 klen, SV *val, register U32 has HeKEY_hek(entry) = share_hek(key, is_utf8?-klen:klen, hash); else /* gotta do the real thing */ HeKEY_hek(entry) = save_hek(key, is_utf8?-klen:klen, hash); + if (key != keysave) + Safefree(key); HeVAL(entry) = val; HeNEXT(entry) = *oentry; *oentry = entry; @@ -484,6 +525,7 @@ Perl_hv_store_ent(pTHX_ HV *hv, SV *keysv, SV *val, register U32 hash) register HE *entry; register HE **oentry; bool is_utf8; + char *keysave; if (!hv) return 0; @@ -513,9 +555,12 @@ Perl_hv_store_ent(pTHX_ HV *hv, SV *keysv, SV *val, register U32 hash) } } - key = SvPV(keysv, klen); + keysave = key = SvPV(keysv, klen); is_utf8 = (SvUTF8(keysv) != 0); + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) + key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8); + if (!hash) PERL_HASH(hash, key, klen); @@ -537,6 +582,8 @@ Perl_hv_store_ent(pTHX_ HV *hv, SV *keysv, SV *val, register U32 hash) continue; SvREFCNT_dec(HeVAL(entry)); HeVAL(entry) = val; + if (key != keysave) + Safefree(key); return entry; } @@ -545,6 +592,8 @@ Perl_hv_store_ent(pTHX_ HV *hv, SV *keysv, SV *val, register U32 hash) HeKEY_hek(entry) = share_hek(key, is_utf8?-klen:klen, hash); else /* gotta do the real thing */ HeKEY_hek(entry) = save_hek(key, is_utf8?-klen:klen, hash); + if (key != keysave) + Safefree(key); HeVAL(entry) = val; HeNEXT(entry) = *oentry; *oentry = entry; @@ -581,6 +630,7 @@ Perl_hv_delete(pTHX_ HV *hv, const char *key, I32 klen, I32 flags) SV **svp; SV *sv; bool is_utf8 = FALSE; + const char *keysave = key; if (!hv) return Nullsv; @@ -615,6 +665,13 @@ Perl_hv_delete(pTHX_ HV *hv, const char *key, I32 klen, I32 flags) if (!xhv->xhv_array) return Nullsv; + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) { + STRLEN tmplen = klen; + /* See the note in hv_fetch(). --jhi */ + key = (char*)bytes_from_utf8((U8*)key, &tmplen, &is_utf8); + klen = tmplen; + } + PERL_HASH(hash, key, klen); oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; @@ -629,6 +686,8 @@ Perl_hv_delete(pTHX_ HV *hv, const char *key, I32 klen, I32 flags) continue; if (HeKUTF8(entry) != (char)is_utf8) continue; + if (key != keysave) + Safefree(key); *oentry = HeNEXT(entry); if (i && !*oentry) xhv->xhv_fill--; @@ -645,6 +704,8 @@ Perl_hv_delete(pTHX_ HV *hv, const char *key, I32 klen, I32 flags) --xhv->xhv_keys; return sv; } + if (key != keysave) + Safefree(key); return Nullsv; } @@ -670,6 +731,7 @@ Perl_hv_delete_ent(pTHX_ HV *hv, SV *keysv, I32 flags, U32 hash) register HE **oentry; SV *sv; bool is_utf8; + char *keysave; if (!hv) return Nullsv; @@ -702,9 +764,12 @@ Perl_hv_delete_ent(pTHX_ HV *hv, SV *keysv, I32 flags, U32 hash) if (!xhv->xhv_array) return Nullsv; - key = SvPV(keysv, klen); + keysave = key = SvPV(keysv, klen); is_utf8 = (SvUTF8(keysv) != 0); + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) + key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8); + if (!hash) PERL_HASH(hash, key, klen); @@ -720,6 +785,8 @@ Perl_hv_delete_ent(pTHX_ HV *hv, SV *keysv, I32 flags, U32 hash) continue; if (HeKUTF8(entry) != (char)is_utf8) continue; + if (key != keysave) + Safefree(key); *oentry = HeNEXT(entry); if (i && !*oentry) xhv->xhv_fill--; @@ -736,6 +803,8 @@ Perl_hv_delete_ent(pTHX_ HV *hv, SV *keysv, I32 flags, U32 hash) --xhv->xhv_keys; return sv; } + if (key != keysave) + Safefree(key); return Nullsv; } @@ -756,6 +825,7 @@ Perl_hv_exists(pTHX_ HV *hv, const char *key, I32 klen) register HE *entry; SV *sv; bool is_utf8 = FALSE; + const char *keysave = key; if (!hv) return 0; @@ -786,6 +856,13 @@ Perl_hv_exists(pTHX_ HV *hv, const char *key, I32 klen) return 0; #endif + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) { + STRLEN tmplen = klen; + /* See the note in hv_fetch(). --jhi */ + key = (char*)bytes_from_utf8((U8*)key, &tmplen, &is_utf8); + klen = tmplen; + } + PERL_HASH(hash, key, klen); #ifdef DYNAMIC_ENV_FETCH @@ -802,6 +879,8 @@ Perl_hv_exists(pTHX_ HV *hv, const char *key, I32 klen) continue; if (HeKUTF8(entry) != (char)is_utf8) continue; + if (key != keysave) + Safefree(key); return TRUE; } #ifdef DYNAMIC_ENV_FETCH /* is it out there? */ @@ -816,6 +895,8 @@ Perl_hv_exists(pTHX_ HV *hv, const char *key, I32 klen) } } #endif + if (key != keysave) + Safefree(key); return FALSE; } @@ -839,17 +920,19 @@ Perl_hv_exists_ent(pTHX_ HV *hv, SV *keysv, U32 hash) register HE *entry; SV *sv; bool is_utf8; + char *keysave; if (!hv) return 0; if (SvRMAGICAL(hv)) { if (mg_find((SV*)hv,'P')) { + SV* svret = sv_newmortal(); sv = sv_newmortal(); keysv = sv_2mortal(newSVsv(keysv)); mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY); - magic_existspack(sv, mg_find(sv, 'p')); - return SvTRUE(sv); + magic_existspack(svret, mg_find(sv, 'p')); + return SvTRUE(svret); } #ifdef ENV_IS_CASELESS else if (mg_find((SV*)hv,'E')) { @@ -867,8 +950,10 @@ Perl_hv_exists_ent(pTHX_ HV *hv, SV *keysv, U32 hash) return 0; #endif - key = SvPV(keysv, klen); + keysave = key = SvPV(keysv, klen); is_utf8 = (SvUTF8(keysv) != 0); + if (is_utf8 && !(PL_hints & HINT_UTF8_DISTINCT)) + key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8); if (!hash) PERL_HASH(hash, key, klen); @@ -886,6 +971,8 @@ Perl_hv_exists_ent(pTHX_ HV *hv, SV *keysv, U32 hash) continue; if (HeKUTF8(entry) != (char)is_utf8) continue; + if (key != keysave) + Safefree(key); return TRUE; } #ifdef DYNAMIC_ENV_FETCH /* is it out there? */ @@ -900,6 +987,8 @@ Perl_hv_exists_ent(pTHX_ HV *hv, SV *keysv, U32 hash) } } #endif + if (key != keysave) + Safefree(key); return FALSE; } @@ -1101,7 +1190,7 @@ Perl_newHVhv(pTHX_ HV *ohv) hv_iterinit(ohv); while ((entry = hv_iternext(ohv))) { hv_store(hv, HeKEY(entry), HeKLEN_UTF8(entry), - SvREFCNT_inc(HeVAL(entry)), HeHASH(entry)); + newSVsv(HeVAL(entry)), HeHASH(entry)); } HvRITER(ohv) = hv_riter; HvEITER(ohv) = hv_eiter; @@ -1471,10 +1560,17 @@ Perl_unsharepvn(pTHX_ const char *str, I32 len, U32 hash) register I32 i = 1; I32 found = 0; bool is_utf8 = FALSE; + const char *save = str; if (len < 0) { len = -len; is_utf8 = TRUE; + if (!(PL_hints & HINT_UTF8_DISTINCT)) { + STRLEN tmplen = len; + /* See the note in hv_fetch(). --jhi */ + str = (char*)bytes_from_utf8((U8*)str, &tmplen, &is_utf8); + len = tmplen; + } } /* what follows is the moral equivalent of: @@ -1507,7 +1603,8 @@ Perl_unsharepvn(pTHX_ const char *str, I32 len, U32 hash) break; } UNLOCK_STRTAB_MUTEX; - + if (str != save) + Safefree(str); if (!found && ckWARN_d(WARN_INTERNAL)) Perl_warner(aTHX_ WARN_INTERNAL, "Attempt to free non-existent shared string '%s'",str); } @@ -1525,10 +1622,17 @@ Perl_share_hek(pTHX_ const char *str, I32 len, register U32 hash) register I32 i = 1; I32 found = 0; bool is_utf8 = FALSE; + const char *save = str; if (len < 0) { len = -len; is_utf8 = TRUE; + if (!(PL_hints & HINT_UTF8_DISTINCT)) { + STRLEN tmplen = len; + /* See the note in hv_fetch(). --jhi */ + str = (char*)bytes_from_utf8((U8*)str, &tmplen, &is_utf8); + len = tmplen; + } } /* what follows is the moral equivalent of: @@ -1568,8 +1672,7 @@ Perl_share_hek(pTHX_ const char *str, I32 len, register U32 hash) ++HeVAL(entry); /* use value slot as REFCNT */ UNLOCK_STRTAB_MUTEX; + if (str != save) + Safefree(str); return HeKEY_hek(entry); } - - -