[njs] Added String.prototype.trimStrart() and String.prototype.trimEnd().
Valentin Bartenev
vbart at nginx.com
Sun Jul 28 10:19:19 UTC 2019
details: https://hg.nginx.org/njs/rev/258b1e34ca0f
branches:
changeset: 1079:258b1e34ca0f
user: Valentin Bartenev <vbart at nginx.com>
date: Sun Jul 28 13:19:03 2019 +0300
description:
Added String.prototype.trimStrart() and String.prototype.trimEnd().
diffstat:
njs/njs_string.c | 248 ++++++++++++++++++++++++----------------------
njs/test/njs_unit_test.c | 12 +-
nxt/nxt_string.h | 19 +++
nxt/nxt_utf8.h | 37 +++++++
4 files changed, 189 insertions(+), 127 deletions(-)
diffs (424 lines):
diff -r ac39f4c902b5 -r 258b1e34ca0f njs/njs_string.c
--- a/njs/njs_string.c Sun Jul 28 13:17:13 2019 +0300
+++ b/njs/njs_string.c Sun Jul 28 13:19:03 2019 +0300
@@ -10,6 +10,10 @@
#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_s
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,
@@ -2356,158 +2362,138 @@ 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;
njs_string_prop_t string;
trim = 0;
- njs_string_prop(&string, &args[0]);
-
- p = string.start;
+ njs_string_prop(&string, value);
+
+ start = string.start;
end = string.start + string.size;
if (string.length == 0 || string.length == string.size) {
/* Byte or ASCII string. */
- while (p < end) {
-
- 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;
-
- default:
- start = p;
- p = end;
-
- 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_START) {
+ for ( ;; ) {
+ if (start == end) {
+ goto empty;
+ }
+
+ if (nxt_is_whitespace(*start)) {
+ start++;
+ trim++;
+ continue;
}
+
+ break;
+ }
+ }
+
+ 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;
-
- 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;
- }
+ if (mode & NJS_TRIM_START) {
+ for ( ;; ) {
+ if (start == end) {
+ goto empty;
+ }
+
+ p = start;
+ u = nxt_utf8_decode(&start, end);
+
+ if (nxt_utf8_is_whitespace(u)) {
+ trim++;
+ continue;
}
+
+ start = p;
+ break;
+ }
+ }
+
+ if (mode & NJS_TRIM_END) {
+ prev = end;
+
+ for ( ;; ) {
+ if (start == prev) {
+ goto empty;
+ }
+
+ prev = nxt_utf8_prev(prev);
+ p = prev;
+ u = nxt_utf8_decode(&p, end);
+
+ if (nxt_utf8_is_whitespace(u)) {
+ trim++;
+ continue;
+ }
+
+ end = p;
+ break;
}
}
}
- vm->retval = njs_string_empty;
-
- return NXT_OK;
-
-done:
-
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_stri
.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,
diff -r ac39f4c902b5 -r 258b1e34ca0f njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Sun Jul 28 13:17:13 2019 +0300
+++ b/njs/test/njs_unit_test.c Sun Jul 28 13:19:03 2019 +0300
@@ -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()"),
diff -r ac39f4c902b5 -r 258b1e34ca0f nxt/nxt_string.h
--- a/nxt/nxt_string.h Sun Jul 28 13:17:13 2019 +0300
+++ b/nxt/nxt_string.h Sun Jul 28 13:19:03 2019 +0300
@@ -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)
{
diff -r ac39f4c902b5 -r 258b1e34ca0f nxt/nxt_utf8.h
--- a/nxt/nxt_utf8.h Sun Jul 28 13:17:13 2019 +0300
+++ b/nxt/nxt_utf8.h Sun Jul 28 13:19:03 2019 +0300
@@ -122,4 +122,41 @@ nxt_utf8_copy(u_char *dst, const u_char
((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_ */
More information about the nginx-devel
mailing list