summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorKarl Williamson <public@khwilliamson.com>2013-12-31 22:41:39 -0700
committerKarl Williamson <public@khwilliamson.com>2014-01-01 13:49:24 -0700
commit626ef08910b91efb9ac7ecd5f41e991c2a4ce5dd (patch)
tree243c359e9d115d0661755f0a66a0cd2ddc78aff9 /numeric.c
parentcb27eebd32af3dfebf46f5eb3778fe29175004b5 (diff)
downloadperl-626ef08910b91efb9ac7ecd5f41e991c2a4ce5dd.tar.gz
numeric.c: Use macros instead of strchr()
This replaces uses of strchr() (and hence its loop) with a simple array lookup, mask, and test. This causes an extra test to be needed later in the hex decoding case to get the hex value, instead of a subtract previously. However these two tests are fewer than the average number in strchr().
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/numeric.c b/numeric.c
index 2725b3cee9..b5144f45b0 100644
--- a/numeric.c
+++ b/numeric.c
@@ -291,15 +291,14 @@ Perl_grok_hex(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
}
for (; len-- && *s; s++) {
- const char *hexdigit = strchr(PL_hexdigit, *s);
- if (hexdigit) {
+ if (isXDIGIT(*s)) {
/* Write it in this wonky order with a goto to attempt to get the
compiler to make the common case integer-only loop pretty tight.
With gcc seems to be much straighter code than old scan_hex. */
redo:
if (!overflowed) {
if (value <= max_div_16) {
- value = (value << 4) | ((hexdigit - PL_hexdigit) & 15);
+ value = (value << 4) | XDIGIT_VALUE(*s);
continue;
}
/* Bah. We're just overflowed. */
@@ -316,11 +315,11 @@ Perl_grok_hex(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
* the low-order bits anyway): we could just remember when
* did we overflow and in the end just multiply value_nv by the
* right amount of 16-tuples. */
- value_nv += (NV)((hexdigit - PL_hexdigit) & 15);
+ value_nv += (NV) XDIGIT_VALUE(*s);
continue;
}
if (*s == '_' && len && allow_underscores && s[1]
- && (hexdigit = strchr(PL_hexdigit, s[1])))
+ && isXDIGIT(s[1]))
{
--len;
++s;
@@ -395,17 +394,14 @@ Perl_grok_oct(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
PERL_ARGS_ASSERT_GROK_OCT;
for (; len-- && *s; s++) {
- /* gcc 2.95 optimiser not smart enough to figure that this subtraction
- out front allows slicker code. */
- int digit = *s - '0';
- if (digit >= 0 && digit <= 7) {
+ if (isOCTAL(*s)) {
/* Write it in this wonky order with a goto to attempt to get the
compiler to make the common case integer-only loop pretty tight.
*/
redo:
if (!overflowed) {
if (value <= max_div_8) {
- value = (value << 3) | digit;
+ value = (value << 3) | OCTAL_VALUE(*s);
continue;
}
/* Bah. We're just overflowed. */
@@ -422,20 +418,19 @@ Perl_grok_oct(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
* the low-order bits anyway): we could just remember when
* did we overflow and in the end just multiply value_nv by the
* right amount of 8-tuples. */
- value_nv += (NV)digit;
+ value_nv += (NV) OCTAL_VALUE(*s);
continue;
}
- if (digit == ('_' - '0') && len && allow_underscores
- && (digit = s[1] - '0') && (digit >= 0 && digit <= 7))
- {
- --len;
- ++s;
- goto redo;
- }
+ if (*s == '_' && len && allow_underscores && isOCTAL(s[1])) {
+ --len;
+ ++s;
+ goto redo;
+ }
/* Allow \octal to work the DWIM way (that is, stop scanning
* as soon as non-octal characters are seen, complain only if
- * someone seems to want to use the digits eight and nine). */
- if (digit == 8 || digit == 9) {
+ * someone seems to want to use the digits eight and nine. Since we
+ * know it is not octal, then if isDIGIT, must be an 8 or 9). */
+ if (isDIGIT(*s)) {
if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
Perl_ck_warner(aTHX_ packWARN(WARN_DIGIT),
"Illegal octal digit '%c' ignored", *s);