summaryrefslogtreecommitdiff
path: root/doop.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2021-07-18 17:30:49 -0600
committerKarl Williamson <khw@cpan.org>2021-08-06 08:48:16 -0600
commit6c4aa50c3d02831e0adee8be4d10577b03de815d (patch)
tree15ace2cd9c4ae67046ea3877aa3102b2dfc90584 /doop.c
parent35e4fe1f5a6c9fdcf227320cf569bcbd28da463a (diff)
downloadperl-6c4aa50c3d02831e0adee8be4d10577b03de815d.tar.gz
doop.c: Refactor do_vecget()
By using a switch statement this function can be cut in half, with fewer conditionals executed.
Diffstat (limited to 'doop.c')
-rw-r--r--doop.c166
1 files changed, 50 insertions, 116 deletions
diff --git a/doop.c b/doop.c
index eab581586c..e179c0f835 100644
--- a/doop.c
+++ b/doop.c
@@ -731,7 +731,7 @@ Perl_do_sprintf(pTHX_ SV *sv, SSize_t len, SV **sarg)
UV
Perl_do_vecget(pTHX_ SV *sv, STRLEN offset, int size)
{
- STRLEN srclen, len, avail, uoffset, bitoffs = 0;
+ STRLEN srclen, avail, uoffset;
const I32 svpv_flags = ((PL_op->op_flags & OPf_MOD || LVRET)
? SV_UNDEF_RETURNS_NULL : 0);
unsigned char *s = (unsigned char *)
@@ -758,131 +758,65 @@ Perl_do_vecget(pTHX_ SV *sv, STRLEN offset, int size)
}
}
- if (size < 8) {
- bitoffs = ((offset % 8) * size) % 8;
+ if (size <= 8) {
+ STRLEN bitoffs = ((offset % 8) * size) % 8;
uoffset = offset / (8 / size);
- }
- else if (size > 8) {
- int n = size/8;
- if (offset > Size_t_MAX / n - 1) /* would overflow */
- return 0;
- uoffset = offset*n;
- }
- else
- uoffset = offset;
-
- if (uoffset >= srclen)
- return 0;
- len = (bitoffs + size + 7)/8; /* required number of bytes */
- avail = srclen - uoffset; /* available number of bytes */
+ if (uoffset >= srclen)
+ return 0;
- /* Does the byte range overlap the end of the string? If so,
- * handle specially. */
- if (avail < len) {
- if (size <= 8)
- retnum = 0;
- else {
- if (size == 16) {
- assert(avail == 1);
- retnum = (UV) s[uoffset] << 8;
- }
- else if (size == 32) {
- assert(avail >= 1 && avail <= 3);
- if (avail == 1)
- retnum =
- ((UV) s[uoffset ] << 24);
- else if (avail == 2)
- retnum =
- ((UV) s[uoffset ] << 24) +
- ((UV) s[uoffset + 1] << 16);
- else
- retnum =
- ((UV) s[uoffset ] << 24) +
- ((UV) s[uoffset + 1] << 16) +
- ( s[uoffset + 2] << 8);
- }
-#ifdef UV_IS_QUAD
- else if (size == 64) {
- Perl_ck_warner(aTHX_ packWARN(WARN_PORTABLE),
- "Bit vector size > 32 non-portable");
- assert(avail >= 1 && avail <= 7);
- if (avail == 1)
- retnum =
- (UV) s[uoffset ] << 56;
- else if (avail == 2)
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48);
- else if (avail == 3)
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48) +
- ((UV) s[uoffset + 2] << 40);
- else if (avail == 4)
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48) +
- ((UV) s[uoffset + 2] << 40) +
- ((UV) s[uoffset + 3] << 32);
- else if (avail == 5)
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48) +
- ((UV) s[uoffset + 2] << 40) +
- ((UV) s[uoffset + 3] << 32) +
- ((UV) s[uoffset + 4] << 24);
- else if (avail == 6)
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48) +
- ((UV) s[uoffset + 2] << 40) +
- ((UV) s[uoffset + 3] << 32) +
- ((UV) s[uoffset + 4] << 24) +
- ((UV) s[uoffset + 5] << 16);
- else
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48) +
- ((UV) s[uoffset + 2] << 40) +
- ((UV) s[uoffset + 3] << 32) +
- ((UV) s[uoffset + 4] << 24) +
- ((UV) s[uoffset + 5] << 16) +
- ((UV) s[uoffset + 6] << 8);
- }
-#endif
- }
- }
- else if (size < 8)
retnum = (s[uoffset] >> bitoffs) & nBIT_MASK(size);
+ }
else {
- if (size == 8)
- retnum = s[uoffset];
- else if (size == 16)
- retnum =
- ((UV) s[uoffset] << 8) +
- s[uoffset + 1];
- else if (size == 32)
- retnum =
- ((UV) s[uoffset ] << 24) +
- ((UV) s[uoffset + 1] << 16) +
- ( s[uoffset + 2] << 8) +
- s[uoffset + 3];
+ int n = size / 8; /* required number of bytes */
+
#ifdef UV_IS_QUAD
- else if (size == 64) {
+
+ if (size == 64) {
Perl_ck_warner(aTHX_ packWARN(WARN_PORTABLE),
"Bit vector size > 32 non-portable");
- retnum =
- ((UV) s[uoffset ] << 56) +
- ((UV) s[uoffset + 1] << 48) +
- ((UV) s[uoffset + 2] << 40) +
- ((UV) s[uoffset + 3] << 32) +
- ((UV) s[uoffset + 4] << 24) +
- ((UV) s[uoffset + 5] << 16) +
- ( s[uoffset + 6] << 8) +
- s[uoffset + 7];
}
#endif
+ if (offset > Size_t_MAX / n - 1) /* would overflow */
+ return 0;
+
+ uoffset = offset * n;
+
+ if (uoffset >= srclen)
+ return 0;
+
+ avail = srclen - uoffset; /* available number of bytes */
+
+ switch (MIN(n, avail)) {
+
+#ifdef UV_IS_QUAD
+
+ case 8:
+ retnum += ((UV) s[uoffset + 7]);
+ /* FALLTHROUGH */
+ case 7:
+ retnum += ((UV) s[uoffset + 6] << 8); /* = size - 56 */
+ /* FALLTHROUGH */
+ case 6:
+ retnum += ((UV) s[uoffset + 5] << 16); /* = size - 48 */
+ /* FALLTHROUGH */
+ case 5:
+ retnum += ((UV) s[uoffset + 4] << 24); /* = size - 40 */
+#endif
+ /* FALLTHROUGH */
+ case 4:
+ retnum += ((UV) s[uoffset + 3] << (size - 32));
+ /* FALLTHROUGH */
+ case 3:
+ retnum += ((UV) s[uoffset + 2] << (size - 24));
+ /* FALLTHROUGH */
+ case 2:
+ retnum += ((UV) s[uoffset + 1] << (size - 16));
+ /* FALLTHROUGH */
+ case 1:
+ retnum += ((UV) s[uoffset ] << (size - 8));
+ break;
+ }
}
return retnum;