[njs] String.padStart() and String.padEnd() methods.

Valentin Bartenev vbart at nginx.com
Mon Jul 2 13:34:31 UTC 2018


details:   http://hg.nginx.org/njs/rev/31e0580b3c02
branches:  
changeset: 547:31e0580b3c02
user:      Valentin Bartenev <vbart at nginx.com>
date:      Fri Jun 29 22:36:41 2018 +0300
description:
String.padStart() and String.padEnd() methods.

diffstat:

 njs/njs_string.c         |  125 +++++++++++++++++++++++++++++++++++++++++++++++
 njs/test/njs_unit_test.c |   99 +++++++++++++++++++++++++++++++++++++
 2 files changed, 224 insertions(+), 0 deletions(-)

diffs (258 lines):

diff -r f2a2c9674082 -r 31e0580b3c02 njs/njs_string.c
--- a/njs/njs_string.c	Mon Jul 02 16:10:52 2018 +0300
+++ b/njs/njs_string.c	Fri Jun 29 22:36:41 2018 +0300
@@ -64,6 +64,8 @@ static njs_ret_t njs_string_from_char_co
     njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t njs_string_starts_or_ends_with(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, nxt_bool_t starts);
+static njs_ret_t njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, nxt_bool_t pad_start);
 static njs_ret_t njs_string_match_multiple(njs_vm_t *vm, njs_value_t *args,
     njs_regexp_pattern_t *pattern);
 static njs_ret_t njs_string_split_part_add(njs_vm_t *vm, njs_array_t *array,
@@ -2073,6 +2075,113 @@ njs_string_prototype_repeat(njs_vm_t *vm
 }
 
 
+static njs_ret_t
+njs_string_prototype_pad_start(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_string_prototype_pad(vm, args, nargs, 1);
+}
+
+
+static njs_ret_t
+njs_string_prototype_pad_end(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_string_prototype_pad(vm, args, nargs, 0);
+}
+
+
+static njs_ret_t
+njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    nxt_bool_t pad_start)
+{
+    u_char             *p, *start;
+    size_t             padding, trunc, new_size;
+    int32_t            length, new_length;
+    uint32_t           n, pad_length;
+    const u_char       *end;
+    njs_string_prop_t  string, pad_string;
+
+    length = njs_string_prop(&string, &args[0]);
+    new_length = nargs > 1 ? args[1].data.u.number : 0;
+
+    if (new_length <= length) {
+        vm->retval = args[0];
+        return NJS_OK;
+    }
+
+    if (nxt_slow_path(new_length >= NJS_STRING_MAX_LENGTH)) {
+        njs_range_error(vm, NULL);
+        return NJS_ERROR;
+    }
+
+    padding = new_length - length;
+
+    /* GCC and Clang complain about uninitialized n and trunc. */
+    n = 0;
+    trunc = 0;
+
+    if (nargs > 2) {
+        pad_length = njs_string_prop(&pad_string, &args[2]);
+
+        if (pad_string.size == 0) {
+            vm->retval = args[0];
+            return NJS_OK;
+        }
+
+        if (pad_string.size > 1) {
+            n = padding / pad_length;
+            trunc = padding % pad_length;
+
+            if (pad_string.size != (size_t) pad_length) {
+                /* UTF-8 string. */
+                end = pad_string.start + pad_string.size;
+                end = njs_string_offset(pad_string.start, end, trunc);
+
+                trunc = end - pad_string.start;
+                padding = pad_string.size * n + trunc;
+            }
+        }
+    }
+
+    new_size = string.size + padding;
+
+    start = njs_string_alloc(vm, &vm->retval, new_size, new_length);
+    if (nxt_slow_path(start == NULL)) {
+        return NJS_ERROR;
+    }
+
+    p = start;
+
+    if (pad_start) {
+        start += padding;
+
+    } else {
+        p += string.size;
+    }
+
+    memcpy(start, string.start, string.size);
+
+    if (nargs == 2) {
+        memset(p, ' ', padding);
+
+    } else if (pad_string.size == 1) {
+        memset(p, pad_string.start[0], padding);
+
+    } else {
+        while (n != 0) {
+            memcpy(p, pad_string.start, pad_string.size);
+            p += pad_string.size;
+            n--;
+        }
+
+        memcpy(p, pad_string.start, trunc);
+    }
+
+    return NJS_OK;
+}
+
+
 /*
  * String.search([regexp])
  */
@@ -3490,6 +3599,22 @@ static const njs_object_prop_t  njs_stri
                      NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG),
     },
 
+    /* ES8. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("padStart"),
+        .value = njs_native_function(njs_string_prototype_pad_start, 0,
+                     NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_STRING_ARG),
+    },
+
+    /* ES8. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("padEnd"),
+        .value = njs_native_function(njs_string_prototype_pad_end, 0,
+                     NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_STRING_ARG),
+    },
+
     {
         .type = NJS_METHOD,
         .name = njs_string("search"),
diff -r f2a2c9674082 -r 31e0580b3c02 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Mon Jul 02 16:10:52 2018 +0300
+++ b/njs/test/njs_unit_test.c	Fri Jun 29 22:36:41 2018 +0300
@@ -4557,6 +4557,105 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("''.repeat(NaN)"),
       nxt_string("") },
 
+    { nxt_string("'abc'.padStart(7)"),
+      nxt_string("    abc") },
+
+    { nxt_string("'абв'.padStart(7)"),
+      nxt_string("    абв") },
+
+    { nxt_string("'abc'.padStart(3)"),
+      nxt_string("abc") },
+
+    { nxt_string("'абв'.padStart(0)"),
+      nxt_string("абв") },
+
+    { nxt_string("'abc'.padStart(NaN)"),
+      nxt_string("abc") },
+
+    { nxt_string("'abc'.padStart(2147483647)"),
+      nxt_string("RangeError") },
+
+    { nxt_string("'abc'.padStart(2147483646, '')"),
+      nxt_string("abc") },
+
+    { nxt_string("''.padStart(0, '')"),
+      nxt_string("") },
+
+    { nxt_string("'1'.padStart(5, 0)"),
+      nxt_string("00001") },
+
+    { nxt_string("''.padStart(1, 'я')"),
+      nxt_string("я") },
+
+    { nxt_string("'abc'.padStart(6, NaN)"),
+      nxt_string("NaNabc") },
+
+    { nxt_string("'abc'.padStart(11, 123)"),
+      nxt_string("12312312abc") },
+
+    { nxt_string("'abc'.padStart(6, 12345)"),
+      nxt_string("123abc") },
+
+    { nxt_string("'абв'.padStart(6, 'эюя')"),
+      nxt_string("эюяабв") },
+
+    { nxt_string("'абв'.padStart(4, 'эюя')"),
+      nxt_string("эабв") },
+
+    { nxt_string("'абв'.padStart(7, 'эюя')"),
+      nxt_string("эюяэабв") },
+
+    { nxt_string("'абв'.padStart(10, 'эю')"),
+      nxt_string("эюэюэюэабв") },
+
+    { nxt_string("'1234'.padEnd(4)"),
+      nxt_string("1234") },
+
+    { nxt_string("'1234'.padEnd(-1)"),
+      nxt_string("1234") },
+
+    { nxt_string("'я'.padEnd(1)"),
+      nxt_string("я") },
+
+    { nxt_string("'1234'.padEnd(5)"),
+      nxt_string("1234 ") },
+
+    { nxt_string("'я'.padEnd(6)"),
+      nxt_string("я     ") },
+
+    { nxt_string("'я'.padEnd(2147483647)"),
+      nxt_string("RangeError") },
+
+    { nxt_string("'я'.padEnd(2147483646, '')"),
+      nxt_string("я") },
+
+    { nxt_string("''.padEnd(0, '')"),
+      nxt_string("") },
+
+    { nxt_string("'эю'.padEnd(3, 'я')"),
+      nxt_string("эюя") },
+
+    { nxt_string("''.padEnd(1, 0)"),
+      nxt_string("0") },
+
+    { nxt_string("'1234'.padEnd(8, 'abcd')"),
+      nxt_string("1234abcd") },
+
+    { nxt_string("'1234'.padEnd(10, 'abcd')"),
+      nxt_string("1234abcdab") },
+
+    { nxt_string("'1234'.padEnd(7, 'abcd')"),
+      nxt_string("1234abc") },
+
+    { nxt_string("'абв'.padEnd(5, 'ГД')"),
+      nxt_string("абвГД") },
+
+    { nxt_string("'абв'.padEnd(4, 'ГДУ')"),
+      nxt_string("абвГ") },
+
+    { nxt_string("'абвг'.padEnd(10, 'ДЕЖЗ')"),
+      nxt_string("абвгДЕЖЗДЕ") },
+
     { nxt_string("encodeURI()"),
       nxt_string("undefined")},
 


More information about the nginx-devel mailing list