Skip to content

Commit 68a142d

Browse files
committed
grok_bin_oct_hex: Use upper bound, not length remaining
Creating an upper limit to parse allows us to write while (s < e) for example, and that limit is constant, requiring fewer operations than the other way, where the remaining length keeps getting changed. It also allows this commit to move an 's++' a couple of lines to get rid of comparing against the number '8' which could get out of sync.
1 parent 72a5920 commit 68a142d

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

numeric.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -403,21 +403,22 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
403403
cBOOL(input_flags & PERL_SCAN_ALLOW_UNDERSCORES);
404404
const char * s = start;
405405
const char * s0 = s; /* Where the significant digits start */
406-
STRLEN len = *len_p;
406+
const char * e = start + *len_p;
407407

408408
if (!(input_flags & PERL_SCAN_DISALLOW_PREFIX)) {
409409

410410
/* strip off leading b or 0b; x or 0x.
411411
for compatibility silently suffer "b" and "0b" as valid binary; "x"
412412
and "0x" as valid hex numbers. */
413-
if (len >= 1) {
413+
if (e - s > 1) {
414414
if (isALPHA_FOLD_EQ(s0[0], prefix)) {
415415
s0++;
416-
len--;
417416
}
418-
else if (len >= 2 && s0[0] == '0' && (isALPHA_FOLD_EQ(s0[1], prefix))) {
417+
else if ( e - s > 2
418+
&& s0[0] == '0'
419+
&& (isALPHA_FOLD_EQ(s0[1], prefix)))
420+
{
419421
s0+=2;
420-
len-=2;
421422
}
422423
}
423424
}
@@ -427,7 +428,7 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
427428

428429
/* Unroll the loop so that the first 8 digits are branchless except for the
429430
* switch. A ninth hex one overflows a 32 bit word. */
430-
switch (len) {
431+
switch (e - s) {
431432
case 0:
432433
return 0;
433434
default:
@@ -468,12 +469,12 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
468469
case 1:
469470
if (UNLIKELY(! generic_isCC_(*s, class_bit))) break;
470471
value = (value << shift) | XDIGIT_VALUE(*s);
472+
s++;
471473

472-
if (LIKELY(len <= 8)) {
474+
if (LIKELY(s >= e)) {
473475
return value;
474476
}
475477

476-
s++;
477478
break;
478479
}
479480

@@ -483,15 +484,14 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
483484
/* In overflows, this keeps track of how much to multiply the overflowed NV
484485
* by as we continue to parse the remaining digits */
485486
NV factor = shift << bytes_so_far;
486-
len -= bytes_so_far;
487487

488488
bool overflowed = FALSE;
489489
NV value_nv = 0;
490490
const PERL_UINT_FAST8_T base = 1 << shift; /* 2, 8, or 16 */
491491
const UV max_div= UV_MAX / base; /* Value above which, the next digit
492492
processed would overflow */
493493

494-
for (; len--; s++) {
494+
for (; s < e; s++) {
495495
if (generic_isCC_(*s, class_bit)) {
496496
/* Write it in this wonky order with a goto to attempt to get the
497497
compiler to make the common case integer-only loop pretty tight.
@@ -540,7 +540,7 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
540540
}
541541

542542
if ( *s == '_'
543-
&& len
543+
&& s < e - 1
544544
&& allow_underscores
545545
&& generic_isCC_(s[1], class_bit)
546546

@@ -550,7 +550,6 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
550550
|| UNLIKELY((input_flags & PERL_SCAN_ALLOW_MEDIAL_UNDERSCORES)
551551
!= PERL_SCAN_ALLOW_MEDIAL_UNDERSCORES)))
552552
{
553-
--len;
554553
++s;
555554
goto redo;
556555
}

0 commit comments

Comments
 (0)