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