diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-10-28 22:47:20 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-10-28 22:47:20 -0700 |
commit | 88b04955bf917680915463d4ea09b03db53330dc (patch) | |
tree | 6643c12d9b67b7d8840cc9774cf9aea5a7f5d8df /ext/File-Glob | |
parent | 03dcbf21884be0f98bc3dc2bfdd8aaaf356ee862 (diff) | |
download | perl-88b04955bf917680915463d4ea09b03db53330dc.tar.gz |
Glob.xs: Refactor iteration into separate function
Parsing of a glob pattern and iteration logic are now in separate
functions, so that another function (soon to be added) can share
the same iteration code.
Diffstat (limited to 'ext/File-Glob')
-rw-r--r-- | ext/File-Glob/Glob.xs | 86 |
1 files changed, 54 insertions, 32 deletions
diff --git a/ext/File-Glob/Glob.xs b/ext/File-Glob/Glob.xs index 030e827c0a..62e6ad4852 100644 --- a/ext/File-Glob/Glob.xs +++ b/ext/File-Glob/Glob.xs @@ -64,7 +64,7 @@ doglob(pTHX_ const char *pattern, int flags) /* borrowed heavily from gsar's File::DosGlob, but translated into C */ static void -csh_glob(pTHX) +iterate(pTHX_ bool(*globber)(pTHX_ SV *entries, SV *patsv)) { dSP; dMY_CXT; @@ -72,13 +72,12 @@ csh_glob(pTHX) SV *cxixsv = POPs; const char *cxixpv; STRLEN cxixlen; - STRLEN len; - const char *s = NULL; SV *itersv; SV *entriesv; - AV *entries = NULL; + AV *entries; U32 gimme = GIMME_V; SV *patsv = POPs; + bool on_stack = FALSE; /* assume global context if not provided one */ SvGETMAGIC(cxixsv); @@ -94,14 +93,55 @@ csh_glob(pTHX) /* if we're just beginning, do it all first */ if (!SvIV(itersv)) { + PUTBACK; + on_stack = globber(aTHX_ entriesv, patsv); + SPAGAIN; + } + + /* chuck it all out, quick or slow */ + assert(SvROK(entriesv)); + entries = (AV *)SvRV(entriesv); + if (gimme == G_ARRAY) { + if (!on_stack) { + Copy(AvARRAY(entries), SP+1, AvFILLp(entries)+1, SV *); + SP += AvFILLp(entries)+1; + } + hv_delete(MY_CXT.x_GLOB_ITER, cxixpv, cxixlen, G_DISCARD); + /* No G_DISCARD here! It will free the stack items. */ + hv_delete(MY_CXT.x_GLOB_ENTRIES, cxixpv, cxixlen, 0); + } + else { + if (AvFILLp(entries) + 1) { + sv_setiv(itersv, AvFILLp(entries) + 1); + mPUSHs(av_shift(entries)); + } + else { + /* return undef for EOL */ + hv_delete(MY_CXT.x_GLOB_ITER, cxixpv, cxixlen, G_DISCARD); + hv_delete(MY_CXT.x_GLOB_ENTRIES, cxixpv, cxixlen, G_DISCARD); + PUSHs(&PL_sv_undef); + } + } + PUTBACK; +} + +/* returns true if the items are on the stack already */ +static bool +csh_glob(pTHX_ SV *entriesv, SV *patsv) +{ + dSP; const char *pat; AV *patav = NULL; + AV *entries = NULL; const char *patend; + const char *s = NULL; const char *piece = NULL; SV *word = NULL; int const flags = (int)SvIV(get_sv("File::Glob::DEFAULT_FLAGS", GV_ADD)); bool is_utf8; + STRLEN len; + U32 const gimme = GIMME_V; /* glob without args defaults to $_ */ SvGETMAGIC(patsv); @@ -245,39 +285,21 @@ csh_glob(pTHX) dMARK; dORIGMARK; /* short-circuit here for a fairly common case */ - if (!patav && gimme == G_ARRAY) goto return_list; + if (!patav && gimme == G_ARRAY) { PUTBACK; return TRUE; } while (++MARK <= SP) av_push(entries, SvREFCNT_inc_simple_NN(*MARK)); SP = ORIGMARK; } } - } + PUTBACK; + return FALSE; +} - /* chuck it all out, quick or slow */ - assert(SvROK(entriesv)); - if (!entries) entries = (AV *)SvRV(entriesv); - if (gimme == G_ARRAY) { - Copy(AvARRAY(entries), SP+1, AvFILLp(entries)+1, SV *); - SP += AvFILLp(entries)+1; - return_list: - hv_delete(MY_CXT.x_GLOB_ITER, cxixpv, cxixlen, G_DISCARD); - /* No G_DISCARD here! It will free the stack items. */ - hv_delete(MY_CXT.x_GLOB_ENTRIES, cxixpv, cxixlen, 0); - } - else { - if (AvFILLp(entries) + 1) { - sv_setiv(itersv, AvFILLp(entries) + 1); - mPUSHs(av_shift(entries)); - } - else { - /* return undef for EOL */ - hv_delete(MY_CXT.x_GLOB_ITER, cxixpv, cxixlen, G_DISCARD); - hv_delete(MY_CXT.x_GLOB_ENTRIES, cxixpv, cxixlen, G_DISCARD); - PUSHs(&PL_sv_undef); - } - } - PUTBACK; +static void +csh_glob_iter(pTHX) +{ + iterate(aTHX_ csh_glob); } MODULE = File::Glob PACKAGE = File::Glob @@ -332,14 +354,14 @@ PPCODE: if (!items) XPUSHs(&PL_sv_undef); } PUTBACK; - csh_glob(aTHX); + csh_glob_iter(aTHX); SPAGAIN; BOOT: { #ifndef PERL_EXTERNAL_GLOB /* Don’t do this at home! The globhook interface is highly volatile. */ - PL_globhook = csh_glob; + PL_globhook = csh_glob_iter; #endif } |