From c6aff1236a12e9704b3b2dc2c83e27dd09eee5c8 Mon Sep 17 00:00:00 2001 From: Tjerk Meesters Date: Sat, 1 Feb 2014 07:22:30 +0800 Subject: [PATCH] Added array_usearch() --- ext/standard/array.c | 72 ++++++++++++++++++++++++++++++++++ ext/standard/basic_functions.c | 6 +++ ext/standard/php_array.h | 4 ++ 3 files changed, 82 insertions(+) diff --git a/ext/standard/array.c b/ext/standard/array.c index 47f21745778dc..b9cf6d550e227 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -130,6 +130,9 @@ 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_USEARCH_USE_KEY", ARRAY_USEARCH_USE_KEY, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_USEARCH_INVERT", ARRAY_USEARCH_INVERT, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } /* }}} */ @@ -1228,6 +1231,75 @@ PHP_FUNCTION(array_search) } /* }}} */ +PHP_FUNCTION(array_usearch) +{ + HashTable *array; + HashPosition pos; + + zend_fcall_info fci; + zend_fcall_info_cache fcc; + zval **args[2], *retval, *key = NULL, **entry; + + int flags = 0, xor_mask = 0; + zend_bool use_keys = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Hf|l", &array, &fci, &fcc, &flags) == FAILURE) { + return; + } + + if (flags & ARRAY_USEARCH_USE_KEY) { + fci.param_count = 2; + MAKE_STD_ZVAL(key); + args[1] = &key; + + use_keys = 1; + } else { + fci.param_count = 1; + } + + if (flags & ARRAY_USEARCH_INVERT) { + xor_mask = 1; + } + + fci.params = args; + fci.no_separation = 0; + fci.retval_ptr_ptr = &retval; + + zend_hash_internal_pointer_reset_ex(array, &pos); + while (zend_hash_get_current_data_ex(array, (void **)&entry, &pos) == SUCCESS) { + zend_bool found = 0; + + args[0] = entry; + if (use_keys) { + zend_hash_get_current_key_zval_ex(array, key, &pos); + } + + if (zend_call_function(&fci, &fcc TSRMLS_CC) == SUCCESS) { + found = zend_is_true(retval TSRMLS_CC) ^ xor_mask; + zval_ptr_dtor(&retval); + } else { + break; + } + + if (found) { + if (use_keys) { + RETURN_ZVAL(key, 0, 1); + } else { + zend_hash_get_current_key_zval_ex(array, return_value, &pos); + return; + } + } + + zend_hash_move_forward_ex(array, &pos); + } + + if (use_keys) { + zval_ptr_dtor(&key); + } + + RETURN_FALSE; +} + static int php_valid_var_name(char *var_name, int var_name_len) /* {{{ */ { int i, ch; diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 33f13649cc146..2cac35e1fb50f 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -320,6 +320,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_array_walk_recursive, 0, 0, 2) ZEND_ARG_INFO(0, userdata) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_array_usearch, 0, 0, 2) + ZEND_ARG_INFO(0, input) + ZEND_ARG_INFO(0, callback_search_func) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_in_array, 0, 0, 2) ZEND_ARG_INFO(0, needle) ZEND_ARG_INFO(0, haystack) /* ARRAY_INFO(0, haystack, 0) */ @@ -3311,6 +3316,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(key, arginfo_key) PHP_FE(min, arginfo_min) PHP_FE(max, arginfo_max) + PHP_FE(array_usearch, arginfo_array_usearch) PHP_FE(in_array, arginfo_in_array) PHP_FE(array_search, arginfo_array_search) PHP_FE(extract, arginfo_extract) diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index ef43cddfcc416..5c2c6af62a899 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -49,6 +49,7 @@ PHP_FUNCTION(current); PHP_FUNCTION(key); PHP_FUNCTION(min); PHP_FUNCTION(max); +PHP_FUNCTION(array_usearch); PHP_FUNCTION(in_array); PHP_FUNCTION(array_search); PHP_FUNCTION(extract); @@ -120,6 +121,9 @@ 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_USEARCH_USE_KEY 1 +#define ARRAY_USEARCH_INVERT 2 + ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; int (*compare_func)(zval *result, zval *op1, zval *op2 TSRMLS_DC);