diff --git a/ext/standard/array.c b/ext/standard/array.c index 6252b61d2042a..1343f262e1b83 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4559,6 +4559,43 @@ PHP_FUNCTION(array_unique) return; } + if (sort_type == PHP_ARRAY_UNIQUE_UNSORTED) { + zend_long input_num_key; + zend_string *input_str_key; + zval *input_val; + + array_init(return_value); + HashTable *result_ht = Z_ARR_P(return_value); + + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), input_num_key, input_str_key, input_val) { + zval *input_val_deref = input_val; + ZVAL_DEREF(input_val_deref); + + zval *result_val; + ZEND_HASH_FOREACH_VAL(result_ht, result_val) { + ZVAL_DEREF(result_val); + if (fast_is_identical_function(input_val_deref, result_val)) { + goto skip_unsorted; + } + } ZEND_HASH_FOREACH_END(); + + if (UNEXPECTED(Z_ISREF_P(input_val) && Z_REFCOUNT_P(input_val) == 1)) { + ZVAL_DEREF(input_val); + } + Z_TRY_ADDREF_P(input_val); + + if (input_str_key) { + zend_hash_add_new(Z_ARRVAL_P(return_value), input_str_key, input_val); + } else { + zend_hash_index_add_new(Z_ARRVAL_P(return_value), input_num_key, input_val); + } + +skip_unsorted:; + } ZEND_HASH_FOREACH_END(); + + return; + } + cmp = php_get_data_compare_func_unstable(sort_type, 0); RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array))); diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index ab56a8c0e8fbb..9737928ba9035 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -87,6 +87,12 @@ */ const SORT_FLAG_CASE = UNKNOWN; +/** + * @var int + * @cvalue PHP_ARRAY_UNIQUE_UNSORTED + */ +const ARRAY_UNIQUE_UNSORTED = UNKNOWN; + /** * @var int * @cvalue PHP_CASE_LOWER diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 077f9876df7c2..1811535a9ce7e 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 39d455982dfdea9d0b9b646bc207b05f7108d1b2 */ + * Stub hash: e50a074c7bef1f26a4a1c643af5bfce641cb6a68 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -3499,6 +3499,7 @@ static void register_basic_functions_symbols(int module_number) REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_FLAG_CASE", PHP_SORT_FLAG_CASE, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_UNIQUE_UNSORTED", PHP_ARRAY_UNIQUE_UNSORTED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CASE_LOWER", PHP_CASE_LOWER, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CASE_UPPER", PHP_CASE_UPPER, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("COUNT_NORMAL", PHP_COUNT_NORMAL, CONST_PERSISTENT); diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 5d42a22f42040..a82af809f038b 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -55,6 +55,10 @@ PHPAPI bool php_array_pick_keys(const php_random_algo *algo, php_random_status * #define PHP_SORT_LOCALE_STRING 5 #define PHP_SORT_NATURAL 6 #define PHP_SORT_FLAG_CASE 8 +//#define PHP_SORT_DONT_USE 9 + +// Must not clash with PHP_SORT_ constants +#define PHP_ARRAY_UNIQUE_UNSORTED 9 #define PHP_COUNT_NORMAL 0 #define PHP_COUNT_RECURSIVE 1 diff --git a/ext/standard/tests/array/array_unique_unsorted.phpt b/ext/standard/tests/array/array_unique_unsorted.phpt new file mode 100755 index 0000000000000..76e9978292cb3 --- /dev/null +++ b/ext/standard/tests/array/array_unique_unsorted.phpt @@ -0,0 +1,83 @@ +--TEST-- +array_unique() with ARRAY_UNIQUE_UNSORTED +--FILE-- + Foo::Bar, + 'b' => Foo::Baz, + 'c' => Foo::Bar, +], ARRAY_UNIQUE_UNSORTED)); + +var_dump(array_unique([ + &$bar, + Foo::Bar, + &$bar2, + Foo::Baz, +], ARRAY_UNIQUE_UNSORTED)); + +$value2 = "hello"; +$value3 = 0; +$value4 = &$value2; +var_dump(array_unique([ + 0, + &$value4, + &$value2, + "hello", + &$value3, + $value4 +], ARRAY_UNIQUE_UNSORTED)); + +?> +--EXPECT-- +array(2) { + [0]=> + enum(Foo::Bar) + [1]=> + enum(Foo::Baz) +} +array(2) { + [0]=> + enum(Foo::Bar) + [2]=> + enum(Foo::Baz) +} +array(2) { + ["a"]=> + enum(Foo::Bar) + ["b"]=> + enum(Foo::Baz) +} +array(2) { + [0]=> + &enum(Foo::Bar) + [3]=> + enum(Foo::Baz) +} +array(2) { + [0]=> + int(0) + [1]=> + &string(5) "hello" +}