Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) /* {{{ */
{
Expand Down
12 changes: 12 additions & 0 deletions ext/standard/basic_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 35 additions & 0 deletions ext/standard/tests/array/array_search_range.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
array_search_range() function - basic test
--FILE--
<?php
$array = ['a' => 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)
Loading