From 616b4d600efb4404ea723d081ca6612a891b5f45 Mon Sep 17 00:00:00 2001 From: Sepehr Date: Sun, 16 Aug 2026 21:46:47 +0330 Subject: [PATCH] Add array_search_range() function --- ext/standard/array.c | 62 +++++++++++++++++++ ext/standard/basic_functions.stub.php | 12 ++++ .../tests/array/array_search_range.phpt | 35 +++++++++++ 3 files changed, 109 insertions(+) create mode 100644 ext/standard/tests/array/array_search_range.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index 648b48479099..0195377dfc61 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1726,6 +1726,68 @@ PHP_FUNCTION(array_search) php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ +/* {{{ Searches a portion of the array for a given value and returns the corresponding key if successful */ +PHP_FUNCTION(array_search_range) +{ + zval *needle; + zend_array *array; + zend_long offset = 0; + zend_long length = 0; + bool strict = false; + zend_long max_count; + HashTable *ht; + zval *entry; + zend_string *key_str; + zend_ulong num_key; + zend_long i = 0; + bool found = false; + + ZEND_PARSE_PARAMETERS_START(2, 5) + Z_PARAM_ZVAL(needle) + Z_PARAM_ARRAY_HT(array) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(offset) + Z_PARAM_LONG(length) + Z_PARAM_BOOL(strict) + ZEND_PARSE_PARAMETERS_END(); + + ht = &array->ht; + + if (offset < 0) { + offset += zend_hash_num_elements(ht); + if (offset < 0) { + offset = 0; + } + } + + if (length < 0) { + php_error_docref(NULL, E_WARNING, "Length must be greater than or equal to zero"); + RETURN_FALSE; + } + + max_count = length ? length : zend_hash_num_elements(ht); + + ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, key_str, entry) { + if (i >= offset && (i < offset + max_count)) { + if (strict ? zend_is_identical(needle, entry) : fast_equal_check_function(needle, entry)) { + found = true; + break; + } + } + i++; + } ZEND_HASH_FOREACH_END(); + + if (!found) { + RETURN_FALSE; + } + + if (key_str) { + RETVAL_STR_COPY(key_str); + } else { + RETVAL_LONG(num_key); + } +} +/* }}} */ static zend_always_inline bool php_valid_var_name(const zend_string *var_name) /* {{{ */ { diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index c87e22433400..d2b5312fc336 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1641,6 +1641,18 @@ function in_array(mixed $needle, array $haystack, bool $strict = false): bool {} * @compile-time-eval */ function array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false {} +/** + * Searches a portion of the array for a given value and returns the first corresponding key if successful + * @param mixed $needle The value to search for + * @param array $haystack The array to search in + * @param int $offset Start searching from this position (0-indexed) + * @param ?int $length Limit the search to this many elements after $offset + * @param bool $strict Use strict comparison + * @return int|string|false The key for $needle if found, false otherwise + * @refcount 1 + */ +function array_search_range(mixed $needle, array $haystack, int $offset = 0, ?int $length = null, bool $strict = false): int|string|false {} + /** * @prefer-ref $array diff --git a/ext/standard/tests/array/array_search_range.phpt b/ext/standard/tests/array/array_search_range.phpt new file mode 100644 index 000000000000..003f1fa69573 --- /dev/null +++ b/ext/standard/tests/array/array_search_range.phpt @@ -0,0 +1,35 @@ +--TEST-- +array_search_range() function - basic test +--FILE-- + 1, 'b' => 2, 'c' => 3, 'd' => 2, 'e' => 1]; + +// Search from beginning +var_dump(array_search_range(2, $array)); + +// Search with offset +var_dump(array_search_range(2, $array, 2)); + +// Search with offset and length +var_dump(array_search_range(2, $array, 0, 2)); + +// Search with strict comparison +var_dump(array_search_range('2', $array, 0, null, true)); + +// Search with negative offset +var_dump(array_search_range(1, $array, -2)); + +// Search with length +var_dump(array_search_range(3, $array, 0, 3)); + +// Not found +var_dump(array_search_range(10, $array)); +?> +--EXPECT-- +string(1) "b" +string(1) "d" +string(1) "b" +bool(false) +string(1) "e" +string(1) "c" +bool(false)