summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorRichard Leach <richardleach@users.noreply.github.com>2020-08-09 22:18:54 +0100
committerTony Cook <tony@develop-help.com>2020-09-30 01:56:53 +0000
commit59892837454d0ca367c3f7c83b2a646c57333b9a (patch)
tree411fe8d0d4273ea4bb08ce26e80d60a0b0fb6172 /pp.c
parent061e8ceefc436d92eaff1b49118f81c22df9e3b3 (diff)
downloadperl-59892837454d0ca367c3f7c83b2a646c57333b9a.tar.gz
pp_split: RXf_NULL branch - separate out (gimme_scalar), reduce unnecessary work
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c100
1 files changed, 47 insertions, 53 deletions
diff --git a/pp.c b/pp.c
index 58181f4e35..06de4e688d 100644
--- a/pp.c
+++ b/pp.c
@@ -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++;
+ }
}
}
}