njs_ret_t njs_array_function(njs_vm_t *vm, njs_param_t *param) { double num; uint32_t size; njs_value_t *value, *args; njs_array_t *array; args = param->args; size = param->nargs; if (size == 1 && njs_is_number(&args[0])) { num = args[0].data.u.number; size = (uint32_t) num; if ((double) size != num) { vm->exception = &njs_exception_range_error; return NXT_ERROR; } args = NULL; } array = njs_array_alloc(vm, size, NJS_ARRAY_SPARE); if (nxt_fast_path(array != NULL)) { vm->retval.data.u.array = array; value = array->start; if (args == NULL) { while (size != 0) { njs_set_invalid(value); value++; size--; } } else { while (size != 0) { njs_retain(args); *value++ = *args++; size--; } } vm->retval.type = NJS_ARRAY; vm->retval.data.truth = 1; return NXT_OK; } return NXT_ERROR; }
static njs_ret_t njs_array_prototype_concat(njs_vm_t *vm, njs_param_t *param) { size_t length; uintptr_t nargs; nxt_uint_t i; njs_value_t *object, *args, *value; njs_array_t *array; object = param->object; if (njs_is_array(object)) { length = object->data.u.array->length; } else { length = 1; } nargs = param->nargs; args = param->args; for (i = 0; i < nargs; i++) { if (njs_is_array(&args[i])) { length += args[i].data.u.array->length; } else { length++; } } array = njs_array_alloc(vm, length, NJS_ARRAY_SPARE); if (nxt_slow_path(array == NULL)) { return NXT_ERROR; } vm->retval.data.u.array = array; vm->retval.type = NJS_ARRAY; vm->retval.data.truth = 1; value = njs_array_copy(array->start, object); for (i = 0; i < nargs; i++) { value = njs_array_copy(value, &args[i]); } return NXT_OK; }
njs_value_t * njs_array_add(njs_vm_t *vm, njs_value_t *value, u_char *start, size_t size) { njs_ret_t ret; njs_array_t *array; if (value != NULL) { array = value->data.u.array; if (array->size == array->length) { ret = njs_array_realloc(vm, array, 0, array->size + 1); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } } } else { value = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t), sizeof(njs_value_t)); if (nxt_slow_path(value == NULL)) { return NULL; } array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE); if (nxt_slow_path(array == NULL)) { return NULL; } value->data.u.array = array; value->type = NJS_ARRAY; value->data.truth = 1; } ret = njs_string_create(vm, &array->start[array->length++], start, size, 0); if (nxt_fast_path(ret == NXT_OK)) { return value; } return NULL; }
static njs_ret_t njs_array_prototype_slice(njs_vm_t *vm, njs_param_t *param) { int32_t start, end, length; uint32_t n; uintptr_t nargs; njs_array_t *array; njs_value_t *object, *args, *value; start = 0; length = 0; object = param->object; if (njs_is_array(object)) { length = object->data.u.array->length; nargs = param->nargs; if (nargs != 0) { args = param->args; start = njs_value_to_number(&args[0]); if (start < 0) { start += length; if (start < 0) { start = 0; } } end = length; if (nargs > 1) { end = njs_value_to_number(&args[1]); if (end < 0) { end += length; } } length = end - start; if (length < 0) { start = 0; length = 0; } } } array = njs_array_alloc(vm, length, NJS_ARRAY_SPARE); if (nxt_slow_path(array == NULL)) { return NXT_ERROR; } vm->retval.data.u.array = array; vm->retval.type = NJS_ARRAY; vm->retval.data.truth = 1; if (length != 0) { value = object->data.u.array->start; n = 0; do { /* GC: retain long string and object in values[start]. */ array->start[n++] = value[start++]; length--; } while (length != 0); } return NXT_OK; }
static njs_ret_t njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp, u_char *string, nxt_regex_match_data_t *match_data, nxt_uint_t utf8) { int *captures; u_char *start; int32_t size, length; njs_ret_t ret; nxt_uint_t i, n; njs_array_t *array; njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; static const njs_value_t njs_string_index = njs_string("index"); static const njs_value_t njs_string_input = njs_string("input"); array = njs_array_alloc(vm, regexp->pattern->ncaptures, 0); if (nxt_slow_path(array == NULL)) { goto fail; } captures = nxt_regex_captures(match_data); for (i = 0; i < regexp->pattern->ncaptures; i++) { n = 2 * i; if (captures[n] != -1) { start = &string[captures[n]]; size = captures[n + 1] - captures[n]; switch (utf8) { case 0: length = 0; break; case 1: length = size; break; default: length = nxt_utf8_length(start, size); break; } ret = njs_regexp_string_create(vm, &array->start[i], start, size, length); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } } else { array->start[i] = njs_value_void; } } prop = njs_object_prop_alloc(vm, &njs_string_index); if (nxt_slow_path(prop == NULL)) { goto fail; } /* TODO: Non UTF-8 position */ njs_number_set(&prop->value, regexp->last_index + captures[0]); if (regexp->pattern->global) { regexp->last_index += captures[1]; } lhq.key_hash = NJS_INDEX_HASH; lhq.key.len = sizeof("index") - 1; lhq.key.data = (u_char *) "index"; lhq.replace = 0; lhq.value = prop; lhq.pool = vm->mem_cache_pool; lhq.proto = &njs_object_hash_proto; ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } prop = njs_object_prop_alloc(vm, &njs_string_input); if (nxt_slow_path(prop == NULL)) { goto fail; } njs_string_copy(&prop->value, ®exp->string); lhq.key_hash = NJS_INPUT_HASH; lhq.key.len = sizeof("input") - 1; lhq.key.data = (u_char *) "input"; lhq.value = prop; ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); if (nxt_fast_path(ret == NXT_OK)) { vm->retval.data.u.array = array; vm->retval.type = NJS_ARRAY; vm->retval.data.truth = 1; ret = NXT_OK; goto done; } fail: ret = NXT_ERROR; done: nxt_regex_match_data_free(match_data, vm->regex_context); return ret; }