diff options
author | Karl Williamson <khw@cpan.org> | 2020-10-16 21:08:13 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2020-10-31 11:04:19 -0600 |
commit | 430f723e6dceffbacbd1d7160d35ee8a2b698448 (patch) | |
tree | ef8d5a4308f1822d1b4dc2813f6b73d792a3b6c1 /ext | |
parent | cc448ceab170493a35039184f4f85054a8ddf971 (diff) | |
download | perl-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.xs | 27 | ||||
-rw-r--r-- | ext/XS-APItest/t/delimcpy.t | 34 |
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(); |