details: https://hg.nginx.org/njs/rev/94499cbdf990 branches: changeset: 1496:94499cbdf990 user: Dmitry Volyntsev <xei...@nginx.com> date: Tue Aug 18 11:52:17 2020 +0000 description: Refactored iterator Array methods.
diffstat: src/njs_array.c | 1879 ++++++++++++++++++++------------------------- src/test/njs_unit_test.c | 104 +- 2 files changed, 873 insertions(+), 1110 deletions(-) diffs (truncated from 2304 to 1000 lines): diff -r 4818a450f4e6 -r 94499cbdf990 src/njs_array.c --- a/src/njs_array.c Mon Aug 17 19:55:46 2020 +0300 +++ b/src/njs_array.c Tue Aug 18 11:52:17 2020 +0000 @@ -8,7 +8,45 @@ #include <njs_main.h> -#define njs_fast_object(_sz) ((_sz) <= NJS_ARRAY_FAST_OBJECT_LENGTH) +#define njs_fast_object(_sz) ((_sz) <= NJS_ARRAY_FAST_OBJECT_LENGTH) + + +#define njs_array_func(type) \ + ((type << 1) | NJS_ARRAY_FUNC) + + +#define njs_array_arg(type) \ + ((type << 1) | NJS_ARRAY_ARG) + + +#define njs_array_type(magic) (magic >> 1) +#define njs_array_arg1(magic) (magic & 0x1) + + +typedef enum { + NJS_ARRAY_EVERY = 0, + NJS_ARRAY_SOME, + NJS_ARRAY_INCLUDES, + NJS_ARRAY_INDEX_OF, + NJS_ARRAY_FOR_EACH, + NJS_ARRAY_FIND, + NJS_ARRAY_FIND_INDEX, + NJS_ARRAY_REDUCE, + NJS_ARRAY_FILTER, + NJS_ARRAY_MAP, +} njs_array_iterator_fun_t; + + +typedef enum { + NJS_ARRAY_LAST_INDEX_OF = 0, + NJS_ARRAY_REDUCE_RIGHT, +} njs_array_reverse_iterator_fun_t; + + +typedef enum { + NJS_ARRAY_FUNC = 0, + NJS_ARRAY_ARG +} njs_array_iterator_arg_t; typedef struct { @@ -1769,380 +1807,6 @@ njs_array_indices(njs_vm_t *vm, njs_valu njs_inline njs_int_t -njs_array_object_handler(njs_vm_t *vm, njs_array_iterator_handler_t handler, - njs_array_iterator_args_t *args, njs_value_t *key, int64_t i) -{ - njs_int_t ret; - njs_value_t prop, *entry; - - if (key != NULL) { - ret = njs_value_property(vm, args->value, key, &prop); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - } else { - ret = njs_value_property_i64(vm, args->value, i, &prop); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - } - - entry = (ret == NJS_OK) ? &prop : njs_value_arg(&njs_value_invalid); - - ret = handler(vm, args, entry, i); - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - - return ret; -} - - -njs_inline njs_int_t -njs_array_iterator(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_array_iterator_handler_t handler) -{ - double idx; - int64_t length, i, from, to; - njs_int_t ret; - njs_array_t *array, *keys; - njs_value_t *value, *entry, prop, character, string_obj; - njs_object_t *object; - const u_char *p, *end, *pos; - njs_string_prop_t string_prop; - - value = args->value; - from = args->from; - to = args->to; - - if (njs_is_array(value)) { - array = njs_array(value); - - for (; from < to; from++) { - if (njs_slow_path(!array->object.fast_array)) { - goto process_object; - } - - if (njs_fast_path(from < array->length - && njs_is_valid(&array->start[from]))) - { - ret = handler(vm, args, &array->start[from], from); - - } else { - entry = njs_value_arg(&njs_value_invalid); - ret = njs_value_property_i64(vm, value, from, &prop); - if (njs_slow_path(ret != NJS_DECLINED)) { - if (ret == NJS_ERROR) { - return NJS_ERROR; - } - - entry = ∝ - } - - ret = handler(vm, args, entry, from); - } - - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - } - - return NJS_OK; - } - - if (njs_is_string(value) || njs_is_object_string(value)) { - - if (njs_is_string(value)) { - object = njs_object_value_alloc(vm, value, NJS_STRING); - if (njs_slow_path(object == NULL)) { - return NJS_ERROR; - } - - njs_set_type_object(&string_obj, object, NJS_OBJECT_STRING); - - args->value = &string_obj; - } - else { - value = njs_object_value(value); - } - - length = njs_string_prop(&string_prop, value); - - p = string_prop.start; - end = p + string_prop.size; - - if ((size_t) length == string_prop.size) { - /* Byte or ASCII string. */ - - for (i = from; i < to; i++) { - /* This cannot fail. */ - (void) njs_string_new(vm, &character, p + i, 1, 1); - - ret = handler(vm, args, &character, i); - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - } - - } else { - /* UTF-8 string. */ - - for (i = from; i < to; i++) { - pos = njs_utf8_next(p, end); - - /* This cannot fail. */ - (void) njs_string_new(vm, &character, p, pos - p, 1); - - ret = handler(vm, args, &character, i); - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - - p = pos; - } - } - - return NJS_OK; - } - - if (!njs_is_object(value)) { - return NJS_OK; - } - -process_object: - - if (!njs_fast_object(to - from)) { - keys = njs_array_indices(vm, value); - if (njs_slow_path(keys == NULL)) { - return NJS_ERROR; - } - - for (i = 0; i < keys->length; i++) { - idx = njs_string_to_index(&keys->start[i]); - - if (idx < from || idx >= to) { - continue; - } - - ret = njs_array_object_handler(vm, handler, args, &keys->start[i], - idx); - if (njs_slow_path(ret != NJS_OK)) { - njs_array_destroy(vm, keys); - return ret; - } - } - - njs_array_destroy(vm, keys); - - return NJS_OK; - } - - for (i = from; i < to; i++) { - ret = njs_array_object_handler(vm, handler, args, NULL, i); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - return NJS_OK; -} - - -njs_inline njs_int_t -njs_array_reverse_iterator(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_array_iterator_handler_t handler) -{ - double idx; - int64_t i, from, to, length; - njs_int_t ret; - njs_array_t *array, *keys; - njs_value_t *entry, *value, prop, character, string_obj; - njs_object_t *object; - const u_char *p, *end, *pos; - njs_string_prop_t string_prop; - - value = args->value; - from = args->from; - to = args->to; - - if (njs_is_array(value)) { - array = njs_array(value); - - from += 1; - - while (from-- > to) { - if (njs_slow_path(!array->object.fast_array)) { - goto process_object; - } - - if (njs_fast_path(from < array->length - && njs_is_valid(&array->start[from]))) - { - ret = handler(vm, args, &array->start[from], from); - - } else { - entry = njs_value_arg(&njs_value_invalid); - ret = njs_value_property_i64(vm, value, from, &prop); - if (njs_slow_path(ret != NJS_DECLINED)) { - if (ret == NJS_ERROR) { - return NJS_ERROR; - } - - entry = ∝ - } - - ret = handler(vm, args, entry, from); - } - - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - } - - return NJS_OK; - } - - if (njs_is_string(value) || njs_is_object_string(value)) { - - if (njs_is_string(value)) { - object = njs_object_value_alloc(vm, value, NJS_STRING); - if (njs_slow_path(object == NULL)) { - return NJS_ERROR; - } - - njs_set_type_object(&string_obj, object, NJS_OBJECT_STRING); - - args->value = &string_obj; - } - else { - value = njs_object_value(value); - } - - length = njs_string_prop(&string_prop, value); - end = string_prop.start + string_prop.size; - - if ((size_t) length == string_prop.size) { - /* Byte or ASCII string. */ - - p = string_prop.start + from; - - i = from + 1; - - while (i-- > to) { - /* This cannot fail. */ - (void) njs_string_new(vm, &character, p, 1, 1); - - ret = handler(vm, args, &character, i); - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - - p--; - } - - } else { - /* UTF-8 string. */ - - p = njs_string_offset(string_prop.start, end, from); - p = njs_utf8_next(p, end); - - i = from + 1; - - while (i-- > to) { - pos = njs_utf8_prev(p); - - /* This cannot fail. */ - (void) njs_string_new(vm, &character, pos, p - pos , 1); - - ret = handler(vm, args, &character, i); - if (njs_slow_path(ret != NJS_OK)) { - if (ret > 0) { - return NJS_DECLINED; - } - - return NJS_ERROR; - } - - p = pos; - } - } - - return NJS_OK; - } - - if (!njs_is_object(value)) { - return NJS_OK; - } - -process_object: - - if (!njs_fast_object(from - to)) { - keys = njs_array_indices(vm, value); - if (njs_slow_path(keys == NULL)) { - return NJS_ERROR; - } - - i = keys->length; - - while (i > 0) { - idx = njs_string_to_index(&keys->start[--i]); - - if (idx < to || idx > from) { - continue; - } - - ret = njs_array_object_handler(vm, handler, args, &keys->start[i], - idx); - if (njs_slow_path(ret != NJS_OK)) { - njs_array_destroy(vm, keys); - return ret; - } - } - - njs_array_destroy(vm, keys); - - return NJS_OK; - } - - i = from + 1; - - while (i-- > to) { - ret = njs_array_object_handler(vm, handler, args, NULL, i); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - return NJS_OK; -} - - -njs_inline njs_int_t njs_is_concat_spreadable(njs_vm_t *vm, njs_value_t *value) { njs_int_t ret; @@ -2326,211 +1990,6 @@ njs_array_prototype_concat(njs_vm_t *vm, static njs_int_t -njs_array_handler_index_of(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, int64_t n) -{ - if (njs_values_strict_equal(args->argument, entry)) { - njs_set_number(&vm->retval, n); - - return 1; - } - - return NJS_OK; -} - - -static njs_int_t -njs_array_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - int64_t from, length; - njs_int_t ret; - njs_array_iterator_args_t iargs; - - iargs.value = njs_argument(args, 0); - - ret = njs_value_to_object(vm, iargs.value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - iargs.argument = njs_arg(args, nargs, 1); - - ret = njs_value_length(vm, iargs.value, &length); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (length == 0 || from >= (int64_t) length) { - goto not_found; - } - - if (from < 0) { - from = length + from; - - if (from < 0) { - from = 0; - } - } - - iargs.from = from; - iargs.to = length; - - ret = njs_array_iterator(vm, &iargs, njs_array_handler_index_of); - if (njs_fast_path(ret != NJS_OK)) { - return (ret == NJS_DECLINED) ? NJS_OK : NJS_ERROR; - } - -not_found: - - njs_set_number(&vm->retval, -1); - - return ret; -} - - -static njs_int_t -njs_array_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused) -{ - int64_t from, length; - njs_int_t ret; - njs_array_iterator_args_t iargs; - - iargs.value = njs_argument(args, 0); - - ret = njs_value_to_object(vm, iargs.value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - iargs.argument = njs_arg(args, nargs, 1); - - ret = njs_value_length(vm, iargs.value, &length); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (length == 0) { - goto not_found; - } - - if (nargs > 2) { - ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - } else { - from = length - 1; - } - - if (from >= 0) { - from = njs_min(from, length - 1); - - } else if (from < 0) { - from += length; - - if (from <= 0) { - goto not_found; - } - } - - iargs.from = from; - iargs.to = 0; - - ret = njs_array_reverse_iterator(vm, &iargs, njs_array_handler_index_of); - if (njs_fast_path(ret != NJS_OK)) { - return (ret == NJS_DECLINED) ? NJS_OK : NJS_ERROR; - } - -not_found: - - njs_set_number(&vm->retval, -1); - - return ret; -} - - -static njs_int_t -njs_array_handler_includes(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, int64_t n) -{ - if (!njs_is_valid(entry)) { - entry = njs_value_arg(&njs_value_undefined); - } - - if (njs_values_same_zero(args->argument, entry)) { - njs_set_true(&vm->retval); - - return 1; - } - - return NJS_OK; -} - - -static njs_int_t -njs_array_prototype_includes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - int64_t from, length; - njs_int_t ret; - njs_array_iterator_args_t iargs; - - iargs.value = njs_argument(args, 0); - - ret = njs_value_to_object(vm, iargs.value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - iargs.argument = njs_arg(args, nargs, 1); - - ret = njs_value_length(vm, iargs.value, &length); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (length == 0) { - goto not_found; - } - - ret = njs_value_to_integer(vm, njs_arg(args, nargs, 2), &from); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (from < 0) { - from += length; - - if (from < 0) { - from = 0; - } - } - - iargs.from = from; - iargs.to = length; - - ret = njs_array_iterator(vm, &iargs, njs_array_handler_includes); - if (njs_fast_path(ret != NJS_OK)) { - return (ret == NJS_DECLINED) ? NJS_OK : NJS_ERROR; - } - -not_found: - - njs_set_false(&vm->retval); - - return NJS_OK; -} - - -static njs_int_t njs_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { @@ -2622,119 +2081,197 @@ njs_array_iterator_call(njs_vm_t *vm, nj } -njs_inline njs_int_t -njs_array_validate_args(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_array_iterator_args_t *iargs) +static njs_int_t +njs_array_object_handler(njs_vm_t *vm, njs_array_iterator_handler_t handler, + njs_array_iterator_args_t *args, njs_value_t *key, int64_t i) { - njs_int_t ret; - - iargs->value = njs_argument(args, 0); - - ret = njs_value_to_object(vm, iargs->value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - ret = njs_value_length(vm, iargs->value, &iargs->to); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + njs_int_t ret; + njs_value_t prop, *entry; + + if (key != NULL) { + ret = njs_value_property(vm, args->value, key, &prop); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + } else { + ret = njs_value_property_i64(vm, args->value, i, &prop); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } } - if (njs_slow_path(!njs_is_function(njs_arg(args, nargs, 1)))) { - goto failed; + entry = (ret == NJS_OK) ? &prop : njs_value_arg(&njs_value_invalid); + + ret = handler(vm, args, entry, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret == NJS_DONE) { + return NJS_DONE; + } + + return NJS_ERROR; } - iargs->from = 0; - iargs->function = njs_function(njs_argument(args, 1)); - iargs->argument = njs_arg(args, nargs, 2); - - return NJS_OK; - -failed: - - njs_type_error(vm, "unexpected iterator arguments"); - - return NJS_ERROR; + return ret; } -static njs_int_t -njs_array_handler_for_each(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, int64_t n) +njs_inline njs_int_t +njs_array_iterator(njs_vm_t *vm, njs_array_iterator_args_t *args, + njs_array_iterator_handler_t handler) { - if (njs_is_valid(entry)) { - return njs_array_iterator_call(vm, args, entry, n); - } - - return NJS_OK; -} - - -static njs_int_t -njs_array_prototype_for_each(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_int_t ret; - njs_array_iterator_args_t iargs; - - ret = njs_array_validate_args(vm, args, nargs, &iargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + double idx; + int64_t length, i, from, to; + njs_int_t ret; + njs_array_t *array, *keys; + njs_value_t *value, *entry, prop, character, string_obj; + njs_object_t *object; + const u_char *p, *end, *pos; + njs_string_prop_t string_prop; + + value = args->value; + from = args->from; + to = args->to; + + if (njs_is_array(value)) { + array = njs_array(value); + + for (; from < to; from++) { + if (njs_slow_path(!array->object.fast_array)) { + goto process_object; + } + + if (njs_fast_path(from < array->length + && njs_is_valid(&array->start[from]))) + { + ret = handler(vm, args, &array->start[from], from); + + } else { + entry = njs_value_arg(&njs_value_invalid); + ret = njs_value_property_i64(vm, value, from, &prop); + if (njs_slow_path(ret != NJS_DECLINED)) { + if (ret == NJS_ERROR) { + return NJS_ERROR; + } + + entry = ∝ + } + + ret = handler(vm, args, entry, from); + } + + if (njs_slow_path(ret != NJS_OK)) { + if (ret == NJS_DONE) { + return NJS_DONE; + } + + return NJS_ERROR; + } + } + + return NJS_OK; } - ret = njs_array_iterator(vm, &iargs, njs_array_handler_for_each); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + if (njs_is_string(value) || njs_is_object_string(value)) { + + if (njs_is_string(value)) { + object = njs_object_value_alloc(vm, value, NJS_STRING); + if (njs_slow_path(object == NULL)) { + return NJS_ERROR; + } + + njs_set_type_object(&string_obj, object, NJS_OBJECT_STRING); + + args->value = &string_obj; + } + else { + value = njs_object_value(value); + } + + length = njs_string_prop(&string_prop, value); + + p = string_prop.start; + end = p + string_prop.size; + + if ((size_t) length == string_prop.size) { + /* Byte or ASCII string. */ + + for (i = from; i < to; i++) { + /* This cannot fail. */ + (void) njs_string_new(vm, &character, p + i, 1, 1); + + ret = handler(vm, args, &character, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret == NJS_DONE) { + return NJS_DONE; + } + + return NJS_ERROR; + } + } + + } else { + /* UTF-8 string. */ + + for (i = from; i < to; i++) { + pos = njs_utf8_next(p, end); + + /* This cannot fail. */ + (void) njs_string_new(vm, &character, p, pos - p, 1); + + ret = handler(vm, args, &character, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret == NJS_DONE) { + return NJS_DONE; + } + + return NJS_ERROR; + } + + p = pos; + } + } + + return NJS_OK; } - njs_set_undefined(&vm->retval); - - return NJS_OK; -} - - -static njs_int_t -njs_array_handler_some(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, int64_t n) -{ - njs_int_t ret; - - if (njs_is_valid(entry)) { - ret = njs_array_iterator_call(vm, args, entry, n); + if (!njs_is_object(value)) { + return NJS_OK; + } + +process_object: + + if (!njs_fast_object(to - from)) { + keys = njs_array_indices(vm, value); + if (njs_slow_path(keys == NULL)) { + return NJS_ERROR; + } + + for (i = 0; i < keys->length; i++) { + idx = njs_string_to_index(&keys->start[i]); + + if (idx < from || idx >= to) { + continue; + } + + ret = njs_array_object_handler(vm, handler, args, &keys->start[i], + idx); + if (njs_slow_path(ret != NJS_OK)) { + njs_array_destroy(vm, keys); + return ret; + } + } + + njs_array_destroy(vm, keys); + + return NJS_OK; + } + + for (i = from; i < to; i++) { + ret = njs_array_object_handler(vm, handler, args, NULL, i); if (njs_slow_path(ret != NJS_OK)) { return ret; } - - if (njs_is_true(&vm->retval)) { - vm->retval = njs_value_true; - - return 1; - } - } - - return NJS_OK; -} - - -static njs_int_t -njs_array_prototype_some(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_int_t ret; - njs_array_iterator_args_t iargs; - - ret = njs_array_validate_args(vm, args, nargs, &iargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - ret = njs_array_iterator(vm, &iargs, njs_array_handler_some); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - if (ret != NJS_DECLINED) { - vm->retval = njs_value_false; } return NJS_OK; @@ -2755,8 +2292,29 @@ njs_array_handler_every(njs_vm_t *vm, nj if (!njs_is_true(&vm->retval)) { vm->retval = njs_value_false; - - return 1; + return NJS_DONE; + } + } + + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_some(njs_vm_t *vm, njs_array_iterator_args_t *args, + njs_value_t *entry, int64_t n) +{ + njs_int_t ret; + + if (njs_is_valid(entry)) { + ret = njs_array_iterator_call(vm, args, entry, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_is_true(&vm->retval)) { + vm->retval = njs_value_true; + return NJS_DONE; } } @@ -2765,24 +2323,17 @@ njs_array_handler_every(njs_vm_t *vm, nj static njs_int_t -njs_array_prototype_every(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) +njs_array_handler_includes(njs_vm_t *vm, njs_array_iterator_args_t *args, + njs_value_t *entry, int64_t n) { - njs_int_t ret; - njs_array_iterator_args_t iargs; - - ret = njs_array_validate_args(vm, args, nargs, &iargs); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + if (!njs_is_valid(entry)) { + entry = njs_value_arg(&njs_value_undefined); } - ret = njs_array_iterator(vm, &iargs, njs_array_handler_every); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - if (ret != NJS_DECLINED) { - vm->retval = njs_value_true; + if (njs_values_same_zero(args->argument, entry)) { + njs_set_true(&vm->retval); + + return NJS_DONE; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel