From: Alexander Borisov Date: Mon, 1 Jul 2019 16:57:34 +0000 (+0300) Subject: Added support for functions in regexp with global match. X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/%7B@url%7D?a=commitdiff_plain;h=f15fb784bbc537917cf59a5de922131fc5c18431;p=njs.git Added support for functions in regexp with global match. This closes #183 issue on GitHub. --- diff --git a/njs/njs_string.c b/njs/njs_string.c index 6ce90ad8..21973b95 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -49,6 +49,8 @@ typedef struct { nxt_regex_match_data_t *match_data; + nxt_bool_t empty; + njs_utf8_t utf8:8; njs_regexp_utf8_t type:8; } njs_string_replace_t; @@ -3143,6 +3145,11 @@ njs_string_replace_regexp(njs_vm_t *vm, njs_value_t *args, r->part[2].start = start + 1; } + if (r->function != NULL) { + return njs_string_replace_regexp_function(vm, args, r, + captures, ret); + } + r->part[0] = replace; } else { @@ -3194,11 +3201,12 @@ static njs_ret_t njs_string_replace_regexp_function(njs_vm_t *vm, njs_value_t *args, njs_string_replace_t *r, int *captures, nxt_uint_t n) { - u_char *start; - size_t size, length; - njs_ret_t ret; - nxt_uint_t i, k; - njs_value_t *arguments; + u_char *start; + size_t size, length; + njs_ret_t ret; + nxt_uint_t i, k; + njs_value_t *arguments; + njs_string_prop_t string; r->u.cont.function = njs_string_replace_regexp_continuation; njs_set_invalid(&r->retval); @@ -3225,14 +3233,18 @@ njs_string_replace_regexp_function(njs_vm_t *vm, njs_value_t *args, } } + r->empty = (captures[0] == captures[1]); + /* The offset of the matched substring. */ njs_value_number_set(&arguments[n + 1], captures[0]); /* The whole string being examined. */ length = njs_string_calc_length(r->utf8, r->part[0].start, r->part[0].size); - ret = njs_string_new(vm, &arguments[n + 2], r->part[0].start, - r->part[0].size, length); + (void) njs_string_prop(&string, &args[0]); + + ret = njs_string_new(vm, &arguments[n + 2], string.start, string.size, + length); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; @@ -3249,15 +3261,23 @@ static njs_ret_t njs_string_replace_regexp_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { + njs_string_prop_t string; njs_string_replace_t *r; r = njs_vm_continuation(vm); + (void) njs_string_prop(&string, &args[0]); + if (njs_is_string(&r->retval)) { - njs_string_replacement_copy(&r->part[1], &r->retval); + njs_string_replacement_copy(&r->part[r->empty ? 0 : 1], &r->retval); if (args[1].data.u.regexp->pattern->global) { r->part += 2; + + if (r->part[0].start > (string.start + string.size)) { + return njs_string_replace_regexp_join(vm, r); + } + return njs_string_replace_regexp(vm, args, r); } diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index e9f688f3..81db47df 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -5560,6 +5560,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("'12345'.replace(3, () => ({toString: () => 'aaaa'}))"), nxt_string("12aaaa45") }, + { nxt_string("'abc'.replace(/(z*)/g, function v0() {return '124'})"), + nxt_string("124a124b124c124") }, + + { nxt_string("'abc'.replace(/(a*)/g, function v0() {return '124'})"), + nxt_string("124124b124c124") }, + { nxt_string("/]/"), nxt_string("/\\]/") },