From 01f1e99ac5b3d61a5e700cd8ebffc2ef6a8acc63 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 28 Oct 2016 13:32:33 +0300 Subject: [PATCH] String.prototype.trim() method. In collaboration with Valentin Bartenev. --- njs/njs_string.c | 136 +++++++++++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 30 +++++++++ 2 files changed, 166 insertions(+) diff --git a/njs/njs_string.c b/njs/njs_string.c index c0e2e195..8e0222f4 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -1614,6 +1614,135 @@ 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) +{ + 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; + end = string.start + string.size; + + if (string.length == 0 || string.length == string.size) { + /* Byte or ASCII string. */ + + while (p < end) { + + switch (*p) { + case 0x09: /* */ + case 0x0A: /* */ + case 0x0B: /* */ + case 0x0C: /* */ + case 0x0D: /* */ + case 0x20: /* */ + case 0xA0: /* */ + trim++; + p++; + continue; + + default: + start = p; + p = end; + + for ( ;; ) { + p--; + + switch (*p) { + case 0x09: /* */ + case 0x0A: /* */ + case 0x0B: /* */ + case 0x0C: /* */ + case 0x0D: /* */ + case 0x20: /* */ + case 0xA0: /* */ + trim++; + continue; + + default: + p++; + goto done; + } + } + } + } + + } else { + /* UTF-8 string. */ + + while (p < end) { + prev = p; + u = nxt_utf8_decode(&p, end); + + switch (u) { + case 0x0009: /* */ + case 0x000A: /* */ + case 0x000B: /* */ + case 0x000C: /* */ + case 0x000D: /* */ + case 0x0020: /* */ + case 0x00A0: /* */ + case 0x2028: /* */ + case 0x2029: /* */ + case 0xFEFF: /* */ + 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: /* */ + case 0x000A: /* */ + case 0x000B: /* */ + case 0x000C: /* */ + case 0x000D: /* */ + case 0x0020: /* */ + case 0x00A0: /* */ + case 0x2028: /* */ + case 0x2029: /* */ + case 0xFEFF: /* */ + trim++; + continue; + + default: + goto done; + } + } + } + } + } + + vm->retval = njs_string_empty; + + return NXT_OK; + +done: + + if (trim == 0) { + /* GC: retain. */ + vm->retval = args[0]; + + return NXT_OK; + } + + length = (string.length != 0) ? string.length - trim : 0; + + return njs_string_new(vm, &vm->retval, start, p - start, length); +} + + /* * String.search([regexp]) */ @@ -2906,6 +3035,13 @@ static const njs_object_prop_t njs_string_prototype_properties[] = NJS_STRING_OBJECT_ARG), }, + { + .type = NJS_METHOD, + .name = njs_string("trim"), + .value = njs_native_function(njs_string_prototype_trim, 0, + NJS_STRING_OBJECT_ARG), + }, + { .type = NJS_METHOD, .name = njs_string("search"), diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 59b64730..96db2f76 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -3326,6 +3326,36 @@ static njs_unit_test_t njs_test[] = "} a"), nxt_string("304,453,456,459,498,1012,7838,8486,8490,8491") }, + { nxt_string("'abc'.trim()"), + nxt_string("abc") }, + + { nxt_string("''.trim()"), + nxt_string("") }, + + { nxt_string("' '.trim()"), + nxt_string("") }, + + { nxt_string("'abc '.trim()"), + nxt_string("abc") }, + + { nxt_string("' abc'.trim()"), + nxt_string("abc") }, + + { nxt_string("' abc '.trim()"), + nxt_string("abc") }, + + { nxt_string("'абв '.trim()"), + nxt_string("абв") }, + + { nxt_string("' абв'.trim()"), + nxt_string("абв") }, + + { nxt_string("' абв '.trim()"), + nxt_string("абв") }, + + { nxt_string("'\\u2029abc\\uFEFF\\u2028'.trim()"), + nxt_string("abc") }, + { nxt_string("'abcdefgh'.search()"), nxt_string("0") }, -- 2.47.3