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