This source file includes following definitions.
- zend_inline_hash_func
- zend_symtable_update
- zend_symtable_del
- zend_symtable_find
- zend_symtable_exists
- zend_symtable_update_current_key_ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #ifndef ZEND_HASH_H
23 #define ZEND_HASH_H
24
25 #include <sys/types.h>
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 #define HASH_KEY_NON_EXISTANT HASH_KEY_NON_EXISTENT
32
33 #define HASH_UPDATE (1<<0)
34 #define HASH_ADD (1<<1)
35 #define HASH_NEXT_INSERT (1<<2)
36
37 #define HASH_DEL_KEY 0
38 #define HASH_DEL_INDEX 1
39 #define HASH_DEL_KEY_QUICK 2
40
41 #define HASH_UPDATE_KEY_IF_NONE 0
42 #define HASH_UPDATE_KEY_IF_BEFORE 1
43 #define HASH_UPDATE_KEY_IF_AFTER 2
44 #define HASH_UPDATE_KEY_ANYWAY 3
45
46 typedef ulong (*hash_func_t)(const char *arKey, uint nKeyLength);
47 typedef int (*compare_func_t)(const void *, const void * TSRMLS_DC);
48 typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t TSRMLS_DC);
49 typedef void (*dtor_func_t)(void *pDest);
50 typedef void (*copy_ctor_func_t)(void *pElement);
51 typedef void (*copy_ctor_param_func_t)(void *pElement, void *pParam);
52
53 struct _hashtable;
54
55 typedef struct bucket {
56 ulong h;
57 uint nKeyLength;
58 void *pData;
59 void *pDataPtr;
60 struct bucket *pListNext;
61 struct bucket *pListLast;
62 struct bucket *pNext;
63 struct bucket *pLast;
64 const char *arKey;
65 } Bucket;
66
67 typedef struct _hashtable {
68 uint nTableSize;
69 uint nTableMask;
70 uint nNumOfElements;
71 ulong nNextFreeElement;
72 Bucket *pInternalPointer;
73 Bucket *pListHead;
74 Bucket *pListTail;
75 Bucket **arBuckets;
76 dtor_func_t pDestructor;
77 zend_bool persistent;
78 unsigned char nApplyCount;
79 zend_bool bApplyProtection;
80 #if ZEND_DEBUG
81 int inconsistent;
82 #endif
83 } HashTable;
84
85
86 typedef struct _zend_hash_key {
87 const char *arKey;
88 uint nKeyLength;
89 ulong h;
90 } zend_hash_key;
91
92
93 typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam);
94
95 typedef Bucket* HashPosition;
96
97 BEGIN_EXTERN_C()
98
99
100 ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
101 ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
102 ZEND_API void zend_hash_destroy(HashTable *ht);
103 ZEND_API void zend_hash_clean(HashTable *ht);
104 #define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pDestructor), (persistent) ZEND_FILE_LINE_CC)
105 #define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC)
106
107
108 ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
109 #define zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
110 _zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
111 #define zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
112 _zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
113
114 ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
115 #define zend_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
116 _zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
117 #define zend_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
118 _zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
119
120 ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
121 #define zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
122 _zend_hash_index_update_or_next_insert(ht, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
123 #define zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
124 _zend_hash_index_update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
125
126 ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint nKeyLength);
127
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)(void *pDest TSRMLS_DC);
134 typedef int (*apply_func_arg_t)(void *pDest, void *argument TSRMLS_DC);
135 typedef int (*apply_func_args_t)(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
136
137 ZEND_API void zend_hash_graceful_destroy(HashTable *ht);
138 ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht);
139 ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC);
140 ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void * TSRMLS_DC);
141 ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int, ...);
142
143
144
145
146
147
148
149 ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC);
150
151
152
153 ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag);
154 #define zend_hash_del(ht, arKey, nKeyLength) \
155 zend_hash_del_key_or_index(ht, arKey, nKeyLength, 0, HASH_DEL_KEY)
156 #define zend_hash_quick_del(ht, arKey, nKeyLength, h) \
157 zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK)
158 #define zend_hash_index_del(ht, h) \
159 zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX)
160 #define zend_get_hash_value \
161 zend_hash_func
162
163
164 ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData);
165 ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void **pData);
166 ZEND_API int zend_hash_index_find(const HashTable *ht, ulong h, void **pData);
167
168
169 ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength);
170 ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h);
171 ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
172 ZEND_API ulong zend_hash_next_free_element(const HashTable *ht);
173
174
175 #define zend_hash_has_more_elements_ex(ht, pos) \
176 (zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTENT ? FAILURE : SUCCESS)
177 ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos);
178 ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos);
179 ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos);
180 ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos);
181 ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos);
182 ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
183 ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
184 ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
185 ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos);
186
187 typedef struct _HashPointer {
188 HashPosition pos;
189 ulong h;
190 } HashPointer;
191
192 ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr);
193 ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
194
195 #define zend_hash_has_more_elements(ht) \
196 zend_hash_has_more_elements_ex(ht, NULL)
197 #define zend_hash_move_forward(ht) \
198 zend_hash_move_forward_ex(ht, NULL)
199 #define zend_hash_move_backwards(ht) \
200 zend_hash_move_backwards_ex(ht, NULL)
201 #define zend_hash_get_current_key(ht, str_index, num_index, duplicate) \
202 zend_hash_get_current_key_ex(ht, str_index, NULL, num_index, duplicate, NULL)
203 #define zend_hash_get_current_key_zval(ht, key) \
204 zend_hash_get_current_key_zval_ex(ht, key, NULL)
205 #define zend_hash_get_current_key_type(ht) \
206 zend_hash_get_current_key_type_ex(ht, NULL)
207 #define zend_hash_get_current_data(ht, pData) \
208 zend_hash_get_current_data_ex(ht, pData, NULL)
209 #define zend_hash_internal_pointer_reset(ht) \
210 zend_hash_internal_pointer_reset_ex(ht, NULL)
211 #define zend_hash_internal_pointer_end(ht) \
212 zend_hash_internal_pointer_end_ex(ht, NULL)
213 #define zend_hash_update_current_key(ht, key_type, str_index, str_length, num_index) \
214 zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, HASH_UPDATE_KEY_ANYWAY, NULL)
215
216
217 ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
218 ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite ZEND_FILE_LINE_DC);
219 ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
220 ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC);
221 ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC);
222 ZEND_API int zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC);
223
224 #define zend_hash_merge(target, source, pCopyConstructor, tmp, size, overwrite) \
225 _zend_hash_merge(target, source, pCopyConstructor, tmp, size, overwrite ZEND_FILE_LINE_CC)
226
227 ZEND_API int zend_hash_num_elements(const HashTable *ht);
228
229 ZEND_API int zend_hash_rehash(HashTable *ht);
230 ZEND_API void zend_hash_reindex(HashTable *ht, zend_bool only_integer_keys);
231
232 ZEND_API void _zend_hash_splice(HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor, uint offset, uint length, void **list, uint list_count, HashTable *removed ZEND_FILE_LINE_DC);
233 #define zend_hash_splice(ht, nDataSize, pCopyConstructor, offset, length, list, list_count, removed) \
234 _zend_hash_splice(ht, nDataSize, pCopyConstructor, offset, length, list, list_count, removed ZEND_FILE_LINE_CC)
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 static inline ulong zend_inline_hash_func(const char *arKey, uint nKeyLength)
270 {
271 register ulong hash = 5381;
272
273
274 for (; nKeyLength >= 8; nKeyLength -= 8) {
275 hash = ((hash << 5) + hash) + *arKey++;
276 hash = ((hash << 5) + hash) + *arKey++;
277 hash = ((hash << 5) + hash) + *arKey++;
278 hash = ((hash << 5) + hash) + *arKey++;
279 hash = ((hash << 5) + hash) + *arKey++;
280 hash = ((hash << 5) + hash) + *arKey++;
281 hash = ((hash << 5) + hash) + *arKey++;
282 hash = ((hash << 5) + hash) + *arKey++;
283 }
284 switch (nKeyLength) {
285 case 7: hash = ((hash << 5) + hash) + *arKey++;
286 case 6: hash = ((hash << 5) + hash) + *arKey++;
287 case 5: hash = ((hash << 5) + hash) + *arKey++;
288 case 4: hash = ((hash << 5) + hash) + *arKey++;
289 case 3: hash = ((hash << 5) + hash) + *arKey++;
290 case 2: hash = ((hash << 5) + hash) + *arKey++;
291 case 1: hash = ((hash << 5) + hash) + *arKey++; break;
292 case 0: break;
293 EMPTY_SWITCH_DEFAULT_CASE()
294 }
295 return hash;
296 }
297
298
299 ZEND_API ulong zend_hash_func(const char *arKey, uint nKeyLength);
300
301 #if ZEND_DEBUG
302
303 void zend_hash_display_pListTail(const HashTable *ht);
304 void zend_hash_display(const HashTable *ht);
305 #endif
306
307 END_EXTERN_C()
308
309 #define ZEND_INIT_SYMTABLE(ht) \
310 ZEND_INIT_SYMTABLE_EX(ht, 2, 0)
311
312 #define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \
313 zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
314
315 #define ZEND_HANDLE_NUMERIC_EX(key, length, idx, func) do { \
316 register const char *tmp = key; \
317 \
318 if (*tmp == '-') { \
319 tmp++; \
320 } \
321 if (*tmp >= '0' && *tmp <= '9') { \
322 const char *end = key + length - 1; \
323 \
324 if ((*end != '\0') \
325 || (*tmp == '0' && length > 2) \
326 || (end - tmp > MAX_LENGTH_OF_LONG - 1) \
327 || (SIZEOF_LONG == 4 && \
328 end - tmp == MAX_LENGTH_OF_LONG - 1 && \
329 *tmp > '2')) { \
330 break; \
331 } \
332 idx = (*tmp - '0'); \
333 while (++tmp != end && *tmp >= '0' && *tmp <= '9') { \
334 idx = (idx * 10) + (*tmp - '0'); \
335 } \
336 if (tmp == end) { \
337 if (*key == '-') { \
338 if (idx-1 > LONG_MAX) { \
339 break; \
340 } \
341 idx = 0 - idx; \
342 } else if (idx > LONG_MAX) { \
343 break; \
344 } \
345 func; \
346 } \
347 } \
348 } while (0)
349
350 #define ZEND_HANDLE_NUMERIC(key, length, func) do { \
351 ulong idx; \
352 \
353 ZEND_HANDLE_NUMERIC_EX(key, length, idx, return func); \
354 } while (0)
355
356 static inline int zend_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) \
357 {
358 ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
359 return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
360 }
361
362
363 static inline int zend_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength)
364 {
365 ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
366 return zend_hash_del(ht, arKey, nKeyLength);
367 }
368
369
370 static inline int zend_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData)
371 {
372 ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
373 return zend_hash_find(ht, arKey, nKeyLength, pData);
374 }
375
376
377 static inline int zend_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength)
378 {
379 ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
380 return zend_hash_exists(ht, arKey, nKeyLength);
381 }
382
383 static inline int zend_symtable_update_current_key_ex(HashTable *ht, const char *arKey, uint nKeyLength, int mode, HashPosition *pos)
384 {
385 ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL, 0, idx, mode, pos));
386 return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, arKey, nKeyLength, 0, mode, pos);
387 }
388 #define zend_symtable_update_current_key(ht,arKey,nKeyLength,mode) \
389 zend_symtable_update_current_key_ex(ht, arKey, nKeyLength, mode, NULL)
390
391
392 #endif
393
394
395
396
397
398
399
400