From d9aa966a44937f5846fe426644bb0aaa74fc64b3 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Mon, 19 Mar 2001 21:20:02 +0000 Subject: [PATCH] @- Added array_map() function that applies a callback to the elements @ of given arrays and returns the result. It can also be used with a @ null callback to transpose arrays. (Andrei) --- ext/standard/array.c | 113 ++++++++++++++++++++++++++++++++- ext/standard/basic_functions.c | 1 + ext/standard/php_array.h | 1 + 3 files changed, 114 insertions(+), 1 deletion(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 6b73339446..c3c7ca8d76 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2941,7 +2941,7 @@ PHP_FUNCTION(array_filter) } else zval_ptr_dtor(&retval); } else { - php_error(E_WARNING, "%s() had an error invoking the reduction callback", get_active_function_name()); + php_error(E_WARNING, "%s() had an error invoking the filter callback", get_active_function_name()); return; } } else if (!zend_is_true(*operand)) @@ -2964,6 +2964,117 @@ PHP_FUNCTION(array_filter) /* }}} */ +/* {{{ proto array array_map(mixed callback, array input1 [, array input2 ,...]) + Applies the callback to the elements in given arrays. */ +PHP_FUNCTION(array_map) +{ + zval ***args = NULL; + zval ***params; + zval *callback; + zval *result, *null; + char *callback_name; + int i, k, maxlen = 0; + int *array_len; + + if (ZEND_NUM_ARGS() < 2) { + WRONG_PARAM_COUNT; + } + + args = (zval ***)emalloc(ZEND_NUM_ARGS() * sizeof(zval **)); + if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + callback = *args[0]; + if (Z_TYPE_P(callback) != IS_NULL && !zend_is_callable(callback, 0, &callback_name)) { + php_error(E_WARNING, "%s() expects argument 1, '%s', to be either NULL or a valid callback", + get_active_function_name(), callback_name); + efree(callback_name); + efree(args); + return; + } + + /* Cache array sizes. */ + array_len = (int*)emalloc((ZEND_NUM_ARGS()-1) * sizeof(int)); + + /* Check that arrays are indeed arrays and calculate maximum size. */ + for (i = 0; i < ZEND_NUM_ARGS()-1; i++) { + if (Z_TYPE_PP(args[i+1]) != IS_ARRAY) { + php_error(E_WARNING, "%s() expects argument %d to be an array", + get_active_function_name(), i + 2); + efree(array_len); + efree(args); + return; + } + array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(args[i+1])); + if (array_len[i] > maxlen) + maxlen = array_len[i]; + } + + /* Short-circuit: if no callback and only one array, just return it. */ + if (Z_TYPE_P(callback) == IS_NULL && ZEND_NUM_ARGS() == 2) { + *return_value = **args[1]; + zval_copy_ctor(return_value); + efree(array_len); + efree(args); + return; + } + + array_init(return_value); + params = (zval ***)emalloc((ZEND_NUM_ARGS()-1) * sizeof(zval **)); + MAKE_STD_ZVAL(null); + ZVAL_NULL(null); + + /* We iterate through all the arrays at once. */ + for (k = 0; k < maxlen; k++) { + /* + * If no callback, the result will be an array, consisting of current + * entries from all arrays. + */ + if (Z_TYPE_P(callback) == IS_NULL) { + MAKE_STD_ZVAL(result); + array_init(result); + } + + for (i = 0; i < ZEND_NUM_ARGS()-1; i++) { + /* + * If this array still hash elements, add the current one to the + * parameter list, otherwise use null value. + */ + if (k < array_len[i]) { + zend_hash_index_find(Z_ARRVAL_PP(args[i+1]), k, (void **)¶ms[i]); + } else { + if (Z_TYPE_P(callback) == IS_NULL) + zval_add_ref(&null); + params[i] = &null; + } + + if (Z_TYPE_P(callback) == IS_NULL) + add_next_index_zval(result, *params[i]); + } + + if (Z_TYPE_P(callback) != IS_NULL) { + if (!call_user_function_ex(EG(function_table), NULL, callback, &result, ZEND_NUM_ARGS()-1, params, 0, NULL) == SUCCESS && result) { + php_error(E_WARNING, "%s() had an error invoking the map callback", get_active_function_name()); + efree(array_len); + efree(args); + zval_dtor(return_value); + RETURN_NULL(); + } + } + + add_next_index_zval(return_value, result); + } + + zval_ptr_dtor(&null); + efree(params); + efree(array_len); + efree(args); +} +/* }}} */ + + /* * Local variables: * tab-width: 4 diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index f8a1fca45a..bf2142d7e7 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -582,6 +582,7 @@ function_entry basic_functions[] = { PHP_FE(array_diff, NULL) PHP_FE(array_sum, NULL) PHP_FE(array_filter, NULL) + PHP_FE(array_map, NULL) /* aliases from array.c */ PHP_FALIAS(pos, current, first_arg_force_ref) diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 226574df92..fb00e2d08a 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -76,6 +76,7 @@ PHP_FUNCTION(array_intersect); PHP_FUNCTION(array_diff); PHP_FUNCTION(array_sum); PHP_FUNCTION(array_filter); +PHP_FUNCTION(array_map); HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **); PHPAPI void php_array_merge(HashTable *dest, HashTable *src, int recursive); -- 2.40.0