[njs] Number.toString(radix).

Igor Sysoev igor at sysoev.ru
Wed Jun 1 12:50:23 UTC 2016


details:   http://hg.nginx.org/njs/rev/23ff7c369101
branches:  
changeset: 102:23ff7c369101
user:      Igor Sysoev <igor at sysoev.ru>
date:      Tue Apr 19 17:26:25 2016 +0300
description:
Number.toString(radix).

diffstat:

 njs/njs_number.c         |  94 ++++++++++++++++++++++++++++++++++++++++++++++-
 njs/test/njs_unit_test.c |  29 ++++++++++++++
 2 files changed, 121 insertions(+), 2 deletions(-)

diffs (164 lines):

diff -r e411e0cbd20d -r 23ff7c369101 njs/njs_number.c
--- a/njs/njs_number.c	Fri Apr 15 18:01:40 2016 +0300
+++ b/njs/njs_number.c	Tue Apr 19 17:26:25 2016 +0300
@@ -22,6 +22,10 @@
 #include <stdio.h>
 
 
+static njs_ret_t njs_number_to_string_radix(njs_vm_t *vm, njs_value_t *string,
+    const njs_value_t *number, uint32_t radix);
+
+
 double
 njs_value_to_number(njs_value_t *value)
 {
@@ -313,6 +317,7 @@ static njs_ret_t
 njs_number_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
+    double       radix;
     njs_value_t  *value;
 
     value = &args[0];
@@ -328,7 +333,91 @@ njs_number_prototype_to_string(njs_vm_t 
         }
     }
 
-    return njs_number_to_string(vm, &vm->retval, value);
+    if (nargs == 1 || args[1].data.u.number == 10) {
+        return njs_number_to_string(vm, &vm->retval, value);
+    }
+
+    radix = args[1].data.u.number;
+
+    if (radix < 2 || radix > 36 || radix != (int) radix) {
+        vm->exception = &njs_exception_range_error;
+        return NXT_ERROR;
+    }
+
+    return njs_number_to_string_radix(vm, &vm->retval, value, radix);
+}
+
+
+/*
+ * The radix equal to 2 produces the longest intergral value of a number
+ * and the maximum value consists of 1024 digits and minus sign.
+ */
+
+#define NJS_STRING_RADIX_INTERGRAL_LEN  (1 + 1024)
+#define NJS_STRING_RADIX_FRACTION_LEN   (1 + 54)
+#define NJS_STRING_RADIX_LEN                                                  \
+    (NJS_STRING_RADIX_INTERGRAL_LEN + NJS_STRING_RADIX_FRACTION_LEN)
+
+
+static njs_ret_t
+njs_number_to_string_radix(njs_vm_t *vm, njs_value_t *string,
+    const njs_value_t *number, uint32_t radix)
+{
+    u_char   *p, *f, *start, *end;
+    double   n, next;
+    size_t   size;
+    uint8_t  reminder;
+    u_char   buf[NJS_STRING_RADIX_LEN];
+
+    static const char  *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+    end = buf + NJS_STRING_RADIX_LEN;
+    p = buf + NJS_STRING_RADIX_INTERGRAL_LEN;
+
+    n = number->data.u.number;
+
+    if (n < 0) {
+        n = -n;
+    }
+
+    do {
+        next = trunc(n / radix);
+        reminder = n - next * radix;
+        *(--p) = digits[reminder];
+        n = next;
+    } while (n != 0);
+
+    n = number->data.u.number;
+
+    if (n < 0) {
+        *(--p) = '-';
+    }
+
+    f = buf + NJS_STRING_RADIX_INTERGRAL_LEN;
+
+    n = n - trunc(n);
+
+    if (n != 0) {
+        *f++ = '.';
+
+        do {
+            n = n * radix;
+            reminder = trunc(n);
+            *f++ = digits[reminder];
+            n = n - reminder;
+        } while (n != 0 && f < end);
+    }
+
+    size = f - p;
+
+    start = njs_string_alloc(vm, string, size, size);
+
+    if (nxt_fast_path(start != NULL)) {
+        memcpy(start, p, size);
+        return NXT_OK;
+    }
+
+    return NXT_ERROR;
 }
 
 
@@ -349,7 +438,8 @@ static const njs_object_prop_t  njs_numb
     {
         .type = NJS_METHOD,
         .name = njs_string("toString"),
-        .value = njs_native_function(njs_number_prototype_to_string, 0, 0),
+        .value = njs_native_function(njs_number_prototype_to_string, 0,
+                     NJS_SKIP_ARG, NJS_NUMBER_ARG),
     },
 };
 
diff -r e411e0cbd20d -r 23ff7c369101 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Fri Apr 15 18:01:40 2016 +0300
+++ b/njs/test/njs_unit_test.c	Tue Apr 19 17:26:25 2016 +0300
@@ -92,6 +92,35 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("\n +1"),
       nxt_string("1") },
 
+    /* Number.toString(radix) method. */
+
+    { nxt_string("0..toString(2)"),
+      nxt_string("0") },
+
+    { nxt_string("240..toString(2)"),
+      nxt_string("11110000") },
+
+    { nxt_string("Math.pow(-2, 1023).toString(2).length"),
+      nxt_string("1025") },
+
+    { nxt_string("8.0625.toString(2)"),
+      nxt_string("1000.0001") },
+
+    { nxt_string("(1/3).toString(2)"),
+      nxt_string("0.010101010101010101010101010101010101010101010101010101") },
+
+    { nxt_string("9999..toString(3)"),
+      nxt_string("111201100") },
+
+    { nxt_string("-9999..toString(3)"),
+      nxt_string("-111201100") },
+
+    { nxt_string("81985529216486895..toString(16)"),
+      nxt_string("123456789abcdf0") },
+
+    { nxt_string("1845449130881..toString(36)"),
+      nxt_string("njscript") },
+
     /* An object "valueOf/toString" methods. */
 
     { nxt_string("var a = { valueOf: function() { return 1 } };    +a"),



More information about the nginx-devel mailing list