]> git.kaiwu.me - njs.git/commitdiff
Introduced StringIndexOf().
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 30 Jun 2020 15:36:31 +0000 (15:36 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Tue, 30 Jun 2020 15:36:31 +0000 (15:36 +0000)
src/njs_string.c

index c57b278d52724ac6842420921dcf96e3cb89ee95..5c2997bed98331367db06a4690221a50926c0c3d 100644 (file)
@@ -1981,98 +1981,99 @@ range_error:
 }
 
 
-static njs_int_t
-njs_string_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
-    njs_index_t unused)
+static int64_t
+njs_string_index_of(njs_string_prop_t *string, njs_string_prop_t *search,
+    size_t from)
 {
-    int64_t            index, length, search_length;
-    njs_int_t          ret;
-    njs_value_t        *value;
-    const u_char       *p, *end;
-    njs_string_prop_t  string, search;
-
-    ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0));
-    if (njs_slow_path(ret != NJS_OK)) {
-        return ret;
-    }
+    size_t        index, length, search_length;
+    const u_char  *p, *end;
 
-    if (nargs > 1) {
-        length = njs_string_prop(&string, njs_argument(args, 0));
+    length = (string->length == 0) ? string->size : string->length;
 
-        value = njs_argument(args, 1);
+    if (njs_slow_path(search->size == 0)) {
+        return (from < length) ? from : length;
+    }
 
-        if (njs_slow_path(!njs_is_string(value))) {
-            ret = njs_value_to_string(vm, value, value);
-            if (njs_slow_path(ret != NJS_OK)) {
-                return ret;
-            }
-        }
+    index = from;
+    search_length = (search->length == 0) ? search->size : search->length;
 
-        search_length = njs_string_prop(&search, value);
+    if (length - index >= search_length) {
+        end = string->start + string->size;
 
-        index = 0;
+        if (string->size == length) {
+            /* Byte or ASCII string. */
 
-        if (nargs > 2) {
-            value = njs_argument(args, 2);
+            end -= (search->size - 1);
 
-            if (njs_slow_path(!njs_is_number(value))) {
-                ret = njs_value_to_integer(vm, value, &index);
-                if (njs_slow_path(ret != NJS_OK)) {
-                    return ret;
+            for (p = string->start + index; p < end; p++) {
+                if (memcmp(p, search->start, search->size) == 0) {
+                    return index;
                 }
 
-            } else {
-                index = njs_number_to_integer(njs_number(value));
+                index++;
             }
 
-            if (index < 0) {
-                index = 0;
-            }
-        }
+        } else {
+            /* UTF-8 string. */
 
-        if (length - index >= search_length) {
-            end = string.start + string.size;
+            p = njs_string_offset(string->start, end, index);
+            end -= search->size - 1;
 
-            if (string.size == (size_t) length) {
-                /* Byte or ASCII string. */
+            while (p < end) {
+                if (memcmp(p, search->start, search->size) == 0) {
+                    return index;
+                }
 
-                end -= (search.size - 1);
+                index++;
+                p = njs_utf8_next(p, end);
+            }
+        }
+    }
 
-                for (p = string.start + index; p < end; p++) {
-                    if (memcmp(p, search.start, search.size) == 0) {
-                        goto done;
-                    }
+    return -1;
+}
 
-                    index++;
-                }
 
-            } else {
-                /* UTF-8 string. */
+static njs_int_t
+njs_string_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+    njs_index_t unused)
+{
+    int64_t            from;
+    njs_int_t          ret;
+    njs_value_t        *this, *search, *pos, search_lvalue, pos_lvalue;
+    njs_string_prop_t  string, s;
 
-                p = njs_string_offset(string.start, end, index);
-                end -= search.size - 1;
+    this = njs_argument(args, 0);
 
-                while (p < end) {
-                    if (memcmp(p, search.start, search.size) == 0) {
-                        goto done;
-                    }
+    if (njs_slow_path(njs_is_null_or_undefined(this))) {
+        njs_type_error(vm, "cannot convert \"%s\"to object",
+                       njs_type_string(this->type));
+        return NJS_ERROR;
+    }
 
-                    index++;
-                    p = njs_utf8_next(p, end);
-                }
-            }
+    ret = njs_value_to_string(vm, this, this);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
 
-        } else if (search.size == 0) {
-            index = length;
-            goto done;
-        }
+    search = njs_lvalue_arg(&search_lvalue, args, nargs, 1);
+    ret = njs_value_to_string(vm, search, search);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
     }
 
-    index = -1;
+    pos = njs_lvalue_arg(&pos_lvalue, args, nargs, 2);
+    ret = njs_value_to_integer(vm, pos, &from);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
+    }
 
-done:
+    (void) njs_string_prop(&string, this);
+    (void) njs_string_prop(&s, search);
 
-    njs_set_number(&vm->retval, index);
+    from = njs_min(njs_max(from, 0), (int64_t) string.length);
+
+    njs_set_number(&vm->retval, njs_string_index_of(&string, &s, from));
 
     return NJS_OK;
 }