Browse Source

change number conversion call sites to use numconv

pull/1/head
Sami Vaarala 12 years ago
parent
commit
b7a89f5c83
  1. 5
      src/duk_api_conv.c
  2. 92
      src/duk_builtin_global.c
  3. 17
      src/duk_builtin_json.c
  4. 40
      src/duk_builtin_number.c
  5. 61
      src/duk_js_ops.c
  6. 20
      src/duk_lexer.c

5
src/duk_api_conv.c

@ -361,12 +361,9 @@ const char *duk_to_string(duk_context *ctx, int index) {
}
default: {
/* number */
double d;
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
d = DUK_TVAL_GET_NUMBER(tv);
duk_push_tval(ctx, tv);
duk_numconv_stringify(ctx,
d,
10 /*radix*/,
0 /*precision:shortest*/,
0 /*force_exponential*/);

92
src/duk_builtin_global.c

@ -513,31 +513,12 @@ int duk_builtin_global_object_eval(duk_context *ctx) {
*/
int duk_builtin_global_object_parse_int(duk_context *ctx) {
duk_hstring *h_str;
duk_u8 *p_start, *p_end, *p, *p_start_dig;
int neg = 0;
int strip_prefix;
duk_i32 radix;
int t;
double val;
int s2n_flags;
DUK_ASSERT_TOP(ctx, 2);
duk_to_string(ctx, 0);
duk_trim(ctx, 0);
h_str = duk_get_hstring(ctx, 0);
DUK_ASSERT(h_str != NULL);
p_start = DUK_HSTRING_GET_DATA(h_str);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
p = p_start;
if (p_end > p) {
t = *p;
if (t == '-') {
neg = 1;
p++;
} else if (t == '+') {
p++;
}
}
strip_prefix = 1;
radix = duk_to_int32(ctx, 1);
@ -551,48 +532,17 @@ int duk_builtin_global_object_parse_int(duk_context *ctx) {
} else {
radix = 10;
}
if (strip_prefix) {
if ((p_end - p >= 2) &&
(p[0] == (duk_u8) '0') &&
((p[1] == (duk_u8) 'x') || (p[1] == (duk_u8) 'X'))) {
p += 2;
radix = 16;
}
}
/* FIXME: this is correct for radix 2, 4, 8, 16, and 32, but incorrect
* for radix 10 which is also required to be "exact". Other radixes are
* not required to be exact, so this would be OK for them.
*/
p_start_dig = p;
val = 0.0;
while (p < p_end) {
t = *p;
if (t >= (int) '0' && t <= (int) '9') {
t = t - (int) '0';
} else if (t >= (int) 'a' && t <= (int) 'z') {
t = t - (int) 'a' + 0x0a;
} else if (t >= (int) 'A' && t <= (int) 'Z') {
t = t - (int) 'A' + 0x0a;
} else {
break;
}
if (t >= radix) {
break;
}
val = val * ((double) radix) + ((double) t);
p++;
}
if (p == p_start_dig) {
goto ret_nan;
}
if (neg) {
val = -val;
}
/* FIXME: octal support */
s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
DUK_S2N_FLAG_ALLOW_GARBAGE |
DUK_S2N_FLAG_ALLOW_PLUS |
DUK_S2N_FLAG_ALLOW_MINUS |
DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
(strip_prefix ? DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT : 0);
duk_push_number(ctx, val);
duk_dup(ctx, 0);
duk_numconv_parse(ctx, radix, s2n_flags);
return 1;
ret_nan:
@ -601,10 +551,24 @@ int duk_builtin_global_object_parse_int(duk_context *ctx) {
}
int duk_builtin_global_object_parse_float(duk_context *ctx) {
/* FIXME: incorrect placeholder */
int s2n_flags;
DUK_ASSERT_TOP(ctx, 1);
duk_to_string(ctx, 0);
duk_trim(ctx, 0);
duk_to_number(ctx, 0);
/* FIXME: flags */
s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
DUK_S2N_FLAG_ALLOW_EXP |
DUK_S2N_FLAG_ALLOW_GARBAGE |
DUK_S2N_FLAG_ALLOW_PLUS |
DUK_S2N_FLAG_ALLOW_MINUS |
DUK_S2N_FLAG_ALLOW_INF |
DUK_S2N_FLAG_ALLOW_FRAC |
DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
return 1;
}

17
src/duk_builtin_json.c

@ -256,6 +256,7 @@ static void json_dec_number(duk_json_dec_ctx *js_ctx) {
duk_context *ctx = (duk_context *) js_ctx->thr;
duk_u8 *p_start;
int x;
int s2n_flags;
DUK_DDDPRINT("parse_number");
@ -290,8 +291,18 @@ static void json_dec_number(duk_json_dec_ctx *js_ctx) {
DUK_ASSERT(js_ctx->p > p_start);
duk_push_lstring(ctx, (const char *) p_start, (size_t) (js_ctx->p - p_start));
s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
DUK_S2N_FLAG_ALLOW_FRAC;
DUK_DDDPRINT("parse_number: string before parsing: %!T", duk_get_tval(ctx, -1));
duk_to_number(ctx, -1);
duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
if (duk_is_nan(ctx, -1)) {
/* FIXME: retcode parse error indicator? */
DUK_ERROR(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid number");
}
DUK_ASSERT(duk_is_number(ctx, -1));
DUK_DDDPRINT("parse_number: final number: %!T", duk_get_tval(ctx, -1));
/* [ ... num ] */
@ -1273,6 +1284,7 @@ static void json_enc_value2(duk_json_enc_ctx *js_ctx) {
int c;
int s;
int stridx;
int n2s_flags;
duk_hstring *h_str;
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
@ -1282,6 +1294,9 @@ static void json_enc_value2(duk_json_enc_ctx *js_ctx) {
if (!(c == FP_INFINITE || c == FP_NAN)) {
DUK_ASSERT(isfinite(d));
n2s_flags = 0;
/* [ ... number ] -> [ ... string ] */
duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
h_str = duk_to_hstring(ctx, -1);
DUK_ASSERT(h_str != NULL);
EMIT_HSTR(js_ctx, h_str);

40
src/duk_builtin_number.c

@ -94,10 +94,10 @@ int duk_builtin_number_prototype_value_of(duk_context *ctx) {
}
int duk_builtin_number_prototype_to_string(duk_context *ctx) {
double d;
int radix;
int n2s_flags;
d = push_this_number_plain(ctx);
(void) push_this_number_plain(ctx);
if (duk_is_undefined(ctx, 0)) {
radix = 10;
} else {
@ -105,11 +105,12 @@ int duk_builtin_number_prototype_to_string(duk_context *ctx) {
}
DUK_DDDPRINT("radix=%d", radix);
n2s_flags = 0;
duk_numconv_stringify(ctx,
d,
radix /*radix*/,
0 /*digits*/,
0 /*flags*/);
n2s_flags /*flags*/);
return 1;
}
@ -130,7 +131,7 @@ int duk_builtin_number_prototype_to_fixed(duk_context *ctx) {
int frac_digits;
double d;
int c;
int flags;
int n2s_flags;
frac_digits = duk_to_int_check_range(ctx, 0, 0, 20);
d = push_this_number_plain(ctx);
@ -144,14 +145,13 @@ int duk_builtin_number_prototype_to_fixed(duk_context *ctx) {
goto use_to_string;
}
flags = DUK_NUMCONV_FLAG_FIXED_FORMAT |
DUK_NUMCONV_FLAG_FRACTION_DIGITS;
n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
DUK_N2S_FLAG_FRACTION_DIGITS;
duk_numconv_stringify(ctx,
d,
10 /*radix*/,
frac_digits /*digits*/,
flags /*flags*/);
n2s_flags /*flags*/);
return 1;
use_to_string:
@ -165,7 +165,7 @@ int duk_builtin_number_prototype_to_exponential(duk_context *ctx) {
int frac_digits;
double d;
int c;
int flags;
int n2s_flags;
d = push_this_number_plain(ctx);
@ -179,18 +179,13 @@ int duk_builtin_number_prototype_to_exponential(duk_context *ctx) {
frac_digits = duk_to_int_check_range(ctx, 0, 0, 20);
if (frac_undefined) {
flags = DUK_NUMCONV_FLAG_FORCE_EXP;
} else {
flags = DUK_NUMCONV_FLAG_FORCE_EXP |
DUK_NUMCONV_FLAG_FIXED_FORMAT;
}
n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
(frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
duk_numconv_stringify(ctx,
d,
10 /*radix*/,
frac_digits + 1 /*leading digit + fractions*/,
flags /*flags*/);
n2s_flags /*flags*/);
return 1;
use_to_string:
@ -208,7 +203,7 @@ int duk_builtin_number_prototype_to_precision(duk_context *ctx) {
double d;
int prec;
int c;
int flags;
int n2s_flags;
DUK_ASSERT_TOP(ctx, 1);
@ -227,14 +222,13 @@ int duk_builtin_number_prototype_to_precision(duk_context *ctx) {
prec = duk_to_int_check_range(ctx, 0, 1, 21);
flags = DUK_NUMCONV_FLAG_FIXED_FORMAT |
DUK_NUMCONV_FLAG_NO_ZERO_PAD;
n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
DUK_N2S_FLAG_NO_ZERO_PAD;
duk_numconv_stringify(ctx,
d,
10 /*radix*/,
prec /*digits*/,
flags /*flags*/);
n2s_flags /*flags*/);
return 1;
use_to_string:

61
src/duk_js_ops.c

@ -133,47 +133,32 @@ int duk_js_toboolean(duk_tval *tv) {
/* E5 Section 9.3.1 */
static double tonumber_string_raw(duk_hthread *thr, duk_hstring *h) {
/* FIXME: just something to work with, not correct,
* need an actual parser, need to accept whitespace,
* need to accept hex, etc.
*/
/*
* Special checks for infinities
*/
duk_context *ctx = (duk_context *) thr;
int s2n_flags;
double d;
if (h == DUK_HTHREAD_STRING_INFINITY(thr)) {
/* "Infinity" */
return INFINITY;
} else if (h == DUK_HTHREAD_STRING_PLUS_INFINITY(thr)) {
/* "+Infinity" */
return INFINITY;
} else if (h == DUK_HTHREAD_STRING_MINUS_INFINITY(thr)) {
/* "-Infinity" */
return -INFINITY;
}
duk_push_hstring(ctx, h);
/*
* Parse as an actual number (decimal or hex, not infinity)
/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
* garbage.
*/
/* FIXME: placeholder */
{
char *p, *p_end;
double d;
p = (char *) DUK_HSTRING_GET_DATA(h);
/* would actually need to tolerate whitespace */
if (strlen(p) == 0) {
return 0.0;
}
d = strtod(p, &p_end);
if (p_end == p || p_end != p + strlen(p)) {
return NAN;
}
return d;
}
s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
DUK_S2N_FLAG_ALLOW_EXP |
DUK_S2N_FLAG_ALLOW_PLUS |
DUK_S2N_FLAG_ALLOW_MINUS |
DUK_S2N_FLAG_ALLOW_INF |
DUK_S2N_FLAG_ALLOW_FRAC |
DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
d = duk_get_number(ctx, -1);
duk_pop(ctx);
return d;
}
double duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {

20
src/duk_lexer.c

@ -1046,6 +1046,7 @@ static void parse_input_element_raw(duk_lexer_ctx *lex_ctx,
* 2=after exp, allow '+' or '-'
* 3=after exp and exp sign
*/
int s2n_flags;
/* FIXME: because of the final check below (that the literal is not
* followed by a digit, this could maybe be simplified, if we bail
@ -1093,11 +1094,24 @@ static void parse_input_element_raw(duk_lexer_ctx *lex_ctx,
ADVANCE(lex_ctx, 1);
}
/* FIXME: incorrect: allows more syntax than should right now */
/* FIXME: better coercion */
internbuffer(lex_ctx, lex_ctx->slot1_idx);
/*out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);*/
val = duk_to_number((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
/* FIXME: octal handling */
s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
DUK_S2N_FLAG_ALLOW_PLUS |
DUK_S2N_FLAG_ALLOW_MINUS |
DUK_S2N_FLAG_ALLOW_FRAC |
DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
DUK_S2N_FLAG_ALLOW_EMPTY_FRAC;
duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
duk_numconv_parse((duk_context *) lex_ctx->thr, 10 /*radix*/, s2n_flags);
val = duk_to_number((duk_context *) lex_ctx->thr, -1);
if (isnan(val)) {
DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid numeric literal");
}
duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); /* FIXME: or pop? */
INITBUFFER(lex_ctx); /* free some memory */
}

Loading…
Cancel
Save