]> git.kaiwu.me - njs.git/commitdiff
Added String.prototype.trimStrart() and String.prototype.trimEnd().
authorValentin Bartenev <vbart@nginx.com>
Sun, 28 Jul 2019 10:19:03 +0000 (13:19 +0300)
committerValentin Bartenev <vbart@nginx.com>
Sun, 28 Jul 2019 10:19:03 +0000 (13:19 +0300)
njs/njs_string.c
njs/test/njs_unit_test.c
nxt/nxt_string.h
nxt/nxt_utf8.h

index 3018ba1d85af8b223a5149f070ad98f8e7f7f12d..218d39fa74adeac28f715a2a25d321bfcb269b7c 100644 (file)
 #include <string.h>
 
 
+#define NJS_TRIM_START  1
+#define NJS_TRIM_END    2
+
+
 typedef struct {
     u_char                     *start;
     size_t                     size;
@@ -68,6 +72,8 @@ static njs_ret_t njs_string_bytes_from_string(njs_vm_t *vm,
     const njs_value_t *args, nxt_uint_t nargs);
 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_trim(njs_vm_t *vm, njs_value_t *value,
+    nxt_uint_t mode);
 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,
@@ -2355,6 +2361,29 @@ njs_string_prototype_to_upper_case(njs_vm_t *vm, njs_value_t *args,
 static njs_ret_t
 njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
+{
+    return njs_string_trim(vm, &args[0], NJS_TRIM_START|NJS_TRIM_END);
+}
+
+
+static njs_ret_t
+njs_string_prototype_trim_start(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_string_trim(vm, &args[0], NJS_TRIM_START);
+}
+
+
+static njs_ret_t
+njs_string_prototype_trim_end(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    return njs_string_trim(vm, &args[0], NJS_TRIM_END);
+}
+
+
+static njs_ret_t
+njs_string_trim(njs_vm_t *vm, njs_value_t *value, nxt_uint_t mode)
 {
     uint32_t           u, trim, length;
     const u_char       *p, *prev, *start, *end;
@@ -2362,152 +2391,109 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
     trim = 0;
 
-    njs_string_prop(&string, &args[0]);
+    njs_string_prop(&string, value);
 
-    p = string.start;
+    start = string.start;
     end = string.start + string.size;
 
     if (string.length == 0 || string.length == string.size) {
         /* Byte or ASCII string. */
 
-        while (p < end) {
+        if (mode & NJS_TRIM_START) {
+            for ( ;; ) {
+                if (start == end) {
+                    goto empty;
+                }
 
-            switch (*p) {
-            case 0x09:  /* <TAB>  */
-            case 0x0A:  /* <LF>   */
-            case 0x0B:  /* <VT>   */
-            case 0x0C:  /* <FF>   */
-            case 0x0D:  /* <CR>   */
-            case 0x20:  /* <SP>   */
-            case 0xA0:  /* <NBSP> */
-                trim++;
-                p++;
-                continue;
+                if (nxt_is_whitespace(*start)) {
+                    start++;
+                    trim++;
+                    continue;
+                }
 
-            default:
-                start = p;
-                p = end;
+                break;
+            }
+        }
 
-                for ( ;; ) {
-                    p--;
-
-                    switch (*p) {
-                    case 0x09:  /* <TAB>  */
-                    case 0x0A:  /* <LF>   */
-                    case 0x0B:  /* <VT>   */
-                    case 0x0C:  /* <FF>   */
-                    case 0x0D:  /* <CR>   */
-                    case 0x20:  /* <SP>   */
-                    case 0xA0:  /* <NBSP> */
-                        trim++;
-                        continue;
-
-                    default:
-                        p++;
-                        goto done;
-                    }
+        if (mode & NJS_TRIM_END) {
+            for ( ;; ) {
+                if (start == end) {
+                    goto empty;
                 }
+
+                end--;
+
+                if (nxt_is_whitespace(*end)) {
+                    trim++;
+                    continue;
+                }
+
+                end++;
+                break;
             }
         }
 
     } else {
         /* UTF-8 string. */
 
-        while (p < end) {
-            prev = p;
-            u = nxt_utf8_decode(&p, end);
-
-            switch (u) {
-            case 0x0009:  /* <TAB>  */
-            case 0x000A:  /* <LF>   */
-            case 0x000B:  /* <VT>   */
-            case 0x000C:  /* <FF>   */
-            case 0x000D:  /* <CR>   */
-            case 0x0020:  /* <SP>   */
-            case 0x00A0:  /* <NBSP> */
-            case 0x1680:
-            case 0x2000:
-            case 0x2001:
-            case 0x2002:
-            case 0x2003:
-            case 0x2004:
-            case 0x2005:
-            case 0x2006:
-            case 0x2007:
-            case 0x2008:
-            case 0x2009:
-            case 0x200A:
-            case 0x2028:  /* <LS>   */
-            case 0x2029:  /* <PS>   */
-            case 0x202F:
-            case 0x205F:
-            case 0x3000:
-            case 0xFEFF:  /* <BOM>  */
-                trim++;
-                continue;
+        if (mode & NJS_TRIM_START) {
+            for ( ;; ) {
+                if (start == end) {
+                    goto empty;
+                }
 
-            default:
-                start = prev;
-                prev = end;
-
-                for ( ;; ) {
-                    prev = nxt_utf8_prev(prev);
-                    p = prev;
-                    u = nxt_utf8_decode(&p, end);
-
-                    switch (u) {
-                    case 0x0009:  /* <TAB>  */
-                    case 0x000A:  /* <LF>   */
-                    case 0x000B:  /* <VT>   */
-                    case 0x000C:  /* <FF>   */
-                    case 0x000D:  /* <CR>   */
-                    case 0x0020:  /* <SP>   */
-                    case 0x00A0:  /* <NBSP> */
-                    case 0x1680:
-                    case 0x2000:
-                    case 0x2001:
-                    case 0x2002:
-                    case 0x2003:
-                    case 0x2004:
-                    case 0x2005:
-                    case 0x2006:
-                    case 0x2007:
-                    case 0x2008:
-                    case 0x2009:
-                    case 0x200A:
-                    case 0x2028:  /* <LS>   */
-                    case 0x2029:  /* <PS>   */
-                    case 0x202F:
-                    case 0x205F:
-                    case 0x3000:
-                    case 0xFEFF:  /* <BOM>  */
-                        trim++;
-                        continue;
-
-                    default:
-                        goto done;
-                    }
+                p = start;
+                u = nxt_utf8_decode(&start, end);
+
+                if (nxt_utf8_is_whitespace(u)) {
+                    trim++;
+                    continue;
                 }
+
+                start = p;
+                break;
             }
         }
-    }
 
-    vm->retval = njs_string_empty;
+        if (mode & NJS_TRIM_END) {
+            prev = end;
 
-    return NXT_OK;
+            for ( ;; ) {
+                if (start == prev) {
+                    goto empty;
+                }
 
-done:
+                prev = nxt_utf8_prev(prev);
+                p = prev;
+                u = nxt_utf8_decode(&p, end);
+
+                if (nxt_utf8_is_whitespace(u)) {
+                    trim++;
+                    continue;
+                }
+
+                end = p;
+                break;
+            }
+        }
+    }
 
     if (trim == 0) {
         /* GC: retain. */
-        vm->retval = args[0];
+        vm->retval = *value;
 
         return NXT_OK;
     }
 
     length = (string.length != 0) ? string.length - trim : 0;
 
-    return njs_string_new(vm, &vm->retval, start, p - start, length);
+    return njs_string_new(vm, &vm->retval, start, end - start, length);
+
+empty:
+
+    vm->retval = njs_string_empty;
+
+    return NXT_OK;
 }
 
 
@@ -4250,6 +4236,26 @@ static const njs_object_prop_t  njs_string_prototype_properties[] =
         .configurable = 1,
     },
 
+    /* ES10. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("trimStart"),
+        .value = njs_native_function(njs_string_prototype_trim_start,
+                                     NJS_STRING_OBJECT_ARG),
+        .writable = 1,
+        .configurable = 1,
+    },
+
+    /* ES10. */
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("trimEnd"),
+        .value = njs_native_function(njs_string_prototype_trim_end,
+                                     NJS_STRING_OBJECT_ARG),
+        .writable = 1,
+        .configurable = 1,
+    },
+
     /* ES6. */
     {
         .type = NJS_METHOD,
index 0c3f0ade3b9bde02baec671477a22b1c225b8562..cb3cc18537d76f396f27970603781e97d6f7e61e 100644 (file)
@@ -5623,7 +5623,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("304,453,456,459,498,1012,7838,8486,8490,8491") },
 #endif
 
-    { nxt_string("'abc'.trim()"),
+    { nxt_string("'abc'.trimStart().trim().trimEnd()"),
       nxt_string("abc") },
 
     { nxt_string("''.trim()"),
@@ -5632,22 +5632,22 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("'    '.trim()"),
       nxt_string("") },
 
-    { nxt_string("'abc  '.trim()"),
+    { nxt_string("'abc  '.trimEnd()"),
       nxt_string("abc") },
 
-    { nxt_string("'   abc'.trim()"),
+    { nxt_string("'   abc'.trimStart()"),
       nxt_string("abc") },
 
     { nxt_string("'   abc  '.trim()"),
       nxt_string("abc") },
 
-    { nxt_string("'абв  '.trim()"),
+    { nxt_string("'абв  '.trimEnd()"),
       nxt_string("абв") },
 
-    { nxt_string("'   абв'.trim()"),
+    { nxt_string("'   абв'.trimStart()"),
       nxt_string("абв") },
 
-    { nxt_string("'   абв  '.trim()"),
+    { nxt_string("'   абв  '.trimStart().trimEnd()"),
       nxt_string("абв") },
 
     { nxt_string("'\\u2029abc\\uFEFF\\u2028'.trim()"),
index 20c8b1bbb7ea40ad3f7ec7c3ea525b310938a498..d7c92024841353051d21987696fbac92fdf8b764 100644 (file)
@@ -41,6 +41,25 @@ nxt_upper_case(u_char c)
 }
 
 
+nxt_inline nxt_bool_t
+nxt_is_whitespace(u_char c)
+{
+    switch (c) {
+    case 0x09:  /* <TAB>  */
+    case 0x0A:  /* <LF>   */
+    case 0x0B:  /* <VT>   */
+    case 0x0C:  /* <FF>   */
+    case 0x0D:  /* <CR>   */
+    case 0x20:  /* <SP>   */
+    case 0xA0:  /* <NBSP> */
+        return 1;
+
+    default:
+        return 0;
+    }
+}
+
+
 nxt_inline u_char *
 nxt_strlchr(u_char *p, u_char *last, u_char c)
 {
index e2d78aa916577b72331c5c4182d74e2f1260bf95..db1a865e9be8268a5112a05f54f82b4c1db638a5 100644 (file)
@@ -122,4 +122,41 @@ nxt_utf8_copy(u_char *dst, const u_char **src, const u_char *end)
     ((u < 0x80) ? 1 : ((u < 0x0800) ? 2 : 3))
 
 
+nxt_inline nxt_bool_t
+nxt_utf8_is_whitespace(uint32_t c)
+{
+    switch (c) {
+    case 0x0009:  /* <TAB>  */
+    case 0x000A:  /* <LF>   */
+    case 0x000B:  /* <VT>   */
+    case 0x000C:  /* <FF>   */
+    case 0x000D:  /* <CR>   */
+    case 0x0020:  /* <SP>   */
+    case 0x00A0:  /* <NBSP> */
+    case 0x1680:
+    case 0x2000:
+    case 0x2001:
+    case 0x2002:
+    case 0x2003:
+    case 0x2004:
+    case 0x2005:
+    case 0x2006:
+    case 0x2007:
+    case 0x2008:
+    case 0x2009:
+    case 0x200A:
+    case 0x2028:  /* <LS>   */
+    case 0x2029:  /* <PS>   */
+    case 0x202F:
+    case 0x205F:
+    case 0x3000:
+    case 0xFEFF:  /* <BOM>  */
+        return 1;
+
+    default:
+        return 0;
+    }
+}
+
+
 #endif /* _NXT_UTF8_H_INCLUDED_ */