SvTAINTED_on(sv);
}
+UV
+Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
+{
+ STRLEN srclen, len;
+ unsigned char *s = (unsigned char *) SvPV(sv, srclen);
+ UV retnum = 0;
+
+ if (offset < 0 || size < 1)
+ return retnum;
+ offset *= size; /* turn into bit offset */
+ len = (offset + size + 7) / 8; /* required number of bytes */
+ if (len > srclen) {
+ if (size <= 8)
+ retnum = 0;
+ else {
+ offset >>= 3; /* turn into byte offset */
+ if (size == 16) {
+ if (offset >= srclen)
+ retnum = 0;
+ else
+ retnum = (UV) s[offset] << 8;
+ }
+ else if (size == 32) {
+ if (offset >= srclen)
+ retnum = 0;
+ else if (offset + 1 >= srclen)
+ retnum =
+ ((UV) s[offset ] << 24);
+ else if (offset + 2 >= srclen)
+ retnum =
+ ((UV) s[offset ] << 24) +
+ ((UV) s[offset + 1] << 16);
+ else
+ retnum =
+ ((UV) s[offset ] << 24) +
+ ((UV) s[offset + 1] << 16) +
+ ( s[offset + 2] << 8);
+ }
+ else
+ Perl_croak(aTHX_ "Illegal number of bits in vec");
+ }
+ }
+ else if (size < 8)
+ retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
+ else {
+ offset >>= 3; /* turn into byte offset */
+ if (size == 8)
+ retnum = s[offset];
+ else if (size == 16)
+ retnum =
+ ((UV) s[offset] << 8) +
+ s[offset + 1];
+ else if (size == 32)
+ retnum =
+ ((UV) s[offset ] << 24) +
+ ((UV) s[offset + 1] << 16) +
+ ( s[offset + 2] << 8) +
+ s[offset + 3];
+ else
+ Perl_croak(aTHX_ "Illegal number of bits in vec");
+ }
+
+ return retnum;
+}
+
void
Perl_do_vecset(pTHX_ SV *sv)
{
register I32 offset;
register I32 size;
register unsigned char *s;
- register unsigned long lval;
+ register UV lval;
I32 mask;
STRLEN targlen;
STRLEN len;
if (!targ)
return;
s = (unsigned char*)SvPV_force(targ, targlen);
- lval = U_L(SvNV(sv));
+ lval = SvUV(sv);
offset = LvTARGOFF(sv);
size = LvTARGLEN(sv);
- len = (offset + size + 7) / 8;
+ offset *= size; /* turn into bit offset */
+ len = (offset + size + 7) / 8; /* required number of bytes */
if (len > targlen) {
s = (unsigned char*)SvGROW(targ, len + 1);
(void)memzero(s + targlen, len - targlen + 1);
mask = (1 << size) - 1;
size = offset & 7;
lval &= mask;
- offset >>= 3;
+ offset >>= 3; /* turn into byte offset */
s[offset] &= ~(mask << size);
s[offset] |= lval << size;
}
else {
- offset >>= 3;
+ offset >>= 3; /* turn into byte offset */
if (size == 8)
s[offset] = lval & 255;
else if (size == 16) {
#define do_sysseek Perl_do_sysseek
#define do_tell Perl_do_tell
#define do_trans Perl_do_trans
+#define do_vecget Perl_do_vecget
#define do_vecset Perl_do_vecset
#define do_vop Perl_do_vop
#define dofile Perl_dofile
#define do_sysseek(a,b,c) Perl_do_sysseek(aTHX_ a,b,c)
#define do_tell(a) Perl_do_tell(aTHX_ a)
#define do_trans(a) Perl_do_trans(aTHX_ a)
+#define do_vecget(a,b,c) Perl_do_vecget(aTHX_ a,b,c)
#define do_vecset(a) Perl_do_vecset(aTHX_ a)
#define do_vop(a,b,c,d) Perl_do_vop(aTHX_ a,b,c,d)
#define dofile(a) Perl_dofile(aTHX_ a)
#define do_tell Perl_do_tell
#define Perl_do_trans CPerlObj::Perl_do_trans
#define do_trans Perl_do_trans
+#define Perl_do_vecget CPerlObj::Perl_do_vecget
+#define do_vecget Perl_do_vecget
#define Perl_do_vecset CPerlObj::Perl_do_vecset
#define do_vecset Perl_do_vecset
#define Perl_do_vop CPerlObj::Perl_do_vop
p |Off_t |do_sysseek |GV* gv|Off_t pos|int whence
p |Off_t |do_tell |GV* gv
p |I32 |do_trans |SV* sv
+p |UV |do_vecget |SV* sv|I32 offset|I32 size
p |void |do_vecset |SV* sv
p |void |do_vop |I32 optype|SV* sv|SV* left|SV* right
p |OP* |dofile |OP* term
Perl_do_sysseek
Perl_do_tell
Perl_do_trans
+Perl_do_vecget
Perl_do_vecset
Perl_do_vop
Perl_dofile
Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg)
{
SV *lsv = LvTARG(sv);
- unsigned char *s;
- unsigned long retnum;
- STRLEN lsvlen;
- I32 len;
- I32 offset;
- I32 size;
if (!lsv) {
SvOK_off(sv);
return 0;
}
- s = (unsigned char *) SvPV(lsv, lsvlen);
- offset = LvTARGOFF(sv);
- size = LvTARGLEN(sv);
- len = (offset + size + 7) / 8;
-
- /* Copied from pp_vec() */
-
- if (len > lsvlen) {
- if (size <= 8)
- retnum = 0;
- else {
- offset >>= 3;
- if (size == 16) {
- if (offset >= lsvlen)
- retnum = 0;
- else
- retnum = (unsigned long) s[offset] << 8;
- }
- else if (size == 32) {
- if (offset >= lsvlen)
- retnum = 0;
- else if (offset + 1 >= lsvlen)
- retnum = (unsigned long) s[offset] << 24;
- else if (offset + 2 >= lsvlen)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16);
- else
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8);
- }
- }
- }
- else if (size < 8)
- retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
- else {
- offset >>= 3;
- if (size == 8)
- retnum = s[offset];
- else if (size == 16)
- retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
- else if (size == 32)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8) + s[offset+3];
- }
- sv_setuv(sv, (UV)retnum);
+ sv_setuv(sv, do_vecget(lsv, LvTARGOFF(sv), LvTARGLEN(sv)));
return 0;
}
#define Perl_do_trans pPerl->Perl_do_trans
#undef do_trans
#define do_trans Perl_do_trans
+#undef Perl_do_vecget
+#define Perl_do_vecget pPerl->Perl_do_vecget
+#undef do_vecget
+#define do_vecget Perl_do_vecget
#undef Perl_do_vecset
#define Perl_do_vecset pPerl->Perl_do_vecset
#undef do_vecset
# endif
# endif
# endif
-#else
+#endif
/* Used with UV/IV arguments: */
/* XXXX: need to speed it up */
return ((CPerlObj*)pPerl)->Perl_do_trans(sv);
}
+#undef Perl_do_vecget
+UV
+Perl_do_vecget(pTHXo_ SV* sv, I32 offset, I32 size)
+{
+ return ((CPerlObj*)pPerl)->Perl_do_vecget(sv, offset, size);
+}
+
#undef Perl_do_vecset
void
Perl_do_vecset(pTHXo_ SV* sv)
in a hexadecimal number. Interpretation of the hexadecimal number stopped
before the illegal character.
+=item Illegal number of bits in vec
+
+(F) The number of bits in vec() (the third argument) must be from 1 to 8
+(inclusive), or 16, or 32.
+
=item Illegal switch in PERL5OPT: %s
(X) The PERL5OPT environment variable may only be used to set the
=item vec EXPR,OFFSET,BITS
Treats the string in EXPR as a vector of unsigned integers, and
-returns the value of the bit field specified by OFFSET. BITS specifies
-the number of bits that are reserved for each entry in the bit
-vector. This must be a power of two from 1 to 32. C<vec> may also be
-assigned to, in which case parentheses are needed to give the expression
-the correct precedence as in
+returns the value of the bit field specified by OFFSET. BITS
+specifies the number of bits that are reserved for each entry in the
+bit vector. This must be between 1 and 8 (inclusive), or 16, or 32.
+C<vec> may also be assigned to, in which case parentheses are needed
+to give the expression the correct precedence as in
vec($image, $max_x * $x + $y, 8) = 3;
register I32 offset = POPi;
register SV *src = POPs;
I32 lvalue = PL_op->op_flags & OPf_MOD;
- STRLEN srclen;
- unsigned char *s = (unsigned char*)SvPV(src, srclen);
- unsigned long retnum;
- I32 len;
- SvTAINTED_off(TARG); /* decontaminate */
- offset *= size; /* turn into bit offset */
- len = (offset + size + 7) / 8;
- if (offset < 0 || size < 1)
- retnum = 0;
- else {
- if (lvalue) { /* it's an lvalue! */
- if (SvTYPE(TARG) < SVt_PVLV) {
- sv_upgrade(TARG, SVt_PVLV);
- sv_magic(TARG, Nullsv, 'v', Nullch, 0);
- }
-
- LvTYPE(TARG) = 'v';
- if (LvTARG(TARG) != src) {
- if (LvTARG(TARG))
- SvREFCNT_dec(LvTARG(TARG));
- LvTARG(TARG) = SvREFCNT_inc(src);
- }
- LvTARGOFF(TARG) = offset;
- LvTARGLEN(TARG) = size;
- }
- if (len > srclen) {
- if (size <= 8)
- retnum = 0;
- else {
- offset >>= 3;
- if (size == 16) {
- if (offset >= srclen)
- retnum = 0;
- else
- retnum = (unsigned long) s[offset] << 8;
- }
- else if (size == 32) {
- if (offset >= srclen)
- retnum = 0;
- else if (offset + 1 >= srclen)
- retnum = (unsigned long) s[offset] << 24;
- else if (offset + 2 >= srclen)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16);
- else
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8);
- }
- }
+ SvTAINTED_off(TARG); /* decontaminate */
+ if (lvalue) { /* it's an lvalue! */
+ if (SvTYPE(TARG) < SVt_PVLV) {
+ sv_upgrade(TARG, SVt_PVLV);
+ sv_magic(TARG, Nullsv, 'v', Nullch, 0);
}
- else if (size < 8)
- retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
- else {
- offset >>= 3;
- if (size == 8)
- retnum = s[offset];
- else if (size == 16)
- retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
- else if (size == 32)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8) + s[offset+3];
+ LvTYPE(TARG) = 'v';
+ if (LvTARG(TARG) != src) {
+ if (LvTARG(TARG))
+ SvREFCNT_dec(LvTARG(TARG));
+ LvTARG(TARG) = SvREFCNT_inc(src);
}
+ LvTARGOFF(TARG) = offset;
+ LvTARGLEN(TARG) = size;
}
- sv_setuv(TARG, (UV)retnum);
+ sv_setuv(TARG, do_vecget(src, offset, size));
PUSHs(TARG);
RETURN;
}
VIRTUAL Off_t Perl_do_sysseek(pTHX_ GV* gv, Off_t pos, int whence);
VIRTUAL Off_t Perl_do_tell(pTHX_ GV* gv);
VIRTUAL I32 Perl_do_trans(pTHX_ SV* sv);
+VIRTUAL UV Perl_do_vecget(pTHX_ SV* sv, I32 offset, I32 size);
VIRTUAL void Perl_do_vecset(pTHX_ SV* sv);
VIRTUAL void Perl_do_vop(pTHX_ I32 optype, SV* sv, SV* left, SV* right);
VIRTUAL OP* Perl_dofile(pTHX_ OP* term);