tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

ht.h (35489B)


      1 /* Copyright (c) 2002, Christopher Clark.
      2 * Copyright (c) 2005-2006, Nick Mathewson.
      3 * Copyright (c) 2007-2019, The Tor Project, Inc. */
      4 /* See license at end. */
      5 
      6 /* Based on ideas by Christopher Clark and interfaces from Niels Provos. */
      7 
      8 /*
      9  These macros provide an intrustive implementation for a typesafe chaining
     10  hash table, loosely based on the BSD tree.h and queue.h macros.  Here's
     11  how to use them.
     12 
     13  First, pick a the structure that you'll be storing in the hashtable. Let's
     14  say that's  "struct dinosaur".  To this structure, you add an HT_ENTRY()
     15  member, as such:
     16 
     17      struct dinosaur {
     18          HT_ENTRY(dinosaur) node; // The name inside the () must match the
     19                                   // struct.
     20 
     21          // These are just fields from the dinosaur structure...
     22          long dinosaur_id;
     23          char *name;
     24          long age;
     25          int is_ornithischian;
     26          int is_herbivorous;
     27      };
     28 
     29  You can declare the hashtable itself as:
     30 
     31      HT_HEAD(dinosaur_ht, dinosaur);
     32 
     33  This declares a new 'struct dinosaur_ht' type.
     34 
     35  Now you need to declare two functions to help implement the hashtable: one
     36  compares two dinosaurs for equality, and one computes the hash of a
     37  dinosaur.  Let's say that two dinosaurs are equal if they have the same ID
     38  and name.
     39 
     40     int
     41     dinosaurs_equal(const struct dinosaur *d1, const struct dinosaur *d2)
     42     {
     43        return d1->dinosaur_id == d2->dinosaur_id &&
     44               0 == strcmp(d1->name, d2->name);
     45     }
     46 
     47     unsigned
     48     dinosaur_hash(const struct dinosaur *d)
     49     {
     50        // This is a very bad hash function. Use siphash24g instead.
     51        return (d->dinosaur_id + d->name[0] ) * 1337 + d->name[1] * 1337;
     52     }
     53 
     54  Now you'll need to declare the functions that manipulate the hash table.
     55  To do this, you put this declaration either in a header file, or inside
     56  a regular module, depending on what visibility you want.
     57 
     58     HT_PROTOTYPE(dinosaur_ht, // The name of the hashtable struct
     59                  dinosaur,    // The name of the element struct,
     60                  node,        // The name of HT_ENTRY member
     61                  dinosaur_hash, dinosaurs_equal);
     62 
     63  Later, inside a C function, you use this macro to declare the hashtable
     64  functions.
     65 
     66     HT_GENERATE2(dinosaur_ht, dinosaur, node, dinosaur_hash, dinosaurs_equal,
     67                  0.6, tor_reallocarray, tor_free_);
     68 
     69  Note the use of tor_free_, not tor_free.  The 0.6 is magic.
     70 
     71  Now you can use the hashtable!  You can initialize one with
     72 
     73     struct dinosaur_ht my_dinos = HT_INITIALIZER();
     74 
     75  Or create one in core with
     76 
     77     struct dinosaur_ht *dinos = tor_malloc(sizeof(dinosaur_ht));
     78     HT_INIT(dinosaur_ht, dinos);
     79 
     80  To the hashtable, you use the HT_FOO(dinosaur_ht, ...) macros.  For
     81  example, to put new_dino into dinos, you say:
     82 
     83     HT_REPLACE(dinosaur_ht, dinos, new_dino);
     84 
     85  If you're searching for an element, you need to use a dummy 'key' element in
     86  the search.  For example.
     87 
     88     struct dinosaur dino_key;
     89     dino_key.dinosaur_id = 12345;
     90     dino_key.name = tor_strdup("Atrociraptor");
     91 
     92     struct dinosaur *found = HT_FIND(dinosaurs_ht, dinos, &dino_key);
     93 
     94  Have fun with your hash table!
     95 
     96 */
     97 
     98 #ifndef HT_H_INCLUDED_
     99 #define HT_H_INCLUDED_
    100 
    101 #define HT_HEAD(name, type)                                             \
    102  struct name {                                                         \
    103    /* The hash table itself. */                                        \
    104    struct type **hth_table;                                            \
    105    /* How long is the hash table? */                                   \
    106    unsigned hth_table_length;                                          \
    107    /* How many elements does the table contain? */                     \
    108    unsigned hth_n_entries;                                             \
    109    /* How many elements will we allow in the table before resizing it? */ \
    110    unsigned hth_load_limit;                                            \
    111    /* Position of hth_table_length in the primes table. */             \
    112    int hth_prime_idx;                                                  \
    113  }
    114 
    115 #define HT_INITIALIZER()                        \
    116  { NULL, 0, 0, 0, -1 }
    117 
    118 #ifdef HT_NO_CACHE_HASH_VALUES
    119 #define HT_ENTRY(type)                          \
    120  struct {                                      \
    121    struct type *hte_next;                      \
    122  }
    123 #else
    124 #define HT_ENTRY(type)                          \
    125  struct {                                      \
    126    struct type *hte_next;                      \
    127    unsigned hte_hash;                          \
    128  }
    129 #endif
    130 
    131 /* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
    132 #define HT_EMPTY(head)                          \
    133  (((head)->hth_n_entries == 0) || 0)
    134 
    135 /* How many elements in 'head'? */
    136 #define HT_SIZE(head)                           \
    137  ((head)->hth_n_entries)
    138 
    139 /* Return memory usage for a hashtable (not counting the entries themselves) */
    140 #define HT_MEM_USAGE(head)                         \
    141  (sizeof(*head) + (head)->hth_table_length * sizeof(void*))
    142 
    143 #define HT_FIND(name, head, elm)     name##_HT_FIND((head), (elm))
    144 #define HT_INSERT(name, head, elm)   name##_HT_INSERT((head), (elm))
    145 #define HT_REPLACE(name, head, elm)  name##_HT_REPLACE((head), (elm))
    146 #define HT_REMOVE(name, head, elm)   name##_HT_REMOVE((head), (elm))
    147 #define HT_START(name, head)         name##_HT_START(head)
    148 #define HT_NEXT(name, head, elm)     name##_HT_NEXT((head), (elm))
    149 #define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm))
    150 #define HT_CLEAR(name, head)         name##_HT_CLEAR(head)
    151 #define HT_INIT(name, head)          name##_HT_INIT(head)
    152 #define HT_REP_IS_BAD_(name, head)    name##_HT_REP_IS_BAD_(head)
    153 #define HT_FOREACH_FN(name, head, fn, data) \
    154   name##_HT_FOREACH_FN((head), (fn), (data))
    155 /* Helper: */
    156 static inline unsigned
    157 ht_improve_hash(unsigned h)
    158 {
    159  /* Aim to protect against poor hash functions by adding logic here
    160   * - logic taken from java 1.4 hashtable source */
    161  h += ~(h << 9);
    162  h ^=  ((h >> 14) | (h << 18)); /* >>> */
    163  h +=  (h << 4);
    164  h ^=  ((h >> 10) | (h << 22)); /* >>> */
    165  return h;
    166 }
    167 
    168 #if 0
    169 /** Basic string hash function, from Java standard String.hashCode(). */
    170 static inline unsigned
    171 ht_string_hash(const char *s)
    172 {
    173  unsigned h = 0;
    174  int m = 1;
    175  while (*s) {
    176    h += ((signed char)*s++)*m;
    177    m = (m<<5)-1; /* m *= 31 */
    178  }
    179  return h;
    180 }
    181 #endif
    182 
    183 #if 0
    184 /** Basic string hash function, from Python's str.__hash__() */
    185 static inline unsigned
    186 ht_string_hash(const char *s)
    187 {
    188  unsigned h;
    189  const unsigned char *cp = (const unsigned char *)s;
    190  h = *cp << 7;
    191  while (*cp) {
    192    h = (1000003*h) ^ *cp++;
    193  }
    194  /* This conversion truncates the length of the string, but that's ok. */
    195  h ^= (unsigned)(cp-(const unsigned char*)s);
    196  return h;
    197 }
    198 #endif
    199 
    200 #ifndef HT_NO_CACHE_HASH_VALUES
    201 #define HT_SET_HASH_(elm, field, hashfn)        \
    202    do { (elm)->field.hte_hash = hashfn(elm); } while (0)
    203 #define HT_SET_HASHVAL_(elm, field, val)        \
    204    do { (elm)->field.hte_hash = (val); } while (0)
    205 #define HT_ELT_HASH_(elm, field, hashfn)        \
    206    ((elm)->field.hte_hash)
    207 #else
    208 #define HT_SET_HASH_(elm, field, hashfn)        \
    209    ((void)0)
    210 #define HT_ELT_HASH_(elm, field, hashfn)        \
    211    (hashfn(elm))
    212 #define HT_SET_HASHVAL_(elm, field, val)        \
    213        ((void)0)
    214 #endif
    215 
    216 #define HT_BUCKET_NUM_(head, field, elm, hashfn)                        \
    217  (HT_ELT_HASH_(elm,field,hashfn) % head->hth_table_length)
    218 
    219 /* Helper: alias for the bucket containing 'elm'. */
    220 #define HT_BUCKET_(head, field, elm, hashfn)                            \
    221  ((head)->hth_table[HT_BUCKET_NUM_(head, field, elm, hashfn)])
    222 
    223 #define HT_FOREACH(x, name, head)                 \
    224  for ((x) = HT_START(name, head);                \
    225       (x) != NULL;                               \
    226       (x) = HT_NEXT(name, head, x))
    227 
    228 #ifndef HT_NDEBUG
    229 #include "lib/err/torerr.h"
    230 #define HT_ASSERT_(x) raw_assert(x)
    231 #else
    232 #define HT_ASSERT_(x) (void)0
    233 #endif
    234 
    235 /* Macro put at the end of the end of a macro definition so that it
    236 * consumes the following semicolon at file scope. Used only inside ht.h. */
    237 #define HT_EAT_SEMICOLON__ struct ht_semicolon_eater
    238 
    239 #define HT_PROTOTYPE(name, type, field, hashfn, eqfn)                   \
    240  int name##_HT_GROW(struct name *ht, unsigned min_capacity);           \
    241  void name##_HT_CLEAR(struct name *ht);                                \
    242  int name##_HT_REP_IS_BAD_(const struct name *ht);                     \
    243  static inline void                                                    \
    244  name##_HT_INIT(struct name *head) {                                   \
    245    head->hth_table_length = 0;                                         \
    246    head->hth_table = NULL;                                             \
    247    head->hth_n_entries = 0;                                            \
    248    head->hth_load_limit = 0;                                           \
    249    head->hth_prime_idx = -1;                                           \
    250  }                                                                     \
    251  /* Helper: returns a pointer to the right location in the table       \
    252   * 'head' to find or insert the element 'elm'. */                     \
    253  static inline struct type **                                          \
    254  name##_HT_FIND_P_(struct name *head, struct type *elm)                \
    255  {                                                                     \
    256    struct type **p;                                                    \
    257    if (!head->hth_table)                                               \
    258      return NULL;                                                      \
    259    p = &HT_BUCKET_(head, field, elm, hashfn);                          \
    260    while (*p) {                                                        \
    261      if (eqfn(*p, elm))                                                \
    262        return p;                                                       \
    263      p = &(*p)->field.hte_next;                                        \
    264    }                                                                   \
    265    return p;                                                           \
    266  }                                                                     \
    267  /* Return a pointer to the element in the table 'head' matching 'elm', \
    268   * or NULL if no such element exists */                               \
    269  ATTR_UNUSED static inline struct type *                               \
    270  name##_HT_FIND(const struct name *head, struct type *elm)             \
    271  {                                                                     \
    272    struct type **p;                                                    \
    273    struct name *h = (struct name *) head;                              \
    274    HT_SET_HASH_(elm, field, hashfn);                                   \
    275    p = name##_HT_FIND_P_(h, elm);                                      \
    276    return p ? *p : NULL;                                               \
    277  }                                                                     \
    278  /* Insert the element 'elm' into the table 'head'.  Do not call this  \
    279   * function if the table might already contain a matching element. */ \
    280  ATTR_UNUSED static inline void                                        \
    281  name##_HT_INSERT(struct name *head, struct type *elm)                 \
    282  {                                                                     \
    283    struct type **p;                                                    \
    284    if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
    285      name##_HT_GROW(head, head->hth_n_entries+1);                      \
    286    ++head->hth_n_entries;                                              \
    287    HT_SET_HASH_(elm, field, hashfn);                                   \
    288    p = &HT_BUCKET_(head, field, elm, hashfn);                          \
    289    elm->field.hte_next = *p;                                           \
    290    *p = elm;                                                           \
    291  }                                                                     \
    292  /* Insert the element 'elm' into the table 'head'. If there already   \
    293   * a matching element in the table, replace that element and return   \
    294   * it. */                                                             \
    295  ATTR_UNUSED static inline struct type *                               \
    296  name##_HT_REPLACE(struct name *head, struct type *elm)                \
    297  {                                                                     \
    298    struct type **p, *r;                                                \
    299    if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
    300      name##_HT_GROW(head, head->hth_n_entries+1);                      \
    301    HT_SET_HASH_(elm, field, hashfn);                                   \
    302    p = name##_HT_FIND_P_(head, elm);                                   \
    303    HT_ASSERT_(p != NULL); /* this holds because we called HT_GROW */   \
    304    r = *p;                                                             \
    305    *p = elm;                                                           \
    306    if (r && (r!=elm)) {                                                \
    307      elm->field.hte_next = r->field.hte_next;                          \
    308      r->field.hte_next = NULL;                                         \
    309      return r;                                                         \
    310    } else {                                                            \
    311      ++head->hth_n_entries;                                            \
    312      return NULL;                                                      \
    313    }                                                                   \
    314  }                                                                     \
    315  /* Remove any element matching 'elm' from the table 'head'.  If such  \
    316   * an element is found, return it; otherwise return NULL. */          \
    317  ATTR_UNUSED static inline struct type *                               \
    318  name##_HT_REMOVE(struct name *head, struct type *elm)                 \
    319  {                                                                     \
    320    struct type **p, *r;                                                \
    321    HT_SET_HASH_(elm, field, hashfn);                                   \
    322    p = name##_HT_FIND_P_(head,elm);                                    \
    323    if (!p || !*p)                                                      \
    324      return NULL;                                                      \
    325    r = *p;                                                             \
    326    *p = r->field.hte_next;                                             \
    327    r->field.hte_next = NULL;                                           \
    328    --head->hth_n_entries;                                              \
    329    return r;                                                           \
    330  }                                                                     \
    331  /* Invoke the function 'fn' on every element of the table 'head',     \
    332   * using 'data' as its second argument.  If the function returns      \
    333   * nonzero, remove the most recently examined element before invoking \
    334   * the function again. */                                             \
    335  ATTR_UNUSED static inline void                                        \
    336  name##_HT_FOREACH_FN(struct name *head,                               \
    337                       int (*fn)(struct type *, void *),                \
    338                       void *data)                                      \
    339 {                                                                       \
    340    unsigned idx;                                                       \
    341    struct type **p, **nextp, *next;                                    \
    342    if (!head->hth_table)                                               \
    343      return;                                                           \
    344    for (idx=0; idx < head->hth_table_length; ++idx) {                  \
    345      p = &head->hth_table[idx];                                        \
    346      while (*p) {                                                      \
    347        nextp = &(*p)->field.hte_next;                                  \
    348        next = *nextp;                                                  \
    349        if (fn(*p, data)) {                                             \
    350          --head->hth_n_entries;                                        \
    351          *p = next;                                                    \
    352        } else {                                                        \
    353          p = nextp;                                                    \
    354        }                                                               \
    355      }                                                                 \
    356    }                                                                   \
    357  }                                                                     \
    358  /* Return a pointer to the first element in the table 'head', under   \
    359   * an arbitrary order.  This order is stable under remove operations, \
    360   * but not under others. If the table is empty, return NULL. */       \
    361  ATTR_UNUSED static inline struct type **                              \
    362  name##_HT_START(struct name *head)                                    \
    363  {                                                                     \
    364    unsigned b = 0;                                                     \
    365    while (b < head->hth_table_length) {                                \
    366      if (head->hth_table[b]) {                                         \
    367        HT_ASSERT_(b ==                                                 \
    368                HT_BUCKET_NUM_(head,field,head->hth_table[b],hashfn));  \
    369        return &head->hth_table[b];                                     \
    370      }                                                                 \
    371      ++b;                                                              \
    372    }                                                                   \
    373    return NULL;                                                        \
    374  }                                                                     \
    375  /* Return the next element in 'head' after 'elm', under the arbitrary \
    376   * order used by HT_START.  If there are no more elements, return     \
    377   * NULL.  If 'elm' is to be removed from the table, you must call     \
    378   * this function for the next value before you remove it, or use      \
    379   * HT_NEXT_RMV instead.                                               \
    380   */                                                                   \
    381  ATTR_UNUSED static inline struct type **                              \
    382  name##_HT_NEXT(struct name *head, struct type **elm)                  \
    383  {                                                                     \
    384    if ((*elm)->field.hte_next) {                                       \
    385      HT_ASSERT_(HT_BUCKET_NUM_(head,field,*elm,hashfn) ==              \
    386             HT_BUCKET_NUM_(head,field,(*elm)->field.hte_next,hashfn)); \
    387      return &(*elm)->field.hte_next;                                   \
    388    } else {                                                            \
    389      unsigned b = HT_BUCKET_NUM_(head,field,*elm,hashfn)+1;            \
    390      while (b < head->hth_table_length) {                              \
    391        if (head->hth_table[b]) {                                       \
    392          HT_ASSERT_(b ==                                               \
    393                 HT_BUCKET_NUM_(head,field,head->hth_table[b],hashfn)); \
    394          return &head->hth_table[b];                                   \
    395        }                                                               \
    396        ++b;                                                            \
    397      }                                                                 \
    398      return NULL;                                                      \
    399    }                                                                   \
    400  }                                                                     \
    401  /* As HT_NEXT, but also remove the current element 'elm' from the     \
    402   * table. */                                                          \
    403  ATTR_UNUSED static inline struct type **                              \
    404  name##_HT_NEXT_RMV(struct name *head, struct type **elm)              \
    405  {                                                                     \
    406    unsigned h = HT_ELT_HASH_(*elm, field, hashfn);                     \
    407    *elm = (*elm)->field.hte_next;                                      \
    408    --head->hth_n_entries;                                              \
    409    if (*elm) {                                                         \
    410      return elm;                                                       \
    411    } else {                                                            \
    412      unsigned b = (h % head->hth_table_length)+1;                      \
    413      while (b < head->hth_table_length) {                              \
    414        if (head->hth_table[b])                                         \
    415          return &head->hth_table[b];                                   \
    416        ++b;                                                            \
    417      }                                                                 \
    418      return NULL;                                                      \
    419    }                                                                   \
    420  }                                                                     \
    421  HT_EAT_SEMICOLON__
    422 
    423 #define HT_GENERATE2(name, type, field, hashfn, eqfn, load, reallocarrayfn, \
    424                     freefn)                                            \
    425  /* Primes that aren't too far from powers of two. We stop at */       \
    426  /* P=402653189 because P*sizeof(void*) is less than SSIZE_MAX */      \
    427  /* even on a 32-bit platform. */                                      \
    428  static unsigned name##_PRIMES[] = {                                   \
    429    53, 97, 193, 389,                                                   \
    430    769, 1543, 3079, 6151,                                              \
    431    12289, 24593, 49157, 98317,                                         \
    432    196613, 393241, 786433, 1572869,                                    \
    433    3145739, 6291469, 12582917, 25165843,                               \
    434    50331653, 100663319, 201326611, 402653189                           \
    435  };                                                                    \
    436  static unsigned name##_N_PRIMES =                                     \
    437    (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0]));         \
    438  /* Expand the internal table of 'head' until it is large enough to    \
    439   * hold 'size' elements.  Return 0 on success, -1 on allocation       \
    440   * failure. */                                                        \
    441  int                                                                   \
    442  name##_HT_GROW(struct name *head, unsigned size)                      \
    443  {                                                                     \
    444    unsigned new_len, new_load_limit;                                   \
    445    int prime_idx;                                                      \
    446    struct type **new_table;                                            \
    447    if (head->hth_prime_idx == (int)name##_N_PRIMES - 1)                \
    448      return 0;                                                         \
    449    if (head->hth_load_limit > size)                                    \
    450      return 0;                                                         \
    451    prime_idx = head->hth_prime_idx;                                    \
    452    do {                                                                \
    453      new_len = name##_PRIMES[++prime_idx];                             \
    454      new_load_limit = (unsigned)(load*new_len);                        \
    455    } while (new_load_limit <= size &&                                  \
    456             prime_idx < (int)name##_N_PRIMES);                         \
    457    if ((new_table = reallocarrayfn(NULL, new_len, sizeof(struct type*)))) { \
    458      unsigned b;                                                       \
    459      memset(new_table, 0, new_len*sizeof(struct type*));               \
    460      for (b = 0; b < head->hth_table_length; ++b) {                    \
    461        struct type *elm, *next;                                        \
    462        unsigned b2;                                                    \
    463        elm = head->hth_table[b];                                       \
    464        while (elm) {                                                   \
    465          next = elm->field.hte_next;                                   \
    466          b2 = HT_ELT_HASH_(elm, field, hashfn) % new_len;              \
    467          elm->field.hte_next = new_table[b2];                          \
    468          new_table[b2] = elm;                                          \
    469          elm = next;                                                   \
    470        }                                                               \
    471      }                                                                 \
    472      if (head->hth_table)                                              \
    473        freefn(head->hth_table);                                        \
    474      head->hth_table = new_table;                                      \
    475    } else {                                                            \
    476      unsigned b, b2;                                                   \
    477      new_table = reallocarrayfn(head->hth_table, new_len, sizeof(struct type*)); \
    478      if (!new_table) return -1;                                        \
    479      memset(new_table + head->hth_table_length, 0,                     \
    480             (new_len - head->hth_table_length)*sizeof(struct type*));  \
    481      for (b=0; b < head->hth_table_length; ++b) {                      \
    482        struct type *e, **pE;                                           \
    483        for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) {         \
    484          b2 = HT_ELT_HASH_(e, field, hashfn) % new_len;                \
    485          if (b2 == b) {                                                \
    486            pE = &e->field.hte_next;                                    \
    487          } else {                                                      \
    488            *pE = e->field.hte_next;                                    \
    489            e->field.hte_next = new_table[b2];                          \
    490            new_table[b2] = e;                                          \
    491          }                                                             \
    492        }                                                               \
    493      }                                                                 \
    494      head->hth_table = new_table;                                      \
    495    }                                                                   \
    496    head->hth_table_length = new_len;                                   \
    497    head->hth_prime_idx = prime_idx;                                    \
    498    head->hth_load_limit = new_load_limit;                              \
    499    return 0;                                                           \
    500  }                                                                     \
    501  /* Free all storage held by 'head'.  Does not free 'head' itself, or  \
    502   * individual elements. */                                            \
    503  void                                                                  \
    504  name##_HT_CLEAR(struct name *head)                                    \
    505  {                                                                     \
    506    if (head->hth_table)                                                \
    507      freefn(head->hth_table);                                          \
    508    head->hth_table_length = 0;                                         \
    509    name##_HT_INIT(head);                                               \
    510  }                                                                     \
    511  /* Debugging helper: return false iff the representation of 'head' is \
    512   * internally consistent. */                                          \
    513  int                                                                   \
    514  name##_HT_REP_IS_BAD_(const struct name *head)                        \
    515  {                                                                     \
    516    unsigned n, i;                                                      \
    517    struct type *elm;                                                   \
    518    if (!head->hth_table_length) {                                      \
    519      if (!head->hth_table && !head->hth_n_entries &&                   \
    520          !head->hth_load_limit && head->hth_prime_idx == -1)           \
    521        return 0;                                                       \
    522      else                                                              \
    523        return 1;                                                       \
    524    }                                                                   \
    525    if (!head->hth_table || head->hth_prime_idx < 0 ||                  \
    526        !head->hth_load_limit)                                          \
    527      return 2;                                                         \
    528    if (head->hth_n_entries > head->hth_load_limit)                     \
    529      return 3;                                                         \
    530    if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx])   \
    531      return 4;                                                         \
    532    if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \
    533      return 5;                                                         \
    534    for (n = i = 0; i < head->hth_table_length; ++i) {                  \
    535      for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) {  \
    536        if (HT_ELT_HASH_(elm, field, hashfn) != hashfn(elm))            \
    537          return 1000 + i;                                              \
    538        if (HT_BUCKET_NUM_(head,field,elm,hashfn) != i)                 \
    539          return 10000 + i;                                             \
    540        ++n;                                                            \
    541      }                                                                 \
    542    }                                                                   \
    543    if (n != head->hth_n_entries)                                       \
    544      return 6;                                                         \
    545    return 0;                                                           \
    546  }                                                                     \
    547  HT_EAT_SEMICOLON__
    548 
    549 #define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn,    \
    550                    reallocfn, freefn)                                  \
    551  static void *                                                         \
    552  name##_reallocarray(void *arg, size_t a, size_t b)                    \
    553  {                                                                     \
    554    if ((b) && (a) > SIZE_MAX / (b))                                    \
    555      return NULL;                                                      \
    556    if (arg)                                                            \
    557      return reallocfn((arg),(a)*(b));                                  \
    558    else                                                                \
    559      return mallocfn((a)*(b));                                         \
    560  }                                                                     \
    561  HT_GENERATE2(name, type, field, hashfn, eqfn, load,                   \
    562               name##_reallocarray, freefn)
    563 
    564 /** Implements an over-optimized "find and insert if absent" block;
    565 * not meant for direct usage by typical code, or usage outside the critical
    566 * path.*/
    567 #define HT_FIND_OR_INSERT_(name, field, hashfn, head, eltype, elm, var, y, n) \
    568  {                                                                     \
    569    struct name *var##_head_ = head;                                    \
    570    struct eltype **var;                                                \
    571    if (!var##_head_->hth_table ||                                      \
    572        var##_head_->hth_n_entries >= var##_head_->hth_load_limit)      \
    573      name##_HT_GROW(var##_head_, var##_head_->hth_n_entries+1);        \
    574    HT_SET_HASH_((elm), field, hashfn);                                 \
    575    var = name##_HT_FIND_P_(var##_head_, (elm));                        \
    576    HT_ASSERT_(var); /* Holds because we called HT_GROW */              \
    577    if (*var) {                                                         \
    578      y;                                                                \
    579    } else {                                                            \
    580      n;                                                                \
    581    }                                                                   \
    582  }
    583 #define HT_FOI_INSERT_(field, head, elm, newent, var)       \
    584  {                                                         \
    585    HT_SET_HASHVAL_(newent, field, (elm)->field.hte_hash);  \
    586    newent->field.hte_next = NULL;                          \
    587    *var = newent;                                          \
    588    ++((head)->hth_n_entries);                              \
    589  }
    590 
    591 /*
    592 * Copyright 2005, Nick Mathewson.  Implementation logic is adapted from code
    593 * by Christopher Clark, retrofit to allow drop-in memory management, and to
    594 * use the same interface as Niels Provos's tree.h.  This is probably still
    595 * a derived work, so the original license below still applies.
    596 *
    597 * Copyright (c) 2002, Christopher Clark
    598 * All rights reserved.
    599 *
    600 * Redistribution and use in source and binary forms, with or without
    601 * modification, are permitted provided that the following conditions
    602 * are met:
    603 *
    604 * * Redistributions of source code must retain the above copyright
    605 * notice, this list of conditions and the following disclaimer.
    606 *
    607 * * Redistributions in binary form must reproduce the above copyright
    608 * notice, this list of conditions and the following disclaimer in the
    609 * documentation and/or other materials provided with the distribution.
    610 *
    611 * * Neither the name of the original author; nor the names of any contributors
    612 * may be used to endorse or promote products derived from this software
    613 * without specific prior written permission.
    614 *
    615 *
    616 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    617 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    618 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    619 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
    620 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    621 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    622 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    623 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    624 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    625 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    626 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    627 */
    628 
    629 #endif