Skip to content

Commit 616b4d6

Browse files
committed
Add array_search_range() function
1 parent 98a259e commit 616b4d6

3 files changed

Lines changed: 109 additions & 0 deletions

File tree

ext/standard/array.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,68 @@ PHP_FUNCTION(array_search)
17261726
php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
17271727
}
17281728
/* }}} */
1729+
/* {{{ Searches a portion of the array for a given value and returns the corresponding key if successful */
1730+
PHP_FUNCTION(array_search_range)
1731+
{
1732+
zval *needle;
1733+
zend_array *array;
1734+
zend_long offset = 0;
1735+
zend_long length = 0;
1736+
bool strict = false;
1737+
zend_long max_count;
1738+
HashTable *ht;
1739+
zval *entry;
1740+
zend_string *key_str;
1741+
zend_ulong num_key;
1742+
zend_long i = 0;
1743+
bool found = false;
1744+
1745+
ZEND_PARSE_PARAMETERS_START(2, 5)
1746+
Z_PARAM_ZVAL(needle)
1747+
Z_PARAM_ARRAY_HT(array)
1748+
Z_PARAM_OPTIONAL
1749+
Z_PARAM_LONG(offset)
1750+
Z_PARAM_LONG(length)
1751+
Z_PARAM_BOOL(strict)
1752+
ZEND_PARSE_PARAMETERS_END();
1753+
1754+
ht = &array->ht;
1755+
1756+
if (offset < 0) {
1757+
offset += zend_hash_num_elements(ht);
1758+
if (offset < 0) {
1759+
offset = 0;
1760+
}
1761+
}
1762+
1763+
if (length < 0) {
1764+
php_error_docref(NULL, E_WARNING, "Length must be greater than or equal to zero");
1765+
RETURN_FALSE;
1766+
}
1767+
1768+
max_count = length ? length : zend_hash_num_elements(ht);
1769+
1770+
ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, key_str, entry) {
1771+
if (i >= offset && (i < offset + max_count)) {
1772+
if (strict ? zend_is_identical(needle, entry) : fast_equal_check_function(needle, entry)) {
1773+
found = true;
1774+
break;
1775+
}
1776+
}
1777+
i++;
1778+
} ZEND_HASH_FOREACH_END();
1779+
1780+
if (!found) {
1781+
RETURN_FALSE;
1782+
}
1783+
1784+
if (key_str) {
1785+
RETVAL_STR_COPY(key_str);
1786+
} else {
1787+
RETVAL_LONG(num_key);
1788+
}
1789+
}
1790+
/* }}} */
17291791

17301792
static zend_always_inline bool php_valid_var_name(const zend_string *var_name) /* {{{ */
17311793
{

ext/standard/basic_functions.stub.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,18 @@ function in_array(mixed $needle, array $haystack, bool $strict = false): bool {}
16411641
* @compile-time-eval
16421642
*/
16431643
function array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false {}
1644+
/**
1645+
* Searches a portion of the array for a given value and returns the first corresponding key if successful
1646+
* @param mixed $needle The value to search for
1647+
* @param array $haystack The array to search in
1648+
* @param int $offset Start searching from this position (0-indexed)
1649+
* @param ?int $length Limit the search to this many elements after $offset
1650+
* @param bool $strict Use strict comparison
1651+
* @return int|string|false The key for $needle if found, false otherwise
1652+
* @refcount 1
1653+
*/
1654+
function array_search_range(mixed $needle, array $haystack, int $offset = 0, ?int $length = null, bool $strict = false): int|string|false {}
1655+
16441656

16451657
/**
16461658
* @prefer-ref $array
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
array_search_range() function - basic test
3+
--FILE--
4+
<?php
5+
$array = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 2, 'e' => 1];
6+
7+
// Search from beginning
8+
var_dump(array_search_range(2, $array));
9+
10+
// Search with offset
11+
var_dump(array_search_range(2, $array, 2));
12+
13+
// Search with offset and length
14+
var_dump(array_search_range(2, $array, 0, 2));
15+
16+
// Search with strict comparison
17+
var_dump(array_search_range('2', $array, 0, null, true));
18+
19+
// Search with negative offset
20+
var_dump(array_search_range(1, $array, -2));
21+
22+
// Search with length
23+
var_dump(array_search_range(3, $array, 0, 3));
24+
25+
// Not found
26+
var_dump(array_search_range(10, $array));
27+
?>
28+
--EXPECT--
29+
string(1) "b"
30+
string(1) "d"
31+
string(1) "b"
32+
bool(false)
33+
string(1) "e"
34+
string(1) "c"
35+
bool(false)

0 commit comments

Comments
 (0)