goto illegal_token;
}
- token->number = njs_number_oct_parse(&p, lexer->end);
+ token->number = njs_number_oct_parse(&p, lexer->end, 1);
if (p < lexer->end && (*p == '8' || *p == '9')) {
goto illegal_trailer;
goto illegal_token;
}
- token->number = njs_number_bin_parse(&p, lexer->end);
+ token->number = njs_number_bin_parse(&p, lexer->end, 1);
if (p < lexer->end && (*p >= '2' && *p <= '9')) {
goto illegal_trailer;
double
-njs_number_oct_parse(const u_char **start, const u_char *end)
+njs_number_oct_parse(const u_char **start, const u_char *end,
+ njs_bool_t literal)
{
u_char c;
double num;
c = *p - '0';
if (njs_slow_path(c > 7)) {
- if (*p == '_' && (p - _) > 1) {
+ if (literal && *p == '_' && (p - _) > 1) {
_ = p;
continue;
}
double
-njs_number_bin_parse(const u_char **start, const u_char *end)
+njs_number_bin_parse(const u_char **start, const u_char *end,
+ njs_bool_t literal)
{
u_char c;
double num;
c = *p - '0';
if (njs_slow_path(c > 1)) {
- if (*p == '_' && (p - _) > 1) {
+ if (literal && *p == '_' && (p - _) > 1) {
_ = p;
continue;
}
njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- njs_int_t ret;
- njs_value_t *value, lvalue;
+ double num;
+ njs_int_t ret;
+ njs_value_t *value, lvalue;
+ njs_bool_t minus;
+ const u_char *p, *start, *end;
+ njs_string_prop_t string;
value = njs_lvalue_arg(&lvalue, args, nargs, 1);
return ret;
}
- njs_set_number(&vm->retval, njs_string_to_number(value, 1));
+ (void) njs_string_trim(value, &string, NJS_TRIM_START);
+
+ p = string.start;
+ end = p + string.size;
+
+ minus = 0;
+
+ if (p == end) {
+ num = NAN;
+ goto done;
+ }
+
+ if (*p == '+') {
+ p++;
+
+ } else if (*p == '-') {
+ p++;
+ minus = 1;
+ }
+
+ start = p;
+ num = njs_number_dec_parse(&p, end, 0);
+
+ if (p == start) {
+ if (p + njs_length("Infinity") > end
+ || memcmp(p, "Infinity", njs_length("Infinity")) != 0)
+ {
+ num = NAN;
+ goto done;
+ }
+
+ num = INFINITY;
+ p += njs_length("Infinity");
+ }
+
+done:
+
+ njs_set_number(&vm->retval, minus ? -num : num);
return NJS_OK;
}
double njs_key_to_index(const njs_value_t *value);
double njs_number_dec_parse(const u_char **start, const u_char *end,
njs_bool_t literal);
-double njs_number_oct_parse(const u_char **start, const u_char *end);
-double njs_number_bin_parse(const u_char **start, const u_char *end);
+double njs_number_oct_parse(const u_char **start, const u_char *end,
+ njs_bool_t literal);
+double njs_number_bin_parse(const u_char **start, const u_char *end,
+ njs_bool_t literal);
double njs_number_hex_parse(const u_char **start, const u_char *end,
njs_bool_t literal);
njs_int_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
double
-njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float)
+njs_string_to_number(const njs_value_t *value)
{
double num;
njs_bool_t minus;
end = p + string.size;
if (p == end) {
- return parse_float ? NAN : 0.0;
+ return 0.0;
}
minus = 0;
- if (*p == '+') {
- p++;
+ if (p + 2 < end && p[0] == '0'
+ && (p[1] == 'x' || p[1] == 'X'
+ || p[1] == 'b' || p[1] == 'B'
+ || p[1] == 'o' || p[1] == 'O'))
+ {
+ p += 2;
- } else if (*p == '-') {
- p++;
- minus = 1;
- }
+ if (p[-1] == 'x' || p[-1] == 'X') {
+ num = njs_number_hex_parse(&p, end, 0);
- if (p == end) {
- return NAN;
- }
+ } else if (p[-1] == 'b' || p[-1] == 'B') {
+ num = njs_number_bin_parse(&p, end, 0);
- if (!parse_float
- && p + 2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
- {
- p += 2;
- num = njs_number_hex_parse(&p, end, 0);
+ } else {
+ num = njs_number_oct_parse(&p, end, 0);
+ }
} else {
+
+ if (*p == '+') {
+ p++;
+
+ } else if (*p == '-') {
+ p++;
+ minus = 1;
+ }
+
start = p;
num = njs_number_dec_parse(&p, end, 0);
}
}
- if (!parse_float) {
- while (p < end) {
- if (!njs_is_whitespace(*p)) {
- return NAN;
- }
-
- p++;
+ while (p < end) {
+ if (!njs_is_whitespace(*p)) {
+ return NAN;
}
+
+ p++;
}
return minus ? -num : num;
const njs_value_t *src);
njs_int_t njs_primitive_value_to_chain(njs_vm_t *vm, njs_chb_t *chain,
const njs_value_t *src);
-double njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float);
+double njs_string_to_number(const njs_value_t *value);
njs_int_t njs_int64_to_string(njs_vm_t *vm, njs_value_t *value, int64_t i64);
njs_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2);
*dst = NAN;
if (njs_is_string(value)) {
- *dst = njs_string_to_number(value, 0);
+ *dst = njs_string_to_number(value);
}
return NJS_OK;
/* If "hv" is a string then "lv" can be a numeric or symbol. */
if (njs_is_string(hv)) {
return !njs_is_symbol(lv)
- && (njs_number(lv) == njs_string_to_number(hv, 0));
+ && (njs_number(lv) == njs_string_to_number(hv));
}
/* "hv" is an object and "lv" is either a string or a symbol or a numeric. */
num2 = njs_number(val2);
} else {
- num2 = njs_string_to_number(val2, 0);
+ num2 = njs_string_to_number(val2);
}
} else if (njs_is_numeric(val2)) {
- num1 = njs_string_to_number(val1, 0);
+ num1 = njs_string_to_number(val1);
num2 = njs_number(val2);
} else {
njs_str("3") },
{ njs_str("5 - '-0x2'"),
- njs_str("7") },
+ njs_str("NaN") },
{ njs_str("5 - '\t 0x2 \t'"),
njs_str("3") },
{ njs_str("Number(false)"),
njs_str("0") },
+ { njs_str("Number('0b111')"),
+ njs_str("7") },
+
+ { njs_str("Number('0B111')"),
+ njs_str("7") },
+
+ { njs_str("Number('0b1_11')"),
+ njs_str("NaN") },
+
+ { njs_str("Number('-0b111')"),
+ njs_str("NaN") },
+
{ njs_str("Number(123)"),
njs_str("123") },
{ njs_str("Number('123')"),
njs_str("123") },
+ { njs_str("Number('0o123')"),
+ njs_str("83") },
+
+ { njs_str("Number('0O123')"),
+ njs_str("83") },
+
+ { njs_str("Number('0o1_23')"),
+ njs_str("NaN") },
+
+ { njs_str("Number('-0o123')"),
+ njs_str("NaN") },
+
+ { njs_str("Number('0x123')"),
+ njs_str("291") },
+
+ { njs_str("Number('0X123')"),
+ njs_str("291") },
+
+ { njs_str("Number('0x1_23')"),
+ njs_str("NaN") },
+
+ { njs_str("Number('-0x123')"),
+ njs_str("NaN") },
+
{ njs_str("['1', ' 1 ', '1\\t', '1\\n', '1\\r\\n'].reduce((a, x) => a + Number(x), 0)"),
njs_str("5") },