@@ -4462,13 +4462,30 @@ PHP_FUNCTION(array_change_key_case)
4462
4462
}
4463
4463
/* }}} */
4464
4464
4465
+ struct bucketindex {
4466
+ Bucket b ;
4467
+ unsigned int i ;
4468
+ };
4469
+
4470
+ static void array_bucketindex_swap (void * p , void * q )
4471
+ {
4472
+ struct bucketindex * f = (struct bucketindex * )p ;
4473
+ struct bucketindex * g = (struct bucketindex * )q ;
4474
+ struct bucketindex t ;
4475
+ t = * f ;
4476
+ * f = * g ;
4477
+ * g = t ;
4478
+ }
4479
+
4465
4480
/* {{{ Removes duplicate values from array */
4466
4481
PHP_FUNCTION (array_unique )
4467
4482
{
4468
4483
zval * array ;
4469
- Bucket * p , * lastkept = NULL ;
4484
+ Bucket * p ;
4470
4485
zend_long sort_type = PHP_SORT_STRING ;
4471
4486
bucket_compare_func_t cmp ;
4487
+ struct bucketindex * arTmp , * cmpdata , * lastkept ;
4488
+ uint32_t i , idx ;
4472
4489
4473
4490
ZEND_PARSE_PARAMETERS_START (1 , 2 )
4474
4491
Z_PARAM_ARRAY (array )
@@ -4520,19 +4537,47 @@ PHP_FUNCTION(array_unique)
4520
4537
return ;
4521
4538
}
4522
4539
4523
- cmp = php_get_data_compare_func (sort_type , 0 );
4540
+ cmp = php_get_data_compare_func_unstable (sort_type , 0 );
4524
4541
4525
4542
RETVAL_ARR (zend_array_dup (Z_ARRVAL_P (array )));
4526
- zend_hash_sort (Z_ARRVAL_P (return_value ), cmp , /* reindex */ 0 );
4527
4543
4544
+ /* create and sort array with pointers to the target_hash buckets */
4545
+ arTmp = pemalloc ((Z_ARRVAL_P (array )-> nNumOfElements + 1 ) * sizeof (struct bucketindex ), GC_FLAGS (Z_ARRVAL_P (array )) & IS_ARRAY_PERSISTENT );
4546
+ for (i = 0 , idx = 0 ; idx < Z_ARRVAL_P (array )-> nNumUsed ; idx ++ ) {
4547
+ p = Z_ARRVAL_P (array )-> arData + idx ;
4548
+ if (Z_TYPE (p -> val ) == IS_UNDEF ) continue ;
4549
+ if (Z_TYPE (p -> val ) == IS_INDIRECT && Z_TYPE_P (Z_INDIRECT (p -> val )) == IS_UNDEF ) continue ;
4550
+ arTmp [i ].b = * p ;
4551
+ arTmp [i ].i = i ;
4552
+ i ++ ;
4553
+ }
4554
+ ZVAL_UNDEF (& arTmp [i ].b .val );
4555
+ zend_sort ((void * ) arTmp , i , sizeof (struct bucketindex ),
4556
+ (compare_func_t ) cmp , (swap_func_t ) array_bucketindex_swap );
4528
4557
/* go through the sorted array and delete duplicates from the copy */
4529
- ZEND_HASH_FOREACH_BUCKET (Z_ARRVAL_P (return_value ), p ) {
4530
- if (!lastkept || cmp (lastkept , p )) {
4531
- lastkept = p ;
4558
+ lastkept = arTmp ;
4559
+ for (cmpdata = arTmp + 1 ; Z_TYPE (cmpdata -> b .val ) != IS_UNDEF ; cmpdata ++ ) {
4560
+ if (cmp (& lastkept -> b , & cmpdata -> b )) {
4561
+ lastkept = cmpdata ;
4532
4562
} else {
4533
- zend_hash_del_bucket (Z_ARRVAL_P (return_value ), p );
4563
+ if (lastkept -> i > cmpdata -> i ) {
4564
+ p = & lastkept -> b ;
4565
+ lastkept = cmpdata ;
4566
+ } else {
4567
+ p = & cmpdata -> b ;
4568
+ }
4569
+ if (p -> key == NULL ) {
4570
+ zend_hash_index_del (Z_ARRVAL_P (return_value ), p -> h );
4571
+ } else {
4572
+ if (Z_ARRVAL_P (return_value ) == & EG (symbol_table )) {
4573
+ zend_delete_global_variable (p -> key );
4574
+ } else {
4575
+ zend_hash_del (Z_ARRVAL_P (return_value ), p -> key );
4576
+ }
4577
+ }
4534
4578
}
4535
- } ZEND_HASH_FOREACH_END ();
4579
+ }
4580
+ pefree (arTmp , GC_FLAGS (Z_ARRVAL_P (array )) & IS_ARRAY_PERSISTENT );
4536
4581
}
4537
4582
/* }}} */
4538
4583
0 commit comments