Created
November 7, 2013 13:14
-
-
Save nikita2206/7354392 to your computer and use it in GitHub Desktop.
php-src patch for allowing array_unique to take callback as an argument for comparing elements...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/standard/array.c b/ext/standard/array.c | |
index 411e8de..1dcdf76 100644 | |
--- a/ext/standard/array.c | |
+++ b/ext/standard/array.c | |
@@ -120,6 +120,7 @@ PHP_MINIT_FUNCTION(array) /* {{{ */ | |
REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT); | |
REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_CS | CONST_PERSISTENT); | |
REGISTER_LONG_CONSTANT("SORT_FLAG_CASE", PHP_SORT_FLAG_CASE, CONST_CS | CONST_PERSISTENT); | |
+ REGISTER_LONG_CONSTANT("SORT_USERDEFINED", PHP_SORT_USERDEFINED, CONST_CS | CONST_PERSISTENT); | |
REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT); | |
REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT); | |
@@ -2818,6 +2819,9 @@ PHP_FUNCTION(array_change_key_case) | |
} | |
/* }}} */ | |
+#define PHP_ARRAY_CMP_FUNC(sort_type) \ | |
+ (sort_type == PHP_SORT_USERDEFINED ? php_array_user_compare : php_array_data_compare) | |
+ | |
/* {{{ proto array array_unique(array input [, int sort_flags]) | |
Removes duplicate values from array */ | |
PHP_FUNCTION(array_unique) | |
@@ -2832,16 +2836,26 @@ PHP_FUNCTION(array_unique) | |
unsigned int i; | |
long sort_type = PHP_SORT_STRING; | |
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) { | |
+ PHP_ARRAY_CMP_FUNC_VARS; | |
+ PHP_ARRAY_CMP_FUNC_BACKUP(); | |
+ | |
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|lf", &array, &sort_type, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { | |
+ PHP_ARRAY_CMP_FUNC_RESTORE(); | |
return; | |
} | |
- php_set_compare_func(sort_type TSRMLS_CC); | |
+ if (sort_type != PHP_SORT_USERDEFINED) { | |
+ php_set_compare_func(sort_type TSRMLS_CC); | |
+ } else if (ZEND_NUM_ARGS() < 3) { | |
+ PHP_ARRAY_CMP_FUNC_RESTORE(); | |
+ zend_error(E_ERROR, "array_unique with flag SORT_USERDEFINED expects compare function as a third argument, nothing given"); | |
+ } | |
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array))); | |
zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval*)); | |
if (Z_ARRVAL_P(array)->nNumOfElements <= 1) { /* nothing to do */ | |
+ PHP_ARRAY_CMP_FUNC_RESTORE(); | |
return; | |
} | |
@@ -2849,6 +2863,7 @@ PHP_FUNCTION(array_unique) | |
arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->persistent); | |
if (!arTmp) { | |
zval_dtor(return_value); | |
+ PHP_ARRAY_CMP_FUNC_RESTORE(); | |
RETURN_FALSE; | |
} | |
for (i = 0, p = Z_ARRVAL_P(array)->pListHead; p; i++, p = p->pListNext) { | |
@@ -2856,12 +2871,13 @@ PHP_FUNCTION(array_unique) | |
arTmp[i].i = i; | |
} | |
arTmp[i].b = NULL; | |
- zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC); | |
+ | |
+ zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), PHP_ARRAY_CMP_FUNC(sort_type) TSRMLS_CC); | |
/* go through the sorted array and delete duplicates from the copy */ | |
lastkept = arTmp; | |
for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) { | |
- if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) { | |
+ if ((PHP_ARRAY_CMP_FUNC(sort_type))(lastkept, cmpdata TSRMLS_CC)) { | |
lastkept = cmpdata; | |
} else { | |
if (lastkept->i > cmpdata->i) { | |
@@ -2882,6 +2898,7 @@ PHP_FUNCTION(array_unique) | |
} | |
} | |
pefree(arTmp, Z_ARRVAL_P(array)->persistent); | |
+ PHP_ARRAY_CMP_FUNC_RESTORE(); | |
} | |
/* }}} */ | |
diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h | |
index 1cf2779..d81664d 100644 | |
--- a/ext/standard/php_array.h | |
+++ b/ext/standard/php_array.h | |
@@ -116,6 +116,7 @@ PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); | |
#define PHP_SORT_LOCALE_STRING 5 | |
#define PHP_SORT_NATURAL 6 | |
#define PHP_SORT_FLAG_CASE 8 | |
+#define PHP_SORT_USERDEFINED 9 | |
ZEND_BEGIN_MODULE_GLOBALS(array) | |
int *multisort_flags[2]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment