summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2020-10-16 21:08:13 -0600
committerKarl Williamson <khw@cpan.org>2020-10-31 11:04:19 -0600
commit430f723e6dceffbacbd1d7160d35ee8a2b698448 (patch)
treeef8d5a4308f1822d1b4dc2813f6b73d792a3b6c1 /ext
parentcc448ceab170493a35039184f4f85054a8ddf971 (diff)
downloadperl-430f723e6dceffbacbd1d7160d35ee8a2b698448.tar.gz
Fix up delimcpy_no_escape()
I modified this function in ab01742544b98b5b5e13d8e1a6e9df474b9e3005, and did not fully understand the edge cases. This commit now handles those properly, the same as plain delimcpy() does.
Diffstat (limited to 'ext')
-rw-r--r--ext/XS-APItest/APItest.xs27
-rw-r--r--ext/XS-APItest/t/delimcpy.t34
2 files changed, 45 insertions, 16 deletions
diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs
index cc31a390e2..549bf54afd 100644
--- a/ext/XS-APItest/APItest.xs
+++ b/ext/XS-APItest/APItest.xs
@@ -6821,6 +6821,33 @@ test_delimcpy(SV * from_sv, STRLEN trunc_from, char delim, STRLEN to_len, STRLEN
OUTPUT:
RETVAL
+AV *
+test_delimcpy_no_escape(SV * from_sv, STRLEN trunc_from, char delim, STRLEN to_len, STRLEN trunc_to, char poison = '?')
+ PREINIT:
+ char * from;
+ AV *av;
+ I32 retlen;
+ char * from_pos_after_copy;
+ char * to;
+ CODE:
+ from = SvPV_nolen(from_sv);
+ Newx(to, to_len, char);
+ PoisonWith(to, to_len, char, poison);
+ assert(trunc_from <= SvCUR(from_sv));
+ /* trunc_to allows us to throttle the output size available */
+ assert(trunc_to <= to_len);
+ from_pos_after_copy = delimcpy_no_escape(to, to + trunc_to,
+ from, from + trunc_from,
+ delim, &retlen);
+ av = newAV();
+ av_push(av, newSVpvn(to, to_len));
+ av_push(av, newSVuv(retlen));
+ av_push(av, newSVuv(from_pos_after_copy - from));
+ Safefree(to);
+ RETVAL = av;
+ OUTPUT:
+ RETVAL
+
SV *
test_Gconvert(SV * number, SV * num_digits)
PREINIT:
diff --git a/ext/XS-APItest/t/delimcpy.t b/ext/XS-APItest/t/delimcpy.t
index 9d2c7d133e..6ea3c43960 100644
--- a/ext/XS-APItest/t/delimcpy.t
+++ b/ext/XS-APItest/t/delimcpy.t
@@ -132,25 +132,26 @@ foreach my $d ("x", "\0") { # Try both printable and NUL delimiters
} while ($trunc_dest_len > 0);
}
-{
- # Repeat a few of the tests with a backslash delimiter, which means there
- # is no possibiliby of an escape
+# Repeat a few of the tests with a backslash delimiter, which means there
+# is no possibiliby of an escape. And this escape-less form can be used to
+# also do a general test on 'delimcpy_no_escape'
+foreach my $d ("x", "\0", '\\') {
+ for my $func (qw(delimcpy delimcpy_no_escape)) {
+ next if $func eq 'delimcpy' && $d ne '\\';
+ my $test_func = "test_$func";
- my $d = "\\";
my $source = $ib;
my $source_len = 1;
my $should_be = $source;
- pass 'delimiter is a backslash for the rest of the tests';
-
- $ret = test_delimcpy($source, $source_len, $d, $source_len, $source_len, $poison);
+ $ret = eval "$test_func(\$source, \$source_len, \$d, \$source_len, \$source_len, \$poison)";
is($ret->[0], expected($source, $source_len, $poison, $source_len),
- "delimcpy works when there is no delimiter at all");
+ "$func works when there is no delimiter at all");
is($ret->[1], $source_len, "Destination length is correct");
is($ret->[2], 1, "Source advance is correct");
$source .= $d;
- $ret = test_delimcpy($source, $source_len, $d, $source_len, $source_len, $poison);
+ $ret = eval "$test_func(\$source, \$source_len, \$d, \$source_len, \$source_len, \$poison)";
is($ret->[0], expected($source, $source_len, $poison, $source_len),
"Works when delimiter is just beyond the examined portion");
is($ret->[1], $source_len, "Destination length is correct");
@@ -158,7 +159,7 @@ foreach my $d ("x", "\0") { # Try both printable and NUL delimiters
# Delimiter in first byte
my $actual_dest_len = 5;
- $ret = test_delimcpy($d, 1, $d, $actual_dest_len, $actual_dest_len, $poison);
+ $ret = eval "$test_func(\$d, 1, \$d, \$actual_dest_len, \$actual_dest_len, \$poison)";
is($ret->[0], "\0" . $poison x ($actual_dest_len - 1),
"Copied correctly when delimiter is first character");
is($ret->[1], 0, "0 bytes copied");
@@ -169,23 +170,24 @@ foreach my $d ("x", "\0") { # Try both printable and NUL delimiters
my $with_NULL = $source . "\0";
$source .= $d . ($ib x 7);
$source_len = length $source;
- $ret = test_delimcpy($source, $source_len, $d, $source_len, $source_len, $poison);
+ $ret = eval "$test_func(\$source, \$source_len, \$d, \$source_len, \$source_len, \$poison)";
is($ret->[0], expected($with_NULL, $len_sans_delim + 1, $poison, $source_len),
- "delimcpy works when delim is in middle of source, plenty of room");
+ "$func works when delim is in middle of source, plenty of room");
is($ret->[1], $len_sans_delim, "Destination length is correct");
is($ret->[2], $len_sans_delim, "Source advance is correct");
- $ret = test_delimcpy($source, $source_len, $d, $source_len, $len_sans_delim, $poison);
+ $ret = eval "$test_func(\$source, \$source_len, \$d, \$source_len, \$len_sans_delim, \$poison)";
is($ret->[0], expected($source, $len_sans_delim, $poison, $source_len),
- "delimcpy works when delim is in middle of source; no room for safety NUL");
+ "$func works when delim is in middle of source; no room for safety NUL");
is($ret->[1], $len_sans_delim, "Destination length is correct");
is($ret->[2], $len_sans_delim, "Source advance is correct");
- $ret = test_delimcpy($source, $source_len, $d, $source_len, $len_sans_delim - 1, $poison);
+ $ret = eval "$test_func(\$source, \$source_len, \$d, \$source_len, \$len_sans_delim - 1, \$poison)";
is($ret->[0], expected($source, $len_sans_delim - 1, $poison, $source_len),
- "delimcpy works when not enough space for copy");
+ "$func works when not enough space for copy");
is($ret->[1], $failure_return, "Destination length is correct");
is($ret->[2], $len_sans_delim, "Source advance is correct");
+ }
}
done_testing();