ref: 4c7f6be4333250cbc544dd758e587342e317e2aa
parent: 1616c1848447fe55117e59dda743dc62cfd74459
author: Tor Andersson <tor.andersson@artifex.com>
date: Thu Mar 25 09:18:06 EDT 2021
Issue #139: Parse integers with floats to support large numbers. Add a js_strtol which parses integers with bases 2..36 using simple double precision arithmetic with no overflow checks.
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -34,7 +34,7 @@
static void jsB_parseInt(js_State *J)
{
const char *s = js_tostring(J, 1);
- int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 10;
+ int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
double sign = 1;
double n;
char *e;
@@ -57,7 +57,7 @@
js_pushnumber(J, NAN);
return;
}
- n = strtol(s, &e, radix);
+ n = js_strtol(s, &e, radix);
if (s == e)
js_pushnumber(J, NAN);
else
--- a/jsi.h
+++ b/jsi.h
@@ -114,6 +114,8 @@
int js_grisu2(double v, char *buffer, int *K);
double js_strtod(const char *as, char **aas);
+double js_strtol(const char *s, char **ep, int radix);
+
/* Private stack functions */
void js_newarguments(js_State *J);
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -7,6 +7,40 @@
#define JSV_ISSTRING(v) (v->type==JS_TSHRSTR || v->type==JS_TMEMSTR || v->type==JS_TLITSTR)
#define JSV_TOSTRING(v) (v->type==JS_TSHRSTR ? v->u.shrstr : v->type==JS_TLITSTR ? v->u.litstr : v->type==JS_TMEMSTR ? v->u.memstr->p : "")
+double js_strtol(const char *s, char **p, int base)
+{
+ /* ascii -> digit value. max base is 36. */
+ static const unsigned char table[256] = {
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 80, 80, 80, 80, 80, 80,
+ 80, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 80, 80, 80, 80, 80,
+ 80, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+ };
+ double x;
+ int c;
+ if (base == 10)
+ for (x = 0, c = *s++; c - '0' < 10; c = *s++)
+ x = x * 10 + (c - '0');
+ else
+ for (x = 0, c = *s++; table[c] < base; c = *s++)
+ x = x * base + table[c];
+ if (p)
+ *p = (char*)s-1;
+ return x;
+}
+
int jsV_numbertointeger(double n)
{
if (n == 0) return 0;
@@ -172,10 +206,10 @@
while (*e >= '0' && *e <= '9') ++e;
isflt = 1;
}
- if (isflt || e - s > 9)
+ if (isflt)
n = js_strtod(s, &end);
else
- n = strtol(s, &end, 10);
+ n = js_strtol(s, &end, 10);
if (end == e) {
*ep = (char*)e;
return n;
@@ -191,7 +225,7 @@
double n;
while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && s[2] != 0)
- n = strtol(s + 2, &e, 16);
+ n = js_strtol(s + 2, &e, 16);
else if (!strncmp(s, "Infinity", 8))
n = INFINITY, e = (char*)s + 8;
else if (!strncmp(s, "+Infinity", 9))