undef arguments are now allowed. Signedness is checked. Functions have prototypes.
#include "bitvect.h"
-STATIC const char svu_error_invarg[] = "Invalid argument";
+STATIC void svu_validate_uv(pTHX_ SV *sv, size_t *offset, const char *desc) {
+#define svu_validate_uv(S, O, D) svu_validate_uv(aTHX_ (S), (O), (D))
+ IV i;
+
+ if (SvOK(sv) && SvIOK(sv)) {
+ if (SvIsUV(sv))
+ *offset = SvUVX(sv);
+ else {
+ i = SvIVX(sv);
+ if (i < 0)
+ goto fail;
+ *offset = i;
+ }
+ } else {
+ i = SvIV(sv);
+ if (i < 0)
+ goto fail;
+ *offset = i;
+ }
+
+ return;
+
+fail:
+ *offset = 0;
+ croak("Invalid negative %s", desc ? desc : "integer");
+}
/* --- XS ------------------------------------------------------------------ */
size_t s, l, n, o;
char f, *v;
CODE:
- if (!SvOK(sv) || !SvOK(ss) || !SvOK(sl) || !SvOK(sf))
- croak(svu_error_invarg);
-
- l = SvUV(sl);
+ svu_validate_uv(sl, &l, "length");
if (!l)
XSRETURN(0);
- s = SvUV(ss);
+ svu_validate_uv(ss, &s, "offset");
f = SvTRUE(sf);
SvUPGRADE(sv, SVt_PV);
size_t fs, ts, l, lf = 0, n, o;
char *t, *f;
CODE:
- if (!SvOK(sf) || !SvOK(sfs) || !SvOK(st) || !SvOK(sts) || !SvOK(sl))
- croak(svu_error_invarg);
-
- l = SvUV(sl);
+ svu_validate_uv(sl, &l, "length");
if (!l)
XSRETURN(0);
- fs = SvUV(sfs);
- ts = SvUV(sts);
+ svu_validate_uv(sfs, &fs, "offset");
+ svu_validate_uv(sts, &ts, "offset");
SvUPGRADE(sf, SVt_PV);
SvUPGRADE(st, SVt_PV);
size_t s1, s2, l, o, n;
char *v1, *v2;
CODE:
- if (!SvOK(sv1) || !SvOK(ss1) || !SvOK(sv2) || !SvOK(ss2) || !SvOK(sl))
- croak(svu_error_invarg);
-
- l = SvUV(sl);
+ svu_validate_uv(sl, &l, "length");
if (!l)
- XSRETURN(0);
- s1 = SvUV(ss1);
- s2 = SvUV(ss2);
+ XSRETURN_YES;
+ svu_validate_uv(ss1, &s1, "offset");
+ svu_validate_uv(ss2, &s2, "offset");
SvUPGRADE(sv1, SVt_PV);
SvUPGRADE(sv2, SVt_PV);
=cut
-sub _alldef {
- for (@_) { return 0 unless defined }
- return 1;
-}
-
sub vfill_pp ($$$$) {
- (undef, my $s, my $l, my $x) = @_;
- croak "Invalid argument" unless _alldef @_;
+ my ($s, $l, $x) = @_[1 .. 3];
return unless $l;
+ croak 'Invalid negative offset' if $s < 0;
+ croak 'Invalid negative length' if $l < 0;
$x = ~0 if $x;
my $SIZE = 32;
my $t = int($s / $SIZE) + 1;
sub vcopy_pp ($$$$$) {
my ($fs, $ts, $l) = @_[1, 3, 4];
- croak "Invalid argument" unless _alldef @_;
return unless $l;
+ croak 'Invalid negative offset' if $fs < 0 or $ts < 0;
+ croak 'Invalid negative length' if $l < 0;
my $step = $ts - $fs;
if ($step <= 0) {
vec($_[2], $_ + $step, 1) = vec($_[0], $_, 1) for $fs .. $fs + $l - 1;
sub vshift ($$$$;$) {
my ($start, $length, $bits, $insert) = @_[1 .. 4];
- return unless $bits;
+ return unless $length and $bits;
+ croak 'Invalid negative offset' if $start < 0;
+ croak 'Invalid negative length' if $length < 0;
my $left = 1;
if ($bits < 0) {
$left = 0;
sub vrot ($$$$) {
my ($start, $length, $bits) = @_[1 .. 3];
return unless $length and $bits;
+ croak 'Invalid negative offset' if $start < 0;
+ croak 'Invalid negative length' if $length < 0;
my $left = 1;
if ($bits < 0) {
$left = 0;
sub veq_pp ($$$$$) {
my ($s1, $s2, $l) = @_[1, 3, 4];
- croak "Invalid argument" unless _alldef @_;
+ croak 'Invalid negative offset' if $s1 < 0 or $s2 < 0;
+ croak 'Invalid negative length' if $l < 0;
my $i = 0;
while ($i < $l) {
return 0 if vec($_[0], $s1 + $i, 1) != vec($_[2], $s2 + $i, 1);
use Scalar::Vec::Util;
-eval { Scalar::Vec::Util::veq_pp(undef, 0, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, undef, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, 0, undef, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, 0, my $y, undef, 0) };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, 0, my $y, 0, undef) };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args = ('1') x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &Scalar::Vec::Util::veq_pp(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
my $p = 8;
my $n = 3 * $p;
use Scalar::Vec::Util qw/veq SVU_SIZE/;
-eval { veq undef, 0, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { veq my $x, undef, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { veq my $x, 0, undef, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { veq my $x, 0, my $y, undef, 0 };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { veq my $x, 0, my $y, 0, undef };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args = ('1') x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &veq(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
my $p = SVU_SIZE;
$p = 8 if $p < 8;
pat $v1, $s1, $l, 0;
pat $v2, $s2, $l, 0;
ok(veq($v1 => $s1, $v2 => $s2, $l), "veq $s1, $s2, $l");
- ok(!veq($v1 => $s1 - 1, $v2 => $s2, $l), 'not veq_pp ' . ($s1 - 1) . ", $s2, $l") if $l > 0;
- ok(!veq($v1 => $s1 + 1, $v2 => $s2, $l), 'not veq_pp ' . ($s1 + 1) . ", $s2, $l") if $l > 0;
+ ok(!veq($v1 => $s1 - 1, $v2 => $s2, $l), 'not veq ' . ($s1 - 1) . ", $s2, $l") if $l > 0;
+ ok(!veq($v1 => $s1 + 1, $v2 => $s2, $l), 'not veq ' . ($s1 + 1) . ", $s2, $l") if $l > 0;
}
}
}
use Scalar::Vec::Util;
-eval { Scalar::Vec::Util::vfill_pp(undef, 0, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { Scalar::Vec::Util::vfill_pp(my $x, undef, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { Scalar::Vec::Util::vfill_pp(my $x, 0, undef, 0) };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { Scalar::Vec::Util::vfill_pp(my $x, 0, 0, undef) };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args = ('1') x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &Scalar::Vec::Util::vfill_pp(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
my $p = 8;
my $n = 3 * $p;
use Scalar::Vec::Util qw/vfill SVU_SIZE/;
-eval { vfill undef, 0, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { vfill my $x, undef, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { vfill my $x, 0, undef, 0 };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { vfill my $x, 0, 0, undef };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args = (~0) x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &vfill(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
my $p = SVU_SIZE;
$p = 8 if $p < 8;
use Scalar::Vec::Util qw/SVU_SIZE/;
-eval { Scalar::Vec::Util::vcopy_pp(undef, 0, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, undef, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, 0, undef, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, 0, my $y, undef, 0) };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, 0, my $y, 0, undef) };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args = ('1') x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &Scalar::Vec::Util::vcopy_pp(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
my $p = SVU_SIZE;
$p = 8 if $p < 8;
use Scalar::Vec::Util qw/vcopy SVU_SIZE/;
-eval { vcopy undef, 0, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { vcopy my $x, undef, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { vcopy my $x, 0, undef, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { vcopy my $x, 0, my $y, undef, 0 };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { vcopy my $x, 0, my $y, 0, undef };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args = (~0) x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &vcopy(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
my $p = SVU_SIZE;
$p = 8 if $p < 8;
use Scalar::Vec::Util qw/vshift SVU_SIZE/;
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args = ('1') x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &vshift(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
+
my $p = SVU_SIZE;
$p = 8 if $p < 8;
my $n = 3 * $p;
use Scalar::Vec::Util qw/vrot vcopy SVU_SIZE/;
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args = ('1') x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &vrot(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
+
my $p = SVU_SIZE;
$p = 8 if $p < 8;
my $n = 3 * $p;
sub expected {
(undef, my $s, my $l, my $b, my $left) = @_;
+ unless ($l) {
+ myfill($_[0], 0, $s, 0);
+ myfill($_[0], $s, $n - $s, 1);
+ return;
+ }
my $lx = int($l / 2);
my $ly = $l - $lx;
$b %= $l;
my ($left) = @_;
my @s = ($p - $q) .. ($p + $q);
for my $s (@s) {
- for my $l (1 .. $n - 1) {
+ for my $l (0 .. $n - 1) {
last if $s + $l > $n;
my $l2 = int($l/2);
rst $v0;