This source file includes following definitions.
- ht_improve_hash
- ht_string_hash
- ht_string_hash
1
2
3
4
5
6
7
8 #ifndef _EVENT_HT_H
9 #define _EVENT_HT_H
10
11 #define HT_HEAD(name, type) \
12 struct name { \
13 \
14 struct type **hth_table; \
15 \
16 unsigned hth_table_length; \
17 \
18 unsigned hth_n_entries; \
19 \
20 unsigned hth_load_limit; \
21 \
22 int hth_prime_idx; \
23 }
24
25 #define HT_INITIALIZER() \
26 { NULL, 0, 0, 0, -1 }
27
28 #ifdef HT_CACHE_HASH_VALUES
29 #define HT_ENTRY(type) \
30 struct { \
31 struct type *hte_next; \
32 unsigned hte_hash; \
33 }
34 #else
35 #define HT_ENTRY(type) \
36 struct { \
37 struct type *hte_next; \
38 }
39 #endif
40
41 #define HT_EMPTY(head) \
42 ((head)->hth_n_entries == 0)
43
44
45 #define HT_SIZE(head) \
46 ((head)->hth_n_entries)
47
48 #define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm))
49 #define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm))
50 #define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm))
51 #define HT_REMOVE(name, head, elm) name##_HT_REMOVE((head), (elm))
52 #define HT_START(name, head) name##_HT_START(head)
53 #define HT_NEXT(name, head, elm) name##_HT_NEXT((head), (elm))
54 #define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm))
55 #define HT_CLEAR(name, head) name##_HT_CLEAR(head)
56 #define HT_INIT(name, head) name##_HT_INIT(head)
57
58 static inline unsigned
59 ht_improve_hash(unsigned h)
60 {
61
62
63 h += ~(h << 9);
64 h ^= ((h >> 14) | (h << 18));
65 h += (h << 4);
66 h ^= ((h >> 10) | (h << 22));
67 return h;
68 }
69
70 #if 0
71
72 static inline unsigned
73 ht_string_hash(const char *s)
74 {
75 unsigned h = 0;
76 int m = 1;
77 while (*s) {
78 h += ((signed char)*s++)*m;
79 m = (m<<5)-1;
80 }
81 return h;
82 }
83 #endif
84
85
86 static inline unsigned
87 ht_string_hash(const char *s)
88 {
89 unsigned h;
90 const unsigned char *cp = (const unsigned char *)s;
91 h = *cp << 7;
92 while (*cp) {
93 h = (1000003*h) ^ *cp++;
94 }
95
96 h ^= (unsigned)(cp-(const unsigned char*)s);
97 return h;
98 }
99
100 #ifdef HT_CACHE_HASH_VALUES
101 #define _HT_SET_HASH(elm, field, hashfn) \
102 do { (elm)->field.hte_hash = hashfn(elm); } while (0)
103 #define _HT_SET_HASHVAL(elm, field, val) \
104 do { (elm)->field.hte_hash = (val); } while (0)
105 #define _HT_ELT_HASH(elm, field, hashfn) \
106 ((elm)->field.hte_hash)
107 #else
108 #define _HT_SET_HASH(elm, field, hashfn) \
109 ((void)0)
110 #define _HT_ELT_HASH(elm, field, hashfn) \
111 (hashfn(elm))
112 #define _HT_SET_HASHVAL(elm, field, val) \
113 ((void)0)
114 #endif
115
116
117 #define _HT_BUCKET(head, field, elm, hashfn) \
118 ((head)->hth_table[_HT_ELT_HASH(elm,field,hashfn) % head->hth_table_length])
119
120 #define HT_FOREACH(x, name, head) \
121 for ((x) = HT_START(name, head); \
122 (x) != NULL; \
123 (x) = HT_NEXT(name, head, x))
124
125 #define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \
126 int name##_HT_GROW(struct name *ht, unsigned min_capacity); \
127 void name##_HT_CLEAR(struct name *ht); \
128 int _##name##_HT_REP_IS_BAD(const struct name *ht); \
129 static inline void \
130 name##_HT_INIT(struct name *head) { \
131 head->hth_table_length = 0; \
132 head->hth_table = NULL; \
133 head->hth_n_entries = 0; \
134 head->hth_load_limit = 0; \
135 head->hth_prime_idx = -1; \
136 } \
137
138 \
139 static inline struct type ** \
140 _##name##_HT_FIND_P(struct name *head, struct type *elm) \
141 { \
142 struct type **p; \
143 if (!head->hth_table) \
144 return NULL; \
145 p = &_HT_BUCKET(head, field, elm, hashfn); \
146 while (*p) { \
147 if (eqfn(*p, elm)) \
148 return p; \
149 p = &(*p)->field.hte_next; \
150 } \
151 return p; \
152 } \
153
154 \
155 static inline struct type * \
156 name##_HT_FIND(const struct name *head, struct type *elm) \
157 { \
158 struct type **p; \
159 struct name *h = (struct name *) head; \
160 _HT_SET_HASH(elm, field, hashfn); \
161 p = _##name##_HT_FIND_P(h, elm); \
162 return p ? *p : NULL; \
163 } \
164
165 \
166 static inline void \
167 name##_HT_INSERT(struct name *head, struct type *elm) \
168 { \
169 struct type **p; \
170 if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
171 name##_HT_GROW(head, head->hth_n_entries+1); \
172 ++head->hth_n_entries; \
173 _HT_SET_HASH(elm, field, hashfn); \
174 p = &_HT_BUCKET(head, field, elm, hashfn); \
175 elm->field.hte_next = *p; \
176 *p = elm; \
177 } \
178
179
180 \
181 static inline struct type * \
182 name##_HT_REPLACE(struct name *head, struct type *elm) \
183 { \
184 struct type **p, *r; \
185 if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
186 name##_HT_GROW(head, head->hth_n_entries+1); \
187 _HT_SET_HASH(elm, field, hashfn); \
188 p = _##name##_HT_FIND_P(head, elm); \
189 r = *p; \
190 *p = elm; \
191 if (r && (r!=elm)) { \
192 elm->field.hte_next = r->field.hte_next; \
193 r->field.hte_next = NULL; \
194 return r; \
195 } else { \
196 ++head->hth_n_entries; \
197 return NULL; \
198 } \
199 } \
200
201 \
202 static inline struct type * \
203 name##_HT_REMOVE(struct name *head, struct type *elm) \
204 { \
205 struct type **p, *r; \
206 _HT_SET_HASH(elm, field, hashfn); \
207 p = _##name##_HT_FIND_P(head,elm); \
208 if (!p || !*p) \
209 return NULL; \
210 r = *p; \
211 *p = r->field.hte_next; \
212 r->field.hte_next = NULL; \
213 --head->hth_n_entries; \
214 return r; \
215 } \
216
217
218
219 \
220 static inline void \
221 name##_HT_FOREACH_FN(struct name *head, \
222 int (*fn)(struct type *, void *), \
223 void *data) \
224 { \
225 unsigned idx; \
226 struct type **p, **nextp, *next; \
227 if (!head->hth_table) \
228 return; \
229 for (idx=0; idx < head->hth_table_length; ++idx) { \
230 p = &head->hth_table[idx]; \
231 while (*p) { \
232 nextp = &(*p)->field.hte_next; \
233 next = *nextp; \
234 if (fn(*p, data)) { \
235 --head->hth_n_entries; \
236 *p = next; \
237 } else { \
238 p = nextp; \
239 } \
240 } \
241 } \
242 } \
243
244
245 \
246 static inline struct type ** \
247 name##_HT_START(struct name *head) \
248 { \
249 unsigned b = 0; \
250 while (b < head->hth_table_length) { \
251 if (head->hth_table[b]) \
252 return &head->hth_table[b]; \
253 ++b; \
254 } \
255 return NULL; \
256 } \
257
258
259
260
261 \
262 static inline struct type ** \
263 name##_HT_NEXT(struct name *head, struct type **elm) \
264 { \
265 if ((*elm)->field.hte_next) { \
266 return &(*elm)->field.hte_next; \
267 } else { \
268 unsigned b = (_HT_ELT_HASH(*elm, field, hashfn) % head->hth_table_length)+1; \
269 while (b < head->hth_table_length) { \
270 if (head->hth_table[b]) \
271 return &head->hth_table[b]; \
272 ++b; \
273 } \
274 return NULL; \
275 } \
276 } \
277 static inline struct type ** \
278 name##_HT_NEXT_RMV(struct name *head, struct type **elm) \
279 { \
280 unsigned h = _HT_ELT_HASH(*elm, field, hashfn); \
281 *elm = (*elm)->field.hte_next; \
282 --head->hth_n_entries; \
283 if (*elm) { \
284 return elm; \
285 } else { \
286 unsigned b = (h % head->hth_table_length)+1; \
287 while (b < head->hth_table_length) { \
288 if (head->hth_table[b]) \
289 return &head->hth_table[b]; \
290 ++b; \
291 } \
292 return NULL; \
293 } \
294 }
295
296 #define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \
297 reallocfn, freefn) \
298 static unsigned name##_PRIMES[] = { \
299 53, 97, 193, 389, \
300 769, 1543, 3079, 6151, \
301 12289, 24593, 49157, 98317, \
302 196613, 393241, 786433, 1572869, \
303 3145739, 6291469, 12582917, 25165843, \
304 50331653, 100663319, 201326611, 402653189, \
305 805306457, 1610612741 \
306 }; \
307 static unsigned name##_N_PRIMES = \
308 (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0])); \
309
310
311 \
312 int \
313 name##_HT_GROW(struct name *head, unsigned size) \
314 { \
315 unsigned new_len, new_load_limit; \
316 int prime_idx; \
317 struct type **new_table; \
318 if (head->hth_prime_idx == (int)name##_N_PRIMES - 1) \
319 return 0; \
320 if (head->hth_load_limit > size) \
321 return 0; \
322 prime_idx = head->hth_prime_idx; \
323 do { \
324 new_len = name##_PRIMES[++prime_idx]; \
325 new_load_limit = (unsigned)(load*new_len); \
326 } while (new_load_limit <= size && \
327 prime_idx < (int)name##_N_PRIMES); \
328 if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \
329 unsigned b; \
330 memset(new_table, 0, new_len*sizeof(struct type*)); \
331 for (b = 0; b < head->hth_table_length; ++b) { \
332 struct type *elm, *next; \
333 unsigned b2; \
334 elm = head->hth_table[b]; \
335 while (elm) { \
336 next = elm->field.hte_next; \
337 b2 = _HT_ELT_HASH(elm, field, hashfn) % new_len; \
338 elm->field.hte_next = new_table[b2]; \
339 new_table[b2] = elm; \
340 elm = next; \
341 } \
342 } \
343 if (head->hth_table) \
344 freefn(head->hth_table); \
345 head->hth_table = new_table; \
346 } else { \
347 unsigned b, b2; \
348 new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \
349 if (!new_table) return -1; \
350 memset(new_table + head->hth_table_length, 0, \
351 (new_len - head->hth_table_length)*sizeof(struct type*)); \
352 for (b=0; b < head->hth_table_length; ++b) { \
353 struct type *e, **pE; \
354 for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) { \
355 b2 = _HT_ELT_HASH(e, field, hashfn) % new_len; \
356 if (b2 == b) { \
357 pE = &e->field.hte_next; \
358 } else { \
359 *pE = e->field.hte_next; \
360 e->field.hte_next = new_table[b2]; \
361 new_table[b2] = e; \
362 } \
363 } \
364 } \
365 head->hth_table = new_table; \
366 } \
367 head->hth_table_length = new_len; \
368 head->hth_prime_idx = prime_idx; \
369 head->hth_load_limit = new_load_limit; \
370 return 0; \
371 } \
372
373 \
374 void \
375 name##_HT_CLEAR(struct name *head) \
376 { \
377 if (head->hth_table) \
378 freefn(head->hth_table); \
379 head->hth_table_length = 0; \
380 name##_HT_INIT(head); \
381 } \
382
383 \
384 int \
385 _##name##_HT_REP_IS_BAD(const struct name *head) \
386 { \
387 unsigned n, i; \
388 struct type *elm; \
389 if (!head->hth_table_length) { \
390 if (!head->hth_table && !head->hth_n_entries && \
391 !head->hth_load_limit && head->hth_prime_idx == -1) \
392 return 0; \
393 else \
394 return 1; \
395 } \
396 if (!head->hth_table || head->hth_prime_idx < 0 || \
397 !head->hth_load_limit) \
398 return 2; \
399 if (head->hth_n_entries > head->hth_load_limit) \
400 return 3; \
401 if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \
402 return 4; \
403 if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \
404 return 5; \
405 for (n = i = 0; i < head->hth_table_length; ++i) { \
406 for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \
407 if (_HT_ELT_HASH(elm, field, hashfn) != hashfn(elm)) \
408 return 1000 + i; \
409 if ((_HT_ELT_HASH(elm, field, hashfn) % head->hth_table_length) != i) \
410 return 10000 + i; \
411 ++n; \
412 } \
413 } \
414 if (n != head->hth_n_entries) \
415 return 6; \
416 return 0; \
417 }
418
419
420
421
422 #define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \
423 { \
424 struct name *_##var##_head = head; \
425 struct eltype **var; \
426 if (!_##var##_head->hth_table || \
427 _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \
428 name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \
429 _HT_SET_HASH((elm), field, hashfn); \
430 var = _##name##_HT_FIND_P(_##var##_head, (elm)); \
431 if (*var) { \
432 y; \
433 } else { \
434 n; \
435 } \
436 }
437 #define _HT_FOI_INSERT(field, head, elm, newent, var) \
438 { \
439 _HT_SET_HASHVAL(newent, field, (elm)->field.hte_hash); \
440 newent->field.hte_next = NULL; \
441 *var = newent; \
442 ++((head)->hth_n_entries); \
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483 #endif
484