Skip to content

Commit 03dba73

Browse files
committed
include/uthash.h: update
1 parent 437dc11 commit 03dba73

File tree

1 file changed

+41
-131
lines changed

1 file changed

+41
-131
lines changed

include/uthash.h

Lines changed: 41 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
2+
Copyright (c) 2003-2025, Troy D. Hanson https://troydhanson.github.io/uthash/
33
All rights reserved.
44
55
Redistribution and use in source and binary forms, with or without
@@ -24,12 +24,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424
#ifndef UTHASH_H
2525
#define UTHASH_H
2626

27-
#define UTHASH_VERSION 2.1.0
27+
#define UTHASH_VERSION 2.3.0
2828

2929
#include <string.h> /* memcmp, memset, strlen */
3030
#include <stddef.h> /* ptrdiff_t */
3131
#include <stdlib.h> /* exit */
3232

33+
#if defined(HASH_NO_STDINT) && HASH_NO_STDINT
34+
/* The user doesn't have <stdint.h>, and must figure out their own way
35+
to provide definitions for uint8_t and uint32_t. */
36+
#else
37+
#include <stdint.h> /* uint8_t, uint32_t */
38+
#endif
39+
3340
/* These macros use decltype or the earlier __typeof GNU extension.
3441
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
3542
when compiling c++ source) this code uses whatever method is needed
@@ -41,6 +48,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4148
#else /* VS2008 or older (or VS2010 in C mode) */
4249
#define NO_DECLTYPE
4350
#endif
51+
#elif defined(__MCST__) /* Elbrus C Compiler */
52+
#define DECLTYPE(x) (__typeof(x))
4453
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
4554
#define NO_DECLTYPE
4655
#else /* GNU, Sun and other compilers */
@@ -62,23 +71,6 @@ do {
6271
} while (0)
6372
#endif
6473

65-
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
66-
#if defined(_WIN32)
67-
#if defined(_MSC_VER) && _MSC_VER >= 1600
68-
#include <stdint.h>
69-
#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
70-
#include <stdint.h>
71-
#else
72-
typedef unsigned int uint32_t;
73-
typedef unsigned char uint8_t;
74-
#endif
75-
#elif defined(__GNUC__) && !defined(__VXWORKS__)
76-
#include <stdint.h>
77-
#else
78-
typedef unsigned int uint32_t;
79-
typedef unsigned char uint8_t;
80-
#endif
81-
8274
#ifndef uthash_malloc
8375
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
8476
#endif
@@ -92,15 +84,12 @@ typedef unsigned char uint8_t;
9284
#define uthash_strlen(s) strlen(s)
9385
#endif
9486

95-
#ifdef uthash_memcmp
96-
/* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */
97-
#warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead"
98-
#else
99-
#define uthash_memcmp(a,b,n) memcmp(a,b,n)
87+
#ifndef HASH_FUNCTION
88+
#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv)
10089
#endif
10190

10291
#ifndef HASH_KEYCMP
103-
#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n)
92+
#define HASH_KEYCMP(a,b,n) memcmp(a,b,n)
10493
#endif
10594

10695
#ifndef uthash_noexpand_fyi
@@ -144,7 +133,7 @@ typedef unsigned char uint8_t;
144133
/* calculate the element whose hash handle address is hhp */
145134
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
146135
/* calculate the hash handle from element address elp */
147-
#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(void *)(((char*)(elp)) + ((tbl)->hho)))
136+
#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho)))
148137

149138
#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \
150139
do { \
@@ -158,7 +147,7 @@ do {
158147

159148
#define HASH_VALUE(keyptr,keylen,hashv) \
160149
do { \
161-
HASH_FCN(keyptr, keylen, hashv); \
150+
HASH_FUNCTION(keyptr, keylen, hashv); \
162151
} while (0)
163152

164153
#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
@@ -167,17 +156,20 @@ do {
167156
if (head) { \
168157
unsigned _hf_bkt; \
169158
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \
170-
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \
159+
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \
171160
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \
172161
} \
173162
} \
174163
} while (0)
175164

176165
#define HASH_FIND(hh,head,keyptr,keylen,out) \
177166
do { \
178-
unsigned _hf_hashv; \
179-
HASH_VALUE(keyptr, keylen, _hf_hashv); \
180-
HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \
167+
(out) = NULL; \
168+
if (head) { \
169+
unsigned _hf_hashv; \
170+
HASH_VALUE(keyptr, keylen, _hf_hashv); \
171+
HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \
172+
} \
181173
} while (0)
182174

183175
#ifdef HASH_BLOOM
@@ -201,7 +193,7 @@ do {
201193
} while (0)
202194

203195
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
204-
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
196+
#define HASH_BLOOM_BITTEST(bv,idx) ((bv[(idx)/8U] & (1U << ((idx)%8U))) != 0)
205197

206198
#define HASH_BLOOM_ADD(tbl,hashv) \
207199
HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
@@ -213,7 +205,7 @@ do {
213205
#define HASH_BLOOM_MAKE(tbl,oomed)
214206
#define HASH_BLOOM_FREE(tbl)
215207
#define HASH_BLOOM_ADD(tbl,hashv)
216-
#define HASH_BLOOM_TEST(tbl,hashv) (1)
208+
#define HASH_BLOOM_TEST(tbl,hashv) 1
217209
#define HASH_BLOOM_BYTELEN 0U
218210
#endif
219211

@@ -405,7 +397,7 @@ do {
405397
do { \
406398
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
407399
(add)->hh.hashv = (hashval); \
408-
(add)->hh.key = (char*) (keyptr); \
400+
(add)->hh.key = (const void*) (keyptr); \
409401
(add)->hh.keylen = (unsigned) (keylen_in); \
410402
if (!(head)) { \
411403
(add)->hh.next = NULL; \
@@ -457,7 +449,7 @@ do {
457449

458450
#define HASH_DELETE_HH(hh,head,delptrhh) \
459451
do { \
460-
struct UT_hash_handle *_hd_hh_del = (delptrhh); \
452+
const struct UT_hash_handle *_hd_hh_del = (delptrhh); \
461453
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
462454
HASH_BLOOM_FREE((head)->hh.tbl); \
463455
uthash_free((head)->hh.tbl->buckets, \
@@ -519,7 +511,8 @@ do {
519511
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
520512
*/
521513
#ifdef HASH_DEBUG
522-
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
514+
#include <stdio.h> /* fprintf, stderr */
515+
#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0)
523516
#define HASH_FSCK(hh,head,where) \
524517
do { \
525518
struct UT_hash_handle *_thh; \
@@ -586,13 +579,6 @@ do {
586579
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
587580
#endif
588581

589-
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
590-
#ifdef HASH_FUNCTION
591-
#define HASH_FCN HASH_FUNCTION
592-
#else
593-
#define HASH_FCN HASH_JEN
594-
#endif
595-
596582
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
597583
#define HASH_BER(key,keylen,hashv) \
598584
do { \
@@ -606,7 +592,9 @@ do {
606592

607593

608594
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
609-
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
595+
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
596+
* (archive link: https://archive.is/Ivcan )
597+
*/
610598
#define HASH_SAX(key,keylen,hashv) \
611599
do { \
612600
unsigned _sx_i; \
@@ -691,7 +679,8 @@ do {
691679
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
692680
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
693681
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
694-
case 1: _hj_i += _hj_key[0]; \
682+
case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \
683+
default: ; \
695684
} \
696685
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
697686
} while (0)
@@ -739,6 +728,8 @@ do {
739728
case 1: hashv += *_sfh_key; \
740729
hashv ^= hashv << 10; \
741730
hashv += hashv >> 1; \
731+
break; \
732+
default: ; \
742733
} \
743734
\
744735
/* Force "avalanching" of final 127 bits */ \
@@ -750,87 +741,6 @@ do {
750741
hashv += hashv >> 6; \
751742
} while (0)
752743

753-
#ifdef HASH_USING_NO_STRICT_ALIASING
754-
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
755-
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
756-
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
757-
*
758-
* Note the preprocessor built-in defines can be emitted using:
759-
*
760-
* gcc -m64 -dM -E - < /dev/null (on gcc)
761-
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
762-
*/
763-
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
764-
#define MUR_GETBLOCK(p,i) p[i]
765-
#else /* non intel */
766-
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)
767-
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)
768-
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
769-
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
770-
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
771-
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
772-
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
773-
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
774-
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
775-
#else /* assume little endian non-intel */
776-
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
777-
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
778-
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
779-
#endif
780-
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
781-
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
782-
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
783-
MUR_ONE_THREE(p))))
784-
#endif
785-
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
786-
#define MUR_FMIX(_h) \
787-
do { \
788-
_h ^= _h >> 16; \
789-
_h *= 0x85ebca6bu; \
790-
_h ^= _h >> 13; \
791-
_h *= 0xc2b2ae35u; \
792-
_h ^= _h >> 16; \
793-
} while (0)
794-
795-
#define HASH_MUR(key,keylen,hashv) \
796-
do { \
797-
const uint8_t *_mur_data = (const uint8_t*)(key); \
798-
const int _mur_nblocks = (int)(keylen) / 4; \
799-
uint32_t _mur_h1 = 0xf88D5353u; \
800-
uint32_t _mur_c1 = 0xcc9e2d51u; \
801-
uint32_t _mur_c2 = 0x1b873593u; \
802-
uint32_t _mur_k1 = 0; \
803-
const uint8_t *_mur_tail; \
804-
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \
805-
int _mur_i; \
806-
for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \
807-
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
808-
_mur_k1 *= _mur_c1; \
809-
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
810-
_mur_k1 *= _mur_c2; \
811-
\
812-
_mur_h1 ^= _mur_k1; \
813-
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
814-
_mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \
815-
} \
816-
_mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \
817-
_mur_k1=0; \
818-
switch ((keylen) & 3U) { \
819-
case 0: break; \
820-
case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \
821-
case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \
822-
case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \
823-
_mur_k1 *= _mur_c1; \
824-
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
825-
_mur_k1 *= _mur_c2; \
826-
_mur_h1 ^= _mur_k1; \
827-
} \
828-
_mur_h1 ^= (uint32_t)(keylen); \
829-
MUR_FMIX(_mur_h1); \
830-
hashv = _mur_h1; \
831-
} while (0)
832-
#endif /* HASH_USING_NO_STRICT_ALIASING */
833-
834744
/* iterate over items in a known bucket to find desired item */
835745
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \
836746
do { \
@@ -841,7 +751,7 @@ do {
841751
} \
842752
while ((out) != NULL) { \
843753
if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
844-
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
754+
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
845755
break; \
846756
} \
847757
} \
@@ -927,12 +837,12 @@ do {
927837
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
928838
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
929839
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
930-
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
840+
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
931841
if (!_he_new_buckets) { \
932842
HASH_RECORD_OOM(oomed); \
933843
} else { \
934844
uthash_bzero(_he_new_buckets, \
935-
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
845+
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
936846
(tbl)->ideal_chain_maxlen = \
937847
((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
938848
((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
@@ -1080,7 +990,7 @@ do {
1080990
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
1081991
if (cond(_elt)) { \
1082992
IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \
1083-
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
993+
_dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \
1084994
_dst_hh->key = _src_hh->key; \
1085995
_dst_hh->keylen = _src_hh->keylen; \
1086996
_dst_hh->hashv = _src_hh->hashv; \
@@ -1219,7 +1129,7 @@ typedef struct UT_hash_handle {
12191129
void *next; /* next element in app order */
12201130
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
12211131
struct UT_hash_handle *hh_next; /* next hh in bucket order */
1222-
void *key; /* ptr to enclosing struct's key */
1132+
const void *key; /* ptr to enclosing struct's key */
12231133
unsigned keylen; /* enclosing struct's key len */
12241134
unsigned hashv; /* result of hash-fcn(key) */
12251135
} UT_hash_handle;

0 commit comments

Comments
 (0)