Skip to content

Commit 42ba894

Browse files
committed
Make sorting stable
1 parent 28af364 commit 42ba894

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
@@ -2453,15 +2453,15 @@ ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q)
24532453
zend_ulong h;
24542454
zend_string *key;
24552455

2456-
ZVAL_COPY_VALUE(&val, &p->val);
2456+
val = p->val;
24572457
h = p->h;
24582458
key = p->key;
24592459

2460-
ZVAL_COPY_VALUE(&p->val, &q->val);
2460+
p->val = q->val;
24612461
p->h = q->h;
24622462
p->key = q->key;
24632463

2464-
ZVAL_COPY_VALUE(&q->val, &val);
2464+
q->val = val;
24652465
q->h = h;
24662466
q->key = key;
24672467
}
@@ -2470,23 +2470,23 @@ ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
24702470
{
24712471
zval val;
24722472

2473-
ZVAL_COPY_VALUE(&val, &p->val);
2474-
ZVAL_COPY_VALUE(&p->val, &q->val);
2475-
ZVAL_COPY_VALUE(&q->val, &val);
2473+
val = p->val;
2474+
p->val = q->val;
2475+
q->val = val;
24762476
}
24772477

24782478
ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q)
24792479
{
24802480
zval val;
24812481
zend_ulong h;
24822482

2483-
ZVAL_COPY_VALUE(&val, &p->val);
2483+
val = p->val;
24842484
h = p->h;
24852485

2486-
ZVAL_COPY_VALUE(&p->val, &q->val);
2486+
p->val = q->val;
24872487
p->h = q->h;
24882488

2489-
ZVAL_COPY_VALUE(&q->val, &val);
2489+
q->val = val;
24902490
q->h = h;
24912491
}
24922492

@@ -2498,28 +2498,34 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b
24982498
IS_CONSISTENT(ht);
24992499
HT_ASSERT_RC1(ht);
25002500

2501-
if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
2501+
if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) {
2502+
/* Doesn't require sorting */
25022503
return;
25032504
}
25042505

25052506
if (HT_IS_WITHOUT_HOLES(ht)) {
2506-
i = ht->nNumUsed;
2507+
/* Store original order of elements in extra space to allow stable sorting. */
2508+
for (i = 0; i < ht->nNumUsed; i++) {
2509+
Z_EXTRA(ht->arData[i].val) = i;
2510+
}
25072511
} else {
2512+
/* Remove holes and store original order. */
25082513
for (j = 0, i = 0; j < ht->nNumUsed; j++) {
25092514
p = ht->arData + j;
25102515
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
25112516
if (i != j) {
25122517
ht->arData[i] = *p;
25132518
}
2519+
Z_EXTRA(ht->arData[i].val) = i;
25142520
i++;
25152521
}
2522+
ht->nNumUsed = i;
25162523
}
25172524

2518-
sort((void *)ht->arData, i, sizeof(Bucket), (compare_func_t) compar,
2525+
sort((void *)ht->arData, ht->nNumUsed, sizeof(Bucket), (compare_func_t) compar,
25192526
(swap_func_t)(renumber? zend_hash_bucket_renum_swap :
25202527
((HT_FLAGS(ht) & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
25212528

2522-
ht->nNumUsed = i;
25232529
ht->nInternalPointer = 0;
25242530

25252531
if (renumber) {

0 commit comments

Comments
 (0)