From a88c7be88b57162eb0a89ff1b7c2ef60ac1de935 Mon Sep 17 00:00:00 2001 From: datibbaw Date: Thu, 21 Feb 2013 14:42:28 +0800 Subject: [PATCH 1/5] added use_keys argument to array_filter() --- ext/standard/array.c | 39 +++++++++-- .../tests/array/array_filter_error.phpt | 4 +- .../tests/array/array_filter_variation10.phpt | 70 +++++++++++++++++++ 3 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 ext/standard/tests/array/array_filter_variation10.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index ae6e5d266fa2..1f98ef16f209 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4194,9 +4194,11 @@ PHP_FUNCTION(array_filter) { zval *array; zval **operand; - zval **args[1]; + zval **args[2]; zval *retval = NULL; + zval *key = NULL; zend_bool have_callback = 0; + zend_bool use_key = 0; char *string_key; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; @@ -4204,7 +4206,7 @@ PHP_FUNCTION(array_filter) ulong num_key; HashPosition pos; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|f", &array, &fci, &fci_cache) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|fb", &array, &fci, &fci_cache, &use_key) == FAILURE) { return; } @@ -4217,23 +4219,52 @@ PHP_FUNCTION(array_filter) have_callback = 1; fci.no_separation = 0; fci.retval_ptr_ptr = &retval; - fci.param_count = 1; + + if (use_key) { + fci.param_count = 2; + args[1] = &key; + } else { + fci.param_count = 1; + } } for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS; zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos) ) { + int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos); + if (have_callback) { + if (use_key) { + MAKE_STD_ZVAL(key); + /* Set up the key */ + switch (key_type) { + case HASH_KEY_IS_LONG: + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = num_key; + break; + + case HASH_KEY_IS_STRING: + ZVAL_STRINGL(key, string_key, string_key_len - 1, 1); + break; + } + } + args[0] = operand; fci.params = args; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { if (!zend_is_true(retval)) { zval_ptr_dtor(&retval); + if (use_key) { + zval_ptr_dtor(&key); + } continue; } else { zval_ptr_dtor(&retval); + if (use_key) { + zval_ptr_dtor(&key); + } } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the filter callback"); @@ -4244,7 +4275,7 @@ PHP_FUNCTION(array_filter) } zval_add_ref(operand); - switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos)) { + switch (key_type) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, operand, sizeof(zval *), NULL); break; diff --git a/ext/standard/tests/array/array_filter_error.phpt b/ext/standard/tests/array/array_filter_error.phpt index 20e89aa4b776..3f8f51bc14a5 100644 --- a/ext/standard/tests/array/array_filter_error.phpt +++ b/ext/standard/tests/array/array_filter_error.phpt @@ -28,7 +28,7 @@ $extra_arg = 10; // with one more than the expected number of arguments echo "-- Testing array_filter() function with more than expected no. of arguments --"; -var_dump( array_filter($input, "odd", $extra_arg) ); +var_dump( array_filter($input, "odd", $extra_arg, $extra_arg) ); // with incorrect callback function echo "-- Testing array_filter() function with incorrect callback --"; @@ -42,7 +42,7 @@ echo "Done" Warning: array_filter() expects at least 1 parameter, 0 given in %s on line %d NULL -- Testing array_filter() function with more than expected no. of arguments -- -Warning: array_filter() expects at most 2 parameters, 3 given in %s on line %d +Warning: array_filter() expects at most 3 parameters, 4 given in %s on line %d NULL -- Testing array_filter() function with incorrect callback -- Warning: array_filter() expects parameter 2 to be a valid callback, function 'even' not found or invalid function name in %s on line %d diff --git a/ext/standard/tests/array/array_filter_variation10.phpt b/ext/standard/tests/array/array_filter_variation10.phpt new file mode 100644 index 000000000000..9a5b2a4a302f --- /dev/null +++ b/ext/standard/tests/array/array_filter_variation10.phpt @@ -0,0 +1,70 @@ +--TEST-- +Test array_filter() function : usage variations - using the array keys inside 'callback' +--FILE-- + 4; +} + +var_dump( array_filter($input, 'dump2', true) ); + +echo "*** Testing array_filter() : usage variations - 'callback' expecting second argument ***\n"; + +var_dump( array_filter($small, 'dump', false) ); + +echo "Done" +?> +--EXPECTF-- +*** Testing array_filter() : usage variations - using array keys in 'callback' *** +0 = 0 +1 = 1 +2 = -1 +3 = 10 +4 = 100 +5 = 1000 +6 = Hello +7 = +array(0) { +} +*** Testing array_filter() : usage variations - 'callback' filters based on key value *** +array(3) { + [5]=> + int(1000) + [6]=> + string(5) "Hello" + [7]=> + NULL +} +*** Testing array_filter() : usage variations - 'callback' expecting second argument *** + +Warning: Missing argument 2 for dump() in /home/tjerk/work/php/php-src/ext/standard/tests/array/array_filter_variation10.php on line %d + +Notice: Undefined variable: key in /home/tjerk/work/php/php-src/ext/standard/tests/array/array_filter_variation10.php on line %d + = 123 +array(0) { +} +Done From 6442e49b22da6dfab8ebcef1a4cf568250b1ee96 Mon Sep 17 00:00:00 2001 From: datibbaw Date: Thu, 21 Feb 2013 16:35:48 +0800 Subject: [PATCH 2/5] forgot introspection changes --- ext/standard/basic_functions.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 3e5084e83764..cb57d755b21a 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -595,6 +595,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_filter, 0, 0, 1) ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ ZEND_ARG_INFO(0, callback) + ZEND_ARG_INFO(0, use_keys) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_map, 0, 0, 2) From b8653d34579409131b8dc6d92e7ac30e28fa95a6 Mon Sep 17 00:00:00 2001 From: Tjerk Anne Meesters Date: Wed, 27 Feb 2013 21:20:28 +0800 Subject: [PATCH 3/5] fixed test case to pass on other systems than my own --- ext/standard/tests/array/array_filter_variation10.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/array/array_filter_variation10.phpt b/ext/standard/tests/array/array_filter_variation10.phpt index 9a5b2a4a302f..1eec4591a1fe 100644 --- a/ext/standard/tests/array/array_filter_variation10.phpt +++ b/ext/standard/tests/array/array_filter_variation10.phpt @@ -61,9 +61,9 @@ array(3) { } *** Testing array_filter() : usage variations - 'callback' expecting second argument *** -Warning: Missing argument 2 for dump() in /home/tjerk/work/php/php-src/ext/standard/tests/array/array_filter_variation10.php on line %d +Warning: Missing argument 2 for dump() in %s on line %d -Notice: Undefined variable: key in /home/tjerk/work/php/php-src/ext/standard/tests/array/array_filter_variation10.php on line %d +Notice: Undefined variable: key in %s on line %d = 123 array(0) { } From 0492145e58bda8fed9f64992a9b8d054d9c80758 Mon Sep 17 00:00:00 2001 From: datibbaw Date: Thu, 26 Sep 2013 11:10:24 +0800 Subject: [PATCH 4/5] added bitmask variation --- ext/standard/array.c | 36 +++++++++++-------- ext/standard/php_array.h | 4 +++ .../tests/array/array_filter_variation10.phpt | 35 +++++++++++++++++- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 1f98ef16f209..13148ec6f008 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -127,6 +127,10 @@ PHP_MINIT_FUNCTION(array) /* {{{ */ REGISTER_LONG_CONSTANT("COUNT_NORMAL", COUNT_NORMAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", COUNT_RECURSIVE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_BOTH", ARRAY_FILTER_USE_BOTH, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_KEY", ARRAY_FILTER_USE_KEY, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_VALUE", ARRAY_FILTER_USE_VALUE, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } /* }}} */ @@ -4198,7 +4202,7 @@ PHP_FUNCTION(array_filter) zval *retval = NULL; zval *key = NULL; zend_bool have_callback = 0; - zend_bool use_key = 0; + long use_type = ARRAY_FILTER_USE_VALUE; char *string_key; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; @@ -4206,7 +4210,7 @@ PHP_FUNCTION(array_filter) ulong num_key; HashPosition pos; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|fb", &array, &fci, &fci_cache, &use_key) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|fl", &array, &fci, &fci_cache, &use_type) == FAILURE) { return; } @@ -4220,11 +4224,14 @@ PHP_FUNCTION(array_filter) fci.no_separation = 0; fci.retval_ptr_ptr = &retval; - if (use_key) { + if (use_type == ARRAY_FILTER_USE_BOTH) { fci.param_count = 2; args[1] = &key; } else { fci.param_count = 1; + if (use_type == ARRAY_FILTER_USE_KEY) { + args[0] = &key; + } } } @@ -4235,7 +4242,7 @@ PHP_FUNCTION(array_filter) int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos); if (have_callback) { - if (use_key) { + if (use_type != ARRAY_FILTER_USE_VALUE) { MAKE_STD_ZVAL(key); /* Set up the key */ switch (key_type) { @@ -4250,21 +4257,20 @@ PHP_FUNCTION(array_filter) } } - args[0] = operand; + if (use_type != ARRAY_FILTER_USE_KEY) { + args[0] = operand; + } fci.params = args; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { - if (!zend_is_true(retval)) { - zval_ptr_dtor(&retval); - if (use_key) { - zval_ptr_dtor(&key); - } + int retval_true = zend_is_true(retval); + + zval_ptr_dtor(&retval); + if (use_type != ARRAY_FILTER_USE_VALUE) { + zval_ptr_dtor(&key); + } + if (!retval_true) { continue; - } else { - zval_ptr_dtor(&retval); - if (use_key) { - zval_ptr_dtor(&key); - } } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the filter callback"); diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 1cf27790718d..7d9733d2964f 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -117,6 +117,10 @@ PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); #define PHP_SORT_NATURAL 6 #define PHP_SORT_FLAG_CASE 8 +#define ARRAY_FILTER_USE_BOTH 1 +#define ARRAY_FILTER_USE_KEY 2 +#define ARRAY_FILTER_USE_VALUE 3 + ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; int (*compare_func)(zval *result, zval *op1, zval *op2 TSRMLS_DC); diff --git a/ext/standard/tests/array/array_filter_variation10.phpt b/ext/standard/tests/array/array_filter_variation10.phpt index 1eec4591a1fe..25698c55c2f6 100644 --- a/ext/standard/tests/array/array_filter_variation10.phpt +++ b/ext/standard/tests/array/array_filter_variation10.phpt @@ -2,7 +2,7 @@ Test array_filter() function : usage variations - using the array keys inside 'callback' --FILE-- 'a', 2 => 'b', 'a' => 1, 'b' => 2); + +var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_KEY)); + +var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_VALUE)); + +var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_BOTH)); + echo "Done" ?> --EXPECTF-- @@ -67,4 +77,27 @@ Notice: Undefined variable: key in %s on line %d = 123 array(0) { } +*** Testing array_filter() with various use types *** +array(2) { + [1]=> + string(1) "a" + [2]=> + string(1) "b" +} +array(2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +} + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 +array(0) { +} Done From 75ba75e2055d670e204e6361732995ba27b05896 Mon Sep 17 00:00:00 2001 From: Tjerk Meesters Date: Fri, 27 Sep 2013 07:42:33 +0800 Subject: [PATCH 5/5] Using only two constants to signal use type intent. --- ext/standard/array.c | 7 +++---- ext/standard/php_array.h | 1 - ext/standard/tests/array/array_filter_variation10.phpt | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 13148ec6f008..5968a41dd5f5 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -129,7 +129,6 @@ PHP_MINIT_FUNCTION(array) /* {{{ */ REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_BOTH", ARRAY_FILTER_USE_BOTH, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_KEY", ARRAY_FILTER_USE_KEY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_VALUE", ARRAY_FILTER_USE_VALUE, CONST_CS | CONST_PERSISTENT); return SUCCESS; } @@ -4202,7 +4201,7 @@ PHP_FUNCTION(array_filter) zval *retval = NULL; zval *key = NULL; zend_bool have_callback = 0; - long use_type = ARRAY_FILTER_USE_VALUE; + long use_type = 0; char *string_key; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; @@ -4242,7 +4241,7 @@ PHP_FUNCTION(array_filter) int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos); if (have_callback) { - if (use_type != ARRAY_FILTER_USE_VALUE) { + if (use_type) { MAKE_STD_ZVAL(key); /* Set up the key */ switch (key_type) { @@ -4266,7 +4265,7 @@ PHP_FUNCTION(array_filter) int retval_true = zend_is_true(retval); zval_ptr_dtor(&retval); - if (use_type != ARRAY_FILTER_USE_VALUE) { + if (use_type) { zval_ptr_dtor(&key); } if (!retval_true) { diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 7d9733d2964f..ef43cddfcc41 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -119,7 +119,6 @@ PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); #define ARRAY_FILTER_USE_BOTH 1 #define ARRAY_FILTER_USE_KEY 2 -#define ARRAY_FILTER_USE_VALUE 3 ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; diff --git a/ext/standard/tests/array/array_filter_variation10.phpt b/ext/standard/tests/array/array_filter_variation10.phpt index 25698c55c2f6..f0a6115f79cc 100644 --- a/ext/standard/tests/array/array_filter_variation10.phpt +++ b/ext/standard/tests/array/array_filter_variation10.phpt @@ -42,7 +42,7 @@ $mixed = array(1 => 'a', 2 => 'b', 'a' => 1, 'b' => 2); var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_KEY)); -var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_VALUE)); +var_dump(array_filter($mixed, 'is_numeric', 0)); var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_BOTH));