[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