From a02eceb5c3e7c444dc60a96fe3117b0506c352dd Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 31 Mar 2025 16:06:39 +0200 Subject: [PATCH] Implement some internal functions in PHP --- ext/standard/array.c | 126 ------------------------- ext/standard/array.php | 37 ++++++++ ext/standard/basic_functions.stub.php | 8 -- ext/standard/basic_functions_arginfo.h | 24 +---- 4 files changed, 38 insertions(+), 157 deletions(-) create mode 100644 ext/standard/array.php diff --git a/ext/standard/array.c b/ext/standard/array.c index adb2a20d60388..d6a8c5bfd6ca9 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6580,132 +6580,6 @@ PHP_FUNCTION(array_filter) } /* }}} */ -/* {{{ Internal function to find an array element for a user closure. */ -enum php_array_find_result { - PHP_ARRAY_FIND_EXCEPTION = -1, - PHP_ARRAY_FIND_NONE = 0, - PHP_ARRAY_FIND_SOME = 1, -}; - -static enum php_array_find_result php_array_find(const HashTable *array, zend_fcall_info fci, zend_fcall_info_cache *fci_cache, zval *result_key, zval *result_value, bool negate_condition) -{ - zend_ulong num_key; - zend_string *str_key; - zval retval; - zval args[2]; - zval *operand; - - if (zend_hash_num_elements(array) == 0) { - return PHP_ARRAY_FIND_NONE; - } - - ZEND_ASSERT(ZEND_FCI_INITIALIZED(fci)); - - fci.retval = &retval; - fci.param_count = 2; - fci.params = args; - - ZEND_HASH_FOREACH_KEY_VAL(array, num_key, str_key, operand) { - /* Set up the key */ - if (!str_key) { - ZVAL_LONG(&args[1], num_key); - } else { - /* Allows copying the numeric branch, without this branch, into the iteration code - * that checks for the packed array flag. */ - ZEND_ASSUME(!HT_IS_PACKED(array)); - ZVAL_STR(&args[1], str_key); - } - - ZVAL_COPY_VALUE(&args[0], operand); - - zend_result result = zend_call_function(&fci, fci_cache); - ZEND_ASSERT(result == SUCCESS); - - if (UNEXPECTED(Z_ISUNDEF(retval))) { - return PHP_ARRAY_FIND_EXCEPTION; - } - - if (php_is_true(&retval) ^ negate_condition) { - if (result_value != NULL) { - ZVAL_COPY_DEREF(result_value, &args[0]); - } - - if (result_key != NULL) { - ZVAL_COPY(result_key, &args[1]); - } - - return PHP_ARRAY_FIND_SOME; - } - } ZEND_HASH_FOREACH_END(); - - return PHP_ARRAY_FIND_NONE; -} -/* }}} */ - -/* {{{ Search within an array and returns the first found element value. */ -PHP_FUNCTION(array_find) -{ - HashTable *array; - zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY_HT(array) - Z_PARAM_FUNC(fci, fci_cache) - ZEND_PARSE_PARAMETERS_END(); - - php_array_find(array, fci, &fci_cache, NULL, return_value, false); -} -/* }}} */ - -/* {{{ Search within an array and returns the first found element key. */ -PHP_FUNCTION(array_find_key) -{ - HashTable *array; - zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY_HT(array) - Z_PARAM_FUNC(fci, fci_cache) - ZEND_PARSE_PARAMETERS_END(); - - php_array_find(array, fci, &fci_cache, return_value, NULL, false); -} -/* }}} */ - -/* {{{ Checks if at least one array element satisfies a callback function. */ -PHP_FUNCTION(array_any) -{ - HashTable *array; - zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY_HT(array) - Z_PARAM_FUNC(fci, fci_cache) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_BOOL(php_array_find(array, fci, &fci_cache, NULL, NULL, false) == PHP_ARRAY_FIND_SOME); -} -/* }}} */ - -/* {{{ Checks if all array elements satisfy a callback function. */ -PHP_FUNCTION(array_all) -{ - HashTable *array; - zend_fcall_info fci; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; - - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ARRAY_HT(array) - Z_PARAM_FUNC(fci, fci_cache) - ZEND_PARSE_PARAMETERS_END(); - - RETURN_BOOL(php_array_find(array, fci, &fci_cache, NULL, NULL, true) == PHP_ARRAY_FIND_NONE); -} -/* }}} */ - /* {{{ Applies the callback to the elements in given arrays. */ PHP_FUNCTION(array_map) { diff --git a/ext/standard/array.php b/ext/standard/array.php new file mode 100644 index 0000000000000..bec74010bb797 --- /dev/null +++ b/ext/standard/array.php @@ -0,0 +1,37 @@ + $value) { + if ($callback($value, $key)) { + return $value; + } + } +} + +function array_find_key(array $array, callable $callback): mixed { + foreach ($array as $key => $value) { + if ($callback($value, $key)) { + return $key; + } + } +} + +function array_any(array $array, callable $callback): bool { + foreach ($array as $key => $value) { + if ($callback($value, $key)) { + return true; + } + } + + return false; +} + +function array_all(array $array, callable $callback): bool { + foreach ($array as $key => $value) { + if (!$callback($value, $key)) { + return false; + } + } + + return true; +} diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index e7f4ff8844714..9802b80c979fc 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1877,14 +1877,6 @@ 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): mixed {} - -function array_find_key(array $array, callable $callback): mixed {} - -function array_any(array $array, callable $callback): bool {} - -function array_all(array $array, callable $callback): bool {} - function array_map(?callable $callback, array $array, array ...$arrays): array {} /** diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 3d92288643159..43c172340a95f 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 85677dc3476d25b7820fd3a26fe39f2e9378b6e7 */ + * Stub hash: 6c0a4f7019317d46630960ec79f0aa0ff8b130c3 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -336,20 +336,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_filter, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_find, 0, 2, IS_MIXED, 0) - ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) -ZEND_END_ARG_INFO() - -#define arginfo_array_find_key arginfo_array_find - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_any, 0, 2, _IS_BOOL, 0) - ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) -ZEND_END_ARG_INFO() - -#define arginfo_array_all arginfo_array_any - ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_map, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 1) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) @@ -2380,10 +2366,6 @@ ZEND_FUNCTION(array_sum); ZEND_FUNCTION(array_product); ZEND_FUNCTION(array_reduce); ZEND_FUNCTION(array_filter); -ZEND_FUNCTION(array_find); -ZEND_FUNCTION(array_find_key); -ZEND_FUNCTION(array_any); -ZEND_FUNCTION(array_all); ZEND_FUNCTION(array_map); ZEND_FUNCTION(array_key_exists); ZEND_FUNCTION(array_chunk); @@ -2973,10 +2955,6 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("array_product", zif_array_product, arginfo_array_product, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_FE(array_reduce, arginfo_array_reduce) ZEND_FE(array_filter, arginfo_array_filter) - ZEND_FE(array_find, arginfo_array_find) - ZEND_FE(array_find_key, arginfo_array_find_key) - ZEND_FE(array_any, arginfo_array_any) - ZEND_FE(array_all, arginfo_array_all) ZEND_FE(array_map, arginfo_array_map) ZEND_RAW_FENTRY("array_key_exists", zif_array_key_exists, arginfo_array_key_exists, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("key_exists", zif_array_key_exists, arginfo_key_exists, 0, NULL, NULL)