Skip to content

Commit

Permalink
Add array_find function
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuaruesweg committed Mar 31, 2024
1 parent 4d7e3fc commit 9f3fc25
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 0 deletions.
72 changes: 72 additions & 0 deletions ext/standard/array.c
Expand Up @@ -6581,6 +6581,78 @@ PHP_FUNCTION(array_filter)
}
/* }}} */

/* {{{ Search within an array and returns the first found element. */
PHP_FUNCTION(array_find)
{
zval *array = NULL;
zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
zend_ulong num_key;
zend_string *str_key;
zval retval;
zval *key;
zval args[2];
zval *operand;
bool return_array_key = 0;

ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_ARRAY(array)
Z_PARAM_FUNC(fci, fci_cache)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(return_array_key)
ZEND_PARSE_PARAMETERS_END();

if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
RETURN_NULL();
}

if (ZEND_FCI_INITIALIZED(fci)) {
fci.retval = &retval;
fci.param_count = 2;
key = &args[1];
}

ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, str_key, operand) {
/* Set up the key */
if (!str_key) {
ZVAL_LONG(key, num_key);
} else {
ZVAL_STR_COPY(key, str_key);
}

ZVAL_COPY(&args[0], operand);
fci.params = args;

if (zend_call_function(&fci, &fci_cache) == SUCCESS) {
int retval_true;

zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&args[1]);

retval_true = zend_is_true(&retval);
zval_ptr_dtor(&retval);
if (retval_true) {
if (return_array_key) {
ZVAL_COPY(return_value, &args[1]);
} else {
ZVAL_COPY(return_value, &args[0]);
}

return;
}
} else {
zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&args[1]);
return;
}
} ZEND_HASH_FOREACH_END();

if (return_value == NULL) {
RETURN_NULL();
}
}
/* }}} */

/* {{{ Applies the callback to the elements in given arrays. */
PHP_FUNCTION(array_map)
{
Expand Down
2 changes: 2 additions & 0 deletions ext/standard/basic_functions.stub.php
Expand Up @@ -1897,6 +1897,8 @@ function array_reduce(array $array, callable $callback, mixed $initial = null):

function array_filter(array $array, ?callable $callback = null, int $mode = 0): array {}

function array_find(array $array, callable $callback, bool $return_array_key = false): mixed {}

function array_map(?callable $callback, array $array, array ...$arrays): array {}

/**
Expand Down
8 changes: 8 additions & 0 deletions ext/standard/basic_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions ext/standard/tests/array/array_find_basic.phpt
@@ -0,0 +1,35 @@
--TEST--
basic array_find test
--FILE--
<?php
$array1 = [
"a" => 1,
"b" => 2,
"c" => 3,
"d" => 4,
"e" => 5,
];
$array2 = [
1, 2, 3, 4, 5
];

var_dump(array_find($array1, fn($value) => $value > 3));
var_dump(array_find($array1, fn($value) => $value > 3, true));
var_dump(array_find($array2, fn($value) => $value > 3));
var_dump(array_find($array2, fn($value) => $value > 5));
var_dump(array_find([], fn($value) => true));
var_dump(array_find($array1, fn($value, $key) => $key === "c"));
var_dump(array_find($array1, fn($value, $key) => $key === "c", true));
var_dump(array_find($array1, fn($value, $key) => false));
var_dump(array_find($array1, fn($value, $key) => false, true));
?>
--EXPECT--
int(4)
string(1) "d"
int(4)
NULL
NULL
int(3)
string(1) "c"
NULL
NULL

0 comments on commit 9f3fc25

Please sign in to comment.