xref: /freebsd-src/contrib/libucl/uthash/uthash.h (revision 6525738f63c6fd15b4ae11d935311b804e0c24a6)
1c99fb5f9SBaptiste Daroussin /*
2c99fb5f9SBaptiste Daroussin Copyright (c) 2003-2013, Troy D. Hanson     http://troydhanson.github.com/uthash/
3c99fb5f9SBaptiste Daroussin All rights reserved.
4c99fb5f9SBaptiste Daroussin 
5c99fb5f9SBaptiste Daroussin Redistribution and use in source and binary forms, with or without
6c99fb5f9SBaptiste Daroussin modification, are permitted provided that the following conditions are met:
7c99fb5f9SBaptiste Daroussin 
8c99fb5f9SBaptiste Daroussin     * Redistributions of source code must retain the above copyright
9c99fb5f9SBaptiste Daroussin       notice, this list of conditions and the following disclaimer.
10c99fb5f9SBaptiste Daroussin 
11c99fb5f9SBaptiste Daroussin THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12c99fb5f9SBaptiste Daroussin IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13c99fb5f9SBaptiste Daroussin TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14c99fb5f9SBaptiste Daroussin PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15c99fb5f9SBaptiste Daroussin OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16c99fb5f9SBaptiste Daroussin EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17c99fb5f9SBaptiste Daroussin PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18c99fb5f9SBaptiste Daroussin PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19c99fb5f9SBaptiste Daroussin LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20c99fb5f9SBaptiste Daroussin NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21c99fb5f9SBaptiste Daroussin SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22c99fb5f9SBaptiste Daroussin */
23c99fb5f9SBaptiste Daroussin 
24c99fb5f9SBaptiste Daroussin #ifndef UTHASH_H
25c99fb5f9SBaptiste Daroussin #define UTHASH_H
26c99fb5f9SBaptiste Daroussin 
27c99fb5f9SBaptiste Daroussin #include <string.h>   /* memcmp,strlen */
28c99fb5f9SBaptiste Daroussin #include <stddef.h>   /* ptrdiff_t */
29c99fb5f9SBaptiste Daroussin #include <stdlib.h>   /* exit() */
30*6525738fSBaptiste Daroussin #include "mum.h"
31c99fb5f9SBaptiste Daroussin 
32c99fb5f9SBaptiste Daroussin /* These macros use decltype or the earlier __typeof GNU extension.
33c99fb5f9SBaptiste Daroussin    As decltype is only available in newer compilers (VS2010 or gcc 4.3+
34c99fb5f9SBaptiste Daroussin    when compiling c++ source) this code uses whatever method is needed
35c99fb5f9SBaptiste Daroussin    or, for VS2008 where neither is available, uses casting workarounds. */
36c99fb5f9SBaptiste Daroussin #ifdef _MSC_VER         /* MS compiler */
37c99fb5f9SBaptiste Daroussin #if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
38c99fb5f9SBaptiste Daroussin #define DECLTYPE(x) (decltype(x))
39c99fb5f9SBaptiste Daroussin #else                   /* VS2008 or older (or VS2010 in C mode) */
40c99fb5f9SBaptiste Daroussin #define NO_DECLTYPE
41c99fb5f9SBaptiste Daroussin #define DECLTYPE(x)
42c99fb5f9SBaptiste Daroussin #endif
43c99fb5f9SBaptiste Daroussin #else                   /* GNU, Sun and other compilers */
44c99fb5f9SBaptiste Daroussin #define DECLTYPE(x) (__typeof(x))
45c99fb5f9SBaptiste Daroussin #endif
46c99fb5f9SBaptiste Daroussin 
47c99fb5f9SBaptiste Daroussin #ifdef NO_DECLTYPE
48c99fb5f9SBaptiste Daroussin #define DECLTYPE_ASSIGN(dst,src)                                                 \
49c99fb5f9SBaptiste Daroussin do {                                                                             \
50c99fb5f9SBaptiste Daroussin   char **_da_dst = (char**)(&(dst));                                             \
51c99fb5f9SBaptiste Daroussin   *_da_dst = (char*)(src);                                                       \
52c99fb5f9SBaptiste Daroussin } while(0)
53c99fb5f9SBaptiste Daroussin #else
54c99fb5f9SBaptiste Daroussin #define DECLTYPE_ASSIGN(dst,src)                                                 \
55c99fb5f9SBaptiste Daroussin do {                                                                             \
56c99fb5f9SBaptiste Daroussin   (dst) = DECLTYPE(dst)(src);                                                    \
57c99fb5f9SBaptiste Daroussin } while(0)
58c99fb5f9SBaptiste Daroussin #endif
59c99fb5f9SBaptiste Daroussin 
60c99fb5f9SBaptiste Daroussin /* a number of the hash function use uint32_t which isn't defined on win32 */
61c99fb5f9SBaptiste Daroussin #ifdef _MSC_VER
62c99fb5f9SBaptiste Daroussin typedef unsigned int uint32_t;
63c99fb5f9SBaptiste Daroussin typedef unsigned char uint8_t;
64c99fb5f9SBaptiste Daroussin #else
65c99fb5f9SBaptiste Daroussin #include <inttypes.h>   /* uint32_t */
66c99fb5f9SBaptiste Daroussin #endif
67c99fb5f9SBaptiste Daroussin 
68c99fb5f9SBaptiste Daroussin #define UTHASH_VERSION 1.9.8
69c99fb5f9SBaptiste Daroussin 
70c99fb5f9SBaptiste Daroussin #ifndef uthash_fatal
71c99fb5f9SBaptiste Daroussin #define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
72c99fb5f9SBaptiste Daroussin #endif
73c99fb5f9SBaptiste Daroussin #ifndef uthash_malloc
74c99fb5f9SBaptiste Daroussin #define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */
75c99fb5f9SBaptiste Daroussin #endif
76c99fb5f9SBaptiste Daroussin #ifndef uthash_free
77c99fb5f9SBaptiste Daroussin #define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */
78c99fb5f9SBaptiste Daroussin #endif
79c99fb5f9SBaptiste Daroussin 
80c99fb5f9SBaptiste Daroussin #ifndef uthash_noexpand_fyi
81c99fb5f9SBaptiste Daroussin #define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
82c99fb5f9SBaptiste Daroussin #endif
83c99fb5f9SBaptiste Daroussin #ifndef uthash_expand_fyi
84c99fb5f9SBaptiste Daroussin #define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
85c99fb5f9SBaptiste Daroussin #endif
86c99fb5f9SBaptiste Daroussin 
87c99fb5f9SBaptiste Daroussin /* initial number of buckets */
88c99fb5f9SBaptiste Daroussin #define HASH_INITIAL_NUM_BUCKETS 32      /* initial number of buckets        */
89c99fb5f9SBaptiste Daroussin #define HASH_INITIAL_NUM_BUCKETS_LOG2 5  /* lg2 of initial number of buckets */
90c99fb5f9SBaptiste Daroussin #define HASH_BKT_CAPACITY_THRESH 10      /* expand when bucket count reaches */
91c99fb5f9SBaptiste Daroussin 
92c99fb5f9SBaptiste Daroussin /* calculate the element whose hash handle address is hhe */
93c99fb5f9SBaptiste Daroussin #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
94c99fb5f9SBaptiste Daroussin 
95c99fb5f9SBaptiste Daroussin #define HASH_FIND(hh,head,keyptr,keylen,out)                                     \
96c99fb5f9SBaptiste Daroussin do {                                                                             \
97c99fb5f9SBaptiste Daroussin   unsigned _hf_bkt,_hf_hashv;                                                    \
98c99fb5f9SBaptiste Daroussin   out=NULL;                                                                      \
99c99fb5f9SBaptiste Daroussin   if (head) {                                                                    \
100c99fb5f9SBaptiste Daroussin      HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt);   \
101c99fb5f9SBaptiste Daroussin      if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) {                           \
102c99fb5f9SBaptiste Daroussin        HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ],  \
103c99fb5f9SBaptiste Daroussin                         keyptr,keylen,out);                                      \
104c99fb5f9SBaptiste Daroussin      }                                                                           \
105c99fb5f9SBaptiste Daroussin   }                                                                              \
106c99fb5f9SBaptiste Daroussin } while (0)
107c99fb5f9SBaptiste Daroussin 
108c99fb5f9SBaptiste Daroussin #ifdef HASH_BLOOM
109c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
110c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
111c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_MAKE(tbl)                                                     \
112c99fb5f9SBaptiste Daroussin do {                                                                             \
113c99fb5f9SBaptiste Daroussin   (tbl)->bloom_nbits = HASH_BLOOM;                                               \
114c99fb5f9SBaptiste Daroussin   (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \
115c99fb5f9SBaptiste Daroussin   if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
116c99fb5f9SBaptiste Daroussin   memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
117c99fb5f9SBaptiste Daroussin   (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
118c99fb5f9SBaptiste Daroussin } while (0)
119c99fb5f9SBaptiste Daroussin 
120c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_FREE(tbl)                                                     \
121c99fb5f9SBaptiste Daroussin do {                                                                             \
122c99fb5f9SBaptiste Daroussin   uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
123c99fb5f9SBaptiste Daroussin } while (0)
124c99fb5f9SBaptiste Daroussin 
125c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
126c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
127c99fb5f9SBaptiste Daroussin 
128c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_ADD(tbl,hashv)                                                \
129c99fb5f9SBaptiste Daroussin   HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
130c99fb5f9SBaptiste Daroussin 
131c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_TEST(tbl,hashv)                                               \
132c99fb5f9SBaptiste Daroussin   HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
133c99fb5f9SBaptiste Daroussin 
134c99fb5f9SBaptiste Daroussin #else
135c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_MAKE(tbl)
136c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_FREE(tbl)
137c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_ADD(tbl,hashv)
138c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_TEST(tbl,hashv) (1)
139c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_BYTELEN 0
140c99fb5f9SBaptiste Daroussin #endif
141c99fb5f9SBaptiste Daroussin 
142c99fb5f9SBaptiste Daroussin #define HASH_MAKE_TABLE(hh,head)                                                 \
143c99fb5f9SBaptiste Daroussin do {                                                                             \
144c99fb5f9SBaptiste Daroussin   (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \
145c99fb5f9SBaptiste Daroussin                   sizeof(UT_hash_table));                                        \
146c99fb5f9SBaptiste Daroussin   if (!((head)->hh.tbl))  { uthash_fatal( "out of memory"); }                    \
147c99fb5f9SBaptiste Daroussin   memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \
148c99fb5f9SBaptiste Daroussin   (head)->hh.tbl->tail = &((head)->hh);                                          \
149c99fb5f9SBaptiste Daroussin   (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \
150c99fb5f9SBaptiste Daroussin   (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \
151c99fb5f9SBaptiste Daroussin   (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \
152c99fb5f9SBaptiste Daroussin   (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \
153c99fb5f9SBaptiste Daroussin           HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
154c99fb5f9SBaptiste Daroussin   if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); }             \
155c99fb5f9SBaptiste Daroussin   memset((head)->hh.tbl->buckets, 0,                                             \
156c99fb5f9SBaptiste Daroussin           HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
157c99fb5f9SBaptiste Daroussin   HASH_BLOOM_MAKE((head)->hh.tbl);                                               \
158c99fb5f9SBaptiste Daroussin   (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \
159c99fb5f9SBaptiste Daroussin } while(0)
160c99fb5f9SBaptiste Daroussin 
161c99fb5f9SBaptiste Daroussin #define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
162c99fb5f9SBaptiste Daroussin         HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
163c99fb5f9SBaptiste Daroussin 
164c99fb5f9SBaptiste Daroussin #define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced)                   \
165c99fb5f9SBaptiste Daroussin do {                                                                             \
166c99fb5f9SBaptiste Daroussin   replaced=NULL;                                                                 \
167c99fb5f9SBaptiste Daroussin   HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced);                     \
168c99fb5f9SBaptiste Daroussin   if (replaced!=NULL) {                                                          \
169c99fb5f9SBaptiste Daroussin      HASH_DELETE(hh,head,replaced);                                              \
170c99fb5f9SBaptiste Daroussin   };                                                                             \
171c99fb5f9SBaptiste Daroussin   HASH_ADD(hh,head,fieldname,keylen_in,add);                                     \
172c99fb5f9SBaptiste Daroussin } while(0)
173c99fb5f9SBaptiste Daroussin 
174c99fb5f9SBaptiste Daroussin #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
175c99fb5f9SBaptiste Daroussin do {                                                                             \
176c99fb5f9SBaptiste Daroussin  unsigned _ha_bkt;                                                               \
177c99fb5f9SBaptiste Daroussin  (add)->hh.next = NULL;                                                          \
178c99fb5f9SBaptiste Daroussin  (add)->hh.key = (const char*)keyptr;                                                  \
179c99fb5f9SBaptiste Daroussin  (add)->hh.keylen = (unsigned)keylen_in;                                                   \
180c99fb5f9SBaptiste Daroussin  if (!(head)) {                                                                  \
181c99fb5f9SBaptiste Daroussin     head = (add);                                                                \
182c99fb5f9SBaptiste Daroussin     (head)->hh.prev = NULL;                                                      \
183c99fb5f9SBaptiste Daroussin     HASH_MAKE_TABLE(hh,head);                                                    \
184c99fb5f9SBaptiste Daroussin  } else {                                                                        \
185c99fb5f9SBaptiste Daroussin     (head)->hh.tbl->tail->next = (add);                                          \
186c99fb5f9SBaptiste Daroussin     (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);         \
187c99fb5f9SBaptiste Daroussin     (head)->hh.tbl->tail = &((add)->hh);                                         \
188c99fb5f9SBaptiste Daroussin  }                                                                               \
189c99fb5f9SBaptiste Daroussin  (head)->hh.tbl->num_items++;                                                    \
190c99fb5f9SBaptiste Daroussin  (add)->hh.tbl = (head)->hh.tbl;                                                 \
191c99fb5f9SBaptiste Daroussin  HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets,                         \
192c99fb5f9SBaptiste Daroussin          (add)->hh.hashv, _ha_bkt);                                              \
193c99fb5f9SBaptiste Daroussin  HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh);                   \
194c99fb5f9SBaptiste Daroussin  HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv);                                 \
195c99fb5f9SBaptiste Daroussin  HASH_EMIT_KEY(hh,head,keyptr,keylen_in);                                        \
196c99fb5f9SBaptiste Daroussin  HASH_FSCK(hh,head);                                                             \
197c99fb5f9SBaptiste Daroussin } while(0)
198c99fb5f9SBaptiste Daroussin 
199c99fb5f9SBaptiste Daroussin #define HASH_TO_BKT( hashv, num_bkts, bkt )                                      \
200c99fb5f9SBaptiste Daroussin do {                                                                             \
201c99fb5f9SBaptiste Daroussin   bkt = ((hashv) & ((num_bkts) - 1));                                            \
202c99fb5f9SBaptiste Daroussin } while(0)
203c99fb5f9SBaptiste Daroussin 
204c99fb5f9SBaptiste Daroussin /* delete "delptr" from the hash table.
205c99fb5f9SBaptiste Daroussin  * "the usual" patch-up process for the app-order doubly-linked-list.
206c99fb5f9SBaptiste Daroussin  * The use of _hd_hh_del below deserves special explanation.
207c99fb5f9SBaptiste Daroussin  * These used to be expressed using (delptr) but that led to a bug
208c99fb5f9SBaptiste Daroussin  * if someone used the same symbol for the head and deletee, like
209c99fb5f9SBaptiste Daroussin  *  HASH_DELETE(hh,users,users);
210c99fb5f9SBaptiste Daroussin  * We want that to work, but by changing the head (users) below
211c99fb5f9SBaptiste Daroussin  * we were forfeiting our ability to further refer to the deletee (users)
212c99fb5f9SBaptiste Daroussin  * in the patch-up process. Solution: use scratch space to
213c99fb5f9SBaptiste Daroussin  * copy the deletee pointer, then the latter references are via that
214c99fb5f9SBaptiste Daroussin  * scratch pointer rather than through the repointed (users) symbol.
215c99fb5f9SBaptiste Daroussin  */
216c99fb5f9SBaptiste Daroussin #define HASH_DELETE(hh,head,delptr)                                              \
217c99fb5f9SBaptiste Daroussin do {                                                                             \
218c99fb5f9SBaptiste Daroussin     unsigned _hd_bkt;                                                            \
219c99fb5f9SBaptiste Daroussin     struct UT_hash_handle *_hd_hh_del;                                           \
220c99fb5f9SBaptiste Daroussin     if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \
221c99fb5f9SBaptiste Daroussin         uthash_free((head)->hh.tbl->buckets,                                     \
222c99fb5f9SBaptiste Daroussin                     (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
223c99fb5f9SBaptiste Daroussin         HASH_BLOOM_FREE((head)->hh.tbl);                                         \
224c99fb5f9SBaptiste Daroussin         uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \
225c99fb5f9SBaptiste Daroussin         head = NULL;                                                             \
226c99fb5f9SBaptiste Daroussin     } else {                                                                     \
227c99fb5f9SBaptiste Daroussin         _hd_hh_del = &((delptr)->hh);                                            \
228c99fb5f9SBaptiste Daroussin         if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
229c99fb5f9SBaptiste Daroussin             (head)->hh.tbl->tail =                                               \
230c99fb5f9SBaptiste Daroussin                 (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \
231c99fb5f9SBaptiste Daroussin                 (head)->hh.tbl->hho);                                            \
232c99fb5f9SBaptiste Daroussin         }                                                                        \
233c99fb5f9SBaptiste Daroussin         if ((delptr)->hh.prev) {                                                 \
234c99fb5f9SBaptiste Daroussin             ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +                  \
235c99fb5f9SBaptiste Daroussin                     (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
236c99fb5f9SBaptiste Daroussin         } else {                                                                 \
237c99fb5f9SBaptiste Daroussin             DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
238c99fb5f9SBaptiste Daroussin         }                                                                        \
239c99fb5f9SBaptiste Daroussin         if (_hd_hh_del->next) {                                                  \
240c99fb5f9SBaptiste Daroussin             ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next +                     \
241c99fb5f9SBaptiste Daroussin                     (head)->hh.tbl->hho))->prev =                                \
242c99fb5f9SBaptiste Daroussin                     _hd_hh_del->prev;                                            \
243c99fb5f9SBaptiste Daroussin         }                                                                        \
244c99fb5f9SBaptiste Daroussin         HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \
245c99fb5f9SBaptiste Daroussin         HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \
246c99fb5f9SBaptiste Daroussin         (head)->hh.tbl->num_items--;                                             \
247c99fb5f9SBaptiste Daroussin     }                                                                            \
248c99fb5f9SBaptiste Daroussin     HASH_FSCK(hh,head);                                                          \
249c99fb5f9SBaptiste Daroussin } while (0)
250c99fb5f9SBaptiste Daroussin 
251c99fb5f9SBaptiste Daroussin 
252c99fb5f9SBaptiste Daroussin /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
253c99fb5f9SBaptiste Daroussin #define HASH_FIND_STR(head,findstr,out)                                          \
254c99fb5f9SBaptiste Daroussin     HASH_FIND(hh,head,findstr,strlen(findstr),out)
255c99fb5f9SBaptiste Daroussin #define HASH_ADD_STR(head,strfield,add)                                          \
256c99fb5f9SBaptiste Daroussin     HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
257c99fb5f9SBaptiste Daroussin #define HASH_REPLACE_STR(head,strfield,add,replaced)                             \
258c99fb5f9SBaptiste Daroussin   HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced)
259c99fb5f9SBaptiste Daroussin #define HASH_FIND_INT(head,findint,out)                                          \
260c99fb5f9SBaptiste Daroussin     HASH_FIND(hh,head,findint,sizeof(int),out)
261c99fb5f9SBaptiste Daroussin #define HASH_ADD_INT(head,intfield,add)                                          \
262c99fb5f9SBaptiste Daroussin     HASH_ADD(hh,head,intfield,sizeof(int),add)
263c99fb5f9SBaptiste Daroussin #define HASH_REPLACE_INT(head,intfield,add,replaced)                             \
264c99fb5f9SBaptiste Daroussin     HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
265c99fb5f9SBaptiste Daroussin #define HASH_FIND_PTR(head,findptr,out)                                          \
266c99fb5f9SBaptiste Daroussin     HASH_FIND(hh,head,findptr,sizeof(void *),out)
267c99fb5f9SBaptiste Daroussin #define HASH_ADD_PTR(head,ptrfield,add)                                          \
268c99fb5f9SBaptiste Daroussin     HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
269c99fb5f9SBaptiste Daroussin #define HASH_REPLACE_PTR(head,ptrfield,add)                                      \
270c99fb5f9SBaptiste Daroussin     HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
271c99fb5f9SBaptiste Daroussin #define HASH_DEL(head,delptr)                                                    \
272c99fb5f9SBaptiste Daroussin     HASH_DELETE(hh,head,delptr)
273c99fb5f9SBaptiste Daroussin 
274c99fb5f9SBaptiste Daroussin /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
275c99fb5f9SBaptiste Daroussin  * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
276c99fb5f9SBaptiste Daroussin  */
277c99fb5f9SBaptiste Daroussin #ifdef HASH_DEBUG
278c99fb5f9SBaptiste Daroussin #define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
279c99fb5f9SBaptiste Daroussin #define HASH_FSCK(hh,head)                                                       \
280c99fb5f9SBaptiste Daroussin do {                                                                             \
281c99fb5f9SBaptiste Daroussin     unsigned _bkt_i;                                                             \
282c99fb5f9SBaptiste Daroussin     unsigned _count, _bkt_count;                                                 \
283c99fb5f9SBaptiste Daroussin     char *_prev;                                                                 \
284c99fb5f9SBaptiste Daroussin     struct UT_hash_handle *_thh;                                                 \
285c99fb5f9SBaptiste Daroussin     if (head) {                                                                  \
286c99fb5f9SBaptiste Daroussin         _count = 0;                                                              \
287c99fb5f9SBaptiste Daroussin         for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \
288c99fb5f9SBaptiste Daroussin             _bkt_count = 0;                                                      \
289c99fb5f9SBaptiste Daroussin             _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \
290c99fb5f9SBaptiste Daroussin             _prev = NULL;                                                        \
291c99fb5f9SBaptiste Daroussin             while (_thh) {                                                       \
292c99fb5f9SBaptiste Daroussin                if (_prev != (char*)(_thh->hh_prev)) {                            \
293c99fb5f9SBaptiste Daroussin                    HASH_OOPS("invalid hh_prev %p, actual %p\n",                  \
294c99fb5f9SBaptiste Daroussin                     _thh->hh_prev, _prev );                                      \
295c99fb5f9SBaptiste Daroussin                }                                                                 \
296c99fb5f9SBaptiste Daroussin                _bkt_count++;                                                     \
297c99fb5f9SBaptiste Daroussin                _prev = (char*)(_thh);                                            \
298c99fb5f9SBaptiste Daroussin                _thh = _thh->hh_next;                                             \
299c99fb5f9SBaptiste Daroussin             }                                                                    \
300c99fb5f9SBaptiste Daroussin             _count += _bkt_count;                                                \
301c99fb5f9SBaptiste Daroussin             if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \
302c99fb5f9SBaptiste Daroussin                HASH_OOPS("invalid bucket count %d, actual %d\n",                 \
303c99fb5f9SBaptiste Daroussin                 (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \
304c99fb5f9SBaptiste Daroussin             }                                                                    \
305c99fb5f9SBaptiste Daroussin         }                                                                        \
306c99fb5f9SBaptiste Daroussin         if (_count != (head)->hh.tbl->num_items) {                               \
307c99fb5f9SBaptiste Daroussin             HASH_OOPS("invalid hh item count %d, actual %d\n",                   \
308c99fb5f9SBaptiste Daroussin                 (head)->hh.tbl->num_items, _count );                             \
309c99fb5f9SBaptiste Daroussin         }                                                                        \
310c99fb5f9SBaptiste Daroussin         /* traverse hh in app order; check next/prev integrity, count */         \
311c99fb5f9SBaptiste Daroussin         _count = 0;                                                              \
312c99fb5f9SBaptiste Daroussin         _prev = NULL;                                                            \
313c99fb5f9SBaptiste Daroussin         _thh =  &(head)->hh;                                                     \
314c99fb5f9SBaptiste Daroussin         while (_thh) {                                                           \
315c99fb5f9SBaptiste Daroussin            _count++;                                                             \
316c99fb5f9SBaptiste Daroussin            if (_prev !=(char*)(_thh->prev)) {                                    \
317c99fb5f9SBaptiste Daroussin               HASH_OOPS("invalid prev %p, actual %p\n",                          \
318c99fb5f9SBaptiste Daroussin                     _thh->prev, _prev );                                         \
319c99fb5f9SBaptiste Daroussin            }                                                                     \
320c99fb5f9SBaptiste Daroussin            _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \
321c99fb5f9SBaptiste Daroussin            _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \
322c99fb5f9SBaptiste Daroussin                                   (head)->hh.tbl->hho) : NULL );                 \
323c99fb5f9SBaptiste Daroussin         }                                                                        \
324c99fb5f9SBaptiste Daroussin         if (_count != (head)->hh.tbl->num_items) {                               \
325c99fb5f9SBaptiste Daroussin             HASH_OOPS("invalid app item count %d, actual %d\n",                  \
326c99fb5f9SBaptiste Daroussin                 (head)->hh.tbl->num_items, _count );                             \
327c99fb5f9SBaptiste Daroussin         }                                                                        \
328c99fb5f9SBaptiste Daroussin     }                                                                            \
329c99fb5f9SBaptiste Daroussin } while (0)
330c99fb5f9SBaptiste Daroussin #else
331c99fb5f9SBaptiste Daroussin #define HASH_FSCK(hh,head)
332c99fb5f9SBaptiste Daroussin #endif
333c99fb5f9SBaptiste Daroussin 
334c99fb5f9SBaptiste Daroussin /* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
335c99fb5f9SBaptiste Daroussin  * the descriptor to which this macro is defined for tuning the hash function.
336c99fb5f9SBaptiste Daroussin  * The app can #include <unistd.h> to get the prototype for write(2). */
337c99fb5f9SBaptiste Daroussin #ifdef HASH_EMIT_KEYS
338c99fb5f9SBaptiste Daroussin #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \
339c99fb5f9SBaptiste Daroussin do {                                                                             \
340c99fb5f9SBaptiste Daroussin     unsigned _klen = fieldlen;                                                   \
341c99fb5f9SBaptiste Daroussin     write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
342c99fb5f9SBaptiste Daroussin     write(HASH_EMIT_KEYS, keyptr, fieldlen);                                     \
343c99fb5f9SBaptiste Daroussin } while (0)
344c99fb5f9SBaptiste Daroussin #else
345c99fb5f9SBaptiste Daroussin #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
346c99fb5f9SBaptiste Daroussin #endif
347c99fb5f9SBaptiste Daroussin 
348c99fb5f9SBaptiste Daroussin /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
349c99fb5f9SBaptiste Daroussin #ifdef HASH_FUNCTION
350c99fb5f9SBaptiste Daroussin #define HASH_FCN HASH_FUNCTION
351c99fb5f9SBaptiste Daroussin #else
352c99fb5f9SBaptiste Daroussin #define HASH_FCN HASH_XX
353c99fb5f9SBaptiste Daroussin #endif
354c99fb5f9SBaptiste Daroussin 
355c99fb5f9SBaptiste Daroussin #define XX_HASH_PRIME 2654435761U
356c99fb5f9SBaptiste Daroussin 
357c99fb5f9SBaptiste Daroussin #define HASH_XX(key,keylen,num_bkts,hashv,bkt)                                  \
358c99fb5f9SBaptiste Daroussin do {                                                                             \
359*6525738fSBaptiste Daroussin   hashv = mum_hash (key, keylen, XX_HASH_PRIME);                                 \
360c99fb5f9SBaptiste Daroussin   bkt = (hashv) & (num_bkts-1);                                                  \
361c99fb5f9SBaptiste Daroussin } while (0)
362c99fb5f9SBaptiste Daroussin 
363c99fb5f9SBaptiste Daroussin 
364c99fb5f9SBaptiste Daroussin 
365c99fb5f9SBaptiste Daroussin /* key comparison function; return 0 if keys equal */
366c99fb5f9SBaptiste Daroussin #define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
367c99fb5f9SBaptiste Daroussin 
368c99fb5f9SBaptiste Daroussin /* iterate over items in a known bucket to find desired item */
369c99fb5f9SBaptiste Daroussin #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
370c99fb5f9SBaptiste Daroussin do {                                                                             \
371c99fb5f9SBaptiste Daroussin  if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head));          \
372c99fb5f9SBaptiste Daroussin  else out=NULL;                                                                  \
373c99fb5f9SBaptiste Daroussin  while (out) {                                                                   \
374c99fb5f9SBaptiste Daroussin     if ((out)->hh.keylen == keylen_in) {                                           \
375c99fb5f9SBaptiste Daroussin         if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break;             \
376c99fb5f9SBaptiste Daroussin     }                                                                            \
377c99fb5f9SBaptiste Daroussin     if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
378c99fb5f9SBaptiste Daroussin     else out = NULL;                                                             \
379c99fb5f9SBaptiste Daroussin  }                                                                               \
380c99fb5f9SBaptiste Daroussin } while(0)
381c99fb5f9SBaptiste Daroussin 
382c99fb5f9SBaptiste Daroussin /* add an item to a bucket  */
383c99fb5f9SBaptiste Daroussin #define HASH_ADD_TO_BKT(head,addhh)                                              \
384c99fb5f9SBaptiste Daroussin do {                                                                             \
385c99fb5f9SBaptiste Daroussin  head.count++;                                                                   \
386c99fb5f9SBaptiste Daroussin  (addhh)->hh_next = head.hh_head;                                                \
387c99fb5f9SBaptiste Daroussin  (addhh)->hh_prev = NULL;                                                        \
388c99fb5f9SBaptiste Daroussin  if (head.hh_head) { (head).hh_head->hh_prev = (addhh); }                        \
389c99fb5f9SBaptiste Daroussin  (head).hh_head=addhh;                                                           \
390c99fb5f9SBaptiste Daroussin  if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH)             \
391c99fb5f9SBaptiste Daroussin      && (addhh)->tbl->noexpand != 1) {                                           \
392c99fb5f9SBaptiste Daroussin        HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \
393c99fb5f9SBaptiste Daroussin  }                                                                               \
394c99fb5f9SBaptiste Daroussin } while(0)
395c99fb5f9SBaptiste Daroussin 
396c99fb5f9SBaptiste Daroussin /* remove an item from a given bucket */
397c99fb5f9SBaptiste Daroussin #define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \
398c99fb5f9SBaptiste Daroussin     (head).count--;                                                              \
399c99fb5f9SBaptiste Daroussin     if ((head).hh_head == hh_del) {                                              \
400c99fb5f9SBaptiste Daroussin       (head).hh_head = hh_del->hh_next;                                          \
401c99fb5f9SBaptiste Daroussin     }                                                                            \
402c99fb5f9SBaptiste Daroussin     if (hh_del->hh_prev) {                                                       \
403c99fb5f9SBaptiste Daroussin         hh_del->hh_prev->hh_next = hh_del->hh_next;                              \
404c99fb5f9SBaptiste Daroussin     }                                                                            \
405c99fb5f9SBaptiste Daroussin     if (hh_del->hh_next) {                                                       \
406c99fb5f9SBaptiste Daroussin         hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
407c99fb5f9SBaptiste Daroussin     }
408c99fb5f9SBaptiste Daroussin 
409c99fb5f9SBaptiste Daroussin /* Bucket expansion has the effect of doubling the number of buckets
410c99fb5f9SBaptiste Daroussin  * and redistributing the items into the new buckets. Ideally the
411c99fb5f9SBaptiste Daroussin  * items will distribute more or less evenly into the new buckets
412c99fb5f9SBaptiste Daroussin  * (the extent to which this is true is a measure of the quality of
413c99fb5f9SBaptiste Daroussin  * the hash function as it applies to the key domain).
414c99fb5f9SBaptiste Daroussin  *
415c99fb5f9SBaptiste Daroussin  * With the items distributed into more buckets, the chain length
416c99fb5f9SBaptiste Daroussin  * (item count) in each bucket is reduced. Thus by expanding buckets
417c99fb5f9SBaptiste Daroussin  * the hash keeps a bound on the chain length. This bounded chain
418c99fb5f9SBaptiste Daroussin  * length is the essence of how a hash provides constant time lookup.
419c99fb5f9SBaptiste Daroussin  *
420c99fb5f9SBaptiste Daroussin  * The calculation of tbl->ideal_chain_maxlen below deserves some
421c99fb5f9SBaptiste Daroussin  * explanation. First, keep in mind that we're calculating the ideal
422c99fb5f9SBaptiste Daroussin  * maximum chain length based on the *new* (doubled) bucket count.
423c99fb5f9SBaptiste Daroussin  * In fractions this is just n/b (n=number of items,b=new num buckets).
424c99fb5f9SBaptiste Daroussin  * Since the ideal chain length is an integer, we want to calculate
425c99fb5f9SBaptiste Daroussin  * ceil(n/b). We don't depend on floating point arithmetic in this
426c99fb5f9SBaptiste Daroussin  * hash, so to calculate ceil(n/b) with integers we could write
427c99fb5f9SBaptiste Daroussin  *
428c99fb5f9SBaptiste Daroussin  *      ceil(n/b) = (n/b) + ((n%b)?1:0)
429c99fb5f9SBaptiste Daroussin  *
430c99fb5f9SBaptiste Daroussin  * and in fact a previous version of this hash did just that.
431c99fb5f9SBaptiste Daroussin  * But now we have improved things a bit by recognizing that b is
432c99fb5f9SBaptiste Daroussin  * always a power of two. We keep its base 2 log handy (call it lb),
433c99fb5f9SBaptiste Daroussin  * so now we can write this with a bit shift and logical AND:
434c99fb5f9SBaptiste Daroussin  *
435c99fb5f9SBaptiste Daroussin  *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
436c99fb5f9SBaptiste Daroussin  *
437c99fb5f9SBaptiste Daroussin  */
438c99fb5f9SBaptiste Daroussin #define HASH_EXPAND_BUCKETS(tbl)                                                 \
439c99fb5f9SBaptiste Daroussin do {                                                                             \
440c99fb5f9SBaptiste Daroussin     unsigned _he_bkt;                                                            \
441c99fb5f9SBaptiste Daroussin     unsigned _he_bkt_i;                                                          \
442c99fb5f9SBaptiste Daroussin     struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \
443c99fb5f9SBaptiste Daroussin     UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \
444c99fb5f9SBaptiste Daroussin     _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \
445c99fb5f9SBaptiste Daroussin              2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));              \
446c99fb5f9SBaptiste Daroussin     if (!_he_new_buckets) { uthash_fatal( "out of memory"); }                    \
447c99fb5f9SBaptiste Daroussin     memset(_he_new_buckets, 0,                                                   \
448c99fb5f9SBaptiste Daroussin             2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));               \
449c99fb5f9SBaptiste Daroussin     tbl->ideal_chain_maxlen =                                                    \
450c99fb5f9SBaptiste Daroussin        (tbl->num_items >> (tbl->log2_num_buckets+1)) +                           \
451c99fb5f9SBaptiste Daroussin        ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0);                    \
452c99fb5f9SBaptiste Daroussin     tbl->nonideal_items = 0;                                                     \
453c99fb5f9SBaptiste Daroussin     for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \
454c99fb5f9SBaptiste Daroussin     {                                                                            \
455c99fb5f9SBaptiste Daroussin         _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \
456c99fb5f9SBaptiste Daroussin         while (_he_thh) {                                                        \
457c99fb5f9SBaptiste Daroussin            _he_hh_nxt = _he_thh->hh_next;                                        \
458c99fb5f9SBaptiste Daroussin            HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt);            \
459c99fb5f9SBaptiste Daroussin            _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \
460c99fb5f9SBaptiste Daroussin            if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \
461c99fb5f9SBaptiste Daroussin              tbl->nonideal_items++;                                              \
462c99fb5f9SBaptiste Daroussin              _he_newbkt->expand_mult = _he_newbkt->count /                       \
463c99fb5f9SBaptiste Daroussin                                         tbl->ideal_chain_maxlen;                 \
464c99fb5f9SBaptiste Daroussin            }                                                                     \
465c99fb5f9SBaptiste Daroussin            _he_thh->hh_prev = NULL;                                              \
466c99fb5f9SBaptiste Daroussin            _he_thh->hh_next = _he_newbkt->hh_head;                               \
467c99fb5f9SBaptiste Daroussin            if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev =               \
468c99fb5f9SBaptiste Daroussin                 _he_thh;                                                         \
469c99fb5f9SBaptiste Daroussin            _he_newbkt->hh_head = _he_thh;                                        \
470c99fb5f9SBaptiste Daroussin            _he_thh = _he_hh_nxt;                                                 \
471c99fb5f9SBaptiste Daroussin         }                                                                        \
472c99fb5f9SBaptiste Daroussin     }                                                                            \
473c99fb5f9SBaptiste Daroussin     uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
474c99fb5f9SBaptiste Daroussin     tbl->num_buckets *= 2;                                                       \
475c99fb5f9SBaptiste Daroussin     tbl->log2_num_buckets++;                                                     \
476c99fb5f9SBaptiste Daroussin     tbl->buckets = _he_new_buckets;                                              \
477c99fb5f9SBaptiste Daroussin     tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \
478c99fb5f9SBaptiste Daroussin         (tbl->ineff_expands+1) : 0;                                              \
479c99fb5f9SBaptiste Daroussin     if (tbl->ineff_expands > 1) {                                                \
480c99fb5f9SBaptiste Daroussin         tbl->noexpand=1;                                                         \
481c99fb5f9SBaptiste Daroussin         uthash_noexpand_fyi(tbl);                                                \
482c99fb5f9SBaptiste Daroussin     }                                                                            \
483c99fb5f9SBaptiste Daroussin     uthash_expand_fyi(tbl);                                                      \
484c99fb5f9SBaptiste Daroussin } while(0)
485c99fb5f9SBaptiste Daroussin 
486c99fb5f9SBaptiste Daroussin 
487c99fb5f9SBaptiste Daroussin /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
488c99fb5f9SBaptiste Daroussin /* Note that HASH_SORT assumes the hash handle name to be hh.
489c99fb5f9SBaptiste Daroussin  * HASH_SRT was added to allow the hash handle name to be passed in. */
490c99fb5f9SBaptiste Daroussin #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
491c99fb5f9SBaptiste Daroussin #define HASH_SRT(hh,head,cmpfcn)                                                 \
492c99fb5f9SBaptiste Daroussin do {                                                                             \
493c99fb5f9SBaptiste Daroussin   unsigned _hs_i;                                                                \
494c99fb5f9SBaptiste Daroussin   unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \
495c99fb5f9SBaptiste Daroussin   struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \
496c99fb5f9SBaptiste Daroussin   if (head) {                                                                    \
497c99fb5f9SBaptiste Daroussin       _hs_insize = 1;                                                            \
498c99fb5f9SBaptiste Daroussin       _hs_looping = 1;                                                           \
499c99fb5f9SBaptiste Daroussin       _hs_list = &((head)->hh);                                                  \
500c99fb5f9SBaptiste Daroussin       while (_hs_looping) {                                                      \
501c99fb5f9SBaptiste Daroussin           _hs_p = _hs_list;                                                      \
502c99fb5f9SBaptiste Daroussin           _hs_list = NULL;                                                       \
503c99fb5f9SBaptiste Daroussin           _hs_tail = NULL;                                                       \
504c99fb5f9SBaptiste Daroussin           _hs_nmerges = 0;                                                       \
505c99fb5f9SBaptiste Daroussin           while (_hs_p) {                                                        \
506c99fb5f9SBaptiste Daroussin               _hs_nmerges++;                                                     \
507c99fb5f9SBaptiste Daroussin               _hs_q = _hs_p;                                                     \
508c99fb5f9SBaptiste Daroussin               _hs_psize = 0;                                                     \
509c99fb5f9SBaptiste Daroussin               for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \
510c99fb5f9SBaptiste Daroussin                   _hs_psize++;                                                   \
511c99fb5f9SBaptiste Daroussin                   _hs_q = (UT_hash_handle*)((_hs_q->next) ?                      \
512c99fb5f9SBaptiste Daroussin                           ((void*)((char*)(_hs_q->next) +                        \
513c99fb5f9SBaptiste Daroussin                           (head)->hh.tbl->hho)) : NULL);                         \
514c99fb5f9SBaptiste Daroussin                   if (! (_hs_q) ) break;                                         \
515c99fb5f9SBaptiste Daroussin               }                                                                  \
516c99fb5f9SBaptiste Daroussin               _hs_qsize = _hs_insize;                                            \
517c99fb5f9SBaptiste Daroussin               while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) {           \
518c99fb5f9SBaptiste Daroussin                   if (_hs_psize == 0) {                                          \
519c99fb5f9SBaptiste Daroussin                       _hs_e = _hs_q;                                             \
520c99fb5f9SBaptiste Daroussin                       _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
521c99fb5f9SBaptiste Daroussin                               ((void*)((char*)(_hs_q->next) +                    \
522c99fb5f9SBaptiste Daroussin                               (head)->hh.tbl->hho)) : NULL);                     \
523c99fb5f9SBaptiste Daroussin                       _hs_qsize--;                                               \
524c99fb5f9SBaptiste Daroussin                   } else if ( (_hs_qsize == 0) || !(_hs_q) ) {                   \
525c99fb5f9SBaptiste Daroussin                       _hs_e = _hs_p;                                             \
526c99fb5f9SBaptiste Daroussin                       if (_hs_p){                                                \
527c99fb5f9SBaptiste Daroussin                         _hs_p = (UT_hash_handle*)((_hs_p->next) ?                \
528c99fb5f9SBaptiste Daroussin                                 ((void*)((char*)(_hs_p->next) +                  \
529c99fb5f9SBaptiste Daroussin                                 (head)->hh.tbl->hho)) : NULL);                   \
530c99fb5f9SBaptiste Daroussin                        }                                                         \
531c99fb5f9SBaptiste Daroussin                       _hs_psize--;                                               \
532c99fb5f9SBaptiste Daroussin                   } else if ((                                                   \
533c99fb5f9SBaptiste Daroussin                       cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
534c99fb5f9SBaptiste Daroussin                              DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
535c99fb5f9SBaptiste Daroussin                              ) <= 0) {                                           \
536c99fb5f9SBaptiste Daroussin                       _hs_e = _hs_p;                                             \
537c99fb5f9SBaptiste Daroussin                       if (_hs_p){                                                \
538c99fb5f9SBaptiste Daroussin                         _hs_p = (UT_hash_handle*)((_hs_p->next) ?                \
539c99fb5f9SBaptiste Daroussin                                ((void*)((char*)(_hs_p->next) +                   \
540c99fb5f9SBaptiste Daroussin                                (head)->hh.tbl->hho)) : NULL);                    \
541c99fb5f9SBaptiste Daroussin                        }                                                         \
542c99fb5f9SBaptiste Daroussin                       _hs_psize--;                                               \
543c99fb5f9SBaptiste Daroussin                   } else {                                                       \
544c99fb5f9SBaptiste Daroussin                       _hs_e = _hs_q;                                             \
545c99fb5f9SBaptiste Daroussin                       _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
546c99fb5f9SBaptiste Daroussin                               ((void*)((char*)(_hs_q->next) +                    \
547c99fb5f9SBaptiste Daroussin                               (head)->hh.tbl->hho)) : NULL);                     \
548c99fb5f9SBaptiste Daroussin                       _hs_qsize--;                                               \
549c99fb5f9SBaptiste Daroussin                   }                                                              \
550c99fb5f9SBaptiste Daroussin                   if ( _hs_tail ) {                                              \
551c99fb5f9SBaptiste Daroussin                       _hs_tail->next = ((_hs_e) ?                                \
552c99fb5f9SBaptiste Daroussin                             ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \
553c99fb5f9SBaptiste Daroussin                   } else {                                                       \
554c99fb5f9SBaptiste Daroussin                       _hs_list = _hs_e;                                          \
555c99fb5f9SBaptiste Daroussin                   }                                                              \
556c99fb5f9SBaptiste Daroussin                   if (_hs_e) {                                                   \
557c99fb5f9SBaptiste Daroussin                   _hs_e->prev = ((_hs_tail) ?                                    \
558c99fb5f9SBaptiste Daroussin                      ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
559c99fb5f9SBaptiste Daroussin                   }                                                              \
560c99fb5f9SBaptiste Daroussin                   _hs_tail = _hs_e;                                              \
561c99fb5f9SBaptiste Daroussin               }                                                                  \
562c99fb5f9SBaptiste Daroussin               _hs_p = _hs_q;                                                     \
563c99fb5f9SBaptiste Daroussin           }                                                                      \
564c99fb5f9SBaptiste Daroussin           if (_hs_tail){                                                         \
565c99fb5f9SBaptiste Daroussin             _hs_tail->next = NULL;                                               \
566c99fb5f9SBaptiste Daroussin           }                                                                      \
567c99fb5f9SBaptiste Daroussin           if ( _hs_nmerges <= 1 ) {                                              \
568c99fb5f9SBaptiste Daroussin               _hs_looping=0;                                                     \
569c99fb5f9SBaptiste Daroussin               (head)->hh.tbl->tail = _hs_tail;                                   \
570c99fb5f9SBaptiste Daroussin               DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \
571c99fb5f9SBaptiste Daroussin           }                                                                      \
572c99fb5f9SBaptiste Daroussin           _hs_insize *= 2;                                                       \
573c99fb5f9SBaptiste Daroussin       }                                                                          \
574c99fb5f9SBaptiste Daroussin       HASH_FSCK(hh,head);                                                        \
575c99fb5f9SBaptiste Daroussin  }                                                                               \
576c99fb5f9SBaptiste Daroussin } while (0)
577c99fb5f9SBaptiste Daroussin 
578c99fb5f9SBaptiste Daroussin /* This function selects items from one hash into another hash.
579c99fb5f9SBaptiste Daroussin  * The end result is that the selected items have dual presence
580c99fb5f9SBaptiste Daroussin  * in both hashes. There is no copy of the items made; rather
581c99fb5f9SBaptiste Daroussin  * they are added into the new hash through a secondary hash
582c99fb5f9SBaptiste Daroussin  * hash handle that must be present in the structure. */
583c99fb5f9SBaptiste Daroussin #define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
584c99fb5f9SBaptiste Daroussin do {                                                                             \
585c99fb5f9SBaptiste Daroussin   unsigned _src_bkt, _dst_bkt;                                                   \
586c99fb5f9SBaptiste Daroussin   void *_last_elt=NULL, *_elt;                                                   \
587c99fb5f9SBaptiste Daroussin   UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \
588c99fb5f9SBaptiste Daroussin   ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \
589c99fb5f9SBaptiste Daroussin   if (src) {                                                                     \
590c99fb5f9SBaptiste Daroussin     for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \
591c99fb5f9SBaptiste Daroussin       for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \
592c99fb5f9SBaptiste Daroussin           _src_hh;                                                               \
593c99fb5f9SBaptiste Daroussin           _src_hh = _src_hh->hh_next) {                                          \
594c99fb5f9SBaptiste Daroussin           _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \
595c99fb5f9SBaptiste Daroussin           if (cond(_elt)) {                                                      \
596c99fb5f9SBaptiste Daroussin             _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \
597c99fb5f9SBaptiste Daroussin             _dst_hh->key = _src_hh->key;                                         \
598c99fb5f9SBaptiste Daroussin             _dst_hh->keylen = _src_hh->keylen;                                   \
599c99fb5f9SBaptiste Daroussin             _dst_hh->hashv = _src_hh->hashv;                                     \
600c99fb5f9SBaptiste Daroussin             _dst_hh->prev = _last_elt;                                           \
601c99fb5f9SBaptiste Daroussin             _dst_hh->next = NULL;                                                \
602c99fb5f9SBaptiste Daroussin             if (_last_elt_hh) { _last_elt_hh->next = _elt; }                     \
603c99fb5f9SBaptiste Daroussin             if (!dst) {                                                          \
604c99fb5f9SBaptiste Daroussin               DECLTYPE_ASSIGN(dst,_elt);                                         \
605c99fb5f9SBaptiste Daroussin               HASH_MAKE_TABLE(hh_dst,dst);                                       \
606c99fb5f9SBaptiste Daroussin             } else {                                                             \
607c99fb5f9SBaptiste Daroussin               _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \
608c99fb5f9SBaptiste Daroussin             }                                                                    \
609c99fb5f9SBaptiste Daroussin             HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \
610c99fb5f9SBaptiste Daroussin             HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \
611c99fb5f9SBaptiste Daroussin             (dst)->hh_dst.tbl->num_items++;                                      \
612c99fb5f9SBaptiste Daroussin             _last_elt = _elt;                                                    \
613c99fb5f9SBaptiste Daroussin             _last_elt_hh = _dst_hh;                                              \
614c99fb5f9SBaptiste Daroussin           }                                                                      \
615c99fb5f9SBaptiste Daroussin       }                                                                          \
616c99fb5f9SBaptiste Daroussin     }                                                                            \
617c99fb5f9SBaptiste Daroussin   }                                                                              \
618c99fb5f9SBaptiste Daroussin   HASH_FSCK(hh_dst,dst);                                                         \
619c99fb5f9SBaptiste Daroussin } while (0)
620c99fb5f9SBaptiste Daroussin 
621c99fb5f9SBaptiste Daroussin #define HASH_CLEAR(hh,head)                                                      \
622c99fb5f9SBaptiste Daroussin do {                                                                             \
623c99fb5f9SBaptiste Daroussin   if (head) {                                                                    \
624c99fb5f9SBaptiste Daroussin     uthash_free((head)->hh.tbl->buckets,                                         \
625c99fb5f9SBaptiste Daroussin                 (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \
626c99fb5f9SBaptiste Daroussin     HASH_BLOOM_FREE((head)->hh.tbl);                                             \
627c99fb5f9SBaptiste Daroussin     uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \
628c99fb5f9SBaptiste Daroussin     (head)=NULL;                                                                 \
629c99fb5f9SBaptiste Daroussin   }                                                                              \
630c99fb5f9SBaptiste Daroussin } while(0)
631c99fb5f9SBaptiste Daroussin 
632c99fb5f9SBaptiste Daroussin #define HASH_OVERHEAD(hh,head)                                                   \
633c99fb5f9SBaptiste Daroussin  (size_t)((((head)->hh.tbl->num_items   * sizeof(UT_hash_handle))   +            \
634c99fb5f9SBaptiste Daroussin            ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket))   +            \
635c99fb5f9SBaptiste Daroussin             (sizeof(UT_hash_table))                                 +            \
636c99fb5f9SBaptiste Daroussin             (HASH_BLOOM_BYTELEN)))
637c99fb5f9SBaptiste Daroussin 
638c99fb5f9SBaptiste Daroussin #ifdef NO_DECLTYPE
639c99fb5f9SBaptiste Daroussin #define HASH_ITER(hh,head,el,tmp)                                                \
640c99fb5f9SBaptiste Daroussin for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
641c99fb5f9SBaptiste Daroussin   el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
642c99fb5f9SBaptiste Daroussin #else
643c99fb5f9SBaptiste Daroussin #define HASH_ITER(hh,head,el,tmp)                                                \
644c99fb5f9SBaptiste Daroussin for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);                 \
645c99fb5f9SBaptiste Daroussin   el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
646c99fb5f9SBaptiste Daroussin #endif
647c99fb5f9SBaptiste Daroussin 
648c99fb5f9SBaptiste Daroussin /* obtain a count of items in the hash */
649c99fb5f9SBaptiste Daroussin #define HASH_COUNT(head) HASH_CNT(hh,head)
650c99fb5f9SBaptiste Daroussin #define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
651c99fb5f9SBaptiste Daroussin 
652c99fb5f9SBaptiste Daroussin typedef struct UT_hash_bucket {
653c99fb5f9SBaptiste Daroussin    struct UT_hash_handle *hh_head;
654c99fb5f9SBaptiste Daroussin    unsigned count;
655c99fb5f9SBaptiste Daroussin 
656c99fb5f9SBaptiste Daroussin    /* expand_mult is normally set to 0. In this situation, the max chain length
657c99fb5f9SBaptiste Daroussin     * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
658c99fb5f9SBaptiste Daroussin     * the bucket's chain exceeds this length, bucket expansion is triggered).
659c99fb5f9SBaptiste Daroussin     * However, setting expand_mult to a non-zero value delays bucket expansion
660c99fb5f9SBaptiste Daroussin     * (that would be triggered by additions to this particular bucket)
661c99fb5f9SBaptiste Daroussin     * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
662c99fb5f9SBaptiste Daroussin     * (The multiplier is simply expand_mult+1). The whole idea of this
663c99fb5f9SBaptiste Daroussin     * multiplier is to reduce bucket expansions, since they are expensive, in
664c99fb5f9SBaptiste Daroussin     * situations where we know that a particular bucket tends to be overused.
665c99fb5f9SBaptiste Daroussin     * It is better to let its chain length grow to a longer yet-still-bounded
666c99fb5f9SBaptiste Daroussin     * value, than to do an O(n) bucket expansion too often.
667c99fb5f9SBaptiste Daroussin     */
668c99fb5f9SBaptiste Daroussin    unsigned expand_mult;
669c99fb5f9SBaptiste Daroussin 
670c99fb5f9SBaptiste Daroussin } UT_hash_bucket;
671c99fb5f9SBaptiste Daroussin 
672c99fb5f9SBaptiste Daroussin /* random signature used only to find hash tables in external analysis */
673c99fb5f9SBaptiste Daroussin #define HASH_SIGNATURE 0xa0111fe1
674c99fb5f9SBaptiste Daroussin #define HASH_BLOOM_SIGNATURE 0xb12220f2
675c99fb5f9SBaptiste Daroussin 
676c99fb5f9SBaptiste Daroussin typedef struct UT_hash_table {
677c99fb5f9SBaptiste Daroussin    UT_hash_bucket *buckets;
678c99fb5f9SBaptiste Daroussin    unsigned num_buckets, log2_num_buckets;
679c99fb5f9SBaptiste Daroussin    unsigned num_items;
680c99fb5f9SBaptiste Daroussin    struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */
681c99fb5f9SBaptiste Daroussin    ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
682c99fb5f9SBaptiste Daroussin 
683c99fb5f9SBaptiste Daroussin    /* in an ideal situation (all buckets used equally), no bucket would have
684c99fb5f9SBaptiste Daroussin     * more than ceil(#items/#buckets) items. that's the ideal chain length. */
685c99fb5f9SBaptiste Daroussin    unsigned ideal_chain_maxlen;
686c99fb5f9SBaptiste Daroussin 
687c99fb5f9SBaptiste Daroussin    /* nonideal_items is the number of items in the hash whose chain position
688c99fb5f9SBaptiste Daroussin     * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
689c99fb5f9SBaptiste Daroussin     * hash distribution; reaching them in a chain traversal takes >ideal steps */
690c99fb5f9SBaptiste Daroussin    unsigned nonideal_items;
691c99fb5f9SBaptiste Daroussin 
692c99fb5f9SBaptiste Daroussin    /* ineffective expands occur when a bucket doubling was performed, but
693c99fb5f9SBaptiste Daroussin     * afterward, more than half the items in the hash had nonideal chain
694c99fb5f9SBaptiste Daroussin     * positions. If this happens on two consecutive expansions we inhibit any
695c99fb5f9SBaptiste Daroussin     * further expansion, as it's not helping; this happens when the hash
696c99fb5f9SBaptiste Daroussin     * function isn't a good fit for the key domain. When expansion is inhibited
697c99fb5f9SBaptiste Daroussin     * the hash will still work, albeit no longer in constant time. */
698c99fb5f9SBaptiste Daroussin    unsigned ineff_expands, noexpand;
699c99fb5f9SBaptiste Daroussin 
700c99fb5f9SBaptiste Daroussin    uint32_t signature; /* used only to find hash tables in external analysis */
701c99fb5f9SBaptiste Daroussin #ifdef HASH_BLOOM
702c99fb5f9SBaptiste Daroussin    uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
703c99fb5f9SBaptiste Daroussin    uint8_t *bloom_bv;
704c99fb5f9SBaptiste Daroussin    char bloom_nbits;
705c99fb5f9SBaptiste Daroussin #endif
706c99fb5f9SBaptiste Daroussin 
707c99fb5f9SBaptiste Daroussin } UT_hash_table;
708c99fb5f9SBaptiste Daroussin 
709c99fb5f9SBaptiste Daroussin typedef struct UT_hash_handle {
710c99fb5f9SBaptiste Daroussin    struct UT_hash_table *tbl;
711c99fb5f9SBaptiste Daroussin    void *prev;                       /* prev element in app order      */
712c99fb5f9SBaptiste Daroussin    void *next;                       /* next element in app order      */
713c99fb5f9SBaptiste Daroussin    struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
714c99fb5f9SBaptiste Daroussin    struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
715c99fb5f9SBaptiste Daroussin    const void *key;                  /* ptr to enclosing struct's key  */
716c99fb5f9SBaptiste Daroussin    unsigned keylen;                  /* enclosing struct's key len     */
717c99fb5f9SBaptiste Daroussin    unsigned hashv;                   /* result of hash-fcn(key)        */
718c99fb5f9SBaptiste Daroussin } UT_hash_handle;
719c99fb5f9SBaptiste Daroussin 
720c99fb5f9SBaptiste Daroussin #endif /* UTHASH_H */
721