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