X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/f4c975aa030b7ad74a7efda242fb8b771ea41c14..eac3f4d5c7d71a1a3a22818c6bcc9c32b312eb40:/hv.c diff --git a/hv.c b/hv.c index 1c339d5..d3d02d1 100644 --- a/hv.c +++ b/hv.c @@ -967,6 +967,79 @@ Perl_hv_scalar(pTHX_ HV *hv) return sv; } + +/* +hv_pushkv(): push all the keys and/or values of a hash onto the stack. +The rough Perl equivalents: + () = %hash; + () = keys %hash; + () = values %hash; + +Resets the hash's iterator. + +flags : 1 = push keys + 2 = push values + 1|2 = push keys and values + XXX use symbolic flag constants at some point? +I might unroll the non-tied hv_iternext() in here at some point - DAPM +*/ + +void +Perl_hv_pushkv(pTHX_ HV *hv, U32 flags) +{ + HE *entry; + bool tied = SvRMAGICAL(hv) && (mg_find(MUTABLE_SV(hv), PERL_MAGIC_tied) +#ifdef DYNAMIC_ENV_FETCH /* might not know number of keys yet */ + || mg_find(MUTABLE_SV(hv), PERL_MAGIC_env) +#endif + ); + dSP; + + PERL_ARGS_ASSERT_HV_PUSHKV; + assert(flags); /* must be pushing at least one of keys and values */ + + (void)hv_iterinit(hv); + + if (tied) { + SSize_t ext = (flags == 3) ? 2 : 1; + while ((entry = hv_iternext(hv))) { + EXTEND(SP, ext); + if (flags & 1) + PUSHs(hv_iterkeysv(entry)); + if (flags & 2) + PUSHs(hv_iterval(hv, entry)); + } + } + else { + Size_t nkeys = HvUSEDKEYS(hv); + SSize_t ext; + + if (!nkeys) + return; + + /* 2*nkeys() should never be big enough to truncate or wrap */ + assert(nkeys <= (SSize_t_MAX >> 1)); + ext = nkeys * ((flags == 3) ? 2 : 1); + + EXTEND_MORTAL(nkeys); + EXTEND(SP, ext); + + while ((entry = hv_iternext(hv))) { + if (flags & 1) { + SV *keysv = newSVhek(HeKEY_hek(entry)); + SvTEMP_on(keysv); + PL_tmps_stack[++PL_tmps_ix] = keysv; + PUSHs(keysv); + } + if (flags & 2) + PUSHs(HeVAL(entry)); + } + } + + PUTBACK; +} + + /* =for apidoc hv_bucket_ratio @@ -1206,7 +1279,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, sv_2mortal((SV *)gv) ); } - else if (klen == 3 && strEQs(key, "ISA") && GvAV(gv)) { + else if (memEQs(key, klen, "ISA") && GvAV(gv)) { AV *isa = GvAV(gv); MAGIC *mg = mg_find((SV*)isa, PERL_MAGIC_isa);