C开源hash项目uthash

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C开源hash项目uthash相关的知识,希望对你有一定的参考价值。

  uthash 是C的比较优秀的开源代码,它实现了常见的hash操作函数,例如查找、插入、删除等。该套开源代码采用宏的方式实现hash函数的相关功能,支持C语言的任意数据结构最为key值,甚至可以采用多个值作为key,无论是自定义的struct还是基本数据类型,需要注意的是不同类型的key其操作接口方式略有不通。

      使用uthash代码时只需要包含头文件"uthash.h"即可。由于该代码采用宏的方式实现,所有的实现代码都在uthash.h文件中,因此只需要在自己的代码中包含该头文件即可。

源代码地址:

https://github.com/troydhanson/uthash

 源码如下:

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

 

节点的结构体(自定义的结构体必须包含)

 1 typedef struct UT_hash_handle {
 2    struct UT_hash_table *tbl;
 3    void *prev;                       /* prev element in app order      */
 4    void *next;                       /* next element in app order      */
 5    struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
 6    struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
 7    void *key;                        /* ptr to enclosing struct‘s key  */
 8    unsigned keylen;                  /* enclosing struct‘s key len     */
 9    unsigned hashv;                   /* result of hash-fcn(key)        */
10 } UT_hash_handle;

 

DEMO

 1 #include <stdio.h>
 2 #include "uthash.h"
 3 
 4 typedef struct HASH_DEMO_ST
 5 {
 6     int key;
 7     int value;
 8     UT_hash_handle hh; // 必须包含
 9 }HASH_DEMO_ST;
10 
11 int main()
12 {
13     HASH_DEMO_ST *hashHead = NULL; // hash表头,必须初始化NULL
14     HASH_DEMO_ST *out = NULL; 
15     HASH_DEMO_ST *tmp = NULL;
16     HASH_DEMO_ST *current = NULL;
17 
18     // 添加节点
19     int i = 0;
20     for (i = 0; i < 10; i++)
21     {
22         HASH_DEMO_ST *new = (HASH_DEMO_ST *)malloc(sizeof(HASH_DEMO_ST)); 
23         new->key = i;
24         new->value = i;
25 
26         // 先判断有没有这个key,然后添加到hash表,保证唯一性
27         HASH_FIND_INT(hashHead, &(new->key), out);
28         if (out != NULL)
29         {
30             printf("the key(%d) is exist in hash\\n", new->key); 
31             free(new);
32             new = NULL;
33             continue;
34         }
35 
36         HASH_ADD_INT(hashHead, key, new);
37     }
38 
39     // 打印节点个数
40     printf("hash count=%d\\n", HASH_COUNT(hashHead));
41 
42     // 通过key查找节点
43     for (i = 0; i < 11; i++)
44     {
45         HASH_FIND_INT(hashHead, &i, out); 
46         if (out == NULL)
47         {
48             printf("the key(%d) is not exist in hash\\n", i); 
49             continue;
50         }
51         else
52         {
53             printf("find key:%d, value:%d\\n", out->key, out->value);
54         }
55     }
56 
57     // 不安全遍历,不能在中间删除节点
58     for(current = hashHead; current != NULL; current = (HASH_DEMO_ST *)(current->hh.next))
59     {
60         printf("[unsafe traversal]key:%d, value:%d\\n", current->key, current->value); 
61 
62         //HASH_DEL(hashHead, current);
63         //free(current);
64         //current = NULL;
65     }
66 
67     // 安全遍历,可以在中间删除节点
68     HASH_ITER(hh, hashHead, current, tmp)
69     {
70         printf("[safe traversal]key:%d, value:%d\\n", current->key, current->value); 
71 
72         HASH_DEL(hashHead, current);
73         free(current);
74         current = NULL;
75     }
76 
77     // 打印节点个数
78     printf("hash count=%d\\n", HASH_COUNT(hashHead));
79 
80     return 0;
81 }

 

以上是关于C开源hash项目uthash的主要内容,如果未能解决你的问题,请参考以下文章

C函数学习:uthash哈希表

C函数学习:uthash哈希表

C函数学习:uthash哈希表

C函数学习:uthash哈希表

如何从URL获取片段标识符(hash#之后的值)?

leetcodeuthash专题