]> git.vpit.fr Git - perl/modules/Scalar-Vec-Util.git/blob - Util.xs
Cover bv_zero()
[perl/modules/Scalar-Vec-Util.git] / Util.xs
1 /* This file is part of the Scalar::Vec::Util Perl module.
2  * See http://search.cpan.org/dist/Scalar-Vec-Util/ */
3
4 #define PERL_NO_GET_CONTEXT
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8
9 #define __PACKAGE__     "Scalar::Vec::Util"
10 #define __PACKAGE_LEN__ (sizeof(__PACKAGE__)-1)
11
12 #include "bitvect.h"
13
14 STATIC size_t svu_validate_uv(pTHX_ SV *sv, const char *desc) {
15 #define svu_validate_uv(S, D) svu_validate_uv(aTHX_ (S), (D))
16  IV i;
17
18  if (SvOK(sv) && SvIOK(sv)) {
19   if (SvIsUV(sv))
20    return SvUVX(sv);
21   else {
22    i = SvIVX(sv);
23    if (i >= 0)
24     return i;
25   }
26  } else {
27   i = SvIV(sv);
28   if (i >= 0)
29    return i;
30  }
31
32  croak("Invalid negative %s", desc ? desc : "integer");
33  return 0;
34 }
35
36 STATIC char *svu_prepare_sv(pTHX_ SV *sv, size_t s, size_t l) {
37 #define svu_prepare_sv(S, I, L) svu_prepare_sv(aTHX_ (S), (I), (L))
38  STRLEN  c;
39  size_t  n = s + l, i, js, jz, k, z;
40  char   *p;
41
42  SvUPGRADE(sv, SVt_PV);
43
44  p = SvGROW(sv, BV_SIZE(n));
45  c = SvCUR(sv);
46
47  js = (s / BITS(BV_UNIT)) * sizeof(BV_UNIT);
48  k  = js + sizeof(BV_UNIT);
49  for (i = c < js ? js : c; i < k; ++i)
50   p[i] = 0;
51
52  jz = ((s + l - 1) / BITS(BV_UNIT)) * sizeof(BV_UNIT);
53  if (jz > js) {
54   k = jz + sizeof(BV_UNIT);
55   for (i = c < jz ? jz : c; i < k; ++i)
56    p[i] = 0;
57  }
58
59  z = 1 + ((s + l - 1) / CHAR_BIT);
60  if (c < z)
61   SvCUR_set(sv, z);
62
63  return p;
64 }
65
66 /* --- XS ------------------------------------------------------------------ */
67
68 MODULE = Scalar::Vec::Util              PACKAGE = Scalar::Vec::Util
69
70 PROTOTYPES: ENABLE
71
72 BOOT:
73 {
74  HV *stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1);
75  newCONSTSUB(stash, "SVU_PP",   newSVuv(0));
76  newCONSTSUB(stash, "SVU_SIZE", newSVuv(SVU_SIZE));
77 }
78
79 void
80 vfill(SV *sv, SV *ss, SV *sl, SV *sf)
81 PROTOTYPE: $$$$
82 PREINIT:
83  size_t s, l;
84  char f, *v;
85 CODE:
86  l = svu_validate_uv(sl, "length");
87  if (!l)
88   XSRETURN(0);
89  s = svu_validate_uv(ss, "offset");
90  v = svu_prepare_sv(sv, s, l);
91  f = SvTRUE(sf);
92
93  bv_fill(v, s, l, f);
94
95  XSRETURN(0);
96
97 void
98 vcopy(SV *sf, SV *sfs, SV *st, SV *sts, SV *sl)
99 PROTOTYPE: $$$$$
100 PREINIT:
101  size_t fs, ts, l, e, lf, cf;
102  char *vt, *vf;
103 CODE:
104  l = svu_validate_uv(sl, "length");
105  if (!l)
106   XSRETURN(0);
107  fs = svu_validate_uv(sfs, "offset");
108  ts = svu_validate_uv(sts, "offset");
109
110  SvUPGRADE(sf, SVt_PV);
111  vt = svu_prepare_sv(st, ts, l);
112
113  /* We fetch vf after upgrading st in case st == sf. */
114  vf = SvPVX(sf);
115  cf = SvCUR(sf) * CHAR_BIT;
116  lf = fs + l;
117  e  = lf > cf ? lf - cf : 0;
118  l  =  l > e  ?  l - e  : 0;
119
120  if (l) {
121   if (vf == vt)
122    bv_move(vf, ts, fs, l);
123   else
124    bv_copy(vt, ts, vf, fs, l);
125  }
126
127  if (e)
128   bv_fill(vt, ts + l, e, 0);
129
130  XSRETURN(0);
131
132 void
133 veq(SV *sv1, SV *ss1, SV *sv2, SV *ss2, SV *sl)
134 PROTOTYPE: $$$$$
135 PREINIT:
136  size_t s1, s2, l, l1, l2, c1, c2, e1, e2, e;
137  int    res = 1;
138  char  *v1, *v2;
139 CODE:
140  l = svu_validate_uv(sl, "length");
141  if (!l)
142   goto done;
143  s1 = svu_validate_uv(ss1, "offset");
144  s2 = svu_validate_uv(ss2, "offset");
145
146  SvUPGRADE(sv1, SVt_PV);
147  SvUPGRADE(sv2, SVt_PV);
148  v1 = SvPVX(sv1);
149  v2 = SvPVX(sv2);
150  c1 = SvCUR(sv1) * CHAR_BIT;
151  c2 = SvCUR(sv2) * CHAR_BIT;
152
153  redo:
154  l1 = s1 + l;
155  l2 = s2 + l;
156  e1 = l1 > c1 ? l1 - c1 : 0;
157  e2 = l2 > c2 ? l2 - c2 : 0;
158  e  = e1 > e2 ? e1 : e2;
159
160  if (l > e) {
161   size_t p = l - e;
162
163   res = bv_eq(v1, s1, v2, s2, p);
164   if (!res || e == 0)
165    goto done;
166
167   /* Bit vectors are equal up to p < l */
168   s1 += p;
169   s2 += p;
170   l   = e;
171   goto redo;
172  }
173
174  /* l <= max(e1, e2), at least one of the vectors is completely out of bounds */
175  e = e1 < e2 ? e1 : e2;
176  if (l > e) {
177   size_t q = l - e;
178
179   if (s1 < c1)
180    res = bv_zero(v1, s1, q);
181   else if (s2 < c2)
182    res = bv_zero(v2, s2, q);
183  }
184
185  done:
186  ST(0) = res ? &PL_sv_yes : &PL_sv_no;
187  XSRETURN(1);