zend_hash.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Zeev Suraski <zeev@php.net> |
  17. | Dmitry Stogov <dmitry@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #ifndef ZEND_HASH_H
  21. #define ZEND_HASH_H
  22. #include "zend.h"
  23. #define HASH_KEY_IS_STRING 1
  24. #define HASH_KEY_IS_LONG 2
  25. #define HASH_KEY_NON_EXISTENT 3
  26. #define HASH_UPDATE (1<<0)
  27. #define HASH_ADD (1<<1)
  28. #define HASH_UPDATE_INDIRECT (1<<2)
  29. #define HASH_ADD_NEW (1<<3)
  30. #define HASH_ADD_NEXT (1<<4)
  31. #define HASH_FLAG_CONSISTENCY ((1<<0) | (1<<1))
  32. #define HASH_FLAG_PACKED (1<<2)
  33. #define HASH_FLAG_INITIALIZED (1<<3)
  34. #define HASH_FLAG_STATIC_KEYS (1<<4) /* long and interned strings */
  35. #define HASH_FLAG_HAS_EMPTY_IND (1<<5)
  36. #define HASH_FLAG_ALLOW_COW_VIOLATION (1<<6)
  37. /* Only the low byte are real flags */
  38. #define HASH_FLAG_MASK 0xff
  39. #define HT_FLAGS(ht) (ht)->u.flags
  40. #define HT_IS_PACKED(ht) \
  41. ((HT_FLAGS(ht) & HASH_FLAG_PACKED) != 0)
  42. #define HT_IS_WITHOUT_HOLES(ht) \
  43. ((ht)->nNumUsed == (ht)->nNumOfElements)
  44. #define HT_HAS_STATIC_KEYS_ONLY(ht) \
  45. ((HT_FLAGS(ht) & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) != 0)
  46. #if ZEND_DEBUG
  47. # define HT_ALLOW_COW_VIOLATION(ht) HT_FLAGS(ht) |= HASH_FLAG_ALLOW_COW_VIOLATION
  48. #else
  49. # define HT_ALLOW_COW_VIOLATION(ht)
  50. #endif
  51. #define HT_ITERATORS_COUNT(ht) (ht)->u.v.nIteratorsCount
  52. #define HT_ITERATORS_OVERFLOW(ht) (HT_ITERATORS_COUNT(ht) == 0xff)
  53. #define HT_HAS_ITERATORS(ht) (HT_ITERATORS_COUNT(ht) != 0)
  54. #define HT_SET_ITERATORS_COUNT(ht, iters) \
  55. do { HT_ITERATORS_COUNT(ht) = (iters); } while (0)
  56. #define HT_INC_ITERATORS_COUNT(ht) \
  57. HT_SET_ITERATORS_COUNT(ht, HT_ITERATORS_COUNT(ht) + 1)
  58. #define HT_DEC_ITERATORS_COUNT(ht) \
  59. HT_SET_ITERATORS_COUNT(ht, HT_ITERATORS_COUNT(ht) - 1)
  60. extern ZEND_API const HashTable zend_empty_array;
  61. #define ZVAL_EMPTY_ARRAY(z) do { \
  62. zval *__z = (z); \
  63. Z_ARR_P(__z) = (zend_array*)&zend_empty_array; \
  64. Z_TYPE_INFO_P(__z) = IS_ARRAY; \
  65. } while (0)
  66. typedef struct _zend_hash_key {
  67. zend_ulong h;
  68. zend_string *key;
  69. } zend_hash_key;
  70. typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, zval *source_data, zend_hash_key *hash_key, void *pParam);
  71. BEGIN_EXTERN_C()
  72. /* startup/shutdown */
  73. ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent);
  74. ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht);
  75. ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht);
  76. #define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) \
  77. _zend_hash_init((ht), (nSize), (pDestructor), (persistent))
  78. #define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) \
  79. _zend_hash_init((ht), (nSize), (pDestructor), (persistent))
  80. ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, zend_bool packed);
  81. ZEND_API void ZEND_FASTCALL zend_hash_real_init_packed(HashTable *ht);
  82. ZEND_API void ZEND_FASTCALL zend_hash_real_init_mixed(HashTable *ht);
  83. ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht);
  84. ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht);
  85. ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, zend_bool packed);
  86. ZEND_API void ZEND_FASTCALL zend_hash_discard(HashTable *ht, uint32_t nNumUsed);
  87. /* additions/updates/changes */
  88. ZEND_API zval* ZEND_FASTCALL zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag);
  89. ZEND_API zval* ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key,zval *pData);
  90. ZEND_API zval* ZEND_FASTCALL zend_hash_update_ind(HashTable *ht, zend_string *key,zval *pData);
  91. ZEND_API zval* ZEND_FASTCALL zend_hash_add(HashTable *ht, zend_string *key,zval *pData);
  92. ZEND_API zval* ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key,zval *pData);
  93. ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_or_update(HashTable *ht, const char *key, size_t len, zval *pData, uint32_t flag);
  94. ZEND_API zval* ZEND_FASTCALL zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData);
  95. ZEND_API zval* ZEND_FASTCALL zend_hash_str_update_ind(HashTable *ht, const char *key, size_t len, zval *pData);
  96. ZEND_API zval* ZEND_FASTCALL zend_hash_str_add(HashTable *ht, const char *key, size_t len, zval *pData);
  97. ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_new(HashTable *ht, const char *key, size_t len, zval *pData);
  98. ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_or_update(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag);
  99. ZEND_API zval* ZEND_FASTCALL zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData);
  100. ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData);
  101. ZEND_API zval* ZEND_FASTCALL zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData);
  102. ZEND_API zval* ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData);
  103. ZEND_API zval* ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval *pData);
  104. ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h);
  105. ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key);
  106. ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *key, size_t len);
  107. #define ZEND_HASH_APPLY_KEEP 0
  108. #define ZEND_HASH_APPLY_REMOVE 1<<0
  109. #define ZEND_HASH_APPLY_STOP 1<<1
  110. typedef int (*apply_func_t)(zval *pDest);
  111. typedef int (*apply_func_arg_t)(zval *pDest, void *argument);
  112. typedef int (*apply_func_args_t)(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key);
  113. ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht);
  114. ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht);
  115. ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func);
  116. ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *);
  117. ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int, ...);
  118. /* This function should be used with special care (in other words,
  119. * it should usually not be used). When used with the ZEND_HASH_APPLY_STOP
  120. * return value, it assumes things about the order of the elements in the hash.
  121. * Also, it does not provide the same kind of reentrancy protection that
  122. * the standard apply functions do.
  123. */
  124. ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func);
  125. /* Deletes */
  126. ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key);
  127. ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key);
  128. ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *key, size_t len);
  129. ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *key, size_t len);
  130. ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h);
  131. ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p);
  132. /* Data retreival */
  133. ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key);
  134. ZEND_API zval* ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *key, size_t len);
  135. ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h);
  136. ZEND_API zval* ZEND_FASTCALL _zend_hash_index_find(const HashTable *ht, zend_ulong h);
  137. /* The same as zend_hash_find(), but hash value of the key must be already calculated */
  138. ZEND_API zval* ZEND_FASTCALL _zend_hash_find_known_hash(const HashTable *ht, zend_string *key);
  139. static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_string *key, zend_bool known_hash)
  140. {
  141. if (known_hash) {
  142. return _zend_hash_find_known_hash(ht, key);
  143. } else {
  144. return zend_hash_find(ht, key);
  145. }
  146. }
  147. #define ZEND_HASH_INDEX_FIND(_ht, _h, _ret, _not_found) do { \
  148. if (EXPECTED(HT_FLAGS(_ht) & HASH_FLAG_PACKED)) { \
  149. if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed)) { \
  150. _ret = &_ht->arData[_h].val; \
  151. if (UNEXPECTED(Z_TYPE_P(_ret) == IS_UNDEF)) { \
  152. goto _not_found; \
  153. } \
  154. } else { \
  155. goto _not_found; \
  156. } \
  157. } else { \
  158. _ret = _zend_hash_index_find(_ht, _h); \
  159. if (UNEXPECTED(_ret == NULL)) { \
  160. goto _not_found; \
  161. } \
  162. } \
  163. } while (0)
  164. /* Misc */
  165. ZEND_API zend_bool ZEND_FASTCALL zend_hash_exists(const HashTable *ht, zend_string *key);
  166. ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const char *str, size_t len);
  167. ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h);
  168. /* traversing */
  169. ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_current_pos(const HashTable *ht);
  170. #define zend_hash_has_more_elements_ex(ht, pos) \
  171. (zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTENT ? FAILURE : SUCCESS)
  172. ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos);
  173. ZEND_API int ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos);
  174. ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, HashPosition *pos);
  175. ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos);
  176. ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos);
  177. ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos);
  178. ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
  179. ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
  180. #define zend_hash_has_more_elements(ht) \
  181. zend_hash_has_more_elements_ex(ht, &(ht)->nInternalPointer)
  182. #define zend_hash_move_forward(ht) \
  183. zend_hash_move_forward_ex(ht, &(ht)->nInternalPointer)
  184. #define zend_hash_move_backwards(ht) \
  185. zend_hash_move_backwards_ex(ht, &(ht)->nInternalPointer)
  186. #define zend_hash_get_current_key(ht, str_index, num_index) \
  187. zend_hash_get_current_key_ex(ht, str_index, num_index, &(ht)->nInternalPointer)
  188. #define zend_hash_get_current_key_zval(ht, key) \
  189. zend_hash_get_current_key_zval_ex(ht, key, &(ht)->nInternalPointer)
  190. #define zend_hash_get_current_key_type(ht) \
  191. zend_hash_get_current_key_type_ex(ht, &(ht)->nInternalPointer)
  192. #define zend_hash_get_current_data(ht) \
  193. zend_hash_get_current_data_ex(ht, &(ht)->nInternalPointer)
  194. #define zend_hash_internal_pointer_reset(ht) \
  195. zend_hash_internal_pointer_reset_ex(ht, &(ht)->nInternalPointer)
  196. #define zend_hash_internal_pointer_end(ht) \
  197. zend_hash_internal_pointer_end_ex(ht, &(ht)->nInternalPointer)
  198. /* Copying, merging and sorting */
  199. ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor);
  200. ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite);
  201. 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);
  202. ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q);
  203. ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q);
  204. ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q);
  205. ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered);
  206. ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber);
  207. ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag);
  208. #define zend_hash_sort(ht, compare_func, renumber) \
  209. zend_hash_sort_ex(ht, zend_sort, compare_func, renumber)
  210. #define zend_hash_num_elements(ht) \
  211. (ht)->nNumOfElements
  212. #define zend_hash_next_free_element(ht) \
  213. (ht)->nNextFreeElement
  214. ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
  215. #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P)
  216. # define zend_new_array(size) \
  217. (__builtin_constant_p(size) ? \
  218. ((((uint32_t)(size)) <= HT_MIN_SIZE) ? \
  219. _zend_new_array_0() \
  220. : \
  221. _zend_new_array((size)) \
  222. ) \
  223. : \
  224. _zend_new_array((size)) \
  225. )
  226. #else
  227. # define zend_new_array(size) \
  228. _zend_new_array(size)
  229. #endif
  230. ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void);
  231. ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size);
  232. ZEND_API uint32_t zend_array_count(HashTable *ht);
  233. ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source);
  234. ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht);
  235. ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht);
  236. ZEND_API HashTable* ZEND_FASTCALL zend_symtable_to_proptable(HashTable *ht);
  237. ZEND_API HashTable* ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, zend_bool always_duplicate);
  238. ZEND_API int ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx);
  239. ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPosition pos);
  240. ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTable *ht);
  241. ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval *array);
  242. ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx);
  243. ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterators_lower_pos(HashTable *ht, HashPosition start);
  244. ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to);
  245. ZEND_API void ZEND_FASTCALL zend_hash_iterators_advance(HashTable *ht, HashPosition step);
  246. static zend_always_inline void zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to)
  247. {
  248. if (UNEXPECTED(HT_HAS_ITERATORS(ht))) {
  249. _zend_hash_iterators_update(ht, from, to);
  250. }
  251. }
  252. END_EXTERN_C()
  253. #define ZEND_INIT_SYMTABLE(ht) \
  254. ZEND_INIT_SYMTABLE_EX(ht, 8, 0)
  255. #define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \
  256. zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
  257. static zend_always_inline int _zend_handle_numeric_str(const char *key, size_t length, zend_ulong *idx)
  258. {
  259. const char *tmp = key;
  260. if (EXPECTED(*tmp > '9')) {
  261. return 0;
  262. } else if (*tmp < '0') {
  263. if (*tmp != '-') {
  264. return 0;
  265. }
  266. tmp++;
  267. if (*tmp > '9' || *tmp < '0') {
  268. return 0;
  269. }
  270. }
  271. return _zend_handle_numeric_str_ex(key, length, idx);
  272. }
  273. #define ZEND_HANDLE_NUMERIC_STR(key, length, idx) \
  274. _zend_handle_numeric_str(key, length, &idx)
  275. #define ZEND_HANDLE_NUMERIC(key, idx) \
  276. ZEND_HANDLE_NUMERIC_STR(ZSTR_VAL(key), ZSTR_LEN(key), idx)
  277. static zend_always_inline zval *zend_hash_find_ind(const HashTable *ht, zend_string *key)
  278. {
  279. zval *zv;
  280. zv = zend_hash_find(ht, key);
  281. return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ?
  282. ((Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF) ? Z_INDIRECT_P(zv) : NULL) : zv;
  283. }
  284. static zend_always_inline zval *zend_hash_find_ex_ind(const HashTable *ht, zend_string *key, zend_bool known_hash)
  285. {
  286. zval *zv;
  287. zv = zend_hash_find_ex(ht, key, known_hash);
  288. return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ?
  289. ((Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF) ? Z_INDIRECT_P(zv) : NULL) : zv;
  290. }
  291. static zend_always_inline int zend_hash_exists_ind(const HashTable *ht, zend_string *key)
  292. {
  293. zval *zv;
  294. zv = zend_hash_find(ht, key);
  295. return zv && (Z_TYPE_P(zv) != IS_INDIRECT ||
  296. Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF);
  297. }
  298. static zend_always_inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, size_t len)
  299. {
  300. zval *zv;
  301. zv = zend_hash_str_find(ht, str, len);
  302. return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ?
  303. ((Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF) ? Z_INDIRECT_P(zv) : NULL) : zv;
  304. }
  305. static zend_always_inline int zend_hash_str_exists_ind(const HashTable *ht, const char *str, size_t len)
  306. {
  307. zval *zv;
  308. zv = zend_hash_str_find(ht, str, len);
  309. return zv && (Z_TYPE_P(zv) != IS_INDIRECT ||
  310. Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF);
  311. }
  312. static zend_always_inline zval *zend_symtable_add_new(HashTable *ht, zend_string *key, zval *pData)
  313. {
  314. zend_ulong idx;
  315. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  316. return zend_hash_index_add_new(ht, idx, pData);
  317. } else {
  318. return zend_hash_add_new(ht, key, pData);
  319. }
  320. }
  321. static zend_always_inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData)
  322. {
  323. zend_ulong idx;
  324. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  325. return zend_hash_index_update(ht, idx, pData);
  326. } else {
  327. return zend_hash_update(ht, key, pData);
  328. }
  329. }
  330. static zend_always_inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zval *pData)
  331. {
  332. zend_ulong idx;
  333. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  334. return zend_hash_index_update(ht, idx, pData);
  335. } else {
  336. return zend_hash_update_ind(ht, key, pData);
  337. }
  338. }
  339. static zend_always_inline int zend_symtable_del(HashTable *ht, zend_string *key)
  340. {
  341. zend_ulong idx;
  342. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  343. return zend_hash_index_del(ht, idx);
  344. } else {
  345. return zend_hash_del(ht, key);
  346. }
  347. }
  348. static zend_always_inline int zend_symtable_del_ind(HashTable *ht, zend_string *key)
  349. {
  350. zend_ulong idx;
  351. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  352. return zend_hash_index_del(ht, idx);
  353. } else {
  354. return zend_hash_del_ind(ht, key);
  355. }
  356. }
  357. static zend_always_inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
  358. {
  359. zend_ulong idx;
  360. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  361. return zend_hash_index_find(ht, idx);
  362. } else {
  363. return zend_hash_find(ht, key);
  364. }
  365. }
  366. static zend_always_inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key)
  367. {
  368. zend_ulong idx;
  369. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  370. return zend_hash_index_find(ht, idx);
  371. } else {
  372. return zend_hash_find_ind(ht, key);
  373. }
  374. }
  375. static zend_always_inline int zend_symtable_exists(HashTable *ht, zend_string *key)
  376. {
  377. zend_ulong idx;
  378. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  379. return zend_hash_index_exists(ht, idx);
  380. } else {
  381. return zend_hash_exists(ht, key);
  382. }
  383. }
  384. static zend_always_inline int zend_symtable_exists_ind(HashTable *ht, zend_string *key)
  385. {
  386. zend_ulong idx;
  387. if (ZEND_HANDLE_NUMERIC(key, idx)) {
  388. return zend_hash_index_exists(ht, idx);
  389. } else {
  390. return zend_hash_exists_ind(ht, key);
  391. }
  392. }
  393. static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const char *str, size_t len, zval *pData)
  394. {
  395. zend_ulong idx;
  396. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  397. return zend_hash_index_update(ht, idx, pData);
  398. } else {
  399. return zend_hash_str_update(ht, str, len, pData);
  400. }
  401. }
  402. static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData)
  403. {
  404. zend_ulong idx;
  405. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  406. return zend_hash_index_update(ht, idx, pData);
  407. } else {
  408. return zend_hash_str_update_ind(ht, str, len, pData);
  409. }
  410. }
  411. static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *str, size_t len)
  412. {
  413. zend_ulong idx;
  414. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  415. return zend_hash_index_del(ht, idx);
  416. } else {
  417. return zend_hash_str_del(ht, str, len);
  418. }
  419. }
  420. static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, size_t len)
  421. {
  422. zend_ulong idx;
  423. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  424. return zend_hash_index_del(ht, idx);
  425. } else {
  426. return zend_hash_str_del_ind(ht, str, len);
  427. }
  428. }
  429. static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char *str, size_t len)
  430. {
  431. zend_ulong idx;
  432. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  433. return zend_hash_index_find(ht, idx);
  434. } else {
  435. return zend_hash_str_find(ht, str, len);
  436. }
  437. }
  438. static zend_always_inline int zend_symtable_str_exists(HashTable *ht, const char *str, size_t len)
  439. {
  440. zend_ulong idx;
  441. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  442. return zend_hash_index_exists(ht, idx);
  443. } else {
  444. return zend_hash_str_exists(ht, str, len);
  445. }
  446. }
  447. static zend_always_inline void *zend_hash_add_ptr(HashTable *ht, zend_string *key, void *pData)
  448. {
  449. zval tmp, *zv;
  450. ZVAL_PTR(&tmp, pData);
  451. zv = zend_hash_add(ht, key, &tmp);
  452. if (zv) {
  453. ZEND_ASSUME(Z_PTR_P(zv));
  454. return Z_PTR_P(zv);
  455. } else {
  456. return NULL;
  457. }
  458. }
  459. static zend_always_inline void *zend_hash_add_new_ptr(HashTable *ht, zend_string *key, void *pData)
  460. {
  461. zval tmp, *zv;
  462. ZVAL_PTR(&tmp, pData);
  463. zv = zend_hash_add_new(ht, key, &tmp);
  464. if (zv) {
  465. ZEND_ASSUME(Z_PTR_P(zv));
  466. return Z_PTR_P(zv);
  467. } else {
  468. return NULL;
  469. }
  470. }
  471. static zend_always_inline void *zend_hash_str_add_ptr(HashTable *ht, const char *str, size_t len, void *pData)
  472. {
  473. zval tmp, *zv;
  474. ZVAL_PTR(&tmp, pData);
  475. zv = zend_hash_str_add(ht, str, len, &tmp);
  476. if (zv) {
  477. ZEND_ASSUME(Z_PTR_P(zv));
  478. return Z_PTR_P(zv);
  479. } else {
  480. return NULL;
  481. }
  482. }
  483. static zend_always_inline void *zend_hash_str_add_new_ptr(HashTable *ht, const char *str, size_t len, void *pData)
  484. {
  485. zval tmp, *zv;
  486. ZVAL_PTR(&tmp, pData);
  487. zv = zend_hash_str_add_new(ht, str, len, &tmp);
  488. if (zv) {
  489. ZEND_ASSUME(Z_PTR_P(zv));
  490. return Z_PTR_P(zv);
  491. } else {
  492. return NULL;
  493. }
  494. }
  495. static zend_always_inline void *zend_hash_update_ptr(HashTable *ht, zend_string *key, void *pData)
  496. {
  497. zval tmp, *zv;
  498. ZVAL_PTR(&tmp, pData);
  499. zv = zend_hash_update(ht, key, &tmp);
  500. ZEND_ASSUME(Z_PTR_P(zv));
  501. return Z_PTR_P(zv);
  502. }
  503. static zend_always_inline void *zend_hash_str_update_ptr(HashTable *ht, const char *str, size_t len, void *pData)
  504. {
  505. zval tmp, *zv;
  506. ZVAL_PTR(&tmp, pData);
  507. zv = zend_hash_str_update(ht, str, len, &tmp);
  508. ZEND_ASSUME(Z_PTR_P(zv));
  509. return Z_PTR_P(zv);
  510. }
  511. static zend_always_inline void *zend_hash_add_mem(HashTable *ht, zend_string *key, void *pData, size_t size)
  512. {
  513. zval tmp, *zv;
  514. ZVAL_PTR(&tmp, NULL);
  515. if ((zv = zend_hash_add(ht, key, &tmp))) {
  516. Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  517. memcpy(Z_PTR_P(zv), pData, size);
  518. return Z_PTR_P(zv);
  519. }
  520. return NULL;
  521. }
  522. static zend_always_inline void *zend_hash_add_new_mem(HashTable *ht, zend_string *key, void *pData, size_t size)
  523. {
  524. zval tmp, *zv;
  525. ZVAL_PTR(&tmp, NULL);
  526. if ((zv = zend_hash_add_new(ht, key, &tmp))) {
  527. Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  528. memcpy(Z_PTR_P(zv), pData, size);
  529. return Z_PTR_P(zv);
  530. }
  531. return NULL;
  532. }
  533. static zend_always_inline void *zend_hash_str_add_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size)
  534. {
  535. zval tmp, *zv;
  536. ZVAL_PTR(&tmp, NULL);
  537. if ((zv = zend_hash_str_add(ht, str, len, &tmp))) {
  538. Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  539. memcpy(Z_PTR_P(zv), pData, size);
  540. return Z_PTR_P(zv);
  541. }
  542. return NULL;
  543. }
  544. static zend_always_inline void *zend_hash_str_add_new_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size)
  545. {
  546. zval tmp, *zv;
  547. ZVAL_PTR(&tmp, NULL);
  548. if ((zv = zend_hash_str_add_new(ht, str, len, &tmp))) {
  549. Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  550. memcpy(Z_PTR_P(zv), pData, size);
  551. return Z_PTR_P(zv);
  552. }
  553. return NULL;
  554. }
  555. static zend_always_inline void *zend_hash_update_mem(HashTable *ht, zend_string *key, void *pData, size_t size)
  556. {
  557. void *p;
  558. p = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  559. memcpy(p, pData, size);
  560. return zend_hash_update_ptr(ht, key, p);
  561. }
  562. static zend_always_inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size)
  563. {
  564. void *p;
  565. p = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  566. memcpy(p, pData, size);
  567. return zend_hash_str_update_ptr(ht, str, len, p);
  568. }
  569. static zend_always_inline void *zend_hash_index_add_ptr(HashTable *ht, zend_ulong h, void *pData)
  570. {
  571. zval tmp, *zv;
  572. ZVAL_PTR(&tmp, pData);
  573. zv = zend_hash_index_add(ht, h, &tmp);
  574. return zv ? Z_PTR_P(zv) : NULL;
  575. }
  576. static zend_always_inline void *zend_hash_index_add_new_ptr(HashTable *ht, zend_ulong h, void *pData)
  577. {
  578. zval tmp, *zv;
  579. ZVAL_PTR(&tmp, pData);
  580. zv = zend_hash_index_add_new(ht, h, &tmp);
  581. return zv ? Z_PTR_P(zv) : NULL;
  582. }
  583. static zend_always_inline void *zend_hash_index_update_ptr(HashTable *ht, zend_ulong h, void *pData)
  584. {
  585. zval tmp, *zv;
  586. ZVAL_PTR(&tmp, pData);
  587. zv = zend_hash_index_update(ht, h, &tmp);
  588. ZEND_ASSUME(Z_PTR_P(zv));
  589. return Z_PTR_P(zv);
  590. }
  591. static zend_always_inline void *zend_hash_index_add_mem(HashTable *ht, zend_ulong h, void *pData, size_t size)
  592. {
  593. zval tmp, *zv;
  594. ZVAL_PTR(&tmp, NULL);
  595. if ((zv = zend_hash_index_add(ht, h, &tmp))) {
  596. Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  597. memcpy(Z_PTR_P(zv), pData, size);
  598. return Z_PTR_P(zv);
  599. }
  600. return NULL;
  601. }
  602. static zend_always_inline void *zend_hash_next_index_insert_ptr(HashTable *ht, void *pData)
  603. {
  604. zval tmp, *zv;
  605. ZVAL_PTR(&tmp, pData);
  606. zv = zend_hash_next_index_insert(ht, &tmp);
  607. if (zv) {
  608. ZEND_ASSUME(Z_PTR_P(zv));
  609. return Z_PTR_P(zv);
  610. } else {
  611. return NULL;
  612. }
  613. }
  614. static zend_always_inline void *zend_hash_index_update_mem(HashTable *ht, zend_ulong h, void *pData, size_t size)
  615. {
  616. void *p;
  617. p = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  618. memcpy(p, pData, size);
  619. return zend_hash_index_update_ptr(ht, h, p);
  620. }
  621. static zend_always_inline void *zend_hash_next_index_insert_mem(HashTable *ht, void *pData, size_t size)
  622. {
  623. zval tmp, *zv;
  624. ZVAL_PTR(&tmp, NULL);
  625. if ((zv = zend_hash_next_index_insert(ht, &tmp))) {
  626. Z_PTR_P(zv) = pemalloc(size, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
  627. memcpy(Z_PTR_P(zv), pData, size);
  628. return Z_PTR_P(zv);
  629. }
  630. return NULL;
  631. }
  632. static zend_always_inline void *zend_hash_find_ptr(const HashTable *ht, zend_string *key)
  633. {
  634. zval *zv;
  635. zv = zend_hash_find(ht, key);
  636. if (zv) {
  637. ZEND_ASSUME(Z_PTR_P(zv));
  638. return Z_PTR_P(zv);
  639. } else {
  640. return NULL;
  641. }
  642. }
  643. static zend_always_inline void *zend_hash_find_ex_ptr(const HashTable *ht, zend_string *key, zend_bool known_hash)
  644. {
  645. zval *zv;
  646. zv = zend_hash_find_ex(ht, key, known_hash);
  647. if (zv) {
  648. ZEND_ASSUME(Z_PTR_P(zv));
  649. return Z_PTR_P(zv);
  650. } else {
  651. return NULL;
  652. }
  653. }
  654. static zend_always_inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str, size_t len)
  655. {
  656. zval *zv;
  657. zv = zend_hash_str_find(ht, str, len);
  658. if (zv) {
  659. ZEND_ASSUME(Z_PTR_P(zv));
  660. return Z_PTR_P(zv);
  661. } else {
  662. return NULL;
  663. }
  664. }
  665. static zend_always_inline void *zend_hash_index_find_ptr(const HashTable *ht, zend_ulong h)
  666. {
  667. zval *zv;
  668. zv = zend_hash_index_find(ht, h);
  669. if (zv) {
  670. ZEND_ASSUME(Z_PTR_P(zv));
  671. return Z_PTR_P(zv);
  672. } else {
  673. return NULL;
  674. }
  675. }
  676. static zend_always_inline zval *zend_hash_index_find_deref(HashTable *ht, zend_ulong h)
  677. {
  678. zval *zv = zend_hash_index_find(ht, h);
  679. if (zv) {
  680. ZVAL_DEREF(zv);
  681. }
  682. return zv;
  683. }
  684. static zend_always_inline zval *zend_hash_find_deref(HashTable *ht, zend_string *str)
  685. {
  686. zval *zv = zend_hash_find(ht, str);
  687. if (zv) {
  688. ZVAL_DEREF(zv);
  689. }
  690. return zv;
  691. }
  692. static zend_always_inline zval *zend_hash_str_find_deref(HashTable *ht, const char *str, size_t len)
  693. {
  694. zval *zv = zend_hash_str_find(ht, str, len);
  695. if (zv) {
  696. ZVAL_DEREF(zv);
  697. }
  698. return zv;
  699. }
  700. static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, size_t len)
  701. {
  702. zend_ulong idx;
  703. if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
  704. return zend_hash_index_find_ptr(ht, idx);
  705. } else {
  706. return zend_hash_str_find_ptr(ht, str, len);
  707. }
  708. }
  709. static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPosition *pos)
  710. {
  711. zval *zv;
  712. zv = zend_hash_get_current_data_ex(ht, pos);
  713. if (zv) {
  714. ZEND_ASSUME(Z_PTR_P(zv));
  715. return Z_PTR_P(zv);
  716. } else {
  717. return NULL;
  718. }
  719. }
  720. #define zend_hash_get_current_data_ptr(ht) \
  721. zend_hash_get_current_data_ptr_ex(ht, &(ht)->nInternalPointer)
  722. #define ZEND_HASH_FOREACH(_ht, indirect) do { \
  723. HashTable *__ht = (_ht); \
  724. Bucket *_p = __ht->arData; \
  725. Bucket *_end = _p + __ht->nNumUsed; \
  726. for (; _p != _end; _p++) { \
  727. zval *_z = &_p->val; \
  728. if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
  729. _z = Z_INDIRECT_P(_z); \
  730. } \
  731. if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue;
  732. #define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \
  733. HashTable *__ht = (_ht); \
  734. uint32_t _idx = __ht->nNumUsed; \
  735. Bucket *_p = __ht->arData + _idx; \
  736. zval *_z; \
  737. for (_idx = __ht->nNumUsed; _idx > 0; _idx--) { \
  738. _p--; \
  739. _z = &_p->val; \
  740. if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
  741. _z = Z_INDIRECT_P(_z); \
  742. } \
  743. if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue;
  744. #define ZEND_HASH_FOREACH_END() \
  745. } \
  746. } while (0)
  747. #define ZEND_HASH_FOREACH_END_DEL() \
  748. __ht->nNumOfElements--; \
  749. do { \
  750. uint32_t j = HT_IDX_TO_HASH(_idx - 1); \
  751. uint32_t nIndex = _p->h | __ht->nTableMask; \
  752. uint32_t i = HT_HASH(__ht, nIndex); \
  753. if (UNEXPECTED(j != i)) { \
  754. Bucket *prev = HT_HASH_TO_BUCKET(__ht, i); \
  755. while (Z_NEXT(prev->val) != j) { \
  756. i = Z_NEXT(prev->val); \
  757. prev = HT_HASH_TO_BUCKET(__ht, i); \
  758. } \
  759. Z_NEXT(prev->val) = Z_NEXT(_p->val); \
  760. } else { \
  761. HT_HASH(__ht, nIndex) = Z_NEXT(_p->val); \
  762. } \
  763. } while (0); \
  764. } \
  765. __ht->nNumUsed = _idx; \
  766. } while (0)
  767. #define ZEND_HASH_FOREACH_BUCKET(ht, _bucket) \
  768. ZEND_HASH_FOREACH(ht, 0); \
  769. _bucket = _p;
  770. #define ZEND_HASH_FOREACH_VAL(ht, _val) \
  771. ZEND_HASH_FOREACH(ht, 0); \
  772. _val = _z;
  773. #define ZEND_HASH_FOREACH_VAL_IND(ht, _val) \
  774. ZEND_HASH_FOREACH(ht, 1); \
  775. _val = _z;
  776. #define ZEND_HASH_FOREACH_PTR(ht, _ptr) \
  777. ZEND_HASH_FOREACH(ht, 0); \
  778. _ptr = Z_PTR_P(_z);
  779. #define ZEND_HASH_FOREACH_NUM_KEY(ht, _h) \
  780. ZEND_HASH_FOREACH(ht, 0); \
  781. _h = _p->h;
  782. #define ZEND_HASH_FOREACH_STR_KEY(ht, _key) \
  783. ZEND_HASH_FOREACH(ht, 0); \
  784. _key = _p->key;
  785. #define ZEND_HASH_FOREACH_KEY(ht, _h, _key) \
  786. ZEND_HASH_FOREACH(ht, 0); \
  787. _h = _p->h; \
  788. _key = _p->key;
  789. #define ZEND_HASH_FOREACH_NUM_KEY_VAL(ht, _h, _val) \
  790. ZEND_HASH_FOREACH(ht, 0); \
  791. _h = _p->h; \
  792. _val = _z;
  793. #define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val) \
  794. ZEND_HASH_FOREACH(ht, 0); \
  795. _key = _p->key; \
  796. _val = _z;
  797. #define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \
  798. ZEND_HASH_FOREACH(ht, 0); \
  799. _h = _p->h; \
  800. _key = _p->key; \
  801. _val = _z;
  802. #define ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, _key, _val) \
  803. ZEND_HASH_FOREACH(ht, 1); \
  804. _key = _p->key; \
  805. _val = _z;
  806. #define ZEND_HASH_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \
  807. ZEND_HASH_FOREACH(ht, 1); \
  808. _h = _p->h; \
  809. _key = _p->key; \
  810. _val = _z;
  811. #define ZEND_HASH_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \
  812. ZEND_HASH_FOREACH(ht, 0); \
  813. _h = _p->h; \
  814. _ptr = Z_PTR_P(_z);
  815. #define ZEND_HASH_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \
  816. ZEND_HASH_FOREACH(ht, 0); \
  817. _key = _p->key; \
  818. _ptr = Z_PTR_P(_z);
  819. #define ZEND_HASH_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \
  820. ZEND_HASH_FOREACH(ht, 0); \
  821. _h = _p->h; \
  822. _key = _p->key; \
  823. _ptr = Z_PTR_P(_z);
  824. #define ZEND_HASH_REVERSE_FOREACH_BUCKET(ht, _bucket) \
  825. ZEND_HASH_REVERSE_FOREACH(ht, 0); \
  826. _bucket = _p;
  827. #define ZEND_HASH_REVERSE_FOREACH_VAL(ht, _val) \
  828. ZEND_HASH_REVERSE_FOREACH(ht, 0); \
  829. _val = _z;
  830. #define ZEND_HASH_REVERSE_FOREACH_PTR(ht, _ptr) \
  831. ZEND_HASH_REVERSE_FOREACH(ht, 0); \
  832. _ptr = Z_PTR_P(_z);
  833. #define ZEND_HASH_REVERSE_FOREACH_VAL_IND(ht, _val) \
  834. ZEND_HASH_REVERSE_FOREACH(ht, 1); \
  835. _val = _z;
  836. #define ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(ht, _key, _val) \
  837. ZEND_HASH_REVERSE_FOREACH(ht, 0); \
  838. _key = _p->key; \
  839. _val = _z;
  840. #define ZEND_HASH_REVERSE_FOREACH_KEY_VAL(ht, _h, _key, _val) \
  841. ZEND_HASH_REVERSE_FOREACH(ht, 0); \
  842. _h = _p->h; \
  843. _key = _p->key; \
  844. _val = _z;
  845. #define ZEND_HASH_REVERSE_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \
  846. ZEND_HASH_REVERSE_FOREACH(ht, 1); \
  847. _h = _p->h; \
  848. _key = _p->key; \
  849. _val = _z;
  850. /* The following macros are useful to insert a sequence of new elements
  851. * of packed array. They may be use insted of series of
  852. * zend_hash_next_index_insert_new()
  853. * (HashTable must have enough free buckets).
  854. */
  855. #define ZEND_HASH_FILL_PACKED(ht) do { \
  856. HashTable *__fill_ht = (ht); \
  857. Bucket *__fill_bkt = __fill_ht->arData + __fill_ht->nNumUsed; \
  858. uint32_t __fill_idx = __fill_ht->nNumUsed; \
  859. ZEND_ASSERT(HT_FLAGS(__fill_ht) & HASH_FLAG_PACKED);
  860. #define ZEND_HASH_FILL_ADD(_val) do { \
  861. ZVAL_COPY_VALUE(&__fill_bkt->val, _val); \
  862. __fill_bkt->h = (__fill_idx); \
  863. __fill_bkt->key = NULL; \
  864. __fill_bkt++; \
  865. __fill_idx++; \
  866. } while (0)
  867. #define ZEND_HASH_FILL_END() \
  868. __fill_ht->nNumUsed = __fill_idx; \
  869. __fill_ht->nNumOfElements = __fill_idx; \
  870. __fill_ht->nNextFreeElement = __fill_idx; \
  871. __fill_ht->nInternalPointer = 0; \
  872. } while (0)
  873. static zend_always_inline zval *_zend_hash_append_ex(HashTable *ht, zend_string *key, zval *zv, int interned)
  874. {
  875. uint32_t idx = ht->nNumUsed++;
  876. uint32_t nIndex;
  877. Bucket *p = ht->arData + idx;
  878. ZVAL_COPY_VALUE(&p->val, zv);
  879. if (!interned && !ZSTR_IS_INTERNED(key)) {
  880. HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
  881. zend_string_addref(key);
  882. zend_string_hash_val(key);
  883. }
  884. p->key = key;
  885. p->h = ZSTR_H(key);
  886. nIndex = (uint32_t)p->h | ht->nTableMask;
  887. Z_NEXT(p->val) = HT_HASH(ht, nIndex);
  888. HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
  889. ht->nNumOfElements++;
  890. return &p->val;
  891. }
  892. static zend_always_inline zval *_zend_hash_append(HashTable *ht, zend_string *key, zval *zv)
  893. {
  894. return _zend_hash_append_ex(ht, key, zv, 0);
  895. }
  896. static zend_always_inline zval *_zend_hash_append_ptr_ex(HashTable *ht, zend_string *key, void *ptr, int interned)
  897. {
  898. uint32_t idx = ht->nNumUsed++;
  899. uint32_t nIndex;
  900. Bucket *p = ht->arData + idx;
  901. ZVAL_PTR(&p->val, ptr);
  902. if (!interned && !ZSTR_IS_INTERNED(key)) {
  903. HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
  904. zend_string_addref(key);
  905. zend_string_hash_val(key);
  906. }
  907. p->key = key;
  908. p->h = ZSTR_H(key);
  909. nIndex = (uint32_t)p->h | ht->nTableMask;
  910. Z_NEXT(p->val) = HT_HASH(ht, nIndex);
  911. HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
  912. ht->nNumOfElements++;
  913. return &p->val;
  914. }
  915. static zend_always_inline zval *_zend_hash_append_ptr(HashTable *ht, zend_string *key, void *ptr)
  916. {
  917. return _zend_hash_append_ptr_ex(ht, key, ptr, 0);
  918. }
  919. static zend_always_inline void _zend_hash_append_ind(HashTable *ht, zend_string *key, zval *ptr)
  920. {
  921. uint32_t idx = ht->nNumUsed++;
  922. uint32_t nIndex;
  923. Bucket *p = ht->arData + idx;
  924. ZVAL_INDIRECT(&p->val, ptr);
  925. if (!ZSTR_IS_INTERNED(key)) {
  926. HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
  927. zend_string_addref(key);
  928. zend_string_hash_val(key);
  929. }
  930. p->key = key;
  931. p->h = ZSTR_H(key);
  932. nIndex = (uint32_t)p->h | ht->nTableMask;
  933. Z_NEXT(p->val) = HT_HASH(ht, nIndex);
  934. HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
  935. ht->nNumOfElements++;
  936. }
  937. #endif /* ZEND_HASH_H */
  938. /*
  939. * Local variables:
  940. * tab-width: 4
  941. * c-basic-offset: 4
  942. * indent-tabs-mode: t
  943. * End:
  944. * vim600: sw=4 ts=4 fdm=marker
  945. * vim<600: sw=4 ts=4
  946. */