diff options
author | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2009-03-17 10:31:45 +0100 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2009-03-17 10:31:45 +0100 |
commit | a4a197da798f1bea5e8df6e5eb339c1552371563 (patch) | |
tree | c2da536e44778a8c6667d45629f3a7bcd405fbb2 /pp_ctl.c | |
parent | 62ec5f58625ce7dd38f2ee3ba00b450373b0de40 (diff) | |
download | perl-a4a197da798f1bea5e8df6e5eb339c1552371563.tar.gz |
Iterative smart match over keys/elements when a coderef is on the RHS
Diffstat (limited to 'pp_ctl.c')
-rw-r--r-- | pp_ctl.c | 86 |
1 files changed, 71 insertions, 15 deletions
@@ -4084,22 +4084,78 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) || (sv_isobject(e) && (SvTYPE(SvRV(e)) != SVt_REGEXP))) Perl_croak(aTHX_ "Smart matching a non-overloaded object breaks encapsulation"); - if (SM_REF(PVCV)) { + if (SvROK(e) && SvTYPE(SvRV(e)) == SVt_PVCV) { I32 c; - ENTER; - SAVETMPS; - PUSHMARK(SP); - PUSHs(Other); - PUTBACK; - c = call_sv(This, G_SCALAR); - SPAGAIN; - if (c == 0) - PUSHs(&PL_sv_no); - else if (SvTEMP(TOPs)) - SvREFCNT_inc_void(TOPs); - FREETMPS; - LEAVE; - RETURN; + if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) { + /* Test sub truth for each key */ + HE *he; + bool andedresults = TRUE; + HV *hv = (HV*) SvRV(d); + (void) hv_iterinit(hv); + while ( (he = hv_iternext(hv)) ) { + ENTER; + SAVETMPS; + PUSHMARK(SP); + PUSHs(hv_iterkeysv(he)); + PUTBACK; + c = call_sv(e, G_SCALAR); + SPAGAIN; + if (c == 0) + andedresults = FALSE; + else + andedresults = SvTRUEx(POPs) && andedresults; + FREETMPS; + LEAVE; + } + if (andedresults) + RETPUSHYES; + else + RETPUSHNO; + } + else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { + /* Test sub truth for each element */ + I32 i; + bool andedresults = TRUE; + AV *av = (AV*) SvRV(d); + const I32 len = av_len(av); + for (i = 0; i <= len; ++i) { + SV * const * const svp = av_fetch(av, i, FALSE); + ENTER; + SAVETMPS; + PUSHMARK(SP); + if (svp) + PUSHs(*svp); + PUTBACK; + c = call_sv(e, G_SCALAR); + SPAGAIN; + if (c == 0) + andedresults = FALSE; + else + andedresults = SvTRUEx(POPs) && andedresults; + FREETMPS; + LEAVE; + } + if (andedresults) + RETPUSHYES; + else + RETPUSHNO; + } + else { + ENTER; + SAVETMPS; + PUSHMARK(SP); + PUSHs(d); + PUTBACK; + c = call_sv(e, G_SCALAR); + SPAGAIN; + if (c == 0) + PUSHs(&PL_sv_no); + else if (SvTEMP(TOPs)) + SvREFCNT_inc_void(TOPs); + FREETMPS; + LEAVE; + RETURN; + } } else if (SM_REF(PVHV)) { if (SM_OTHER_REF(PVHV)) { |