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