[njs] parseInt() function.
Igor Sysoev
igor at sysoev.ru
Wed Jun 1 12:50:32 UTC 2016
details: http://hg.nginx.org/njs/rev/ffe9a5658450
branches:
changeset: 109:ffe9a5658450
user: Igor Sysoev <igor at sysoev.ru>
date: Mon Apr 25 17:28:34 2016 +0300
description:
parseInt() function.
diffstat:
njs/njs_builtin.c | 3 +
njs/njs_generator.c | 1 +
njs/njs_lexer_keyword.c | 1 +
njs/njs_number.c | 99 ++++++++++++++++++++++++++++++++++++++++++-----
njs/njs_number.h | 5 +-
njs/njs_parser.c | 3 +-
njs/njs_parser.h | 1 +
njs/njs_vm.h | 3 +-
njs/test/njs_unit_test.c | 18 ++++++++
9 files changed, 119 insertions(+), 15 deletions(-)
diffs (267 lines):
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_builtin.c
--- a/njs/njs_builtin.c Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_builtin.c Mon Apr 25 17:28:34 2016 +0300
@@ -83,6 +83,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
NULL,
NULL,
NULL,
+ NULL,
};
static const njs_function_init_t native_functions[] = {
@@ -91,6 +92,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
{ njs_object_prototype_to_string, { 0 } },
{ njs_number_is_nan, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
{ njs_number_is_finite, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
+ { njs_number_parse_int,
+ { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG } },
};
static const njs_object_prop_t null_proto_property = {
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_generator.c
--- a/njs/njs_generator.c Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_generator.c Mon Apr 25 17:28:34 2016 +0300
@@ -297,6 +297,7 @@ njs_generator(njs_vm_t *vm, njs_parser_t
case NJS_TOKEN_TO_STRING:
case NJS_TOKEN_IS_NAN:
case NJS_TOKEN_IS_FINITE:
+ case NJS_TOKEN_PARSE_INT:
return njs_generate_builtin_object(vm, parser, node);
case NJS_TOKEN_FUNCTION:
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_lexer_keyword.c Mon Apr 25 17:28:34 2016 +0300
@@ -91,6 +91,7 @@ static const njs_keyword_t njs_keywords
{ nxt_string("toString"), NJS_TOKEN_TO_STRING, 0 },
{ nxt_string("isNaN"), NJS_TOKEN_IS_NAN, 0 },
{ nxt_string("isFinite"), NJS_TOKEN_IS_FINITE, 0 },
+ { nxt_string("parseInt"), NJS_TOKEN_PARSE_INT, 0 },
/* Reserved words. */
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_number.c
--- a/njs/njs_number.c Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_number.c Mon Apr 25 17:28:34 2016 +0300
@@ -121,22 +121,22 @@ njs_number_parse(const u_char **start, c
int64_t
-njs_hex_number_parse(u_char *p, u_char *end)
+njs_number_radix_parse(u_char *p, u_char *end, uint8_t radix, nxt_bool_t exact)
{
- int8_t d;
- uint32_t n;
+ uint8_t d;
+ uint64_t n;
- static const int8_t hex[256]
+ static const int8_t digits[256]
nxt_aligned(32) =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 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, -1, -1, -1, -1, -1,
+ -1, 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, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -150,13 +150,13 @@ njs_hex_number_parse(u_char *p, u_char *
n = 0;
while (p < end) {
- d = hex[*p++];
+ d = digits[*p++];
- if (nxt_slow_path(d < 0)) {
- return -1;
+ if (nxt_slow_path(d >= radix)) {
+ return (exact) ? -1 : (int64_t) n;
}
- n = (n << 4) + d;
+ n = (n * radix) + d;
}
return n;
@@ -474,3 +474,78 @@ njs_number_is_finite(njs_vm_t *vm, njs_v
return NXT_OK;
}
+
+
+njs_ret_t
+njs_number_parse_int(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+ u_char *p, *end;
+ int64_t n;
+ uint8_t radix;
+ nxt_bool_t minus;
+ njs_string_prop_t string;
+
+ num = NJS_NAN;
+
+ if (nargs > 1) {
+ (void) njs_string_prop(&string, &args[1]);
+
+ p = string.start;
+ end = string.start + string.size;
+
+ while (p < end) {
+ if (*p != ' ') {
+ goto found;
+ }
+ }
+
+ goto done;
+
+ found:
+
+ minus = 0;
+
+ if (p[0] == '-') {
+ p++;
+ minus = 1;
+
+ } else if (p[0] == '+') {
+ p++;
+ }
+
+ if (end - p > 1 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ p += 2;
+ radix = 16;
+
+ } else {
+ radix = 10;
+ }
+
+ if (nargs > 2) {
+ n = args[2].data.u.number;
+
+ if (n != 0) {
+
+ if (n < 2 || n > 36) {
+ goto done;
+ }
+
+ radix = n;
+ }
+ }
+
+ n = njs_number_radix_parse(p, end, radix, 0);
+
+ if (n >= 0) {
+ num = (minus) ? -n : n;
+ }
+ }
+
+done:
+
+ njs_number_set(&vm->retval, num);
+
+ return NXT_OK;
+}
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_number.h
--- a/njs/njs_number.h Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_number.h Mon Apr 25 17:28:34 2016 +0300
@@ -25,7 +25,8 @@
double njs_value_to_number(njs_value_t *value);
double njs_number_parse(const u_char **start, const u_char *end);
-int64_t njs_hex_number_parse(u_char *p, u_char *end);
+int64_t njs_number_radix_parse(u_char *p, u_char *end, uint8_t radix,
+ nxt_bool_t exact);
njs_ret_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
const njs_value_t *number);
njs_ret_t njs_number_constructor(njs_vm_t *vm, njs_value_t *args,
@@ -34,6 +35,8 @@ njs_ret_t njs_number_is_nan(njs_vm_t *vm
njs_index_t unused);
njs_ret_t njs_number_is_finite(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_number_parse_int(njs_vm_t *vm, njs_value_t *args,
+ nxt_uint_t nargs, njs_index_t unused);
extern const njs_object_init_t njs_number_constructor_init;
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_parser.c
--- a/njs/njs_parser.c Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_parser.c Mon Apr 25 17:28:34 2016 +0300
@@ -1647,6 +1647,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
case NJS_TOKEN_TO_STRING:
case NJS_TOKEN_IS_NAN:
case NJS_TOKEN_IS_FINITE:
+ case NJS_TOKEN_PARSE_INT:
return njs_parser_builtin_function(vm, parser, node);
default:
@@ -2071,7 +2072,7 @@ njs_parser_escape_string_create(njs_vm_t
return NJS_TOKEN_ILLEGAL;
}
- u = njs_hex_number_parse(src, hex_end);
+ u = njs_number_radix_parse(src, hex_end, 16, 1);
if (nxt_slow_path(u < 0)) {
return NJS_TOKEN_ILLEGAL;
}
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_parser.h
--- a/njs/njs_parser.h Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_parser.h Mon Apr 25 17:28:34 2016 +0300
@@ -178,6 +178,7 @@ typedef enum {
NJS_TOKEN_TO_STRING,
NJS_TOKEN_IS_NAN,
NJS_TOKEN_IS_FINITE,
+ NJS_TOKEN_PARSE_INT,
NJS_TOKEN_RESERVED,
} njs_token_t;
diff -r fd72dd7112c2 -r ffe9a5658450 njs/njs_vm.h
--- a/njs/njs_vm.h Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/njs_vm.h Mon Apr 25 17:28:34 2016 +0300
@@ -704,7 +704,8 @@ enum njs_function_e {
NJS_FUNCTION_TO_STRING = 1,
NJS_FUNCTION_IS_NAN = 2,
NJS_FUNCTION_IS_FINITE = 3,
-#define NJS_FUNCTION_MAX (NJS_FUNCTION_IS_FINITE + 1)
+ NJS_FUNCTION_PARSE_INT = 4,
+#define NJS_FUNCTION_MAX (NJS_FUNCTION_PARSE_INT + 1)
};
diff -r fd72dd7112c2 -r ffe9a5658450 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Apr 21 18:23:16 2016 +0300
+++ b/njs/test/njs_unit_test.c Mon Apr 25 17:28:34 2016 +0300
@@ -4431,6 +4431,24 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("isFinite('abc')"),
nxt_string("false") },
+ { nxt_string("parseInt('12345abc')"),
+ nxt_string("12345") },
+
+ { nxt_string("parseInt('1010', 2)"),
+ nxt_string("10") },
+
+ { nxt_string("parseInt('aBc', 16)"),
+ nxt_string("2748") },
+
+ { nxt_string("parseInt('0XaBc')"),
+ nxt_string("2748") },
+
+ { nxt_string("parseInt('-0xabc')"),
+ nxt_string("-2748") },
+
+ { nxt_string("parseInt('njscript', 36)"),
+ nxt_string("1845449130881") },
+
/* External interface. */
{ nxt_string("function f(req) { return req.uri }"),
More information about the nginx-devel
mailing list