PageRenderTime 93ms CodeModel.GetById 75ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 1ms

/src/rt/uthash/uthash.h

http://github.com/jruderman/rust
C Header | 766 lines | 599 code | 52 blank | 115 comment | 99 complexity | f2b3e43b1c3a339950b5b2f7dab0ef35 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file