]> git.vpit.fr Git - perl/modules/Scalar-Vec-Util.git/commitdiff
Properly prepare the scalars before filling or copying into them
authorVincent Pit <vince@profvince.com>
Sat, 23 Apr 2011 14:16:27 +0000 (16:16 +0200)
committerVincent Pit <vince@profvince.com>
Sat, 23 Apr 2011 14:18:46 +0000 (16:18 +0200)
Util.xs
bitvect.h

diff --git a/Util.xs b/Util.xs
index f48753935ca5bbe54c1b7beb730acf74a8a970e4..28fe705bec7846296a88232e785bf2ced3e5b4a2 100644 (file)
--- a/Util.xs
+++ b/Util.xs
@@ -33,6 +33,36 @@ STATIC size_t svu_validate_uv(pTHX_ SV *sv, const char *desc) {
  return 0;
 }
 
+STATIC char *svu_prepare_sv(pTHX_ SV *sv, size_t s, size_t l) {
+#define svu_prepare_sv(S, I, L) svu_prepare_sv(aTHX_ (S), (I), (L))
+ STRLEN  c;
+ size_t  n = s + l, i, j1, j2, k, z;
+ char   *p;
+
+ SvUPGRADE(sv, SVt_PV);
+
+ p = SvGROW(sv, BV_SIZE(n));
+ c = SvCUR(sv);
+
+ j1 = (s / BITS(BV_UNIT)) * sizeof(BV_UNIT);
+ k  = j1 + sizeof(BV_UNIT);
+ for (i = c < j1 ? j1 : c; i < k; ++i)
+  p[i] = 0;
+
+ j2 = ((s + l - 1) / BITS(BV_UNIT)) * sizeof(BV_UNIT);
+ if (j2 > j1) {
+  k = j2 + sizeof(BV_UNIT);
+  for (i = c < j2 ? j2 : c; i < k; ++i)
+   p[i] = 0;
+ }
+
+ z = 1 + ((s + l - 1) / CHAR_BIT);
+ if (c < z)
+  SvCUR_set(sv, z);
+
+ return p;
+}
+
 /* --- XS ------------------------------------------------------------------ */
 
 MODULE = Scalar::Vec::Util              PACKAGE = Scalar::Vec::Util
@@ -50,26 +80,15 @@ void
 vfill(SV *sv, SV *ss, SV *sl, SV *sf)
 PROTOTYPE: $$$$
 PREINIT:
- size_t s, l, n, o;
+ size_t s, l;
  char f, *v;
 CODE:
  l = svu_validate_uv(sl, "length");
  if (!l)
   XSRETURN(0);
  s = svu_validate_uv(ss, "offset");
+ v = svu_prepare_sv(sv, s, l);
  f = SvTRUE(sf);
- SvUPGRADE(sv, SVt_PV);
-
- n = BV_SIZE(s + l);
- o = SvLEN(sv);
- if (n > o) {
-  v = SvGROW(sv, n);
-  Zero(v + o, n - o, char);
- } else {
-  v = SvPVX(sv);
- }
- if (SvCUR(sv) < n)
-  SvCUR_set(sv, n);
 
  bv_fill(v, s, l, f);
 
@@ -79,7 +98,7 @@ void
 vcopy(SV *sf, SV *sfs, SV *st, SV *sts, SV *sl)
 PROTOTYPE: $$$$$
 PREINIT:
- size_t fs, ts, l, lf = 0, n, o;
+ size_t fs, ts, l, lf = 0, c;
  char *t, *f;
 CODE:
  l = svu_validate_uv(sl, "length");
@@ -87,26 +106,14 @@ CODE:
   XSRETURN(0);
  fs = svu_validate_uv(sfs, "offset");
  ts = svu_validate_uv(sts, "offset");
- SvUPGRADE(sf, SVt_PV);
- SvUPGRADE(st, SVt_PV);
 
- n  = BV_SIZE(ts + l);
- o  = SvLEN(st);
- if (n > o) {
-  t = SvGROW(st, n);
-  Zero(t + o, n - o, char);
- } else {
-  t = SvPVX(st);
- }
- if (SvCUR(st) < n)
-  SvCUR_set(st, n);
- f = SvPVX(sf); /* We do it there in case st == sf. */
+ t = svu_prepare_sv(st, ts, l);
 
- n  = BV_SIZE(fs + l);
o  = SvLEN(sf);
- if (n > o) {
-  lf = fs + l - o * CHAR_BIT;
-  l  = o * CHAR_BIT - fs;
+ 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;
  }
 
  if (f == t) {
index b50c1a10407323cd5de02b6cfadeb9f5578045f7..0f096fdb7f61ec000de50f0cd8d6705485f5f116 100644 (file)
--- a/bitvect.h
+++ b/bitvect.h
 # define BV_UNIT unsigned char
 #endif
 
-#define BV_SIZE(I) ((((I) % CHAR_BIT) != 0) + ((I) / CHAR_BIT))
-
 #define BITS(T) (CHAR_BIT * sizeof(T))
 
+#define BV_SIZE(I) (((((I) % BITS(BV_UNIT)) != 0) + ((I) / BITS(BV_UNIT))) * sizeof(BV_UNIT))
+
 /* 0 <= I <  CHAR_BIT * sizeof(T) */
 #define BV_MASK_LOWER(T, I)  (~((~((T) 0)) << (I)))
 /* 0 <  I <= CHAR_BIT * sizeof(T) */