Skip to content

Instantly share code, notes, and snippets.

@nikita2206
Created November 7, 2013 13:14
Show Gist options
  • Save nikita2206/7354392 to your computer and use it in GitHub Desktop.
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...
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