Skip to content

Commit ef8848a

Browse files
committed
Optimize array_unique() implementation
1 parent 42ba894 commit ef8848a

File tree

1 file changed

+7
-54
lines changed

1 file changed

+7
-54
lines changed

ext/standard/array.c

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4440,31 +4440,12 @@ PHP_FUNCTION(array_change_key_case)
44404440
}
44414441
/* }}} */
44424442

4443-
struct bucketindex {
4444-
Bucket b;
4445-
unsigned int i;
4446-
};
4447-
4448-
static void array_bucketindex_swap(void *p, void *q) /* {{{ */
4449-
{
4450-
struct bucketindex *f = (struct bucketindex *)p;
4451-
struct bucketindex *g = (struct bucketindex *)q;
4452-
struct bucketindex t;
4453-
t = *f;
4454-
*f = *g;
4455-
*g = t;
4456-
}
4457-
/* }}} */
4458-
44594443
/* {{{ proto array array_unique(array input [, int sort_flags])
44604444
Removes duplicate values from array */
44614445
PHP_FUNCTION(array_unique)
44624446
{
44634447
zval *array;
4464-
uint32_t idx;
4465-
Bucket *p;
4466-
struct bucketindex *arTmp, *cmpdata, *lastkept;
4467-
unsigned int i;
4448+
Bucket *p, *lastkept = NULL;
44684449
zend_long sort_type = PHP_SORT_STRING;
44694450
bucket_compare_func_t cmp;
44704451

@@ -4521,44 +4502,16 @@ PHP_FUNCTION(array_unique)
45214502
cmp = php_get_data_compare_func(sort_type, 0);
45224503

45234504
RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
4505+
zend_hash_sort(Z_ARRVAL_P(return_value), cmp, /* reindex */ 0);
45244506

4525-
/* create and sort array with pointers to the target_hash buckets */
4526-
arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
4527-
for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) {
4528-
p = Z_ARRVAL_P(array)->arData + idx;
4529-
if (Z_TYPE(p->val) == IS_UNDEF) continue;
4530-
if (Z_TYPE(p->val) == IS_INDIRECT && Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) continue;
4531-
arTmp[i].b = *p;
4532-
arTmp[i].i = i;
4533-
i++;
4534-
}
4535-
ZVAL_UNDEF(&arTmp[i].b.val);
4536-
zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
4537-
(compare_func_t) cmp, (swap_func_t)array_bucketindex_swap);
45384507
/* go through the sorted array and delete duplicates from the copy */
4539-
lastkept = arTmp;
4540-
for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
4541-
if (cmp(&lastkept->b, &cmpdata->b)) {
4542-
lastkept = cmpdata;
4508+
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(return_value), p) {
4509+
if (!lastkept || cmp(lastkept, p)) {
4510+
lastkept = p;
45434511
} else {
4544-
if (lastkept->i > cmpdata->i) {
4545-
p = &lastkept->b;
4546-
lastkept = cmpdata;
4547-
} else {
4548-
p = &cmpdata->b;
4549-
}
4550-
if (p->key == NULL) {
4551-
zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
4552-
} else {
4553-
if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
4554-
zend_delete_global_variable(p->key);
4555-
} else {
4556-
zend_hash_del(Z_ARRVAL_P(return_value), p->key);
4557-
}
4558-
}
4512+
zend_hash_del_bucket(Z_ARRVAL_P(return_value), p);
45594513
}
4560-
}
4561-
pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
4514+
} ZEND_HASH_FOREACH_END();
45624515
}
45634516
/* }}} */
45644517

0 commit comments

Comments
 (0)