Improve number conversions
- pass string length to `js_atof()` instead of end pointer - get string length from `bf_ftoa()` in `js_bigint_to_string1`
This commit is contained in:
parent
bb4878dd50
commit
3eaea6c4cf
1 changed files with 24 additions and 21 deletions
45
quickjs.c
45
quickjs.c
|
@ -10163,17 +10163,18 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf, int radix)
|
||||||
return JS_CompactBigInt1(ctx, val);
|
return JS_CompactBigInt1(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* `js_atof(ctx, p, end, pp, radix, flags)`
|
/* `js_atof(ctx, p, len, pp, radix, flags)`
|
||||||
|
Convert the string pointed to by `p` to a number value.
|
||||||
Return an exception in case of memory error.
|
Return an exception in case of memory error.
|
||||||
Return `JS_NAN` if invalid syntax.
|
Return `JS_NAN` if invalid syntax.
|
||||||
- `p` points to a null terminated UTF-8 encoded char array
|
- `p` points to a null terminated UTF-8 encoded char array,
|
||||||
- `end` points to the end of the array.
|
- `len` the length of the array,
|
||||||
- `pp` if not null receives a pointer to the next character
|
- `pp` if not null receives a pointer to the next character,
|
||||||
- `radix` must be in range 2 to 36, else return `JS_NAN`
|
- `radix` must be in range 2 to 36, else return `JS_NAN`.
|
||||||
- `flags` is a combination of the flags below
|
- `flags` is a combination of the flags below.
|
||||||
There is a null byte at `*end`, but there might be embedded null bytes
|
There is a null byte at `p[len]`, but there might be embedded null
|
||||||
between `p` and `end` which must produce `JS_NAN` if the
|
bytes between `p[0]` and `p[len]` which must produce `JS_NAN` if
|
||||||
`ATOD_NO_TRAILING_CHARS` flag is not present.
|
the `ATOD_NO_TRAILING_CHARS` flag is present.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ATOD_TRIM_SPACES (1 << 0) /* trim white space */
|
#define ATOD_TRIM_SPACES (1 << 0) /* trim white space */
|
||||||
|
@ -10188,14 +10189,15 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf, int radix)
|
||||||
#define ATOD_DECIMAL_AFTER_SIGN (1 << 9) /* only accept decimal number after sign */
|
#define ATOD_DECIMAL_AFTER_SIGN (1 << 9) /* only accept decimal number after sign */
|
||||||
#define ATOD_NO_TRAILING_CHARS (1 << 10) /* do not accept trailing characters */
|
#define ATOD_NO_TRAILING_CHARS (1 << 10) /* do not accept trailing characters */
|
||||||
|
|
||||||
static JSValue js_atof(JSContext *ctx, const char *p, const char *end,
|
static JSValue js_atof(JSContext *ctx, const char *p, size_t len,
|
||||||
const char **pp, int radix, int flags)
|
const char **pp, int radix, int flags)
|
||||||
{
|
{
|
||||||
const char *p_start;
|
const char *p_start;
|
||||||
|
const char *end = p + len;
|
||||||
int sep;
|
int sep;
|
||||||
BOOL is_float;
|
BOOL is_float;
|
||||||
char buf1[64], *buf = buf1;
|
char buf1[64], *buf = buf1;
|
||||||
size_t i, j, len;
|
size_t i, j;
|
||||||
JSValue val = JS_NAN;
|
JSValue val = JS_NAN;
|
||||||
double d;
|
double d;
|
||||||
char sign;
|
char sign;
|
||||||
|
@ -10377,7 +10379,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
|
||||||
ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY |
|
ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY |
|
||||||
ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
|
ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
|
||||||
ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS;
|
ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS;
|
||||||
ret = js_atof(ctx, str, str + len, NULL, 10, flags);
|
ret = js_atof(ctx, str, len, NULL, 10, flags);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -10961,6 +10963,7 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValue val, int radix)
|
||||||
bf_t a_s, *a;
|
bf_t a_s, *a;
|
||||||
char *str;
|
char *str;
|
||||||
int saved_sign;
|
int saved_sign;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
a = JS_ToBigInt(ctx, &a_s, val);
|
a = JS_ToBigInt(ctx, &a_s, val);
|
||||||
if (!a)
|
if (!a)
|
||||||
|
@ -10968,14 +10971,13 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValue val, int radix)
|
||||||
saved_sign = a->sign;
|
saved_sign = a->sign;
|
||||||
if (a->expn == BF_EXP_ZERO)
|
if (a->expn == BF_EXP_ZERO)
|
||||||
a->sign = 0;
|
a->sign = 0;
|
||||||
// TODO(chqrlie) bf_ftoa should return the string length to the caller
|
str = bf_ftoa(&len, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC |
|
||||||
str = bf_ftoa(NULL, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC |
|
|
||||||
BF_FTOA_JS_QUIRKS);
|
BF_FTOA_JS_QUIRKS);
|
||||||
a->sign = saved_sign;
|
a->sign = saved_sign;
|
||||||
JS_FreeBigInt(ctx, a, &a_s);
|
JS_FreeBigInt(ctx, a, &a_s);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_ThrowOutOfMemory(ctx);
|
return JS_ThrowOutOfMemory(ctx);
|
||||||
ret = js_new_string8(ctx, str);
|
ret = js_new_string8_len(ctx, str, len);
|
||||||
bf_free(ctx->bf_ctx, str);
|
bf_free(ctx->bf_ctx, str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -11903,7 +11905,7 @@ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
|
||||||
ATOD_TRIM_SPACES | ATOD_ACCEPT_EMPTY |
|
ATOD_TRIM_SPACES | ATOD_ACCEPT_EMPTY |
|
||||||
ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
|
ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT |
|
||||||
ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS;
|
ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS;
|
||||||
val = js_atof(ctx, str, str + len, NULL, 10, flags);
|
val = js_atof(ctx, str, len, NULL, 10, flags);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -19342,13 +19344,14 @@ static __exception int next_token(JSParseState *s)
|
||||||
/* number */
|
/* number */
|
||||||
{
|
{
|
||||||
JSValue ret;
|
JSValue ret;
|
||||||
const uint8_t *p1;
|
const char *p1;
|
||||||
|
|
||||||
flags = ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX;
|
flags = ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX;
|
||||||
radix = 10;
|
radix = 10;
|
||||||
parse_number:
|
parse_number:
|
||||||
ret = js_atof(s->ctx, (const char *)p, (const char *)s->buf_end,
|
p1 = (const char *)p;
|
||||||
(const char **)&p, radix, flags);
|
ret = js_atof(s->ctx, p1, s->buf_end - p, &p1, radix, flags);
|
||||||
|
p = (const uint8_t *)p1;
|
||||||
if (JS_IsException(ret))
|
if (JS_IsException(ret))
|
||||||
goto fail;
|
goto fail;
|
||||||
/* reject `10instanceof Number` */
|
/* reject `10instanceof Number` */
|
||||||
|
@ -39217,7 +39220,7 @@ static JSValue js_parseInt(JSContext *ctx, JSValue this_val,
|
||||||
flags |= ATOD_ACCEPT_HEX_PREFIX; // Only 0x and 0X are supported
|
flags |= ATOD_ACCEPT_HEX_PREFIX; // Only 0x and 0X are supported
|
||||||
radix = 10;
|
radix = 10;
|
||||||
}
|
}
|
||||||
ret = js_atof(ctx, str, str + len, NULL, radix, flags);
|
ret = js_atof(ctx, str, len, NULL, radix, flags);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -39234,7 +39237,7 @@ static JSValue js_parseFloat(JSContext *ctx, JSValue this_val,
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
flags = ATOD_TRIM_SPACES | ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY;
|
flags = ATOD_TRIM_SPACES | ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY;
|
||||||
ret = js_atof(ctx, str, str + len, NULL, 10, flags);
|
ret = js_atof(ctx, str, len, NULL, 10, flags);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue