1e25b118aSDominic Spill /* 2*935bdedbSDominic Spill Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ 3e25b118aSDominic Spill All rights reserved. 4e25b118aSDominic Spill 5e25b118aSDominic Spill Redistribution and use in source and binary forms, with or without 6e25b118aSDominic Spill modification, are permitted provided that the following conditions are met: 7e25b118aSDominic Spill 8e25b118aSDominic Spill * Redistributions of source code must retain the above copyright 9e25b118aSDominic Spill notice, this list of conditions and the following disclaimer. 10e25b118aSDominic Spill 11e25b118aSDominic Spill THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12e25b118aSDominic Spill IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13e25b118aSDominic Spill TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14e25b118aSDominic Spill PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15e25b118aSDominic Spill OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16e25b118aSDominic Spill EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17e25b118aSDominic Spill PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18e25b118aSDominic Spill PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19e25b118aSDominic Spill LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20e25b118aSDominic Spill NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21e25b118aSDominic Spill SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22e25b118aSDominic Spill */ 23e25b118aSDominic Spill 24e25b118aSDominic Spill #ifndef UTHASH_H 25e25b118aSDominic Spill #define UTHASH_H 26e25b118aSDominic Spill 27e25b118aSDominic Spill #include <string.h> /* memcmp,strlen */ 28e25b118aSDominic Spill #include <stddef.h> /* ptrdiff_t */ 29e25b118aSDominic Spill #include <stdlib.h> /* exit() */ 30e25b118aSDominic Spill 31e25b118aSDominic Spill /* These macros use decltype or the earlier __typeof GNU extension. 32e25b118aSDominic Spill As decltype is only available in newer compilers (VS2010 or gcc 4.3+ 33e25b118aSDominic Spill when compiling c++ source) this code uses whatever method is needed 34e25b118aSDominic Spill or, for VS2008 where neither is available, uses casting workarounds. */ 35e25b118aSDominic Spill #ifdef _MSC_VER /* MS compiler */ 36e25b118aSDominic Spill #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ 37e25b118aSDominic Spill #define DECLTYPE(x) (decltype(x)) 38e25b118aSDominic Spill #else /* VS2008 or older (or VS2010 in C mode) */ 39e25b118aSDominic Spill #define NO_DECLTYPE 40e25b118aSDominic Spill #define DECLTYPE(x) 41e25b118aSDominic Spill #endif 42e25b118aSDominic Spill #else /* GNU, Sun and other compilers */ 43e25b118aSDominic Spill #define DECLTYPE(x) (__typeof(x)) 44e25b118aSDominic Spill #endif 45e25b118aSDominic Spill 46e25b118aSDominic Spill #ifdef NO_DECLTYPE 47e25b118aSDominic Spill #define DECLTYPE_ASSIGN(dst,src) \ 48e25b118aSDominic Spill do { \ 49e25b118aSDominic Spill char **_da_dst = (char**)(&(dst)); \ 50e25b118aSDominic Spill *_da_dst = (char*)(src); \ 51e25b118aSDominic Spill } while(0) 52e25b118aSDominic Spill #else 53e25b118aSDominic Spill #define DECLTYPE_ASSIGN(dst,src) \ 54e25b118aSDominic Spill do { \ 55e25b118aSDominic Spill (dst) = DECLTYPE(dst)(src); \ 56e25b118aSDominic Spill } while(0) 57e25b118aSDominic Spill #endif 58e25b118aSDominic Spill 59e25b118aSDominic Spill /* a number of the hash function use uint32_t which isn't defined on win32 */ 60e25b118aSDominic Spill #ifdef _MSC_VER 61e25b118aSDominic Spill typedef unsigned int uint32_t; 62e25b118aSDominic Spill typedef unsigned char uint8_t; 63e25b118aSDominic Spill #else 64e25b118aSDominic Spill #include <inttypes.h> /* uint32_t */ 65e25b118aSDominic Spill #endif 66e25b118aSDominic Spill 67*935bdedbSDominic Spill #define UTHASH_VERSION 1.9.8 68e25b118aSDominic Spill 69e25b118aSDominic Spill #ifndef uthash_fatal 70e25b118aSDominic Spill #define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ 71e25b118aSDominic Spill #endif 72e25b118aSDominic Spill #ifndef uthash_malloc 73e25b118aSDominic Spill #define uthash_malloc(sz) malloc(sz) /* malloc fcn */ 74e25b118aSDominic Spill #endif 75e25b118aSDominic Spill #ifndef uthash_free 76e25b118aSDominic Spill #define uthash_free(ptr,sz) free(ptr) /* free fcn */ 77e25b118aSDominic Spill #endif 78e25b118aSDominic Spill 79e25b118aSDominic Spill #ifndef uthash_noexpand_fyi 80e25b118aSDominic Spill #define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ 81e25b118aSDominic Spill #endif 82e25b118aSDominic Spill #ifndef uthash_expand_fyi 83e25b118aSDominic Spill #define uthash_expand_fyi(tbl) /* can be defined to log expands */ 84e25b118aSDominic Spill #endif 85e25b118aSDominic Spill 86e25b118aSDominic Spill /* initial number of buckets */ 87e25b118aSDominic Spill #define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ 88e25b118aSDominic Spill #define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ 89e25b118aSDominic Spill #define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ 90e25b118aSDominic Spill 91e25b118aSDominic Spill /* calculate the element whose hash handle address is hhe */ 92e25b118aSDominic Spill #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) 93e25b118aSDominic Spill 94e25b118aSDominic Spill #define HASH_FIND(hh,head,keyptr,keylen,out) \ 95e25b118aSDominic Spill do { \ 96e25b118aSDominic Spill unsigned _hf_bkt,_hf_hashv; \ 97e25b118aSDominic Spill out=NULL; \ 98e25b118aSDominic Spill if (head) { \ 99e25b118aSDominic Spill HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ 100e25b118aSDominic Spill if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ 101e25b118aSDominic Spill HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ 102e25b118aSDominic Spill keyptr,keylen,out); \ 103e25b118aSDominic Spill } \ 104e25b118aSDominic Spill } \ 105e25b118aSDominic Spill } while (0) 106e25b118aSDominic Spill 107e25b118aSDominic Spill #ifdef HASH_BLOOM 108e25b118aSDominic Spill #define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) 109e25b118aSDominic Spill #define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) 110e25b118aSDominic Spill #define HASH_BLOOM_MAKE(tbl) \ 111e25b118aSDominic Spill do { \ 112e25b118aSDominic Spill (tbl)->bloom_nbits = HASH_BLOOM; \ 113e25b118aSDominic Spill (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ 114e25b118aSDominic Spill if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ 115e25b118aSDominic Spill memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ 116e25b118aSDominic Spill (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ 117e25b118aSDominic Spill } while (0) 118e25b118aSDominic Spill 119e25b118aSDominic Spill #define HASH_BLOOM_FREE(tbl) \ 120e25b118aSDominic Spill do { \ 121e25b118aSDominic Spill uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ 122e25b118aSDominic Spill } while (0) 123e25b118aSDominic Spill 124e25b118aSDominic Spill #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) 125e25b118aSDominic Spill #define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) 126e25b118aSDominic Spill 127e25b118aSDominic Spill #define HASH_BLOOM_ADD(tbl,hashv) \ 128e25b118aSDominic Spill HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) 129e25b118aSDominic Spill 130e25b118aSDominic Spill #define HASH_BLOOM_TEST(tbl,hashv) \ 131e25b118aSDominic Spill HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) 132e25b118aSDominic Spill 133e25b118aSDominic Spill #else 134e25b118aSDominic Spill #define HASH_BLOOM_MAKE(tbl) 135e25b118aSDominic Spill #define HASH_BLOOM_FREE(tbl) 136e25b118aSDominic Spill #define HASH_BLOOM_ADD(tbl,hashv) 137e25b118aSDominic Spill #define HASH_BLOOM_TEST(tbl,hashv) (1) 138*935bdedbSDominic Spill #define HASH_BLOOM_BYTELEN 0 139e25b118aSDominic Spill #endif 140e25b118aSDominic Spill 141e25b118aSDominic Spill #define HASH_MAKE_TABLE(hh,head) \ 142e25b118aSDominic Spill do { \ 143e25b118aSDominic Spill (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ 144e25b118aSDominic Spill sizeof(UT_hash_table)); \ 145e25b118aSDominic Spill if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ 146e25b118aSDominic Spill memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ 147e25b118aSDominic Spill (head)->hh.tbl->tail = &((head)->hh); \ 148e25b118aSDominic Spill (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ 149e25b118aSDominic Spill (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ 150e25b118aSDominic Spill (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ 151e25b118aSDominic Spill (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ 152e25b118aSDominic Spill HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ 153e25b118aSDominic Spill if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ 154e25b118aSDominic Spill memset((head)->hh.tbl->buckets, 0, \ 155e25b118aSDominic Spill HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ 156e25b118aSDominic Spill HASH_BLOOM_MAKE((head)->hh.tbl); \ 157e25b118aSDominic Spill (head)->hh.tbl->signature = HASH_SIGNATURE; \ 158e25b118aSDominic Spill } while(0) 159e25b118aSDominic Spill 160e25b118aSDominic Spill #define HASH_ADD(hh,head,fieldname,keylen_in,add) \ 161e25b118aSDominic Spill HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) 162e25b118aSDominic Spill 163*935bdedbSDominic Spill #define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ 164*935bdedbSDominic Spill do { \ 165*935bdedbSDominic Spill replaced=NULL; \ 166*935bdedbSDominic Spill HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ 167*935bdedbSDominic Spill if (replaced!=NULL) { \ 168*935bdedbSDominic Spill HASH_DELETE(hh,head,replaced); \ 169*935bdedbSDominic Spill }; \ 170*935bdedbSDominic Spill HASH_ADD(hh,head,fieldname,keylen_in,add); \ 171*935bdedbSDominic Spill } while(0) 172*935bdedbSDominic Spill 173e25b118aSDominic Spill #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ 174e25b118aSDominic Spill do { \ 175e25b118aSDominic Spill unsigned _ha_bkt; \ 176e25b118aSDominic Spill (add)->hh.next = NULL; \ 177e25b118aSDominic Spill (add)->hh.key = (char*)keyptr; \ 178e25b118aSDominic Spill (add)->hh.keylen = (unsigned)keylen_in; \ 179e25b118aSDominic Spill if (!(head)) { \ 180e25b118aSDominic Spill head = (add); \ 181e25b118aSDominic Spill (head)->hh.prev = NULL; \ 182e25b118aSDominic Spill HASH_MAKE_TABLE(hh,head); \ 183e25b118aSDominic Spill } else { \ 184e25b118aSDominic Spill (head)->hh.tbl->tail->next = (add); \ 185e25b118aSDominic Spill (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ 186e25b118aSDominic Spill (head)->hh.tbl->tail = &((add)->hh); \ 187e25b118aSDominic Spill } \ 188e25b118aSDominic Spill (head)->hh.tbl->num_items++; \ 189e25b118aSDominic Spill (add)->hh.tbl = (head)->hh.tbl; \ 190e25b118aSDominic Spill HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ 191e25b118aSDominic Spill (add)->hh.hashv, _ha_bkt); \ 192e25b118aSDominic Spill HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ 193e25b118aSDominic Spill HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ 194e25b118aSDominic Spill HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ 195e25b118aSDominic Spill HASH_FSCK(hh,head); \ 196e25b118aSDominic Spill } while(0) 197e25b118aSDominic Spill 198e25b118aSDominic Spill #define HASH_TO_BKT( hashv, num_bkts, bkt ) \ 199e25b118aSDominic Spill do { \ 200e25b118aSDominic Spill bkt = ((hashv) & ((num_bkts) - 1)); \ 201e25b118aSDominic Spill } while(0) 202e25b118aSDominic Spill 203e25b118aSDominic Spill /* delete "delptr" from the hash table. 204e25b118aSDominic Spill * "the usual" patch-up process for the app-order doubly-linked-list. 205e25b118aSDominic Spill * The use of _hd_hh_del below deserves special explanation. 206e25b118aSDominic Spill * These used to be expressed using (delptr) but that led to a bug 207e25b118aSDominic Spill * if someone used the same symbol for the head and deletee, like 208e25b118aSDominic Spill * HASH_DELETE(hh,users,users); 209e25b118aSDominic Spill * We want that to work, but by changing the head (users) below 210e25b118aSDominic Spill * we were forfeiting our ability to further refer to the deletee (users) 211e25b118aSDominic Spill * in the patch-up process. Solution: use scratch space to 212e25b118aSDominic Spill * copy the deletee pointer, then the latter references are via that 213e25b118aSDominic Spill * scratch pointer rather than through the repointed (users) symbol. 214e25b118aSDominic Spill */ 215e25b118aSDominic Spill #define HASH_DELETE(hh,head,delptr) \ 216e25b118aSDominic Spill do { \ 217e25b118aSDominic Spill unsigned _hd_bkt; \ 218e25b118aSDominic Spill struct UT_hash_handle *_hd_hh_del; \ 219e25b118aSDominic Spill if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ 220e25b118aSDominic Spill uthash_free((head)->hh.tbl->buckets, \ 221e25b118aSDominic Spill (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ 222e25b118aSDominic Spill HASH_BLOOM_FREE((head)->hh.tbl); \ 223e25b118aSDominic Spill uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ 224e25b118aSDominic Spill head = NULL; \ 225e25b118aSDominic Spill } else { \ 226e25b118aSDominic Spill _hd_hh_del = &((delptr)->hh); \ 227e25b118aSDominic Spill if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ 228e25b118aSDominic Spill (head)->hh.tbl->tail = \ 229e25b118aSDominic Spill (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ 230e25b118aSDominic Spill (head)->hh.tbl->hho); \ 231e25b118aSDominic Spill } \ 232e25b118aSDominic Spill if ((delptr)->hh.prev) { \ 233e25b118aSDominic Spill ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ 234e25b118aSDominic Spill (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ 235e25b118aSDominic Spill } else { \ 236e25b118aSDominic Spill DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ 237e25b118aSDominic Spill } \ 238e25b118aSDominic Spill if (_hd_hh_del->next) { \ 239e25b118aSDominic Spill ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ 240e25b118aSDominic Spill (head)->hh.tbl->hho))->prev = \ 241e25b118aSDominic Spill _hd_hh_del->prev; \ 242e25b118aSDominic Spill } \ 243e25b118aSDominic Spill HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ 244e25b118aSDominic Spill HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ 245e25b118aSDominic Spill (head)->hh.tbl->num_items--; \ 246e25b118aSDominic Spill } \ 247e25b118aSDominic Spill HASH_FSCK(hh,head); \ 248e25b118aSDominic Spill } while (0) 249e25b118aSDominic Spill 250e25b118aSDominic Spill 251e25b118aSDominic Spill /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ 252e25b118aSDominic Spill #define HASH_FIND_STR(head,findstr,out) \ 253e25b118aSDominic Spill HASH_FIND(hh,head,findstr,strlen(findstr),out) 254e25b118aSDominic Spill #define HASH_ADD_STR(head,strfield,add) \ 255e25b118aSDominic Spill HASH_ADD(hh,head,strfield,strlen(add->strfield),add) 256*935bdedbSDominic Spill #define HASH_REPLACE_STR(head,strfield,add,replaced) \ 257*935bdedbSDominic Spill HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced) 258e25b118aSDominic Spill #define HASH_FIND_INT(head,findint,out) \ 259e25b118aSDominic Spill HASH_FIND(hh,head,findint,sizeof(int),out) 260e25b118aSDominic Spill #define HASH_ADD_INT(head,intfield,add) \ 261e25b118aSDominic Spill HASH_ADD(hh,head,intfield,sizeof(int),add) 262*935bdedbSDominic Spill #define HASH_REPLACE_INT(head,intfield,add,replaced) \ 263*935bdedbSDominic Spill HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) 264e25b118aSDominic Spill #define HASH_FIND_PTR(head,findptr,out) \ 265e25b118aSDominic Spill HASH_FIND(hh,head,findptr,sizeof(void *),out) 266e25b118aSDominic Spill #define HASH_ADD_PTR(head,ptrfield,add) \ 267e25b118aSDominic Spill HASH_ADD(hh,head,ptrfield,sizeof(void *),add) 268*935bdedbSDominic Spill #define HASH_REPLACE_PTR(head,ptrfield,add) \ 269*935bdedbSDominic Spill HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) 270e25b118aSDominic Spill #define HASH_DEL(head,delptr) \ 271e25b118aSDominic Spill HASH_DELETE(hh,head,delptr) 272e25b118aSDominic Spill 273e25b118aSDominic Spill /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. 274e25b118aSDominic Spill * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. 275e25b118aSDominic Spill */ 276e25b118aSDominic Spill #ifdef HASH_DEBUG 277e25b118aSDominic Spill #define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) 278e25b118aSDominic Spill #define HASH_FSCK(hh,head) \ 279e25b118aSDominic Spill do { \ 280e25b118aSDominic Spill unsigned _bkt_i; \ 281e25b118aSDominic Spill unsigned _count, _bkt_count; \ 282e25b118aSDominic Spill char *_prev; \ 283e25b118aSDominic Spill struct UT_hash_handle *_thh; \ 284e25b118aSDominic Spill if (head) { \ 285e25b118aSDominic Spill _count = 0; \ 286e25b118aSDominic Spill for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ 287e25b118aSDominic Spill _bkt_count = 0; \ 288e25b118aSDominic Spill _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ 289e25b118aSDominic Spill _prev = NULL; \ 290e25b118aSDominic Spill while (_thh) { \ 291e25b118aSDominic Spill if (_prev != (char*)(_thh->hh_prev)) { \ 292e25b118aSDominic Spill HASH_OOPS("invalid hh_prev %p, actual %p\n", \ 293e25b118aSDominic Spill _thh->hh_prev, _prev ); \ 294e25b118aSDominic Spill } \ 295e25b118aSDominic Spill _bkt_count++; \ 296e25b118aSDominic Spill _prev = (char*)(_thh); \ 297e25b118aSDominic Spill _thh = _thh->hh_next; \ 298e25b118aSDominic Spill } \ 299e25b118aSDominic Spill _count += _bkt_count; \ 300e25b118aSDominic Spill if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ 301e25b118aSDominic Spill HASH_OOPS("invalid bucket count %d, actual %d\n", \ 302e25b118aSDominic Spill (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ 303e25b118aSDominic Spill } \ 304e25b118aSDominic Spill } \ 305e25b118aSDominic Spill if (_count != (head)->hh.tbl->num_items) { \ 306e25b118aSDominic Spill HASH_OOPS("invalid hh item count %d, actual %d\n", \ 307e25b118aSDominic Spill (head)->hh.tbl->num_items, _count ); \ 308e25b118aSDominic Spill } \ 309e25b118aSDominic Spill /* traverse hh in app order; check next/prev integrity, count */ \ 310e25b118aSDominic Spill _count = 0; \ 311e25b118aSDominic Spill _prev = NULL; \ 312e25b118aSDominic Spill _thh = &(head)->hh; \ 313e25b118aSDominic Spill while (_thh) { \ 314e25b118aSDominic Spill _count++; \ 315e25b118aSDominic Spill if (_prev !=(char*)(_thh->prev)) { \ 316e25b118aSDominic Spill HASH_OOPS("invalid prev %p, actual %p\n", \ 317e25b118aSDominic Spill _thh->prev, _prev ); \ 318e25b118aSDominic Spill } \ 319e25b118aSDominic Spill _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ 320e25b118aSDominic Spill _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ 321e25b118aSDominic Spill (head)->hh.tbl->hho) : NULL ); \ 322e25b118aSDominic Spill } \ 323e25b118aSDominic Spill if (_count != (head)->hh.tbl->num_items) { \ 324e25b118aSDominic Spill HASH_OOPS("invalid app item count %d, actual %d\n", \ 325e25b118aSDominic Spill (head)->hh.tbl->num_items, _count ); \ 326e25b118aSDominic Spill } \ 327e25b118aSDominic Spill } \ 328e25b118aSDominic Spill } while (0) 329e25b118aSDominic Spill #else 330e25b118aSDominic Spill #define HASH_FSCK(hh,head) 331e25b118aSDominic Spill #endif 332e25b118aSDominic Spill 333e25b118aSDominic Spill /* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to 334e25b118aSDominic Spill * the descriptor to which this macro is defined for tuning the hash function. 335e25b118aSDominic Spill * The app can #include <unistd.h> to get the prototype for write(2). */ 336e25b118aSDominic Spill #ifdef HASH_EMIT_KEYS 337e25b118aSDominic Spill #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ 338e25b118aSDominic Spill do { \ 339e25b118aSDominic Spill unsigned _klen = fieldlen; \ 340e25b118aSDominic Spill write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ 341e25b118aSDominic Spill write(HASH_EMIT_KEYS, keyptr, fieldlen); \ 342e25b118aSDominic Spill } while (0) 343e25b118aSDominic Spill #else 344e25b118aSDominic Spill #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) 345e25b118aSDominic Spill #endif 346e25b118aSDominic Spill 347e25b118aSDominic Spill /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ 348e25b118aSDominic Spill #ifdef HASH_FUNCTION 349e25b118aSDominic Spill #define HASH_FCN HASH_FUNCTION 350e25b118aSDominic Spill #else 351e25b118aSDominic Spill #define HASH_FCN HASH_JEN 352e25b118aSDominic Spill #endif 353e25b118aSDominic Spill 354e25b118aSDominic Spill /* The Bernstein hash function, used in Perl prior to v5.6 */ 355e25b118aSDominic Spill #define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ 356e25b118aSDominic Spill do { \ 357e25b118aSDominic Spill unsigned _hb_keylen=keylen; \ 358e25b118aSDominic Spill char *_hb_key=(char*)(key); \ 359e25b118aSDominic Spill (hashv) = 0; \ 360e25b118aSDominic Spill while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ 361e25b118aSDominic Spill bkt = (hashv) & (num_bkts-1); \ 362e25b118aSDominic Spill } while (0) 363e25b118aSDominic Spill 364e25b118aSDominic Spill 365e25b118aSDominic Spill /* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at 366e25b118aSDominic Spill * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ 367e25b118aSDominic Spill #define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ 368e25b118aSDominic Spill do { \ 369e25b118aSDominic Spill unsigned _sx_i; \ 370e25b118aSDominic Spill char *_hs_key=(char*)(key); \ 371e25b118aSDominic Spill hashv = 0; \ 372e25b118aSDominic Spill for(_sx_i=0; _sx_i < keylen; _sx_i++) \ 373e25b118aSDominic Spill hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ 374e25b118aSDominic Spill bkt = hashv & (num_bkts-1); \ 375e25b118aSDominic Spill } while (0) 376e25b118aSDominic Spill 377e25b118aSDominic Spill #define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ 378e25b118aSDominic Spill do { \ 379e25b118aSDominic Spill unsigned _fn_i; \ 380e25b118aSDominic Spill char *_hf_key=(char*)(key); \ 381e25b118aSDominic Spill hashv = 2166136261UL; \ 382e25b118aSDominic Spill for(_fn_i=0; _fn_i < keylen; _fn_i++) \ 383e25b118aSDominic Spill hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ 384e25b118aSDominic Spill bkt = hashv & (num_bkts-1); \ 385e25b118aSDominic Spill } while(0) 386e25b118aSDominic Spill 387e25b118aSDominic Spill #define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ 388e25b118aSDominic Spill do { \ 389e25b118aSDominic Spill unsigned _ho_i; \ 390e25b118aSDominic Spill char *_ho_key=(char*)(key); \ 391e25b118aSDominic Spill hashv = 0; \ 392e25b118aSDominic Spill for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ 393e25b118aSDominic Spill hashv += _ho_key[_ho_i]; \ 394e25b118aSDominic Spill hashv += (hashv << 10); \ 395e25b118aSDominic Spill hashv ^= (hashv >> 6); \ 396e25b118aSDominic Spill } \ 397e25b118aSDominic Spill hashv += (hashv << 3); \ 398e25b118aSDominic Spill hashv ^= (hashv >> 11); \ 399e25b118aSDominic Spill hashv += (hashv << 15); \ 400e25b118aSDominic Spill bkt = hashv & (num_bkts-1); \ 401e25b118aSDominic Spill } while(0) 402e25b118aSDominic Spill 403e25b118aSDominic Spill #define HASH_JEN_MIX(a,b,c) \ 404e25b118aSDominic Spill do { \ 405e25b118aSDominic Spill a -= b; a -= c; a ^= ( c >> 13 ); \ 406e25b118aSDominic Spill b -= c; b -= a; b ^= ( a << 8 ); \ 407e25b118aSDominic Spill c -= a; c -= b; c ^= ( b >> 13 ); \ 408e25b118aSDominic Spill a -= b; a -= c; a ^= ( c >> 12 ); \ 409e25b118aSDominic Spill b -= c; b -= a; b ^= ( a << 16 ); \ 410e25b118aSDominic Spill c -= a; c -= b; c ^= ( b >> 5 ); \ 411e25b118aSDominic Spill a -= b; a -= c; a ^= ( c >> 3 ); \ 412e25b118aSDominic Spill b -= c; b -= a; b ^= ( a << 10 ); \ 413e25b118aSDominic Spill c -= a; c -= b; c ^= ( b >> 15 ); \ 414e25b118aSDominic Spill } while (0) 415e25b118aSDominic Spill 416e25b118aSDominic Spill #define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ 417e25b118aSDominic Spill do { \ 418e25b118aSDominic Spill unsigned _hj_i,_hj_j,_hj_k; \ 419*935bdedbSDominic Spill unsigned char *_hj_key=(unsigned char*)(key); \ 420e25b118aSDominic Spill hashv = 0xfeedbeef; \ 421e25b118aSDominic Spill _hj_i = _hj_j = 0x9e3779b9; \ 422e25b118aSDominic Spill _hj_k = (unsigned)keylen; \ 423e25b118aSDominic Spill while (_hj_k >= 12) { \ 424e25b118aSDominic Spill _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ 425e25b118aSDominic Spill + ( (unsigned)_hj_key[2] << 16 ) \ 426e25b118aSDominic Spill + ( (unsigned)_hj_key[3] << 24 ) ); \ 427e25b118aSDominic Spill _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ 428e25b118aSDominic Spill + ( (unsigned)_hj_key[6] << 16 ) \ 429e25b118aSDominic Spill + ( (unsigned)_hj_key[7] << 24 ) ); \ 430e25b118aSDominic Spill hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ 431e25b118aSDominic Spill + ( (unsigned)_hj_key[10] << 16 ) \ 432e25b118aSDominic Spill + ( (unsigned)_hj_key[11] << 24 ) ); \ 433e25b118aSDominic Spill \ 434e25b118aSDominic Spill HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ 435e25b118aSDominic Spill \ 436e25b118aSDominic Spill _hj_key += 12; \ 437e25b118aSDominic Spill _hj_k -= 12; \ 438e25b118aSDominic Spill } \ 439e25b118aSDominic Spill hashv += keylen; \ 440e25b118aSDominic Spill switch ( _hj_k ) { \ 441e25b118aSDominic Spill case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ 442e25b118aSDominic Spill case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ 443e25b118aSDominic Spill case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ 444e25b118aSDominic Spill case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ 445e25b118aSDominic Spill case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ 446e25b118aSDominic Spill case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ 447e25b118aSDominic Spill case 5: _hj_j += _hj_key[4]; \ 448e25b118aSDominic Spill case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ 449e25b118aSDominic Spill case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ 450e25b118aSDominic Spill case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ 451e25b118aSDominic Spill case 1: _hj_i += _hj_key[0]; \ 452e25b118aSDominic Spill } \ 453e25b118aSDominic Spill HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ 454e25b118aSDominic Spill bkt = hashv & (num_bkts-1); \ 455e25b118aSDominic Spill } while(0) 456e25b118aSDominic Spill 457e25b118aSDominic Spill /* The Paul Hsieh hash function */ 458e25b118aSDominic Spill #undef get16bits 459e25b118aSDominic Spill #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ 460e25b118aSDominic Spill || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) 461e25b118aSDominic Spill #define get16bits(d) (*((const uint16_t *) (d))) 462e25b118aSDominic Spill #endif 463e25b118aSDominic Spill 464e25b118aSDominic Spill #if !defined (get16bits) 465e25b118aSDominic Spill #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ 466e25b118aSDominic Spill +(uint32_t)(((const uint8_t *)(d))[0]) ) 467e25b118aSDominic Spill #endif 468e25b118aSDominic Spill #define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ 469e25b118aSDominic Spill do { \ 470*935bdedbSDominic Spill unsigned char *_sfh_key=(unsigned char*)(key); \ 471e25b118aSDominic Spill uint32_t _sfh_tmp, _sfh_len = keylen; \ 472e25b118aSDominic Spill \ 473e25b118aSDominic Spill int _sfh_rem = _sfh_len & 3; \ 474e25b118aSDominic Spill _sfh_len >>= 2; \ 475e25b118aSDominic Spill hashv = 0xcafebabe; \ 476e25b118aSDominic Spill \ 477e25b118aSDominic Spill /* Main loop */ \ 478e25b118aSDominic Spill for (;_sfh_len > 0; _sfh_len--) { \ 479e25b118aSDominic Spill hashv += get16bits (_sfh_key); \ 480*935bdedbSDominic Spill _sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \ 481e25b118aSDominic Spill hashv = (hashv << 16) ^ _sfh_tmp; \ 482e25b118aSDominic Spill _sfh_key += 2*sizeof (uint16_t); \ 483e25b118aSDominic Spill hashv += hashv >> 11; \ 484e25b118aSDominic Spill } \ 485e25b118aSDominic Spill \ 486e25b118aSDominic Spill /* Handle end cases */ \ 487e25b118aSDominic Spill switch (_sfh_rem) { \ 488e25b118aSDominic Spill case 3: hashv += get16bits (_sfh_key); \ 489e25b118aSDominic Spill hashv ^= hashv << 16; \ 490*935bdedbSDominic Spill hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \ 491e25b118aSDominic Spill hashv += hashv >> 11; \ 492e25b118aSDominic Spill break; \ 493e25b118aSDominic Spill case 2: hashv += get16bits (_sfh_key); \ 494e25b118aSDominic Spill hashv ^= hashv << 11; \ 495e25b118aSDominic Spill hashv += hashv >> 17; \ 496e25b118aSDominic Spill break; \ 497e25b118aSDominic Spill case 1: hashv += *_sfh_key; \ 498e25b118aSDominic Spill hashv ^= hashv << 10; \ 499e25b118aSDominic Spill hashv += hashv >> 1; \ 500e25b118aSDominic Spill } \ 501e25b118aSDominic Spill \ 502e25b118aSDominic Spill /* Force "avalanching" of final 127 bits */ \ 503e25b118aSDominic Spill hashv ^= hashv << 3; \ 504e25b118aSDominic Spill hashv += hashv >> 5; \ 505e25b118aSDominic Spill hashv ^= hashv << 4; \ 506e25b118aSDominic Spill hashv += hashv >> 17; \ 507e25b118aSDominic Spill hashv ^= hashv << 25; \ 508e25b118aSDominic Spill hashv += hashv >> 6; \ 509e25b118aSDominic Spill bkt = hashv & (num_bkts-1); \ 510e25b118aSDominic Spill } while(0) 511e25b118aSDominic Spill 512e25b118aSDominic Spill #ifdef HASH_USING_NO_STRICT_ALIASING 513e25b118aSDominic Spill /* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. 514e25b118aSDominic Spill * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. 515e25b118aSDominic Spill * MurmurHash uses the faster approach only on CPU's where we know it's safe. 516e25b118aSDominic Spill * 517e25b118aSDominic Spill * Note the preprocessor built-in defines can be emitted using: 518e25b118aSDominic Spill * 519e25b118aSDominic Spill * gcc -m64 -dM -E - < /dev/null (on gcc) 520e25b118aSDominic Spill * cc -## a.c (where a.c is a simple test file) (Sun Studio) 521e25b118aSDominic Spill */ 522e25b118aSDominic Spill #if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) 523e25b118aSDominic Spill #define MUR_GETBLOCK(p,i) p[i] 524e25b118aSDominic Spill #else /* non intel */ 525e25b118aSDominic Spill #define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0) 526e25b118aSDominic Spill #define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1) 527e25b118aSDominic Spill #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2) 528e25b118aSDominic Spill #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3) 529e25b118aSDominic Spill #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) 530e25b118aSDominic Spill #if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) 531e25b118aSDominic Spill #define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) 532e25b118aSDominic Spill #define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) 533e25b118aSDominic Spill #define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) 534e25b118aSDominic Spill #else /* assume little endian non-intel */ 535e25b118aSDominic Spill #define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) 536e25b118aSDominic Spill #define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) 537e25b118aSDominic Spill #define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) 538e25b118aSDominic Spill #endif 539e25b118aSDominic Spill #define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ 540e25b118aSDominic Spill (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ 541e25b118aSDominic Spill (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ 542e25b118aSDominic Spill MUR_ONE_THREE(p)))) 543e25b118aSDominic Spill #endif 544e25b118aSDominic Spill #define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) 545e25b118aSDominic Spill #define MUR_FMIX(_h) \ 546e25b118aSDominic Spill do { \ 547e25b118aSDominic Spill _h ^= _h >> 16; \ 548e25b118aSDominic Spill _h *= 0x85ebca6b; \ 549e25b118aSDominic Spill _h ^= _h >> 13; \ 550e25b118aSDominic Spill _h *= 0xc2b2ae35l; \ 551e25b118aSDominic Spill _h ^= _h >> 16; \ 552e25b118aSDominic Spill } while(0) 553e25b118aSDominic Spill 554e25b118aSDominic Spill #define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \ 555e25b118aSDominic Spill do { \ 556e25b118aSDominic Spill const uint8_t *_mur_data = (const uint8_t*)(key); \ 557e25b118aSDominic Spill const int _mur_nblocks = (keylen) / 4; \ 558e25b118aSDominic Spill uint32_t _mur_h1 = 0xf88D5353; \ 559e25b118aSDominic Spill uint32_t _mur_c1 = 0xcc9e2d51; \ 560e25b118aSDominic Spill uint32_t _mur_c2 = 0x1b873593; \ 561e25b118aSDominic Spill uint32_t _mur_k1 = 0; \ 562e25b118aSDominic Spill const uint8_t *_mur_tail; \ 563e25b118aSDominic Spill const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \ 564e25b118aSDominic Spill int _mur_i; \ 565e25b118aSDominic Spill for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \ 566e25b118aSDominic Spill _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ 567e25b118aSDominic Spill _mur_k1 *= _mur_c1; \ 568e25b118aSDominic Spill _mur_k1 = MUR_ROTL32(_mur_k1,15); \ 569e25b118aSDominic Spill _mur_k1 *= _mur_c2; \ 570e25b118aSDominic Spill \ 571e25b118aSDominic Spill _mur_h1 ^= _mur_k1; \ 572e25b118aSDominic Spill _mur_h1 = MUR_ROTL32(_mur_h1,13); \ 573e25b118aSDominic Spill _mur_h1 = _mur_h1*5+0xe6546b64; \ 574e25b118aSDominic Spill } \ 575e25b118aSDominic Spill _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ 576e25b118aSDominic Spill _mur_k1=0; \ 577e25b118aSDominic Spill switch((keylen) & 3) { \ 578e25b118aSDominic Spill case 3: _mur_k1 ^= _mur_tail[2] << 16; \ 579e25b118aSDominic Spill case 2: _mur_k1 ^= _mur_tail[1] << 8; \ 580e25b118aSDominic Spill case 1: _mur_k1 ^= _mur_tail[0]; \ 581e25b118aSDominic Spill _mur_k1 *= _mur_c1; \ 582e25b118aSDominic Spill _mur_k1 = MUR_ROTL32(_mur_k1,15); \ 583e25b118aSDominic Spill _mur_k1 *= _mur_c2; \ 584e25b118aSDominic Spill _mur_h1 ^= _mur_k1; \ 585e25b118aSDominic Spill } \ 586e25b118aSDominic Spill _mur_h1 ^= (keylen); \ 587e25b118aSDominic Spill MUR_FMIX(_mur_h1); \ 588e25b118aSDominic Spill hashv = _mur_h1; \ 589e25b118aSDominic Spill bkt = hashv & (num_bkts-1); \ 590e25b118aSDominic Spill } while(0) 591e25b118aSDominic Spill #endif /* HASH_USING_NO_STRICT_ALIASING */ 592e25b118aSDominic Spill 593e25b118aSDominic Spill /* key comparison function; return 0 if keys equal */ 594e25b118aSDominic Spill #define HASH_KEYCMP(a,b,len) memcmp(a,b,len) 595e25b118aSDominic Spill 596e25b118aSDominic Spill /* iterate over items in a known bucket to find desired item */ 597e25b118aSDominic Spill #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ 598e25b118aSDominic Spill do { \ 599e25b118aSDominic Spill if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ 600e25b118aSDominic Spill else out=NULL; \ 601e25b118aSDominic Spill while (out) { \ 602e25b118aSDominic Spill if ((out)->hh.keylen == keylen_in) { \ 603e25b118aSDominic Spill if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \ 604e25b118aSDominic Spill } \ 605e25b118aSDominic Spill if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \ 606e25b118aSDominic Spill else out = NULL; \ 607e25b118aSDominic Spill } \ 608e25b118aSDominic Spill } while(0) 609e25b118aSDominic Spill 610e25b118aSDominic Spill /* add an item to a bucket */ 611e25b118aSDominic Spill #define HASH_ADD_TO_BKT(head,addhh) \ 612e25b118aSDominic Spill do { \ 613e25b118aSDominic Spill head.count++; \ 614e25b118aSDominic Spill (addhh)->hh_next = head.hh_head; \ 615e25b118aSDominic Spill (addhh)->hh_prev = NULL; \ 616e25b118aSDominic Spill if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ 617e25b118aSDominic Spill (head).hh_head=addhh; \ 618e25b118aSDominic Spill if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ 619e25b118aSDominic Spill && (addhh)->tbl->noexpand != 1) { \ 620e25b118aSDominic Spill HASH_EXPAND_BUCKETS((addhh)->tbl); \ 621e25b118aSDominic Spill } \ 622e25b118aSDominic Spill } while(0) 623e25b118aSDominic Spill 624e25b118aSDominic Spill /* remove an item from a given bucket */ 625e25b118aSDominic Spill #define HASH_DEL_IN_BKT(hh,head,hh_del) \ 626e25b118aSDominic Spill (head).count--; \ 627e25b118aSDominic Spill if ((head).hh_head == hh_del) { \ 628e25b118aSDominic Spill (head).hh_head = hh_del->hh_next; \ 629e25b118aSDominic Spill } \ 630e25b118aSDominic Spill if (hh_del->hh_prev) { \ 631e25b118aSDominic Spill hh_del->hh_prev->hh_next = hh_del->hh_next; \ 632e25b118aSDominic Spill } \ 633e25b118aSDominic Spill if (hh_del->hh_next) { \ 634e25b118aSDominic Spill hh_del->hh_next->hh_prev = hh_del->hh_prev; \ 635e25b118aSDominic Spill } 636e25b118aSDominic Spill 637e25b118aSDominic Spill /* Bucket expansion has the effect of doubling the number of buckets 638e25b118aSDominic Spill * and redistributing the items into the new buckets. Ideally the 639e25b118aSDominic Spill * items will distribute more or less evenly into the new buckets 640e25b118aSDominic Spill * (the extent to which this is true is a measure of the quality of 641e25b118aSDominic Spill * the hash function as it applies to the key domain). 642e25b118aSDominic Spill * 643e25b118aSDominic Spill * With the items distributed into more buckets, the chain length 644e25b118aSDominic Spill * (item count) in each bucket is reduced. Thus by expanding buckets 645e25b118aSDominic Spill * the hash keeps a bound on the chain length. This bounded chain 646e25b118aSDominic Spill * length is the essence of how a hash provides constant time lookup. 647e25b118aSDominic Spill * 648e25b118aSDominic Spill * The calculation of tbl->ideal_chain_maxlen below deserves some 649e25b118aSDominic Spill * explanation. First, keep in mind that we're calculating the ideal 650e25b118aSDominic Spill * maximum chain length based on the *new* (doubled) bucket count. 651e25b118aSDominic Spill * In fractions this is just n/b (n=number of items,b=new num buckets). 652e25b118aSDominic Spill * Since the ideal chain length is an integer, we want to calculate 653e25b118aSDominic Spill * ceil(n/b). We don't depend on floating point arithmetic in this 654e25b118aSDominic Spill * hash, so to calculate ceil(n/b) with integers we could write 655e25b118aSDominic Spill * 656e25b118aSDominic Spill * ceil(n/b) = (n/b) + ((n%b)?1:0) 657e25b118aSDominic Spill * 658e25b118aSDominic Spill * and in fact a previous version of this hash did just that. 659e25b118aSDominic Spill * But now we have improved things a bit by recognizing that b is 660e25b118aSDominic Spill * always a power of two. We keep its base 2 log handy (call it lb), 661e25b118aSDominic Spill * so now we can write this with a bit shift and logical AND: 662e25b118aSDominic Spill * 663e25b118aSDominic Spill * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) 664e25b118aSDominic Spill * 665e25b118aSDominic Spill */ 666e25b118aSDominic Spill #define HASH_EXPAND_BUCKETS(tbl) \ 667e25b118aSDominic Spill do { \ 668e25b118aSDominic Spill unsigned _he_bkt; \ 669e25b118aSDominic Spill unsigned _he_bkt_i; \ 670e25b118aSDominic Spill struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ 671e25b118aSDominic Spill UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ 672e25b118aSDominic Spill _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ 673e25b118aSDominic Spill 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ 674e25b118aSDominic Spill if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ 675e25b118aSDominic Spill memset(_he_new_buckets, 0, \ 676e25b118aSDominic Spill 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ 677e25b118aSDominic Spill tbl->ideal_chain_maxlen = \ 678e25b118aSDominic Spill (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ 679e25b118aSDominic Spill ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ 680e25b118aSDominic Spill tbl->nonideal_items = 0; \ 681e25b118aSDominic Spill for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ 682e25b118aSDominic Spill { \ 683e25b118aSDominic Spill _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ 684e25b118aSDominic Spill while (_he_thh) { \ 685e25b118aSDominic Spill _he_hh_nxt = _he_thh->hh_next; \ 686e25b118aSDominic Spill HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ 687e25b118aSDominic Spill _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ 688e25b118aSDominic Spill if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ 689e25b118aSDominic Spill tbl->nonideal_items++; \ 690e25b118aSDominic Spill _he_newbkt->expand_mult = _he_newbkt->count / \ 691e25b118aSDominic Spill tbl->ideal_chain_maxlen; \ 692e25b118aSDominic Spill } \ 693e25b118aSDominic Spill _he_thh->hh_prev = NULL; \ 694e25b118aSDominic Spill _he_thh->hh_next = _he_newbkt->hh_head; \ 695e25b118aSDominic Spill if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ 696e25b118aSDominic Spill _he_thh; \ 697e25b118aSDominic Spill _he_newbkt->hh_head = _he_thh; \ 698e25b118aSDominic Spill _he_thh = _he_hh_nxt; \ 699e25b118aSDominic Spill } \ 700e25b118aSDominic Spill } \ 701e25b118aSDominic Spill uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ 702e25b118aSDominic Spill tbl->num_buckets *= 2; \ 703e25b118aSDominic Spill tbl->log2_num_buckets++; \ 704e25b118aSDominic Spill tbl->buckets = _he_new_buckets; \ 705e25b118aSDominic Spill tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ 706e25b118aSDominic Spill (tbl->ineff_expands+1) : 0; \ 707e25b118aSDominic Spill if (tbl->ineff_expands > 1) { \ 708e25b118aSDominic Spill tbl->noexpand=1; \ 709e25b118aSDominic Spill uthash_noexpand_fyi(tbl); \ 710e25b118aSDominic Spill } \ 711e25b118aSDominic Spill uthash_expand_fyi(tbl); \ 712e25b118aSDominic Spill } while(0) 713e25b118aSDominic Spill 714e25b118aSDominic Spill 715e25b118aSDominic Spill /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ 716e25b118aSDominic Spill /* Note that HASH_SORT assumes the hash handle name to be hh. 717e25b118aSDominic Spill * HASH_SRT was added to allow the hash handle name to be passed in. */ 718e25b118aSDominic Spill #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) 719e25b118aSDominic Spill #define HASH_SRT(hh,head,cmpfcn) \ 720e25b118aSDominic Spill do { \ 721e25b118aSDominic Spill unsigned _hs_i; \ 722e25b118aSDominic Spill unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ 723e25b118aSDominic Spill struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ 724e25b118aSDominic Spill if (head) { \ 725e25b118aSDominic Spill _hs_insize = 1; \ 726e25b118aSDominic Spill _hs_looping = 1; \ 727e25b118aSDominic Spill _hs_list = &((head)->hh); \ 728e25b118aSDominic Spill while (_hs_looping) { \ 729e25b118aSDominic Spill _hs_p = _hs_list; \ 730e25b118aSDominic Spill _hs_list = NULL; \ 731e25b118aSDominic Spill _hs_tail = NULL; \ 732e25b118aSDominic Spill _hs_nmerges = 0; \ 733e25b118aSDominic Spill while (_hs_p) { \ 734e25b118aSDominic Spill _hs_nmerges++; \ 735e25b118aSDominic Spill _hs_q = _hs_p; \ 736e25b118aSDominic Spill _hs_psize = 0; \ 737e25b118aSDominic Spill for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ 738e25b118aSDominic Spill _hs_psize++; \ 739e25b118aSDominic Spill _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ 740e25b118aSDominic Spill ((void*)((char*)(_hs_q->next) + \ 741e25b118aSDominic Spill (head)->hh.tbl->hho)) : NULL); \ 742e25b118aSDominic Spill if (! (_hs_q) ) break; \ 743e25b118aSDominic Spill } \ 744e25b118aSDominic Spill _hs_qsize = _hs_insize; \ 745e25b118aSDominic Spill while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ 746e25b118aSDominic Spill if (_hs_psize == 0) { \ 747e25b118aSDominic Spill _hs_e = _hs_q; \ 748e25b118aSDominic Spill _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ 749e25b118aSDominic Spill ((void*)((char*)(_hs_q->next) + \ 750e25b118aSDominic Spill (head)->hh.tbl->hho)) : NULL); \ 751e25b118aSDominic Spill _hs_qsize--; \ 752e25b118aSDominic Spill } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ 753e25b118aSDominic Spill _hs_e = _hs_p; \ 754*935bdedbSDominic Spill if (_hs_p){ \ 755e25b118aSDominic Spill _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ 756e25b118aSDominic Spill ((void*)((char*)(_hs_p->next) + \ 757e25b118aSDominic Spill (head)->hh.tbl->hho)) : NULL); \ 758*935bdedbSDominic Spill } \ 759e25b118aSDominic Spill _hs_psize--; \ 760e25b118aSDominic Spill } else if (( \ 761e25b118aSDominic Spill cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ 762e25b118aSDominic Spill DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ 763e25b118aSDominic Spill ) <= 0) { \ 764e25b118aSDominic Spill _hs_e = _hs_p; \ 765*935bdedbSDominic Spill if (_hs_p){ \ 766e25b118aSDominic Spill _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ 767e25b118aSDominic Spill ((void*)((char*)(_hs_p->next) + \ 768e25b118aSDominic Spill (head)->hh.tbl->hho)) : NULL); \ 769*935bdedbSDominic Spill } \ 770e25b118aSDominic Spill _hs_psize--; \ 771e25b118aSDominic Spill } else { \ 772e25b118aSDominic Spill _hs_e = _hs_q; \ 773e25b118aSDominic Spill _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ 774e25b118aSDominic Spill ((void*)((char*)(_hs_q->next) + \ 775e25b118aSDominic Spill (head)->hh.tbl->hho)) : NULL); \ 776e25b118aSDominic Spill _hs_qsize--; \ 777e25b118aSDominic Spill } \ 778e25b118aSDominic Spill if ( _hs_tail ) { \ 779e25b118aSDominic Spill _hs_tail->next = ((_hs_e) ? \ 780e25b118aSDominic Spill ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ 781e25b118aSDominic Spill } else { \ 782e25b118aSDominic Spill _hs_list = _hs_e; \ 783e25b118aSDominic Spill } \ 784*935bdedbSDominic Spill if (_hs_e) { \ 785e25b118aSDominic Spill _hs_e->prev = ((_hs_tail) ? \ 786e25b118aSDominic Spill ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ 787*935bdedbSDominic Spill } \ 788e25b118aSDominic Spill _hs_tail = _hs_e; \ 789e25b118aSDominic Spill } \ 790e25b118aSDominic Spill _hs_p = _hs_q; \ 791e25b118aSDominic Spill } \ 792*935bdedbSDominic Spill if (_hs_tail){ \ 793e25b118aSDominic Spill _hs_tail->next = NULL; \ 794*935bdedbSDominic Spill } \ 795e25b118aSDominic Spill if ( _hs_nmerges <= 1 ) { \ 796e25b118aSDominic Spill _hs_looping=0; \ 797e25b118aSDominic Spill (head)->hh.tbl->tail = _hs_tail; \ 798e25b118aSDominic Spill DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ 799e25b118aSDominic Spill } \ 800e25b118aSDominic Spill _hs_insize *= 2; \ 801e25b118aSDominic Spill } \ 802e25b118aSDominic Spill HASH_FSCK(hh,head); \ 803e25b118aSDominic Spill } \ 804e25b118aSDominic Spill } while (0) 805e25b118aSDominic Spill 806e25b118aSDominic Spill /* This function selects items from one hash into another hash. 807e25b118aSDominic Spill * The end result is that the selected items have dual presence 808e25b118aSDominic Spill * in both hashes. There is no copy of the items made; rather 809e25b118aSDominic Spill * they are added into the new hash through a secondary hash 810e25b118aSDominic Spill * hash handle that must be present in the structure. */ 811e25b118aSDominic Spill #define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ 812e25b118aSDominic Spill do { \ 813e25b118aSDominic Spill unsigned _src_bkt, _dst_bkt; \ 814e25b118aSDominic Spill void *_last_elt=NULL, *_elt; \ 815e25b118aSDominic Spill UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ 816e25b118aSDominic Spill ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ 817e25b118aSDominic Spill if (src) { \ 818e25b118aSDominic Spill for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ 819e25b118aSDominic Spill for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ 820e25b118aSDominic Spill _src_hh; \ 821e25b118aSDominic Spill _src_hh = _src_hh->hh_next) { \ 822e25b118aSDominic Spill _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ 823e25b118aSDominic Spill if (cond(_elt)) { \ 824e25b118aSDominic Spill _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ 825e25b118aSDominic Spill _dst_hh->key = _src_hh->key; \ 826e25b118aSDominic Spill _dst_hh->keylen = _src_hh->keylen; \ 827e25b118aSDominic Spill _dst_hh->hashv = _src_hh->hashv; \ 828e25b118aSDominic Spill _dst_hh->prev = _last_elt; \ 829e25b118aSDominic Spill _dst_hh->next = NULL; \ 830e25b118aSDominic Spill if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ 831e25b118aSDominic Spill if (!dst) { \ 832e25b118aSDominic Spill DECLTYPE_ASSIGN(dst,_elt); \ 833e25b118aSDominic Spill HASH_MAKE_TABLE(hh_dst,dst); \ 834e25b118aSDominic Spill } else { \ 835e25b118aSDominic Spill _dst_hh->tbl = (dst)->hh_dst.tbl; \ 836e25b118aSDominic Spill } \ 837e25b118aSDominic Spill HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ 838e25b118aSDominic Spill HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ 839e25b118aSDominic Spill (dst)->hh_dst.tbl->num_items++; \ 840e25b118aSDominic Spill _last_elt = _elt; \ 841e25b118aSDominic Spill _last_elt_hh = _dst_hh; \ 842e25b118aSDominic Spill } \ 843e25b118aSDominic Spill } \ 844e25b118aSDominic Spill } \ 845e25b118aSDominic Spill } \ 846e25b118aSDominic Spill HASH_FSCK(hh_dst,dst); \ 847e25b118aSDominic Spill } while (0) 848e25b118aSDominic Spill 849e25b118aSDominic Spill #define HASH_CLEAR(hh,head) \ 850e25b118aSDominic Spill do { \ 851e25b118aSDominic Spill if (head) { \ 852e25b118aSDominic Spill uthash_free((head)->hh.tbl->buckets, \ 853e25b118aSDominic Spill (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ 854e25b118aSDominic Spill HASH_BLOOM_FREE((head)->hh.tbl); \ 855e25b118aSDominic Spill uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ 856e25b118aSDominic Spill (head)=NULL; \ 857e25b118aSDominic Spill } \ 858e25b118aSDominic Spill } while(0) 859e25b118aSDominic Spill 860*935bdedbSDominic Spill #define HASH_OVERHEAD(hh,head) \ 861*935bdedbSDominic Spill (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ 862*935bdedbSDominic Spill ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ 863*935bdedbSDominic Spill (sizeof(UT_hash_table)) + \ 864*935bdedbSDominic Spill (HASH_BLOOM_BYTELEN))) 865*935bdedbSDominic Spill 866e25b118aSDominic Spill #ifdef NO_DECLTYPE 867e25b118aSDominic Spill #define HASH_ITER(hh,head,el,tmp) \ 868e25b118aSDominic Spill for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ 869e25b118aSDominic Spill el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) 870e25b118aSDominic Spill #else 871e25b118aSDominic Spill #define HASH_ITER(hh,head,el,tmp) \ 872e25b118aSDominic Spill for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ 873e25b118aSDominic Spill el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) 874e25b118aSDominic Spill #endif 875e25b118aSDominic Spill 876e25b118aSDominic Spill /* obtain a count of items in the hash */ 877e25b118aSDominic Spill #define HASH_COUNT(head) HASH_CNT(hh,head) 878e25b118aSDominic Spill #define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) 879e25b118aSDominic Spill 880e25b118aSDominic Spill typedef struct UT_hash_bucket { 881e25b118aSDominic Spill struct UT_hash_handle *hh_head; 882e25b118aSDominic Spill unsigned count; 883e25b118aSDominic Spill 884e25b118aSDominic Spill /* expand_mult is normally set to 0. In this situation, the max chain length 885e25b118aSDominic Spill * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If 886e25b118aSDominic Spill * the bucket's chain exceeds this length, bucket expansion is triggered). 887e25b118aSDominic Spill * However, setting expand_mult to a non-zero value delays bucket expansion 888e25b118aSDominic Spill * (that would be triggered by additions to this particular bucket) 889e25b118aSDominic Spill * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. 890e25b118aSDominic Spill * (The multiplier is simply expand_mult+1). The whole idea of this 891e25b118aSDominic Spill * multiplier is to reduce bucket expansions, since they are expensive, in 892e25b118aSDominic Spill * situations where we know that a particular bucket tends to be overused. 893e25b118aSDominic Spill * It is better to let its chain length grow to a longer yet-still-bounded 894e25b118aSDominic Spill * value, than to do an O(n) bucket expansion too often. 895e25b118aSDominic Spill */ 896e25b118aSDominic Spill unsigned expand_mult; 897e25b118aSDominic Spill 898e25b118aSDominic Spill } UT_hash_bucket; 899e25b118aSDominic Spill 900e25b118aSDominic Spill /* random signature used only to find hash tables in external analysis */ 901e25b118aSDominic Spill #define HASH_SIGNATURE 0xa0111fe1 902e25b118aSDominic Spill #define HASH_BLOOM_SIGNATURE 0xb12220f2 903e25b118aSDominic Spill 904e25b118aSDominic Spill typedef struct UT_hash_table { 905e25b118aSDominic Spill UT_hash_bucket *buckets; 906e25b118aSDominic Spill unsigned num_buckets, log2_num_buckets; 907e25b118aSDominic Spill unsigned num_items; 908e25b118aSDominic Spill struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ 909e25b118aSDominic Spill ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ 910e25b118aSDominic Spill 911e25b118aSDominic Spill /* in an ideal situation (all buckets used equally), no bucket would have 912e25b118aSDominic Spill * more than ceil(#items/#buckets) items. that's the ideal chain length. */ 913e25b118aSDominic Spill unsigned ideal_chain_maxlen; 914e25b118aSDominic Spill 915e25b118aSDominic Spill /* nonideal_items is the number of items in the hash whose chain position 916e25b118aSDominic Spill * exceeds the ideal chain maxlen. these items pay the penalty for an uneven 917e25b118aSDominic Spill * hash distribution; reaching them in a chain traversal takes >ideal steps */ 918e25b118aSDominic Spill unsigned nonideal_items; 919e25b118aSDominic Spill 920e25b118aSDominic Spill /* ineffective expands occur when a bucket doubling was performed, but 921e25b118aSDominic Spill * afterward, more than half the items in the hash had nonideal chain 922e25b118aSDominic Spill * positions. If this happens on two consecutive expansions we inhibit any 923e25b118aSDominic Spill * further expansion, as it's not helping; this happens when the hash 924e25b118aSDominic Spill * function isn't a good fit for the key domain. When expansion is inhibited 925e25b118aSDominic Spill * the hash will still work, albeit no longer in constant time. */ 926e25b118aSDominic Spill unsigned ineff_expands, noexpand; 927e25b118aSDominic Spill 928e25b118aSDominic Spill uint32_t signature; /* used only to find hash tables in external analysis */ 929e25b118aSDominic Spill #ifdef HASH_BLOOM 930e25b118aSDominic Spill uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ 931e25b118aSDominic Spill uint8_t *bloom_bv; 932e25b118aSDominic Spill char bloom_nbits; 933e25b118aSDominic Spill #endif 934e25b118aSDominic Spill 935e25b118aSDominic Spill } UT_hash_table; 936e25b118aSDominic Spill 937e25b118aSDominic Spill typedef struct UT_hash_handle { 938e25b118aSDominic Spill struct UT_hash_table *tbl; 939e25b118aSDominic Spill void *prev; /* prev element in app order */ 940e25b118aSDominic Spill void *next; /* next element in app order */ 941e25b118aSDominic Spill struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ 942e25b118aSDominic Spill struct UT_hash_handle *hh_next; /* next hh in bucket order */ 943e25b118aSDominic Spill void *key; /* ptr to enclosing struct's key */ 944e25b118aSDominic Spill unsigned keylen; /* enclosing struct's key len */ 945e25b118aSDominic Spill unsigned hashv; /* result of hash-fcn(key) */ 946e25b118aSDominic Spill } UT_hash_handle; 947e25b118aSDominic Spill 948e25b118aSDominic Spill #endif /* UTHASH_H */ 949