diff options
Diffstat (limited to 'src/njs_string.c')
-rw-r--r-- | src/njs_string.c | 148 |
1 files changed, 122 insertions, 26 deletions
diff --git a/src/njs_string.c b/src/njs_string.c index 6d7c464d..1a2b2333 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -601,56 +601,152 @@ njs_int_t njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - u_char *p, *start; - uint64_t size, length, mask; + char *np, *np_end; + double num; + u_char *p; + uint64_t sz, size, length; njs_int_t ret; njs_uint_t i; njs_string_prop_t string; + char buf[512]; + +#define NJS_SZ_LAST 64 if (njs_is_null_or_undefined(&args[0])) { njs_type_error(vm, "\"this\" argument is null or undefined"); return NJS_ERROR; } + size = 0; + length = 0; + + np = buf; + np_end = buf + sizeof(buf); + *np = 0; + for (i = 0; i < nargs; i++) { - if (!njs_is_string(&args[i])) { - ret = njs_value_to_string(vm, &args[i], &args[i]); - if (ret != NJS_OK) { - return ret; + if (njs_is_number(&args[i])) { + num = njs_number(&args[i]); + + if (isnan(num)) { + size += njs_length("NaN"); + length += njs_length("NaN"); + + } else if (isinf(num)) { + if (num < 0) { + size += njs_length("-Infinity"); + length += njs_length("-Infinity"); + + } else { + size += njs_length("Infinity"); + length += njs_length("Infinity"); + } + + } else { + sz = njs_dtoa(num, np + sizeof(uint8_t)); + + if (*np == 0) { + if (np + sizeof(uint8_t) + sz + < np_end - NJS_DTOA_MAX_LEN - sizeof(uint8_t)) + { + *np = (uint8_t) sz; + np += sizeof(uint8_t) + sz; + *np = 0; + + } else { + *np = NJS_SZ_LAST; + } + } + + size += sz; + length += sz; + } + + } else if (njs_is_boolean(&args[i])) { + if (njs_is_true(&args[i])) { + size += njs_length("true"); + length += njs_length("true"); + } else { + size += njs_length("false"); + length += njs_length("false"); + } + + } else if (njs_is_null(&args[i])) { + size += njs_length("null"); + length += njs_length("null"); + + } else if (njs_is_undefined(&args[i])) { + size += njs_length("undefined"); + length += njs_length("undefined"); + + } else { + if (!njs_is_string(&args[i])) { + ret = njs_value_to_string(vm, &args[i], &args[i]); + if (ret != NJS_OK) { + return ret; + } + } + + njs_string_prop(vm, &string, &args[i]); + + size += string.size; + length += string.length; } } - if (nargs == 1) { - njs_string_copy(retval, &args[0]); - return NJS_OK; + p = njs_string_alloc(vm, retval, size, length); + if (njs_slow_path(p == NULL)) { + return NJS_ERROR; } - size = 0; - length = 0; - mask = -1; + np = buf; for (i = 0; i < nargs; i++) { - (void) njs_string_prop(vm, &string, &args[i]); + if (njs_is_number(&args[i])) { + num = njs_number(&args[i]); - size += string.size; - length += string.length; - } + if (isnan(num)) { + p = njs_cpymem(p, "NaN", njs_length("NaN")); - length &= mask; + } else if (isinf(num)) { + if (num < 0) { + p = njs_cpymem(p, "-Infinity", njs_length("-Infinity")); - start = njs_string_alloc(vm, retval, size, length); - if (njs_slow_path(start == NULL)) { - return NJS_ERROR; - } + } else { + p = njs_cpymem(p, "Infinity", njs_length("Infinity")); + } - p = start; + } else { + if (*np != NJS_SZ_LAST) { + sz = *np++; + p = njs_cpymem(p, np, sz); + np += sz; - for (i = 0; i < nargs; i++) { - (void) njs_string_prop(vm, &string, &args[i]); + } else { + sz = njs_dtoa(num, (char *) p); + p += sz; + } + } - p = memcpy(p, string.start, string.size); - p += string.size; + } else if (njs_is_boolean(&args[i])) { + if (njs_is_true(&args[i])) { + p = njs_cpymem(p, "true", njs_length("true")); + } else { + p = njs_cpymem(p, "false", njs_length("false")); + } + + } else if (njs_is_null(&args[i])) { + p = njs_cpymem(p, "null", njs_length("null")); + + } else if (njs_is_undefined(&args[i])) { + p = njs_cpymem(p, "undefined", njs_length("undefined")); + + } else { + njs_string_prop(vm, &string, &args[i]); + + p = njs_cpymem(p, string.start, string.size); + } } return NJS_OK; |