25#if defined(__aarch64__) || defined(_M_ARM64)
31# include <immintrin.h>
32#elif defined( __SSE2__)
34# include <emmintrin.h>
38# define HT_ASSERT(ht, expr) \
39 ZEND_ASSERT((expr) || (HT_FLAGS(ht) & HASH_FLAG_ALLOW_COW_VIOLATION))
41# define HT_ASSERT(ht, expr)
44#define HT_ASSERT_RC1(ht) HT_ASSERT(ht, GC_REFCOUNT(ht) == 1)
46#define HT_POISONED_PTR ((HashTable *) (intptr_t) -1)
51#define HT_IS_DESTROYING 0x01
52#define HT_DESTROYED 0x02
53#define HT_CLEANING 0x03
61 case HT_IS_DESTROYING:
76#define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
77#define SET_INCONSISTENT(n) do { \
78 HT_FLAGS(ht) = (HT_FLAGS(ht) & ~HASH_FLAG_CONSISTENCY) | (n); \
81#define IS_CONSISTENT(a)
82#define SET_INCONSISTENT(n)
85#define ZEND_HASH_IF_FULL_DO_RESIZE(ht) \
86 if ((ht)->nNumUsed >= (ht)->nTableSize) { \
87 zend_hash_do_resize(ht); \
107 result = zend_hash_find_ptr(
ht, lc_key);
108 zend_string_release(lc_key);
129 if (BitScanReverse(&index, nSize - 1)) {
130 return 0x2u << ((31 - index) ^ 0x1f);
136#elif (defined(__GNUC__) || __has_builtin(__builtin_clz)) && defined(PHP_HAVE_BUILTIN_CLZ)
137 return 0x2u << (__builtin_clz(nSize - 1) ^ 0x1f);
140 nSize |= (nSize >> 1);
141 nSize |= (nSize >> 2);
142 nSize |= (nSize >> 4);
143 nSize |= (nSize >> 8);
144 nSize |= (nSize >> 16);
170 uint32_t nSize =
ht->nTableSize;
184 __m256i ymm0 = _mm256_setzero_si256();
185 ymm0 = _mm256_cmpeq_epi64(ymm0, ymm0);
189#elif defined (__SSE2__)
191 __m128i xmm0 = _mm_setzero_si128();
192 xmm0 = _mm_cmpeq_epi8(xmm0, xmm0);
198#elif defined(__aarch64__) || defined(_M_ARM64)
200 int32x4_t t = vdupq_n_s32(-1);
239 zend_hash_real_init_packed_ex(
ht);
241 zend_hash_real_init_mixed_ex(
ht);
245static const uint32_t uninitialized_bucket[-
HT_MIN_MASK] =
253 {.arData = (
Bucket*)&uninitialized_bucket[2]},
257 .nInternalPointer = 0,
270 ht->nNumOfElements = 0;
271 ht->nInternalPointer = 0;
273 ht->pDestructor = pDestructor;
274 ht->nTableSize = zend_hash_check_size(nSize);
279 _zend_hash_init_int(
ht, nSize, pDestructor,
persistent);
301 ht->nNumUsed =
ht->nNumOfElements =
ht->nNextFreeElement = 2;
302 zend_hash_real_init_packed_ex(
ht);
314 if (
ht->nTableSize >= HT_MAX_SIZE) {
317 uint32_t newTableSize =
ht->nTableSize * 2;
319 ht->nTableSize = newTableSize;
327 zend_hash_real_init_ex(
ht, packed);
335 zend_hash_real_init_packed_ex(
ht);
343 zend_hash_real_init_mixed_ex(
ht);
352 uint32_t nSize =
ht->nTableSize;
363 for (i = 0; i <
ht->nNumUsed; i++) {
388 for (i = 0; i <
ht->nNumUsed; i++) {
400 if (nSize == 0)
return;
405 if (nSize >
ht->nTableSize) {
406 ht->nTableSize = zend_hash_check_size(nSize);
412 if (nSize >
ht->nTableSize) {
413 uint32_t newTableSize = zend_hash_check_size(nSize);
415 ht->nTableSize = newTableSize;
419 if (nSize >
ht->nTableSize) {
422 nSize = zend_hash_check_size(nSize);
424 ht->nTableSize = nSize;
442 p = arData +
ht->nNumUsed;
443 end = arData + nNumUsed;
444 ht->nNumUsed = nNumUsed;
448 ht->nNumOfElements--;
455 nIndex =
p->h |
ht->nTableMask;
460static uint32_t zend_array_recalc_elements(
HashTable *
ht)
463 uint32_t num =
ht->nNumOfElements;
480 num = zend_array_recalc_elements(
ht);
485 num = zend_array_recalc_elements(
ht);
487 num = zend_hash_num_elements(
ht);
509 return _zend_hash_get_valid_pos(
ht,
ht->nInternalPointer);
514 return _zend_hash_get_current_pos(
ht);
519 return _zend_hash_get_valid_pos(
ht,
pos);
522static void zend_hash_remove_iterator_copies(uint32_t idx) {
527 while (next_idx != idx) {
528 uint32_t cur_idx = next_idx;
546 while (iter !=
end) {
550 idx = iter -
EG(ht_iterators);
552 if (idx + 1 >
EG(ht_iterators_used)) {
553 EG(ht_iterators_used) = idx + 1;
559 if (
EG(ht_iterators) ==
EG(ht_iterators_slots)) {
565 iter =
EG(ht_iterators) +
EG(ht_iterators_count);
566 EG(ht_iterators_count) += 8;
570 idx = iter -
EG(ht_iterators);
572 EG(ht_iterators_used) = idx + 1;
583 while (next_idx != idx) {
584 copy_iter =
EG(ht_iterators) + next_idx;
585 if (copy_iter->
ht ==
ht) {
595 iter->
ht = copy_iter->
ht;
596 iter->
pos = copy_iter->
pos;
597 zend_hash_remove_iterator_copies(idx);
602 zend_hash_remove_iterator_copies(idx);
613 if (
UNEXPECTED(iter->
ht !=
ht) && !zend_hash_iterator_find_copy_pos(idx,
ht)) {
622 iter->
pos = _zend_hash_get_current_pos(
ht);
633 if (
UNEXPECTED(iter->
ht !=
ht) && !zend_hash_iterator_find_copy_pos(idx,
ht)) {
644 iter->
pos = _zend_hash_get_current_pos(
ht);
663 zend_hash_remove_iterator_copies(idx);
666 if (idx ==
EG(ht_iterators_used) - 1) {
667 while (idx > 0 &&
EG(ht_iterators)[idx - 1].
ht ==
NULL) {
670 EG(ht_iterators_used) = idx;
679 while (iter !=
end) {
680 if (iter->
ht ==
ht) {
690 _zend_hash_iterators_remove(
ht);
700 while (iter !=
end) {
701 if (iter->
ht ==
ht) {
716 while (iter !=
end) {
717 if (iter->
ht ==
ht && iter->
pos == from) {
729 while (iter !=
end) {
730 if (iter->
ht ==
ht) {
753 p = HT_HASH_TO_BUCKET_EX(arData, idx);
761 zend_string_equal_content(
p->key,
key)) {
768 p = HT_HASH_TO_BUCKET_EX(arData, idx);
782 nIndex = h |
ht->nTableMask;
786 p = HT_HASH_TO_BUCKET_EX(arData, idx);
789 && zend_string_equals_cstr(
p->key, str,
len)) {
804 nIndex = h |
ht->nTableMask;
808 p = HT_HASH_TO_BUCKET_EX(arData, idx);
809 if (
p->h == h && !
p->key) {
826 zend_string_hash_val(
key);
836 p = zend_hash_find_bucket(
ht,
key);
865 if (
ht->pDestructor) {
877 zend_string_addref(
key);
880 idx =
ht->nNumUsed++;
881 ht->nNumOfElements++;
886 nIndex = h |
ht->nTableMask;
888 HT_HASH_EX(arData, nIndex) = HT_IDX_TO_HASH(idx);
916 p = zend_hash_str_find_bucket(
ht, str,
len, h);
944 if (
ht->pDestructor) {
955 idx =
ht->nNumUsed++;
956 ht->nNumOfElements++;
957 p =
ht->arData + idx;
971 nIndex = h |
ht->nTableMask;
973 HT_HASH(
ht, nIndex) = HT_IDX_TO_HASH(idx);
1035 return _zend_hash_str_add_or_update_i(
ht, str,
len, h, pData,
HASH_UPDATE);
1049 return _zend_hash_str_add_or_update_i(
ht, str,
len, h, pData,
HASH_ADD);
1099 && h < ht->nNumUsed) {
1100 zv =
ht->arPacked + h;
1109 if (
ht->pDestructor) {
1110 ht->pDestructor(
zv);
1115 goto convert_to_hash;
1117 }
else if (
EXPECTED(h < ht->nTableSize)) {
1119 zv =
ht->arPacked + h;
1122 if (h >
ht->nNumUsed) {
1123 zval *q =
ht->arPacked +
ht->nNumUsed;
1130 ht->nNextFreeElement =
ht->nNumUsed = h + 1;
1131 ht->nNumOfElements++;
1139 }
else if ((h >> 1) <
ht->nTableSize &&
1140 (
ht->nTableSize >> 1) <
ht->nNumOfElements) {
1144 if (
ht->nNumUsed >=
ht->nTableSize) {
1145 ht->nTableSize +=
ht->nTableSize;
1151 if (h < ht->nTableSize) {
1152 zend_hash_real_init_packed_ex(
ht);
1158 p = zend_hash_index_find_bucket(
ht, h);
1171 idx =
ht->nNumUsed++;
1172 nIndex = h |
ht->nTableMask;
1173 p =
ht->arData + idx;
1175 HT_HASH(
ht, nIndex) = HT_IDX_TO_HASH(idx);
1179 ht->nNumOfElements++;
1211 return _zend_hash_index_add_or_update_i(
ht, h, pData,
HASH_ADD);
1221 return _zend_hash_index_add_or_update_i(
ht, h, pData,
HASH_UPDATE);
1249 (
void)zend_string_hash_val(
key);
1250 p = zend_hash_find_bucket(
ht,
key);
1252 return (
p == b) ? &
p->val :
NULL;
1256 zend_string_addref(
key);
1260 arData =
ht->arData;
1263 idx = HT_IDX_TO_HASH(b - arData);
1264 nIndex = b->
h |
ht->nTableMask;
1269 p = HT_HASH_TO_BUCKET_EX(arData, i);
1270 while (
Z_NEXT(
p->val) != idx) {
1272 p = HT_HASH_TO_BUCKET_EX(arData, i);
1276 zend_string_release(b->
key);
1282 nIndex = b->
h |
ht->nTableMask;
1283 idx = HT_IDX_TO_HASH(idx);
1289 p = HT_HASH_TO_BUCKET_EX(arData, i);
1292 p = HT_HASH_TO_BUCKET_EX(arData, i);
1307 if (
ht->nNumUsed >
ht->nNumOfElements + (
ht->nNumOfElements >> 5)) {
1309 }
else if (
ht->nTableSize < HT_MAX_SIZE) {
1311 uint32_t nSize =
ht->nTableSize +
ht->nTableSize;
1317 ht->nTableSize = nSize;
1340 ht->nInternalPointer = 0;
1344 while (iter !=
end) {
1345 if (iter->
ht ==
ht) {
1360 nIndex =
p->h |
ht->nTableMask;
1362 HT_HASH(
ht, nIndex) = HT_IDX_TO_HASH(i);
1364 }
while (++i < ht->nNumUsed);
1366 uint32_t old_num_used =
ht->nNumUsed;
1373 while (++i < ht->nNumUsed) {
1378 nIndex = q->
h |
ht->nTableMask;
1383 ht->nInternalPointer =
j;
1392 while (++i < ht->nNumUsed) {
1397 nIndex = q->
h |
ht->nTableMask;
1402 ht->nInternalPointer =
j;
1406 zend_hash_iterators_update(
ht, iter_pos,
j);
1408 }
while (iter_pos < i);
1418 nIndex =
p->h |
ht->nTableMask;
1420 HT_HASH(
ht, nIndex) = HT_IDX_TO_HASH(i);
1422 }
while (++i < ht->nNumUsed);
1437 while (iter !=
end) {
1438 if (iter->
ht ==
ht) {
1448 idx = HT_HASH_TO_IDX(idx);
1449 ht->nNumOfElements--;
1450 if (
ht->nNumUsed - 1 == idx) {
1454 ht->nInternalPointer =
MIN(
ht->nInternalPointer,
ht->nNumUsed);
1455 zend_hash_iterators_clamp_max(
ht,
ht->nNumUsed);
1457 if (
ht->pDestructor) {
1461 ht->pDestructor(&tmp);
1474 idx = HT_HASH_TO_IDX(idx);
1475 ht->nNumOfElements--;
1476 if (
ht->nNumUsed - 1 == idx) {
1480 ht->nInternalPointer =
MIN(
ht->nInternalPointer,
ht->nNumUsed);
1481 zend_hash_iterators_clamp_max(
ht,
ht->nNumUsed);
1483 if (
ht->pDestructor) {
1487 ht->pDestructor(&tmp);
1499 nIndex =
p->h |
ht->nTableMask;
1511 zend_string_release(
p->key);
1514 _zend_hash_del_el_ex(
ht, idx,
p,
prev);
1522 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(
zv -
ht->arPacked),
zv);
1531 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(
p -
ht->arData),
p);
1545 h = zend_string_hash_val(
key);
1546 nIndex = h |
ht->nTableMask;
1551 if ((
p->key ==
key) ||
1554 zend_string_equal_content(
p->key,
key))) {
1555 zend_string_release(
p->key);
1557 _zend_hash_del_el_ex(
ht, idx,
p,
prev);
1577 h = zend_string_hash_val(
key);
1578 nIndex = h |
ht->nTableMask;
1583 if ((
p->key ==
key) ||
1586 zend_string_equal_content(
p->key,
key))) {
1593 if (
ht->pDestructor) {
1597 ht->pDestructor(&tmp);
1604 zend_string_release(
p->key);
1606 _zend_hash_del_el_ex(
ht, idx,
p,
prev);
1627 h = zend_inline_hash_func(str,
len);
1628 nIndex = h |
ht->nTableMask;
1635 && zend_string_equals_cstr(
p->key, str,
len)) {
1642 if (
ht->pDestructor) {
1649 zend_string_release(
p->key);
1651 _zend_hash_del_el_ex(
ht, idx,
p,
prev);
1672 h = zend_inline_hash_func(str,
len);
1673 nIndex = h |
ht->nTableMask;
1680 && zend_string_equals_cstr(
p->key, str,
len)) {
1681 zend_string_release(
p->key);
1683 _zend_hash_del_el_ex(
ht, idx,
p,
prev);
1703 if (h < ht->nNumUsed) {
1706 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(h),
zv);
1712 nIndex = h |
ht->nTableMask;
1717 if ((
p->h == h) && (
p->key ==
NULL)) {
1718 _zend_hash_del_el_ex(
ht, idx,
p,
prev);
1734 if (
ht->pDestructor) {
1741 ht->pDestructor(
zv);
1742 }
while (++
zv !=
end);
1746 ht->pDestructor(
zv);
1748 }
while (++
zv !=
end);
1752 zend_hash_iterators_remove(
ht);
1757 if (
ht->pDestructor) {
1763 ht->pDestructor(&
p->val);
1764 }
while (++
p !=
end);
1768 ht->pDestructor(&
p->val);
1770 }
while (++
p !=
end);
1774 ht->pDestructor(&
p->val);
1776 zend_string_release(
p->key);
1778 }
while (++
p !=
end);
1782 ht->pDestructor(&
p->val);
1784 zend_string_release(
p->key);
1787 }
while (++
p !=
end);
1795 zend_string_release(
p->key);
1797 }
while (++
p !=
end);
1800 zend_hash_iterators_remove(
ht);
1831 i_zval_ptr_dtor(
zv);
1832 }
while (++
zv !=
end);
1839 i_zval_ptr_dtor(&
p->val);
1840 }
while (++
p !=
end);
1843 i_zval_ptr_dtor(&
p->val);
1847 }
while (++
p !=
end);
1851 i_zval_ptr_dtor(&
p->val);
1856 }
while (++
p !=
end);
1865 zend_hash_iterators_remove(
ht);
1879 if (
ht->pDestructor) {
1883 ht->pDestructor(
zv);
1884 }
while (++
zv !=
end);
1888 ht->pDestructor(
zv);
1890 }
while (++
zv !=
end);
1898 if (
ht->pDestructor) {
1902 ht->pDestructor(&
p->val);
1903 }
while (++
p !=
end);
1907 ht->pDestructor(&
p->val);
1909 }
while (++
p !=
end);
1913 ht->pDestructor(&
p->val);
1915 zend_string_release(
p->key);
1917 }
while (++
p !=
end);
1921 ht->pDestructor(&
p->val);
1923 zend_string_release(
p->key);
1926 }
while (++
p !=
end);
1932 zend_string_release(
p->key);
1934 }
while (++
p !=
end);
1941 ht->nNumOfElements = 0;
1943 ht->nInternalPointer = 0;
1959 i_zval_ptr_dtor(&
p->val);
1960 }
while (++
p !=
end);
1963 i_zval_ptr_dtor(&
p->val);
1965 zend_string_release(
p->key);
1967 }
while (++
p !=
end);
1971 i_zval_ptr_dtor(&
p->val);
1973 zend_string_release(
p->key);
1976 }
while (++
p !=
end);
1981 ht->nNumOfElements = 0;
1983 ht->nInternalPointer = 0;
1996 for (idx = 0; idx <
ht->nNumUsed; idx++,
zv++) {
1998 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(idx),
zv);
2003 for (idx = 0; idx <
ht->nNumUsed; idx++,
p++) {
2005 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(idx),
p);
2030 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(idx),
zv);
2039 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(idx),
p);
2066 for (idx = 0; idx <
ht->nNumUsed; idx++) {
2074 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(idx),
zv);
2081 for (idx = 0; idx <
ht->nNumUsed; idx++) {
2089 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(idx),
p);
2106 for (idx = 0; idx <
ht->nNumUsed; idx++) {
2113 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(idx),
zv);
2120 for (idx = 0; idx <
ht->nNumUsed; idx++) {
2123 result = apply_func(&
p->val, argument);
2127 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(idx),
p);
2147 for (idx = 0; idx <
ht->nNumUsed; idx++) {
2159 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(idx),
zv);
2168 for (idx = 0; idx <
ht->nNumUsed; idx++) {
2174 hash_key.
key =
p->key;
2180 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(idx),
p);
2205 zv =
ht->arPacked + idx;
2212 _zend_hash_packed_del_val(
ht, HT_IDX_TO_HASH(idx),
zv);
2223 p =
ht->arData + idx;
2230 _zend_hash_del_el(
ht, HT_IDX_TO_HASH(idx),
p);
2250 for (idx = 0; idx < source->
nNumUsed; idx++) {
2255 if (pCopyConstructor) {
2256 pCopyConstructor(new_entry);
2262 for (idx = 0; idx < source->
nNumUsed; idx++) {
2280 if (pCopyConstructor) {
2281 pCopyConstructor(new_entry);
2296 }
else if (!packed) {
2326 if (!zend_array_dup_value(source, target, &
p->val, &q->
val, packed, with_holes)) {
2335 if (!static_keys && q->
key) {
2336 zend_string_addref(q->
key);
2339 nIndex = q->
h | target->nTableMask;
2341 HT_HASH(target, nIndex) = HT_IDX_TO_HASH(idx);
2348 uint32_t iter_index = 0;
2349 uint32_t end_index =
EG(ht_iterators_used);
2351 while (iter_index != end_index) {
2353 if (iter->
ht == source) {
2356 iter = &
EG(ht_iterators)[iter_index];
2368 zval *q = target->arPacked;
2372 if (!zend_array_dup_value(source, target,
p, q, 1, with_holes)) {
2381 zend_array_dup_ht_iterators(source, target);
2389 Bucket *q = target->arData;
2393 zend_array_dup_ht_iterators(source, target);
2397 if (!zend_array_dup_element(source, target, idx,
p, q, 0, static_keys, with_holes)) {
2398 uint32_t target_idx = idx;
2403 if (zend_array_dup_element(source, target, target_idx,
p, q, 0, static_keys, with_holes)) {
2405 target->nInternalPointer = target_idx;
2412 target->nNumUsed = source->
nNumUsed;
2416 if (zend_array_dup_element(source, target, target_idx,
p, q, 0, static_keys, with_holes)) {
2418 target->nInternalPointer = target_idx;
2422 zend_hash_iterators_update(target, iter_pos, target_idx);
2424 }
while (iter_pos < idx);
2454 target->nNumUsed = 0;
2455 target->nNumOfElements = 0;
2457 target->nInternalPointer = 0;
2463 target->nNumUsed = source->
nNumUsed;
2479 target->nNumUsed = source->
nNumUsed;
2484 target->nInternalPointer =
2491 zend_array_dup_packed_elements(source, target, 0);
2493 zend_array_dup_packed_elements(source, target, 1);
2499 target->nInternalPointer =
2509 idx = zend_array_dup_elements(source, target, 1, 0);
2511 idx = zend_array_dup_elements(source, target, 1, 1);
2515 idx = zend_array_dup_elements(source, target, 0, 0);
2517 idx = zend_array_dup_elements(source, target, 0, 1);
2520 target->nNumUsed = idx;
2521 target->nNumOfElements = idx;
2559 for (idx = 0; idx < source->
nNumUsed; idx++) {
2565 if (pCopyConstructor) {
2566 pCopyConstructor(t);
2572 for (idx = 0; idx < source->
nNumUsed; idx++) {
2583 if (pCopyConstructor) {
2584 pCopyConstructor(t);
2588 if (pCopyConstructor) {
2589 pCopyConstructor(t);
2595 for (idx = 0; idx < source->
nNumUsed; idx++) {
2601 if (t && pCopyConstructor) {
2602 pCopyConstructor(t);
2608 for (idx = 0; idx < source->
nNumUsed; idx++) {
2619 if (t && pCopyConstructor) {
2620 pCopyConstructor(t);
2624 if (t && pCopyConstructor) {
2625 pCopyConstructor(t);
2639 return merge_checker_func(target, source_data, &hash_key, pParam);
2654 for (idx = 0; idx < source->
nNumUsed; idx++) {
2657 if (zend_hash_replace_checker_wrapper(target, &
p->val,
p->h,
p->key, pParam, pMergeSource)) {
2659 if (pCopyConstructor) {
2660 pCopyConstructor(t);
2674 (
void)zend_string_hash_val(
key);
2675 p = zend_hash_find_bucket(
ht,
key);
2676 return p ? &
p->val :
NULL;
2685 p = zend_hash_find_bucket(
ht,
key);
2686 return p ? &
p->val :
NULL;
2696 h = zend_inline_hash_func(str,
len);
2697 p = zend_hash_str_find_bucket(
ht, str,
len, h);
2698 return p ? &
p->val :
NULL;
2708 if (h < ht->nNumUsed) {
2718 p = zend_hash_index_find_bucket(
ht, h);
2719 return p ? &
p->val :
NULL;
2729 p = zend_hash_index_find_bucket(
ht, h);
2730 return p ? &
p->val :
NULL;
2737 *
pos = _zend_hash_get_valid_pos(
ht, 0);
2769 *
pos =
ht->nNumUsed;
2780 idx = _zend_hash_get_valid_pos(
ht, *
pos);
2781 if (idx < ht->nNumUsed) {
2785 if (idx >=
ht->nNumUsed) {
2786 *
pos =
ht->nNumUsed;
2797 if (idx >=
ht->nNumUsed) {
2798 *
pos =
ht->nNumUsed;
2814 uint32_t idx = *
pos;
2819 if (idx < ht->nNumUsed) {
2837 *
pos =
ht->nNumUsed;
2852 idx = _zend_hash_get_valid_pos(
ht, *
pos);
2853 if (idx < ht->nNumUsed) {
2858 p =
ht->arData + idx;
2860 *str_index =
p->key;
2876 idx = _zend_hash_get_valid_pos(
ht, *
pos);
2877 if (idx >=
ht->nNumUsed) {
2884 p =
ht->arData + idx;
2899 idx = _zend_hash_get_valid_pos(
ht, *
pos);
2900 if (idx < ht->nNumUsed) {
2904 p =
ht->arData + idx;
2921 idx = _zend_hash_get_valid_pos(
ht, *
pos);
2922 if (idx < ht->nNumUsed) {
2924 return &
ht->arPacked[idx];
2926 p =
ht->arData + idx;
2983 if (!(
ht->nNumOfElements>1) && !(renumber &&
ht->nNumOfElements>0)) {
2994 for (i = 0; i <
ht->nNumUsed; i++) {
2999 for (
j = 0, i = 0;
j <
ht->nNumUsed;
j++) {
3025 ht->nInternalPointer = 0;
3028 for (
j = 0;
j < i;
j++) {
3032 zend_string_release(
p->key);
3037 ht->nNextFreeElement = i;
3055 for (i = 0; i <
ht->nTableSize; i++) {
3071 zend_hash_sort_internal(
ht, sort, compar, renumber);
3086 zend_hash_sort_internal(
ht, sort, compar, renumber);
3096 uint32_t idx1, idx2;
3099 zval *pData1, *pData2;;
3106 for (idx1 = 0, idx2 = 0; idx1 < ht1->
nNumUsed; idx1++) {
3141 if (key1 ==
NULL && key2 ==
NULL) {
3143 return h1 > h2 ? 1 : -1;
3145 }
else if (key1 !=
NULL && key2 !=
NULL) {
3156 return key1 !=
NULL ? 1 : -1;
3162 if (pData2 ==
NULL) {
3167 if (pData2 ==
NULL) {
3187 result = compar(pData1, pData2);
3217 result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
3231 if (
ht->nNumOfElements == 0 ) {
3240 if (idx ==
ht->nNumUsed) {
3246 res =
ht->arPacked + idx;
3247 for (; idx <
ht->nNumUsed; idx++) {
3248 zv =
ht->arPacked + idx;
3252 if (compar(
res,
zv) < 0) {
3256 if (compar(
res,
zv) > 0) {
3266 if (idx ==
ht->nNumUsed) {
3272 res = &
ht->arData[idx].val;
3273 for (; idx <
ht->nNumUsed; idx++) {
3274 p =
ht->arData + idx;
3278 if (compar(
res, &
p->val) < 0) {
3282 if (compar(
res, &
p->val) > 0) {
3293 const char *tmp =
key;
3295 const char *
end =
key + length;
3301 if ((*tmp ==
'0' && length > 1)
3308 *idx = (*tmp -
'0');
3322 if (*tmp <=
'9' && *tmp >=
'0') {
3323 *idx = (*idx * 10) + (*tmp -
'0');
3363 zend_string_delref(str_key);
3406 if (always_duplicate) {
file(string $filename, int $flags=0, $context=null)
prev(array|object &$array)
memset(ptr, 0, type->size)
unsigned const char * end
unsigned const char * pos
unsigned char key[REFLECTION_KEY_LEN]
#define zend_hash_str_add(...)
zend_long nNextFreeElement
uint32_t nInternalPointer
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
ZEND_API ZEND_COLD void zend_output_debug_string(bool trigger_break, const char *format,...)
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
#define perealloc2(ptr, size, copy_size, persistent)
#define pefree(ptr, persistent)
#define pemalloc(size, persistent)
#define FREE_HASHTABLE(ht)
#define erealloc(ptr, size)
#define ALLOC_HASHTABLE(ht)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define GC_REMOVE_FROM_BUFFER(p)
#define HT_ASSERT(ht, expr)
ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
ZEND_API HashTable *ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, bool always_duplicate)
ZEND_API HashTable *ZEND_FASTCALL _zend_new_array_0(void)
ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q)
ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
ZEND_API HashTable *ZEND_FASTCALL zend_symtable_to_proptable(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func)
ZEND_API void ZEND_FASTCALL zend_hash_real_init_packed(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args,...)
ZEND_API HashTable * zend_array_to_list(HashTable *source)
ZEND_API uint32_t zend_array_count(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
ZEND_API zval *ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, zend_string *key)
ZEND_API zend_result ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag)
ZEND_API HashTable *ZEND_FASTCALL _zend_new_array(uint32_t nSize)
ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval *pData)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData)
ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPosition pos)
ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, const HashPosition *pos)
ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q)
ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
ZEND_API void * zend_hash_str_find_ptr_lc(const HashTable *ht, const char *str, size_t len)
ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, bool packed)
ZEND_API void ZEND_FASTCALL zend_hash_iterators_advance(HashTable *ht, HashPosition step)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h)
ZEND_API zval *ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData)
ZEND_API zval *ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key)
ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, bool persistent)
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered)
ZEND_API void ZEND_FASTCALL zend_hash_packed_del_val(HashTable *ht, zval *zv)
ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, bool overwrite)
ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p)
ZEND_API zval *ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData)
ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
ZEND_API zval *ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, const zend_string *key)
ZEND_API zval *ZEND_FASTCALL zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData)
ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht)
ZEND_API zend_result ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, const HashPosition *pos)
ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTable *ht)
#define ZEND_HASH_IF_FULL_DO_RESIZE(ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData)
ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool packed)
ZEND_API zend_result ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
ZEND_API bool ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData)
ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
#define SET_INCONSISTENT(n)
ZEND_API HashTable *ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2)
ZEND_API zval *ZEND_FASTCALL zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
#define HT_ASSERT_RC1(ht)
ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval *array)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData)
void ZEND_FASTCALL zend_array_sort_ex(HashTable *ht, sort_func_t sort, bucket_compare_func_t compar, bool renumber)
ZEND_API void ZEND_FASTCALL zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_current_pos_ex(const HashTable *ht, HashPosition pos)
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
ZEND_API void * zend_hash_find_ptr_lc(const HashTable *ht, zend_string *key)
ZEND_API void ZEND_FASTCALL zend_hash_real_init_mixed(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
ZEND_API zval *ZEND_FASTCALL _zend_hash_index_find(const HashTable *ht, zend_ulong h)
ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
ZEND_API zval *ZEND_FASTCALL zend_hash_add(HashTable *ht, zend_string *key, zval *pData)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
ZEND_API const HashTable zend_empty_array
ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterators_lower_pos(HashTable *ht, HashPosition start)
ZEND_API void ZEND_FASTCALL zend_hash_discard(HashTable *ht, uint32_t nNumUsed)
ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, bucket_compare_func_t compar, bool renumber)
ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_current_pos(const HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add_or_update(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag)
ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to)
#define ZEND_HASH_FILL_ADD(_val)
int(* apply_func_arg_t)(zval *pDest, void *argument)
#define ZEND_HASH_MAP_FOREACH_VAL(ht, _val)
#define HASH_KEY_NON_EXISTENT
struct _zend_hash_key zend_hash_key
#define ZEND_HASH_APPLY_STOP
#define HASH_KEY_IS_STRING
#define HT_IS_WITHOUT_HOLES(ht)
#define ZEND_HASH_FILL_PACKED(ht)
bool(* merge_checker_func_t)(HashTable *target_ht, zval *source_data, zend_hash_key *hash_key, void *pParam)
int(* apply_func_args_t)(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key)
int(* bucket_compare_func_t)(Bucket *a, Bucket *b)
#define ZEND_HASH_APPLY_REMOVE
#define ZEND_HASH_FILL_END()
#define HT_DEC_ITERATORS_COUNT(ht)
#define HASH_FLAG_STATIC_KEYS
#define HT_HAS_STATIC_KEYS_ONLY(ht)
#define HT_ITERATORS_COUNT(ht)
#define HT_HAS_ITERATORS(ht)
#define HT_INC_ITERATORS_COUNT(ht)
#define zend_new_array(size)
#define ZEND_HANDLE_NUMERIC(key, idx)
#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val)
#define HASH_FLAG_UNINITIALIZED
#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key)
#define HT_ITERATORS_OVERFLOW(ht)
int(* apply_func_t)(zval *pDest)
#define HASH_UPDATE_INDIRECT
#define ZEND_HASH_FOREACH_END()
#define HASH_FLAG_CONSISTENCY
#define HASH_FLAG_HAS_EMPTY_IND
#define ZEND_HASH_FOREACH_VAL(ht, _val)
#define ZEND_HASH_MAP_FOREACH_KEY_VAL_IND(ht, _h, _key, _val)
#define MAX_LENGTH_OF_LONG
struct _zend_string zend_string
ZEND_API zend_string *ZEND_FASTCALL zend_long_to_str(zend_long num)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length)
#define ZEND_UNCOMPARABLE
#define ALLOCA_FLAG(name)
#define zend_never_inline
#define EXPECTED(condition)
#define do_alloca(p, use_heap)
#define zend_always_inline
#define ZEND_UNREACHABLE()
#define free_alloca(p, use_heap)
#define UNEXPECTED(condition)
ZEND_API zend_ulong ZEND_FASTCALL zend_hash_func(const char *str, size_t len)
#define ZSTR_IS_INTERNED(s)
int(* compare_func_t)(const void *, const void *)
#define HT_PACKED_SIZE_EX(nTableSize, nTableMask)
#define Z_ISREF_P(zval_p)
#define Z_TRY_ADDREF_P(pz)
#define GC_SET_REFCOUNT(p, rc)
#define Z_REFVAL_P(zval_p)
#define Z_ARRVAL_P(zval_p)
#define Z_OPT_REFCOUNTED_P(zval_p)
#define HT_HASH_TO_BUCKET(ht, idx)
#define ZVAL_STR_COPY(z, s)
struct _zend_array HashTable
void(* sort_func_t)(void *, size_t, size_t, compare_func_t, swap_func_t)
#define Z_TYPE_INFO_P(zval_p)
void(* dtor_func_t)(zval *pDest)
#define GC_MAKE_PERSISTENT_LOCAL(p)
#define HT_PACKED_SIZE(ht)
#define GC_TRY_UNPROTECT_RECURSION(p)
#define HT_SIZE_EX(nTableSize, nTableMask)
#define GC_TRY_PROTECT_RECURSION(p)
void(* copy_ctor_func_t)(zval *pElement)
#define GC_PERSISTENT_LOCAL
#define HT_HASH_RESET(ht)
#define HT_GET_DATA_ADDR(ht)
struct _zend_refcounted zend_refcounted
#define HT_SIZE_TO_MASK(nTableSize)
#define Z_TYPE_INFO(zval)
void(* swap_func_t)(void *, void *)
#define HT_HASH_EX(data, idx)
#define Z_INDIRECT_P(zval_p)
#define HT_SET_DATA_ADDR(ht, ptr)
ZEND_RESULT_CODE zend_result
#define IS_ARRAY_IMMUTABLE
struct _HashTableIterator HashTableIterator
#define IS_ARRAY_PERSISTENT
#define GC_NOT_COLLECTABLE
#define SEPARATE_ARRAY(zv)
#define HT_HASH_RESET_PACKED(ht)
#define GC_IS_RECURSIVE(p)
#define HT_PACKED_USED_SIZE(ht)
#define ZVAL_COPY_VALUE(z, v)