diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 1999-08-19 12:49:41 +0000 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 1999-08-19 12:49:41 +0000 |
commit | 81e118e078828ea41cd654ee18f4193484a89cf3 (patch) | |
tree | 62637e08be5499f11f20df252b484d835c58e171 /doop.c | |
parent | 41bd693c38b93b50972065296573f26c13cc43d1 (diff) | |
download | perl-81e118e078828ea41cd654ee18f4193484a89cf3.tar.gz |
Removed duplicated code (in pp.c and mg.c) by introducing
do_vecget(). NOTE: the calling convention of do_vecset()
changes, too: the `offset' that is assigned to LvTARGOFF(TARG)
in pp_vec() is no more multiplied by `size' in pp_vec(),
the multiplication is now done in do_vecset().
Also fix a cpp thinko in change #4002.
p4raw-link: @4002 on //depot/cfgperl: 24db6c0d56fddf85ee587fc1cb1dbce678fa6a8c
p4raw-id: //depot/cfgperl@4004
Diffstat (limited to 'doop.c')
-rw-r--r-- | doop.c | 76 |
1 files changed, 71 insertions, 5 deletions
@@ -697,6 +697,71 @@ Perl_do_sprintf(pTHX_ SV *sv, I32 len, SV **sarg) 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) { @@ -704,7 +769,7 @@ 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; @@ -712,11 +777,12 @@ Perl_do_vecset(pTHX_ SV *sv) 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); @@ -727,12 +793,12 @@ Perl_do_vecset(pTHX_ SV *sv) 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) { |