vcopy(SV *sf, SV *sfs, SV *st, SV *sts, SV *sl)
PROTOTYPE: $$$$$
PREINIT:
- size_t fs, ts, l, lf = 0, c;
- char *t, *f;
+ size_t fs, ts, l, e, lf, cf;
+ char *vt, *vf;
CODE:
l = svu_validate_uv(sl, "length");
if (!l)
fs = svu_validate_uv(sfs, "offset");
ts = svu_validate_uv(sts, "offset");
- t = svu_prepare_sv(st, ts, l);
-
- f = SvPVX(sf); /* We do it there in case st == sf. */
- c = SvCUR(sf);
- if (c * CHAR_BIT <= fs + l && c <= SvCUR(st)) {
- lf = fs + l - c * CHAR_BIT;
- l = c * CHAR_BIT - fs;
+ SvUPGRADE(sf, SVt_PV);
+ vt = svu_prepare_sv(st, ts, l);
+
+ /* We fetch vf after upgrading st in case st == sf. */
+ vf = SvPVX(sf);
+ cf = SvCUR(sf) * CHAR_BIT;
+ lf = fs + l;
+ e = lf > cf ? lf - cf : 0;
+ l = l > e ? l - e : 0;
+
+ if (l) {
+ if (vf == vt)
+ bv_move(vf, ts, fs, l);
+ else
+ bv_copy(vt, ts, vf, fs, l);
}
- if (f == t) {
- bv_move(f, ts, fs, l);
- } else {
- bv_copy(t, ts, f, fs, l);
- }
-
- if (lf) {
- bv_fill(t, ts + l, lf, 0);
- }
+ if (e)
+ bv_fill(vt, ts + l, e, 0);
XSRETURN(0);
for my $l (0 .. $n - 1) {
for my $x (0 .. $q) {
for my $y (0 .. $q) {
- last if $s1 + $l + $x > $n or $s1 + $x + $y > $l
- or $s2 + $l + $x > $n or $s2 + $x + $y > $l;
+ next if $l - $x - $y < 0 or $s2 + $l - $y < 0;
my $desc = "vcopy [ $x, $y ], $s1, $s2, $l (move)";
pat $v, $s1 + $x, $l - $x - $y, 0;
my $v0 = $v;