Skip to content

Commit 17e92f3

Browse files
committed
Add SORT_STRICT option to array_unique()
Provide a way to request the use of strict comparison (===) when using `array_unique`.
1 parent 78ef25b commit 17e92f3

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

ext/standard/array.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ PHP_MINIT_FUNCTION(array) /* {{{ */
103103

104104
REGISTER_LONG_CONSTANT("SORT_REGULAR", PHP_SORT_REGULAR, CONST_CS | CONST_PERSISTENT);
105105
REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT);
106+
REGISTER_LONG_CONSTANT("SORT_STRICT", PHP_SORT_STRICT, CONST_CS | CONST_PERSISTENT);
106107
REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT);
107108
REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT);
108109
REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_CS | CONST_PERSISTENT);
@@ -349,6 +350,22 @@ static zend_always_inline int php_array_data_compare_unstable_i(Bucket *f, Bucke
349350
}
350351
/* }}} */
351352

353+
static zend_always_inline int php_array_data_compare_strict_unstable_i(Bucket *f, Bucket *s) /* {{{ */
354+
{
355+
if (zend_is_identical(&f->val, &s->val)) {
356+
return 0;
357+
}
358+
int c = zend_compare(&f->val, &s->val);
359+
if (c != 0) {
360+
return c;
361+
}
362+
// types must be different; compare based on type.
363+
int t1 = Z_TYPE_P(&f->val);
364+
int t2 = Z_TYPE_P(&s->val);
365+
return (t1 < t2) ? -1 : 1;
366+
}
367+
/* }}} */
368+
352369
static zend_always_inline int php_array_data_compare_numeric_unstable_i(Bucket *f, Bucket *s) /* {{{ */
353370
{
354371
return numeric_compare_function(&f->val, &s->val);
@@ -405,6 +422,7 @@ DEFINE_SORT_VARIANTS(key_compare_string_case);
405422
DEFINE_SORT_VARIANTS(key_compare_string);
406423
DEFINE_SORT_VARIANTS(key_compare_string_locale);
407424
DEFINE_SORT_VARIANTS(data_compare);
425+
DEFINE_SORT_VARIANTS(data_compare_strict);
408426
DEFINE_SORT_VARIANTS(data_compare_numeric);
409427
DEFINE_SORT_VARIANTS(data_compare_string_case);
410428
DEFINE_SORT_VARIANTS(data_compare_string);
@@ -527,6 +545,14 @@ static bucket_compare_func_t php_get_data_compare_func(zend_long sort_type, int
527545
}
528546
break;
529547

548+
case PHP_SORT_STRICT:
549+
if (reverse) {
550+
return php_array_reverse_data_compare_strict;
551+
} else {
552+
return php_array_data_compare_strict;
553+
}
554+
break;
555+
530556
case PHP_SORT_REGULAR:
531557
default:
532558
if (reverse) {
@@ -591,6 +617,14 @@ static bucket_compare_func_t php_get_data_compare_func_unstable(zend_long sort_t
591617
}
592618
break;
593619

620+
case PHP_SORT_STRICT:
621+
if (reverse) {
622+
return php_array_reverse_data_compare_strict_unstable;
623+
} else {
624+
return php_array_data_compare_strict_unstable;
625+
}
626+
break;
627+
594628
case PHP_SORT_REGULAR:
595629
default:
596630
if (reverse) {

ext/standard/php_array.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ PHPAPI zend_long php_count_recursive(HashTable *ht);
3636
#define PHP_SORT_ASC 4
3737
#define PHP_SORT_LOCALE_STRING 5
3838
#define PHP_SORT_NATURAL 6
39+
#define PHP_SORT_STRICT 7
3940
#define PHP_SORT_FLAG_CASE 8
4041

4142
#define COUNT_NORMAL 0
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Test array_unique() function : SORT_STRICT functionality
3+
--FILE--
4+
<?php
5+
echo "*** Testing array_unique() : SORT_STRICT functionality ***\n";
6+
7+
var_dump( array_unique( [ "1234", 1234 ] ) );
8+
var_dump( array_unique( [ "1234", "1234" ], SORT_STRICT ) );
9+
var_dump( array_unique( [ "1234", 1234 ], SORT_STRICT ) );
10+
11+
var_dump( array_unique( [ 0, "0", 0.0, '', null, null ] ) );
12+
var_dump( array_unique( [ 0, "0", 0.0, '', null, null ], SORT_STRICT ) );
13+
14+
?>
15+
--EXPECT--
16+
*** Testing array_unique() : SORT_STRICT functionality ***
17+
array(1) {
18+
[0]=>
19+
string(4) "1234"
20+
}
21+
array(1) {
22+
[0]=>
23+
string(4) "1234"
24+
}
25+
array(2) {
26+
[0]=>
27+
string(4) "1234"
28+
[1]=>
29+
int(1234)
30+
}
31+
array(2) {
32+
[0]=>
33+
int(0)
34+
[3]=>
35+
string(0) ""
36+
}
37+
array(5) {
38+
[0]=>
39+
int(0)
40+
[1]=>
41+
string(1) "0"
42+
[2]=>
43+
float(0)
44+
[3]=>
45+
string(0) ""
46+
[4]=>
47+
NULL
48+
}

0 commit comments

Comments
 (0)