Skip to content

Commit 37632e8

Browse files
committed
Make sorting stable
1 parent 33ef3d6 commit 37632e8

File tree

7 files changed

+188
-150
lines changed

7 files changed

+188
-150
lines changed

Zend/zend_hash.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,15 +2431,15 @@ ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q)
24312431
zend_ulong h;
24322432
zend_string *key;
24332433

2434-
ZVAL_COPY_VALUE(&val, &p->val);
2434+
val = p->val;
24352435
h = p->h;
24362436
key = p->key;
24372437

2438-
ZVAL_COPY_VALUE(&p->val, &q->val);
2438+
p->val = q->val;
24392439
p->h = q->h;
24402440
p->key = q->key;
24412441

2442-
ZVAL_COPY_VALUE(&q->val, &val);
2442+
q->val = val;
24432443
q->h = h;
24442444
q->key = key;
24452445
}
@@ -2448,23 +2448,23 @@ ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
24482448
{
24492449
zval val;
24502450

2451-
ZVAL_COPY_VALUE(&val, &p->val);
2452-
ZVAL_COPY_VALUE(&p->val, &q->val);
2453-
ZVAL_COPY_VALUE(&q->val, &val);
2451+
val = p->val;
2452+
p->val = q->val;
2453+
q->val = val;
24542454
}
24552455

24562456
ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q)
24572457
{
24582458
zval val;
24592459
zend_ulong h;
24602460

2461-
ZVAL_COPY_VALUE(&val, &p->val);
2461+
val = p->val;
24622462
h = p->h;
24632463

2464-
ZVAL_COPY_VALUE(&p->val, &q->val);
2464+
p->val = q->val;
24652465
p->h = q->h;
24662466

2467-
ZVAL_COPY_VALUE(&q->val, &val);
2467+
q->val = val;
24682468
q->h = h;
24692469
}
24702470

@@ -2476,28 +2476,34 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b
24762476
IS_CONSISTENT(ht);
24772477
HT_ASSERT_RC1(ht);
24782478

2479-
if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
2479+
if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) {
2480+
/* Doesn't require sorting */
24802481
return;
24812482
}
24822483

24832484
if (HT_IS_WITHOUT_HOLES(ht)) {
2484-
i = ht->nNumUsed;
2485+
/* Store original order of elements in extra space to allow stable sorting. */
2486+
for (i = 0; i < ht->nNumUsed; i++) {
2487+
Z_EXTRA(ht->arData[i].val) = i;
2488+
}
24852489
} else {
2490+
/* Remove holes and store original order. */
24862491
for (j = 0, i = 0; j < ht->nNumUsed; j++) {
24872492
p = ht->arData + j;
24882493
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
24892494
if (i != j) {
24902495
ht->arData[i] = *p;
24912496
}
2497+
Z_EXTRA(ht->arData[i].val) = i;
24922498
i++;
24932499
}
2500+
ht->nNumUsed = i;
24942501
}
24952502

2496-
sort((void *)ht->arData, i, sizeof(Bucket), (compare_func_t) compar,
2503+
sort((void *)ht->arData, ht->nNumUsed, sizeof(Bucket), (compare_func_t) compar,
24972504
(swap_func_t)(renumber? zend_hash_bucket_renum_swap :
24982505
((HT_FLAGS(ht) & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
24992506

2500-
ht->nNumUsed = i;
25012507
ht->nInternalPointer = 0;
25022508

25032509
if (renumber) {

0 commit comments

Comments
 (0)