diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2020-08-09 22:18:54 +0100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2020-09-30 01:56:53 +0000 |
commit | 59892837454d0ca367c3f7c83b2a646c57333b9a (patch) | |
tree | 411fe8d0d4273ea4bb08ce26e80d60a0b0fb6172 /pp.c | |
parent | 061e8ceefc436d92eaff1b49118f81c22df9e3b3 (diff) | |
download | perl-59892837454d0ca367c3f7c83b2a646c57333b9a.tar.gz |
pp_split: RXf_NULL branch - separate out (gimme_scalar), reduce unnecessary work
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 100 |
1 files changed, 47 insertions, 53 deletions
@@ -6174,62 +6174,56 @@ PP(pp_split) } } else if (RX_EXTFLAGS(rx) & RXf_NULL && !(s >= strend)) { - /* - Pre-extend the stack, either the number of bytes or - characters in the string or a limited amount, triggered by: - - my ($x, $y) = split //, $str; - or - split //, $str, $i; - */ - if (!gimme_scalar) { - const IV items = limit - 1; - /* setting it to -1 will trigger a panic in EXTEND() */ - const SSize_t sslen = slen > SSize_t_MAX ? -1 : (SSize_t)slen; - if (items >=0 && items < sslen) - EXTEND(SP, items); - else - EXTEND(SP, sslen); - } - - if (do_utf8) { - while (--limit) { - /* keep track of how many bytes we skip over */ - m = s; - s += UTF8SKIP(s); - if (gimme_scalar) { - iters++; - if (s-m == 0) - trailing_empty++; - else - trailing_empty = 0; - } else { - dstr = newSVpvn_flags(m, s-m, SVf_UTF8 | make_mortal); - - PUSHs(dstr); - } - - if (s >= strend) - break; + /* This case boils down to deciding which is the smaller of: + * limit - effectively a number of characters + * slen - which already contains the number of characters in s + * + * The resulting number is the number of iters (for gimme_scalar) + * or the number of SVs to create (!gimme_scalar). */ + + /* setting it to -1 will trigger a panic in EXTEND() */ + const SSize_t sslen = slen > SSize_t_MAX ? -1 : (SSize_t)slen; + /*limit is not needed later, so can clobber it here */ + limit--; + if (sslen < limit || limit < 0) { + iters = slen -1; + limit = slen; + /* Note: The same result is returned if the following block + * is removed, because of the "keep field after final delim?" + * adjustment, but having the following makes the "correct" + * behaviour more apparent. */ + if (gimme_scalar) { + s = strend; + iters++; } } else { - while (--limit) { - if (gimme_scalar) { - iters++; - } else { - dstr = newSVpvn(s, 1); - - - if (make_mortal) - sv_2mortal(dstr); - - PUSHs(dstr); - } - - s++; + iters = limit; + } - if (s >= strend) - break; + if (!gimme_scalar) { + /* + Pre-extend the stack, either the number of bytes or + characters in the string or a limited amount, triggered by: + + my ($x, $y) = split //, $str; + or + split //, $str, $i; + */ + EXTEND(SP, limit); + + if (do_utf8) { + while (--limit) { + m = s; + s += UTF8SKIP(s); + dstr = newSVpvn_flags(m, s-m, SVf_UTF8 | make_mortal); + PUSHs(dstr); + } + } else { + while (--limit) { + dstr = newSVpvn_flags(s, 1, make_mortal); + PUSHs(dstr); + s++; + } } } } |