diff options
author | Andrei Zmievski <andrei@php.net> | 2001-03-12 03:06:53 +0000 |
---|---|---|
committer | Andrei Zmievski <andrei@php.net> | 2001-03-12 03:06:53 +0000 |
commit | d73ef1242986f84a7bb9e6fa088f19d4f22b05dc (patch) | |
tree | 9c64de3a3ae754aab5226d151403886c5896e4a4 /ext/standard/array.c | |
parent | 2d54fb39b957cc0ca973d0cbb5d1869567c2df76 (diff) | |
download | php-git-d73ef1242986f84a7bb9e6fa088f19d4f22b05dc.tar.gz |
@- Added array_reduce(), which allows iterative reduction of an array
@ to a single value via a callback function. (Andrei)
- Added array_reduce(), which allows iterative reduction of an array
to a single value via a callback function.
- Fixed usage of zend_is_callable() in PCRE.
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r-- | ext/standard/array.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index 4538b6bc14..7dcf6b7ebb 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2815,6 +2815,66 @@ PHP_FUNCTION(array_sum) /* }}} */ +/* {{{ proto mixed array_reduce(array input, mixed callback [, int initial]) + Reduce the array by calling the callback */ +PHP_FUNCTION(array_reduce) +{ + zval **input, **callback, **initial; + zval **args[2]; + zval **operand; + zval *result = NULL; + zval *retval; + char *callback_name; + + if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 || + zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &callback, &initial) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if (Z_TYPE_PP(input) != IS_ARRAY) { + php_error(E_WARNING, "%s() expects argument 1 to be an array", + get_active_function_name()); + return; + } + + if (!zend_is_callable(*callback, 0, &callback_name)) { + php_error(E_WARNING, "%s() expects argument 2, '%s', to be a valid callback", + get_active_function_name(), callback_name); + efree(callback_name); + return; + } + + if (ZEND_NUM_ARGS() > 2) + result = *initial; + + if (zend_hash_num_elements(Z_ARRVAL_PP(input)) == 0) { + if (result) { + *return_value = *result; + zval_copy_ctor(return_value); + } + return; + } + + zend_hash_internal_pointer_reset(Z_ARRVAL_PP(input)); + while (zend_hash_get_current_data(Z_ARRVAL_PP(input), (void **)&operand) == SUCCESS) { + if (result) { + args[0] = &result; + args[1] = operand; + if (call_user_function_ex(EG(function_table), NULL, *callback, &retval, 2, args, 0, NULL) == SUCCESS && retval) { + result = retval; + } else { + php_error(E_WARNING, "%s() had an error invoking the reduction callback", get_active_function_name()); + return; + } + } else + result = *operand; + + zend_hash_move_forward(Z_ARRVAL_PP(input)); + } + + *return_value = *result; +} + /* * Local variables: * tab-width: 4 |