00001
00002
00003
00004
00005
00006
00007
00008 #ifndef _TOR_HT_H
00009 #define _TOR_HT_H
00010
00011 #define HT_HEAD(name, type) \
00012 struct name { \
00013 \
00014 struct type **hth_table; \
00015 \
00016 unsigned hth_table_length; \
00017 \
00018 unsigned hth_n_entries; \
00019 \
00020 unsigned hth_load_limit; \
00021 \
00022 int hth_prime_idx; \
00023 }
00024
00025 #define HT_INITIALIZER() \
00026 { NULL, 0, 0, 0, -1 }
00027
00028 #define HT_ENTRY(type) \
00029 struct { \
00030 struct type *hte_next; \
00031 unsigned hte_hash; \
00032 }
00033
00034 #define HT_EMPTY(head) \
00035 ((head)->hth_n_entries == 0)
00036
00037
00038 #define _HT_BUCKET(head, field, elm) \
00039 ((head)->hth_table[elm->field.hte_hash % head->hth_table_length])
00040
00041
00042 #define HT_SIZE(head) \
00043 ((head)->hth_n_entries)
00044
00045
00046 #define HT_MEM_USAGE(head) \
00047 (sizeof(*head) + (head)->hth_table_length * sizeof(void*))
00048
00049 #define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm))
00050 #define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm))
00051 #define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm))
00052 #define HT_REMOVE(name, head, elm) name##_HT_REMOVE((head), (elm))
00053 #define HT_START(name, head) name##_HT_START(head)
00054 #define HT_NEXT(name, head, elm) name##_HT_NEXT((head), (elm))
00055 #define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm))
00056 #define HT_CLEAR(name, head) name##_HT_CLEAR(head)
00057 #define HT_INIT(name, head) name##_HT_INIT(head)
00058
00059 static INLINE unsigned
00060 ht_improve_hash(unsigned h)
00061 {
00062
00063
00064 h += ~(h << 9);
00065 h ^= ((h >> 14) | (h << 18));
00066 h += (h << 4);
00067 h ^= ((h >> 10) | (h << 22));
00068 return h;
00069 }
00070
00071 #if 0
00072
00073 static INLINE unsigned
00074 ht_string_hash(const char *s)
00075 {
00076 unsigned h = 0;
00077 int m = 1;
00078 while (*s) {
00079 h += ((signed char)*s++)*m;
00080 m = (m<<5)-1;
00081 }
00082 return h;
00083 }
00084 #endif
00085
00087 static INLINE unsigned
00088 ht_string_hash(const char *s)
00089 {
00090 unsigned h;
00091 const unsigned char *cp = (const unsigned char *)s;
00092 h = *cp << 7;
00093 while (*cp) {
00094 h = (1000003*h) ^ *cp++;
00095 }
00096
00097 h ^= (unsigned)(cp-(const unsigned char*)s);
00098 return h;
00099 }
00100
00101 #define _HT_SET_HASH(elm, field, hashfn) \
00102 (elm)->field.hte_hash = hashfn(elm)
00103
00104 #define HT_FOREACH(x, name, head) \
00105 for ((x) = HT_START(name, head); \
00106 (x) != NULL; \
00107 (x) = HT_NEXT(name, head, x))
00108
00109 #define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \
00110 int name##_HT_GROW(struct name *ht, unsigned min_capacity); \
00111 void name##_HT_CLEAR(struct name *ht); \
00112 int _##name##_HT_REP_IS_BAD(const struct name *ht); \
00113 static INLINE void \
00114 name##_HT_INIT(struct name *head) { \
00115 head->hth_table_length = 0; \
00116 head->hth_table = NULL; \
00117 head->hth_n_entries = 0; \
00118 head->hth_load_limit = 0; \
00119 head->hth_prime_idx = -1; \
00120 } \
00121
00122 \
00123 static INLINE struct type ** \
00124 _##name##_HT_FIND_P(struct name *head, struct type *elm) \
00125 { \
00126 struct type **p; \
00127 if (!head->hth_table) \
00128 return NULL; \
00129 p = &_HT_BUCKET(head, field, elm); \
00130 while (*p) { \
00131 if (eqfn(*p, elm)) \
00132 return p; \
00133 p = &(*p)->field.hte_next; \
00134 } \
00135 return p; \
00136 } \
00137
00138 \
00139 static INLINE struct type * \
00140 name##_HT_FIND(const struct name *head, struct type *elm) \
00141 { \
00142 struct type **p; \
00143 struct name *h = (struct name *) head; \
00144 _HT_SET_HASH(elm, field, hashfn); \
00145 p = _##name##_HT_FIND_P(h, elm); \
00146 return p ? *p : NULL; \
00147 } \
00148
00149 \
00150 static INLINE void \
00151 name##_HT_INSERT(struct name *head, struct type *elm) \
00152 { \
00153 struct type **p; \
00154 if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
00155 name##_HT_GROW(head, head->hth_n_entries+1); \
00156 ++head->hth_n_entries; \
00157 _HT_SET_HASH(elm, field, hashfn); \
00158 p = &_HT_BUCKET(head, field, elm); \
00159 elm->field.hte_next = *p; \
00160 *p = elm; \
00161 } \
00162
00163
00164 \
00165 static INLINE struct type * \
00166 name##_HT_REPLACE(struct name *head, struct type *elm) \
00167 { \
00168 struct type **p, *r; \
00169 if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
00170 name##_HT_GROW(head, head->hth_n_entries+1); \
00171 _HT_SET_HASH(elm, field, hashfn); \
00172 p = _##name##_HT_FIND_P(head, elm); \
00173 r = *p; \
00174 *p = elm; \
00175 if (r && (r!=elm)) { \
00176 elm->field.hte_next = r->field.hte_next; \
00177 r->field.hte_next = NULL; \
00178 return r; \
00179 } else { \
00180 ++head->hth_n_entries; \
00181 return NULL; \
00182 } \
00183 } \
00184
00185 \
00186 static INLINE struct type * \
00187 name##_HT_REMOVE(struct name *head, struct type *elm) \
00188 { \
00189 struct type **p, *r; \
00190 _HT_SET_HASH(elm, field, hashfn); \
00191 p = _##name##_HT_FIND_P(head,elm); \
00192 if (!p || !*p) \
00193 return NULL; \
00194 r = *p; \
00195 *p = r->field.hte_next; \
00196 r->field.hte_next = NULL; \
00197 --head->hth_n_entries; \
00198 return r; \
00199 } \
00200
00201
00202
00203 \
00204 static INLINE void \
00205 name##_HT_FOREACH_FN(struct name *head, \
00206 int (*fn)(struct type *, void *), \
00207 void *data) \
00208 { \
00209 unsigned idx; \
00210 int remove; \
00211 struct type **p, **nextp, *next; \
00212 if (!head->hth_table) \
00213 return; \
00214 for (idx=0; idx < head->hth_table_length; ++idx) { \
00215 p = &head->hth_table[idx]; \
00216 while (*p) { \
00217 nextp = &(*p)->field.hte_next; \
00218 next = *nextp; \
00219 remove = fn(*p, data); \
00220 if (remove) { \
00221 --head->hth_n_entries; \
00222 *p = next; \
00223 } else { \
00224 p = nextp; \
00225 } \
00226 } \
00227 } \
00228 } \
00229
00230
00231 \
00232 static INLINE struct type ** \
00233 name##_HT_START(struct name *head) \
00234 { \
00235 unsigned b = 0; \
00236 while (b < head->hth_table_length) { \
00237 if (head->hth_table[b]) \
00238 return &head->hth_table[b]; \
00239 ++b; \
00240 } \
00241 return NULL; \
00242 } \
00243
00244
00245
00246
00247 \
00248 static INLINE struct type ** \
00249 name##_HT_NEXT(struct name *head, struct type **elm) \
00250 { \
00251 if ((*elm)->field.hte_next) { \
00252 return &(*elm)->field.hte_next; \
00253 } else { \
00254 unsigned b = ((*elm)->field.hte_hash % head->hth_table_length)+1; \
00255 while (b < head->hth_table_length) { \
00256 if (head->hth_table[b]) \
00257 return &head->hth_table[b]; \
00258 ++b; \
00259 } \
00260 return NULL; \
00261 } \
00262 } \
00263 static INLINE struct type ** \
00264 name##_HT_NEXT_RMV(struct name *head, struct type **elm) \
00265 { \
00266 unsigned h = (*elm)->field.hte_hash; \
00267 *elm = (*elm)->field.hte_next; \
00268 --head->hth_n_entries; \
00269 if (*elm) { \
00270 return elm; \
00271 } else { \
00272 unsigned b = (h % head->hth_table_length)+1; \
00273 while (b < head->hth_table_length) { \
00274 if (head->hth_table[b]) \
00275 return &head->hth_table[b]; \
00276 ++b; \
00277 } \
00278 return NULL; \
00279 } \
00280 }
00281
00282 #define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \
00283 reallocfn, freefn) \
00284 static unsigned name##_PRIMES[] = { \
00285 53, 97, 193, 389, \
00286 769, 1543, 3079, 6151, \
00287 12289, 24593, 49157, 98317, \
00288 196613, 393241, 786433, 1572869, \
00289 3145739, 6291469, 12582917, 25165843, \
00290 50331653, 100663319, 201326611, 402653189, \
00291 805306457, 1610612741 \
00292 }; \
00293 static unsigned name##_N_PRIMES = \
00294 (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0])); \
00295
00296
00297 \
00298 int \
00299 name##_HT_GROW(struct name *head, unsigned size) \
00300 { \
00301 unsigned new_len, new_load_limit; \
00302 int prime_idx; \
00303 struct type **new_table; \
00304 if (head->hth_prime_idx == (int)name##_N_PRIMES - 1) \
00305 return 0; \
00306 if (head->hth_load_limit > size) \
00307 return 0; \
00308 prime_idx = head->hth_prime_idx; \
00309 do { \
00310 new_len = name##_PRIMES[++prime_idx]; \
00311 new_load_limit = (unsigned)(load*new_len); \
00312 } while (new_load_limit <= size && \
00313 prime_idx < (int)name##_N_PRIMES); \
00314 if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \
00315 unsigned b; \
00316 memset(new_table, 0, new_len*sizeof(struct type*)); \
00317 for (b = 0; b < head->hth_table_length; ++b) { \
00318 struct type *elm, *next; \
00319 unsigned b2; \
00320 elm = head->hth_table[b]; \
00321 while (elm) { \
00322 next = elm->field.hte_next; \
00323 b2 = elm->field.hte_hash % new_len; \
00324 elm->field.hte_next = new_table[b2]; \
00325 new_table[b2] = elm; \
00326 elm = next; \
00327 } \
00328 } \
00329 if (head->hth_table) \
00330 freefn(head->hth_table); \
00331 head->hth_table = new_table; \
00332 } else { \
00333 unsigned b, b2; \
00334 new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \
00335 if (!new_table) return -1; \
00336 memset(new_table + head->hth_table_length, 0, \
00337 (new_len - head->hth_table_length)*sizeof(struct type*)); \
00338 for (b=0; b < head->hth_table_length; ++b) { \
00339 struct type *e, **pE; \
00340 for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) { \
00341 b2 = e->field.hte_hash % new_len; \
00342 if (b2 == b) { \
00343 pE = &e->field.hte_next; \
00344 } else { \
00345 *pE = e->field.hte_next; \
00346 e->field.hte_next = new_table[b2]; \
00347 new_table[b2] = e; \
00348 } \
00349 } \
00350 } \
00351 head->hth_table = new_table; \
00352 } \
00353 head->hth_table_length = new_len; \
00354 head->hth_prime_idx = prime_idx; \
00355 head->hth_load_limit = new_load_limit; \
00356 return 0; \
00357 } \
00358
00359 \
00360 void \
00361 name##_HT_CLEAR(struct name *head) \
00362 { \
00363 if (head->hth_table) \
00364 freefn(head->hth_table); \
00365 head->hth_table_length = 0; \
00366 name##_HT_INIT(head); \
00367 } \
00368
00369 \
00370 int \
00371 _##name##_HT_REP_IS_BAD(const struct name *head) \
00372 { \
00373 unsigned n, i; \
00374 struct type *elm; \
00375 if (!head->hth_table_length) { \
00376 if (!head->hth_table && !head->hth_n_entries && \
00377 !head->hth_load_limit && head->hth_prime_idx == -1) \
00378 return 0; \
00379 else \
00380 return 1; \
00381 } \
00382 if (!head->hth_table || head->hth_prime_idx < 0 || \
00383 !head->hth_load_limit) \
00384 return 2; \
00385 if (head->hth_n_entries > head->hth_load_limit) \
00386 return 3; \
00387 if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \
00388 return 4; \
00389 if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \
00390 return 5; \
00391 for (n = i = 0; i < head->hth_table_length; ++i) { \
00392 for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \
00393 if (elm->field.hte_hash != hashfn(elm)) \
00394 return 1000 + i; \
00395 if ((elm->field.hte_hash % head->hth_table_length) != i) \
00396 return 10000 + i; \
00397 ++n; \
00398 } \
00399 } \
00400 if (n != head->hth_n_entries) \
00401 return 6; \
00402 return 0; \
00403 }
00404
00408 #define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \
00409 { \
00410 struct name *_##var##_head = head; \
00411 eltype **var; \
00412 if (!_##var##_head->hth_table || \
00413 _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \
00414 name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \
00415 _HT_SET_HASH((elm), field, hashfn); \
00416 var = _##name##_HT_FIND_P(_##var##_head, (elm)); \
00417 if (*var) { \
00418 y; \
00419 } else { \
00420 n; \
00421 } \
00422 }
00423 #define _HT_FOI_INSERT(field, head, elm, newent, var) \
00424 { \
00425 newent->field.hte_hash = (elm)->field.hte_hash; \
00426 newent->field.hte_next = NULL; \
00427 *var = newent; \
00428 ++((head)->hth_n_entries); \
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 #endif
00471