mathematical 1.6.20 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +26 -16
- data/Rakefile +80 -17
- data/ext/mathematical/CMakeLists.txt +23 -43
- data/ext/mathematical/extconf.rb +70 -24
- data/ext/mathematical/mtex2MML/CMakeLists.txt +5 -5
- data/ext/mathematical/mtex2MML/README.md +19 -19
- data/ext/mathematical/mtex2MML/deps/uthash/package.json +2 -1
- data/ext/mathematical/mtex2MML/deps/uthash/utarray.h +35 -22
- data/ext/mathematical/mtex2MML/deps/uthash/uthash.h +524 -458
- data/ext/mathematical/mtex2MML/deps/uthash/utlist.h +255 -74
- data/ext/mathematical/mtex2MML/deps/uthash/utringbuffer.h +14 -14
- data/ext/mathematical/mtex2MML/deps/uthash/utstack.h +88 -0
- data/ext/mathematical/mtex2MML/deps/uthash/utstring.h +34 -25
- data/ext/mathematical/mtex2MML/script/cibuild +5 -48
- data/ext/mathematical/mtex2MML/script/test-quick +48 -0
- data/ext/mathematical/mtex2MML/src/environment.c +5 -1
- data/ext/mathematical/mtex2MML/tests/mathjax.c +591 -591
- data/ext/pulldown-latex/Cargo.lock +1833 -0
- data/fonts/cmex10.ttf +0 -0
- data/fonts/cmmi10.ttf +0 -0
- data/fonts/cmr10.ttf +0 -0
- data/fonts/cmsy10.ttf +0 -0
- data/fonts/eufm10.ttf +0 -0
- data/fonts/fonts.conf +11 -0
- data/fonts/msam10.ttf +0 -0
- data/fonts/msbm10.ttf +0 -0
- data/lib/mathematical/version.rb +1 -1
- data/lib/mathematical.rb +16 -1
- data/mathematical.gemspec +6 -2
- metadata +34 -11
- data/ext/mathematical/mtex2MML/appveyor.yml +0 -35
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright (c) 2003-
|
|
2
|
+
Copyright (c) 2003-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
|
3
3
|
All rights reserved.
|
|
4
4
|
|
|
5
5
|
Redistribution and use in source and binary forms, with or without
|
|
@@ -24,31 +24,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
24
24
|
#ifndef UTHASH_H
|
|
25
25
|
#define UTHASH_H
|
|
26
26
|
|
|
27
|
-
#define UTHASH_VERSION 2.0
|
|
27
|
+
#define UTHASH_VERSION 2.3.0
|
|
28
28
|
|
|
29
|
-
#include <string.h> /* memcmp,strlen */
|
|
29
|
+
#include <string.h> /* memcmp, memset, strlen */
|
|
30
30
|
#include <stddef.h> /* ptrdiff_t */
|
|
31
|
-
#include <stdlib.h> /* exit
|
|
31
|
+
#include <stdlib.h> /* exit */
|
|
32
|
+
|
|
33
|
+
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
|
|
34
|
+
/* This codepath is provided for backward compatibility, but I plan to remove it. */
|
|
35
|
+
#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead"
|
|
36
|
+
typedef unsigned int uint32_t;
|
|
37
|
+
typedef unsigned char uint8_t;
|
|
38
|
+
#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
|
39
|
+
#else
|
|
40
|
+
#include <stdint.h> /* uint8_t, uint32_t */
|
|
41
|
+
#endif
|
|
32
42
|
|
|
33
43
|
/* These macros use decltype or the earlier __typeof GNU extension.
|
|
34
44
|
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
|
35
45
|
when compiling c++ source) this code uses whatever method is needed
|
|
36
46
|
or, for VS2008 where neither is available, uses casting workarounds. */
|
|
47
|
+
#if !defined(DECLTYPE) && !defined(NO_DECLTYPE)
|
|
37
48
|
#if defined(_MSC_VER) /* MS compiler */
|
|
38
49
|
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
|
39
50
|
#define DECLTYPE(x) (decltype(x))
|
|
40
51
|
#else /* VS2008 or older (or VS2010 in C mode) */
|
|
41
52
|
#define NO_DECLTYPE
|
|
42
|
-
#define DECLTYPE(x)
|
|
43
53
|
#endif
|
|
44
|
-
#elif defined(
|
|
54
|
+
#elif defined(__MCST__) /* Elbrus C Compiler */
|
|
55
|
+
#define DECLTYPE(x) (__typeof(x))
|
|
56
|
+
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
|
45
57
|
#define NO_DECLTYPE
|
|
46
|
-
#define DECLTYPE(x)
|
|
47
58
|
#else /* GNU, Sun and other compilers */
|
|
48
59
|
#define DECLTYPE(x) (__typeof(x))
|
|
49
60
|
#endif
|
|
61
|
+
#endif
|
|
50
62
|
|
|
51
63
|
#ifdef NO_DECLTYPE
|
|
64
|
+
#define DECLTYPE(x)
|
|
52
65
|
#define DECLTYPE_ASSIGN(dst,src) \
|
|
53
66
|
do { \
|
|
54
67
|
char **_da_dst = (char**)(&(dst)); \
|
|
@@ -61,37 +74,25 @@ do {
|
|
|
61
74
|
} while (0)
|
|
62
75
|
#endif
|
|
63
76
|
|
|
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
77
|
#ifndef uthash_malloc
|
|
85
78
|
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
|
86
79
|
#endif
|
|
87
80
|
#ifndef uthash_free
|
|
88
81
|
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
|
|
89
82
|
#endif
|
|
83
|
+
#ifndef uthash_bzero
|
|
84
|
+
#define uthash_bzero(a,n) memset(a,'\0',n)
|
|
85
|
+
#endif
|
|
90
86
|
#ifndef uthash_strlen
|
|
91
87
|
#define uthash_strlen(s) strlen(s)
|
|
92
88
|
#endif
|
|
93
|
-
|
|
94
|
-
#
|
|
89
|
+
|
|
90
|
+
#ifndef HASH_FUNCTION
|
|
91
|
+
#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv)
|
|
92
|
+
#endif
|
|
93
|
+
|
|
94
|
+
#ifndef HASH_KEYCMP
|
|
95
|
+
#define HASH_KEYCMP(a,b,n) memcmp(a,b,n)
|
|
95
96
|
#endif
|
|
96
97
|
|
|
97
98
|
#ifndef uthash_noexpand_fyi
|
|
@@ -101,6 +102,32 @@ typedef unsigned char uint8_t;
|
|
|
101
102
|
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
|
|
102
103
|
#endif
|
|
103
104
|
|
|
105
|
+
#ifndef HASH_NONFATAL_OOM
|
|
106
|
+
#define HASH_NONFATAL_OOM 0
|
|
107
|
+
#endif
|
|
108
|
+
|
|
109
|
+
#if HASH_NONFATAL_OOM
|
|
110
|
+
/* malloc failures can be recovered from */
|
|
111
|
+
|
|
112
|
+
#ifndef uthash_nonfatal_oom
|
|
113
|
+
#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */
|
|
114
|
+
#endif
|
|
115
|
+
|
|
116
|
+
#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0)
|
|
117
|
+
#define IF_HASH_NONFATAL_OOM(x) x
|
|
118
|
+
|
|
119
|
+
#else
|
|
120
|
+
/* malloc failures result in lost memory, hash tables are unusable */
|
|
121
|
+
|
|
122
|
+
#ifndef uthash_fatal
|
|
123
|
+
#define uthash_fatal(msg) exit(-1) /* fatal OOM error */
|
|
124
|
+
#endif
|
|
125
|
+
|
|
126
|
+
#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory")
|
|
127
|
+
#define IF_HASH_NONFATAL_OOM(x)
|
|
128
|
+
|
|
129
|
+
#endif
|
|
130
|
+
|
|
104
131
|
/* initial number of buckets */
|
|
105
132
|
#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */
|
|
106
133
|
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */
|
|
@@ -109,11 +136,21 @@ typedef unsigned char uint8_t;
|
|
|
109
136
|
/* calculate the element whose hash handle address is hhp */
|
|
110
137
|
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
|
111
138
|
/* calculate the hash handle from element address elp */
|
|
112
|
-
#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle
|
|
139
|
+
#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho)))
|
|
140
|
+
|
|
141
|
+
#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \
|
|
142
|
+
do { \
|
|
143
|
+
struct UT_hash_handle *_hd_hh_item = (itemptrhh); \
|
|
144
|
+
unsigned _hd_bkt; \
|
|
145
|
+
HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
|
146
|
+
(head)->hh.tbl->buckets[_hd_bkt].count++; \
|
|
147
|
+
_hd_hh_item->hh_next = NULL; \
|
|
148
|
+
_hd_hh_item->hh_prev = NULL; \
|
|
149
|
+
} while (0)
|
|
113
150
|
|
|
114
151
|
#define HASH_VALUE(keyptr,keylen,hashv) \
|
|
115
152
|
do { \
|
|
116
|
-
|
|
153
|
+
HASH_FUNCTION(keyptr, keylen, hashv); \
|
|
117
154
|
} while (0)
|
|
118
155
|
|
|
119
156
|
#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
|
|
@@ -130,21 +167,27 @@ do {
|
|
|
130
167
|
|
|
131
168
|
#define HASH_FIND(hh,head,keyptr,keylen,out) \
|
|
132
169
|
do { \
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
170
|
+
(out) = NULL; \
|
|
171
|
+
if (head) { \
|
|
172
|
+
unsigned _hf_hashv; \
|
|
173
|
+
HASH_VALUE(keyptr, keylen, _hf_hashv); \
|
|
174
|
+
HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \
|
|
175
|
+
} \
|
|
136
176
|
} while (0)
|
|
137
177
|
|
|
138
178
|
#ifdef HASH_BLOOM
|
|
139
179
|
#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)
|
|
140
180
|
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)
|
|
141
|
-
#define HASH_BLOOM_MAKE(tbl)
|
|
181
|
+
#define HASH_BLOOM_MAKE(tbl,oomed) \
|
|
142
182
|
do { \
|
|
143
183
|
(tbl)->bloom_nbits = HASH_BLOOM; \
|
|
144
184
|
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
|
|
145
|
-
if (!(
|
|
146
|
-
|
|
147
|
-
|
|
185
|
+
if (!(tbl)->bloom_bv) { \
|
|
186
|
+
HASH_RECORD_OOM(oomed); \
|
|
187
|
+
} else { \
|
|
188
|
+
uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
|
|
189
|
+
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
|
|
190
|
+
} \
|
|
148
191
|
} while (0)
|
|
149
192
|
|
|
150
193
|
#define HASH_BLOOM_FREE(tbl) \
|
|
@@ -156,36 +199,49 @@ do {
|
|
|
156
199
|
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
|
|
157
200
|
|
|
158
201
|
#define HASH_BLOOM_ADD(tbl,hashv) \
|
|
159
|
-
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((
|
|
202
|
+
HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
|
|
160
203
|
|
|
161
204
|
#define HASH_BLOOM_TEST(tbl,hashv) \
|
|
162
|
-
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((
|
|
205
|
+
HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
|
|
163
206
|
|
|
164
207
|
#else
|
|
165
|
-
#define HASH_BLOOM_MAKE(tbl)
|
|
208
|
+
#define HASH_BLOOM_MAKE(tbl,oomed)
|
|
166
209
|
#define HASH_BLOOM_FREE(tbl)
|
|
167
210
|
#define HASH_BLOOM_ADD(tbl,hashv)
|
|
168
211
|
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
|
169
212
|
#define HASH_BLOOM_BYTELEN 0U
|
|
170
213
|
#endif
|
|
171
214
|
|
|
172
|
-
#define HASH_MAKE_TABLE(hh,head)
|
|
215
|
+
#define HASH_MAKE_TABLE(hh,head,oomed) \
|
|
173
216
|
do { \
|
|
174
|
-
(head)->hh.tbl = (UT_hash_table*)uthash_malloc(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
217
|
+
(head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \
|
|
218
|
+
if (!(head)->hh.tbl) { \
|
|
219
|
+
HASH_RECORD_OOM(oomed); \
|
|
220
|
+
} else { \
|
|
221
|
+
uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \
|
|
222
|
+
(head)->hh.tbl->tail = &((head)->hh); \
|
|
223
|
+
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
|
|
224
|
+
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
|
|
225
|
+
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
|
|
226
|
+
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
|
|
227
|
+
HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \
|
|
228
|
+
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
|
229
|
+
if (!(head)->hh.tbl->buckets) { \
|
|
230
|
+
HASH_RECORD_OOM(oomed); \
|
|
231
|
+
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
|
232
|
+
} else { \
|
|
233
|
+
uthash_bzero((head)->hh.tbl->buckets, \
|
|
234
|
+
HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \
|
|
235
|
+
HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \
|
|
236
|
+
IF_HASH_NONFATAL_OOM( \
|
|
237
|
+
if (oomed) { \
|
|
238
|
+
uthash_free((head)->hh.tbl->buckets, \
|
|
239
|
+
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
|
240
|
+
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
|
241
|
+
} \
|
|
242
|
+
) \
|
|
243
|
+
} \
|
|
244
|
+
} \
|
|
189
245
|
} while (0)
|
|
190
246
|
|
|
191
247
|
#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \
|
|
@@ -193,7 +249,7 @@ do {
|
|
|
193
249
|
(replaced) = NULL; \
|
|
194
250
|
HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \
|
|
195
251
|
if (replaced) { \
|
|
196
|
-
|
|
252
|
+
HASH_DELETE(hh, head, replaced); \
|
|
197
253
|
} \
|
|
198
254
|
HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \
|
|
199
255
|
} while (0)
|
|
@@ -203,7 +259,7 @@ do {
|
|
|
203
259
|
(replaced) = NULL; \
|
|
204
260
|
HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \
|
|
205
261
|
if (replaced) { \
|
|
206
|
-
|
|
262
|
+
HASH_DELETE(hh, head, replaced); \
|
|
207
263
|
} \
|
|
208
264
|
HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \
|
|
209
265
|
} while (0)
|
|
@@ -230,42 +286,101 @@ do {
|
|
|
230
286
|
(head)->hh.tbl->tail = &((add)->hh); \
|
|
231
287
|
} while (0)
|
|
232
288
|
|
|
233
|
-
#define
|
|
289
|
+
#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \
|
|
290
|
+
do { \
|
|
291
|
+
do { \
|
|
292
|
+
if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \
|
|
293
|
+
break; \
|
|
294
|
+
} \
|
|
295
|
+
} while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \
|
|
296
|
+
} while (0)
|
|
297
|
+
|
|
298
|
+
#ifdef NO_DECLTYPE
|
|
299
|
+
#undef HASH_AKBI_INNER_LOOP
|
|
300
|
+
#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \
|
|
301
|
+
do { \
|
|
302
|
+
char *_hs_saved_head = (char*)(head); \
|
|
303
|
+
do { \
|
|
304
|
+
DECLTYPE_ASSIGN(head, _hs_iter); \
|
|
305
|
+
if (cmpfcn(head, add) > 0) { \
|
|
306
|
+
DECLTYPE_ASSIGN(head, _hs_saved_head); \
|
|
307
|
+
break; \
|
|
308
|
+
} \
|
|
309
|
+
DECLTYPE_ASSIGN(head, _hs_saved_head); \
|
|
310
|
+
} while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \
|
|
311
|
+
} while (0)
|
|
312
|
+
#endif
|
|
313
|
+
|
|
314
|
+
#if HASH_NONFATAL_OOM
|
|
315
|
+
|
|
316
|
+
#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \
|
|
317
|
+
do { \
|
|
318
|
+
if (!(oomed)) { \
|
|
319
|
+
unsigned _ha_bkt; \
|
|
320
|
+
(head)->hh.tbl->num_items++; \
|
|
321
|
+
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \
|
|
322
|
+
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \
|
|
323
|
+
if (oomed) { \
|
|
324
|
+
HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \
|
|
325
|
+
HASH_DELETE_HH(hh, head, &(add)->hh); \
|
|
326
|
+
(add)->hh.tbl = NULL; \
|
|
327
|
+
uthash_nonfatal_oom(add); \
|
|
328
|
+
} else { \
|
|
329
|
+
HASH_BLOOM_ADD((head)->hh.tbl, hashval); \
|
|
330
|
+
HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \
|
|
331
|
+
} \
|
|
332
|
+
} else { \
|
|
333
|
+
(add)->hh.tbl = NULL; \
|
|
334
|
+
uthash_nonfatal_oom(add); \
|
|
335
|
+
} \
|
|
336
|
+
} while (0)
|
|
337
|
+
|
|
338
|
+
#else
|
|
339
|
+
|
|
340
|
+
#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \
|
|
234
341
|
do { \
|
|
235
342
|
unsigned _ha_bkt; \
|
|
343
|
+
(head)->hh.tbl->num_items++; \
|
|
344
|
+
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \
|
|
345
|
+
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \
|
|
346
|
+
HASH_BLOOM_ADD((head)->hh.tbl, hashval); \
|
|
347
|
+
HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \
|
|
348
|
+
} while (0)
|
|
349
|
+
|
|
350
|
+
#endif
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \
|
|
354
|
+
do { \
|
|
355
|
+
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
|
|
236
356
|
(add)->hh.hashv = (hashval); \
|
|
237
357
|
(add)->hh.key = (char*) (keyptr); \
|
|
238
358
|
(add)->hh.keylen = (unsigned) (keylen_in); \
|
|
239
359
|
if (!(head)) { \
|
|
240
360
|
(add)->hh.next = NULL; \
|
|
241
361
|
(add)->hh.prev = NULL; \
|
|
242
|
-
(
|
|
243
|
-
|
|
362
|
+
HASH_MAKE_TABLE(hh, add, _ha_oomed); \
|
|
363
|
+
IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \
|
|
364
|
+
(head) = (add); \
|
|
365
|
+
IF_HASH_NONFATAL_OOM( } ) \
|
|
244
366
|
} else { \
|
|
245
|
-
|
|
367
|
+
void *_hs_iter = (head); \
|
|
246
368
|
(add)->hh.tbl = (head)->hh.tbl; \
|
|
247
|
-
|
|
248
|
-
if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \
|
|
249
|
-
break; \
|
|
250
|
-
} while ((_hs_iter = _hs_iter->next)); \
|
|
369
|
+
HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \
|
|
251
370
|
if (_hs_iter) { \
|
|
252
371
|
(add)->hh.next = _hs_iter; \
|
|
253
|
-
if (((add)->hh.prev = _hs_iter->prev)) {
|
|
254
|
-
HH_FROM_ELMT((head)->hh.tbl,
|
|
372
|
+
if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \
|
|
373
|
+
HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \
|
|
255
374
|
} else { \
|
|
256
375
|
(head) = (add); \
|
|
257
376
|
} \
|
|
258
|
-
_hs_iter->prev = (add);
|
|
377
|
+
HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \
|
|
259
378
|
} else { \
|
|
260
379
|
HASH_APPEND_LIST(hh, head, add); \
|
|
261
380
|
} \
|
|
262
381
|
} \
|
|
263
|
-
(head)
|
|
264
|
-
|
|
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); \
|
|
382
|
+
HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \
|
|
383
|
+
HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \
|
|
269
384
|
} while (0)
|
|
270
385
|
|
|
271
386
|
#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \
|
|
@@ -283,25 +398,23 @@ do {
|
|
|
283
398
|
|
|
284
399
|
#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \
|
|
285
400
|
do { \
|
|
286
|
-
|
|
401
|
+
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
|
|
287
402
|
(add)->hh.hashv = (hashval); \
|
|
288
|
-
(add)->hh.key = (
|
|
403
|
+
(add)->hh.key = (const void*) (keyptr); \
|
|
289
404
|
(add)->hh.keylen = (unsigned) (keylen_in); \
|
|
290
405
|
if (!(head)) { \
|
|
291
406
|
(add)->hh.next = NULL; \
|
|
292
407
|
(add)->hh.prev = NULL; \
|
|
293
|
-
(
|
|
294
|
-
|
|
408
|
+
HASH_MAKE_TABLE(hh, add, _ha_oomed); \
|
|
409
|
+
IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \
|
|
410
|
+
(head) = (add); \
|
|
411
|
+
IF_HASH_NONFATAL_OOM( } ) \
|
|
295
412
|
} else { \
|
|
296
413
|
(add)->hh.tbl = (head)->hh.tbl; \
|
|
297
414
|
HASH_APPEND_LIST(hh, head, add); \
|
|
298
415
|
} \
|
|
299
|
-
(head)
|
|
300
|
-
|
|
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); \
|
|
416
|
+
HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \
|
|
417
|
+
HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \
|
|
305
418
|
} while (0)
|
|
306
419
|
|
|
307
420
|
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
|
@@ -335,48 +448,53 @@ do {
|
|
|
335
448
|
* scratch pointer rather than through the repointed (users) symbol.
|
|
336
449
|
*/
|
|
337
450
|
#define HASH_DELETE(hh,head,delptr) \
|
|
451
|
+
HASH_DELETE_HH(hh, head, &(delptr)->hh)
|
|
452
|
+
|
|
453
|
+
#define HASH_DELETE_HH(hh,head,delptrhh) \
|
|
338
454
|
do { \
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
455
|
+
const struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
|
456
|
+
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
|
|
457
|
+
HASH_BLOOM_FREE((head)->hh.tbl); \
|
|
458
|
+
uthash_free((head)->hh.tbl->buckets, \
|
|
459
|
+
(head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
|
460
|
+
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
|
461
|
+
(head) = NULL; \
|
|
462
|
+
} else { \
|
|
463
|
+
unsigned _hd_bkt; \
|
|
464
|
+
if (_hd_hh_del == (head)->hh.tbl->tail) { \
|
|
465
|
+
(head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \
|
|
466
|
+
} \
|
|
467
|
+
if (_hd_hh_del->prev != NULL) { \
|
|
468
|
+
HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \
|
|
346
469
|
} else { \
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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--; \
|
|
470
|
+
DECLTYPE_ASSIGN(head, _hd_hh_del->next); \
|
|
471
|
+
} \
|
|
472
|
+
if (_hd_hh_del->next != NULL) { \
|
|
473
|
+
HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \
|
|
368
474
|
} \
|
|
369
|
-
|
|
475
|
+
HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
|
476
|
+
HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
|
|
477
|
+
(head)->hh.tbl->num_items--; \
|
|
478
|
+
} \
|
|
479
|
+
HASH_FSCK(hh, head, "HASH_DELETE_HH"); \
|
|
370
480
|
} while (0)
|
|
371
481
|
|
|
372
|
-
|
|
373
482
|
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
|
|
374
483
|
#define HASH_FIND_STR(head,findstr,out) \
|
|
375
|
-
|
|
484
|
+
do { \
|
|
485
|
+
unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \
|
|
486
|
+
HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \
|
|
487
|
+
} while (0)
|
|
376
488
|
#define HASH_ADD_STR(head,strfield,add) \
|
|
377
|
-
|
|
489
|
+
do { \
|
|
490
|
+
unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \
|
|
491
|
+
HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \
|
|
492
|
+
} while (0)
|
|
378
493
|
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
|
|
379
|
-
|
|
494
|
+
do { \
|
|
495
|
+
unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \
|
|
496
|
+
HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \
|
|
497
|
+
} while (0)
|
|
380
498
|
#define HASH_FIND_INT(head,findint,out) \
|
|
381
499
|
HASH_FIND(hh,head,findint,sizeof(int),out)
|
|
382
500
|
#define HASH_ADD_INT(head,intfield,add) \
|
|
@@ -396,60 +514,58 @@ do {
|
|
|
396
514
|
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
|
|
397
515
|
*/
|
|
398
516
|
#ifdef HASH_DEBUG
|
|
399
|
-
#
|
|
400
|
-
#define
|
|
517
|
+
#include <stdio.h> /* fprintf, stderr */
|
|
518
|
+
#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0)
|
|
519
|
+
#define HASH_FSCK(hh,head,where) \
|
|
401
520
|
do { \
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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 ); \
|
|
521
|
+
struct UT_hash_handle *_thh; \
|
|
522
|
+
if (head) { \
|
|
523
|
+
unsigned _bkt_i; \
|
|
524
|
+
unsigned _count = 0; \
|
|
525
|
+
char *_prev; \
|
|
526
|
+
for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \
|
|
527
|
+
unsigned _bkt_count = 0; \
|
|
528
|
+
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
|
|
529
|
+
_prev = NULL; \
|
|
530
|
+
while (_thh) { \
|
|
531
|
+
if (_prev != (char*)(_thh->hh_prev)) { \
|
|
532
|
+
HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \
|
|
533
|
+
(where), (void*)_thh->hh_prev, (void*)_prev); \
|
|
448
534
|
} \
|
|
535
|
+
_bkt_count++; \
|
|
536
|
+
_prev = (char*)(_thh); \
|
|
537
|
+
_thh = _thh->hh_next; \
|
|
538
|
+
} \
|
|
539
|
+
_count += _bkt_count; \
|
|
540
|
+
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
|
|
541
|
+
HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \
|
|
542
|
+
(where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
|
|
543
|
+
} \
|
|
449
544
|
} \
|
|
545
|
+
if (_count != (head)->hh.tbl->num_items) { \
|
|
546
|
+
HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \
|
|
547
|
+
(where), (head)->hh.tbl->num_items, _count); \
|
|
548
|
+
} \
|
|
549
|
+
_count = 0; \
|
|
550
|
+
_prev = NULL; \
|
|
551
|
+
_thh = &(head)->hh; \
|
|
552
|
+
while (_thh) { \
|
|
553
|
+
_count++; \
|
|
554
|
+
if (_prev != (char*)_thh->prev) { \
|
|
555
|
+
HASH_OOPS("%s: invalid prev %p, actual %p\n", \
|
|
556
|
+
(where), (void*)_thh->prev, (void*)_prev); \
|
|
557
|
+
} \
|
|
558
|
+
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
|
|
559
|
+
_thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \
|
|
560
|
+
} \
|
|
561
|
+
if (_count != (head)->hh.tbl->num_items) { \
|
|
562
|
+
HASH_OOPS("%s: invalid app item count %u, actual %u\n", \
|
|
563
|
+
(where), (head)->hh.tbl->num_items, _count); \
|
|
564
|
+
} \
|
|
565
|
+
} \
|
|
450
566
|
} while (0)
|
|
451
567
|
#else
|
|
452
|
-
#define HASH_FSCK(hh,head)
|
|
568
|
+
#define HASH_FSCK(hh,head,where)
|
|
453
569
|
#endif
|
|
454
570
|
|
|
455
571
|
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
|
|
@@ -458,53 +574,48 @@ do {
|
|
|
458
574
|
#ifdef HASH_EMIT_KEYS
|
|
459
575
|
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
|
|
460
576
|
do { \
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
577
|
+
unsigned _klen = fieldlen; \
|
|
578
|
+
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
|
|
579
|
+
write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \
|
|
464
580
|
} while (0)
|
|
465
581
|
#else
|
|
466
582
|
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
|
467
583
|
#endif
|
|
468
584
|
|
|
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
585
|
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
|
477
586
|
#define HASH_BER(key,keylen,hashv) \
|
|
478
587
|
do { \
|
|
479
|
-
unsigned _hb_keylen=(unsigned)keylen;
|
|
480
|
-
const unsigned char *_hb_key=(const unsigned char*)(key);
|
|
588
|
+
unsigned _hb_keylen = (unsigned)keylen; \
|
|
589
|
+
const unsigned char *_hb_key = (const unsigned char*)(key); \
|
|
481
590
|
(hashv) = 0; \
|
|
482
591
|
while (_hb_keylen-- != 0U) { \
|
|
483
|
-
|
|
592
|
+
(hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \
|
|
484
593
|
} \
|
|
485
594
|
} while (0)
|
|
486
595
|
|
|
487
596
|
|
|
488
597
|
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
|
489
|
-
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
|
598
|
+
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
|
599
|
+
* (archive link: https://archive.is/Ivcan )
|
|
600
|
+
*/
|
|
490
601
|
#define HASH_SAX(key,keylen,hashv) \
|
|
491
602
|
do { \
|
|
492
603
|
unsigned _sx_i; \
|
|
493
|
-
const unsigned char *_hs_key=(const unsigned char*)(key);
|
|
604
|
+
const unsigned char *_hs_key = (const unsigned char*)(key); \
|
|
494
605
|
hashv = 0; \
|
|
495
|
-
for(_sx_i=0; _sx_i < keylen; _sx_i++) {
|
|
496
|
-
|
|
606
|
+
for (_sx_i=0; _sx_i < keylen; _sx_i++) { \
|
|
607
|
+
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
|
|
497
608
|
} \
|
|
498
609
|
} while (0)
|
|
499
610
|
/* FNV-1a variation */
|
|
500
611
|
#define HASH_FNV(key,keylen,hashv) \
|
|
501
612
|
do { \
|
|
502
613
|
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
|
-
|
|
507
|
-
|
|
614
|
+
const unsigned char *_hf_key = (const unsigned char*)(key); \
|
|
615
|
+
(hashv) = 2166136261U; \
|
|
616
|
+
for (_fn_i=0; _fn_i < keylen; _fn_i++) { \
|
|
617
|
+
hashv = hashv ^ _hf_key[_fn_i]; \
|
|
618
|
+
hashv = hashv * 16777619U; \
|
|
508
619
|
} \
|
|
509
620
|
} while (0)
|
|
510
621
|
|
|
@@ -561,17 +672,18 @@ do {
|
|
|
561
672
|
} \
|
|
562
673
|
hashv += (unsigned)(keylen); \
|
|
563
674
|
switch ( _hj_k ) { \
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
675
|
+
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \
|
|
676
|
+
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \
|
|
677
|
+
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \
|
|
678
|
+
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \
|
|
679
|
+
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \
|
|
680
|
+
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \
|
|
681
|
+
case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \
|
|
682
|
+
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
|
|
683
|
+
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
|
|
684
|
+
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
|
|
685
|
+
case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \
|
|
686
|
+
default: ; \
|
|
575
687
|
} \
|
|
576
688
|
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
|
577
689
|
} while (0)
|
|
@@ -619,97 +731,19 @@ do {
|
|
|
619
731
|
case 1: hashv += *_sfh_key; \
|
|
620
732
|
hashv ^= hashv << 10; \
|
|
621
733
|
hashv += hashv >> 1; \
|
|
734
|
+
break; \
|
|
735
|
+
default: ; \
|
|
622
736
|
} \
|
|
623
737
|
\
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
738
|
+
/* Force "avalanching" of final 127 bits */ \
|
|
739
|
+
hashv ^= hashv << 3; \
|
|
740
|
+
hashv += hashv >> 5; \
|
|
741
|
+
hashv ^= hashv << 4; \
|
|
742
|
+
hashv += hashv >> 17; \
|
|
743
|
+
hashv ^= hashv << 25; \
|
|
744
|
+
hashv += hashv >> 6; \
|
|
631
745
|
} while (0)
|
|
632
746
|
|
|
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
747
|
/* iterate over items in a known bucket to find desired item */
|
|
714
748
|
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \
|
|
715
749
|
do { \
|
|
@@ -720,7 +754,7 @@ do {
|
|
|
720
754
|
} \
|
|
721
755
|
while ((out) != NULL) { \
|
|
722
756
|
if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
|
|
723
|
-
if (
|
|
757
|
+
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
|
724
758
|
break; \
|
|
725
759
|
} \
|
|
726
760
|
} \
|
|
@@ -733,31 +767,42 @@ do {
|
|
|
733
767
|
} while (0)
|
|
734
768
|
|
|
735
769
|
/* add an item to a bucket */
|
|
736
|
-
#define HASH_ADD_TO_BKT(head,addhh)
|
|
770
|
+
#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \
|
|
737
771
|
do { \
|
|
738
|
-
head
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
772
|
+
UT_hash_bucket *_ha_head = &(head); \
|
|
773
|
+
_ha_head->count++; \
|
|
774
|
+
(addhh)->hh_next = _ha_head->hh_head; \
|
|
775
|
+
(addhh)->hh_prev = NULL; \
|
|
776
|
+
if (_ha_head->hh_head != NULL) { \
|
|
777
|
+
_ha_head->hh_head->hh_prev = (addhh); \
|
|
778
|
+
} \
|
|
779
|
+
_ha_head->hh_head = (addhh); \
|
|
780
|
+
if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \
|
|
781
|
+
&& !(addhh)->tbl->noexpand) { \
|
|
782
|
+
HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \
|
|
783
|
+
IF_HASH_NONFATAL_OOM( \
|
|
784
|
+
if (oomed) { \
|
|
785
|
+
HASH_DEL_IN_BKT(head,addhh); \
|
|
786
|
+
} \
|
|
787
|
+
) \
|
|
788
|
+
} \
|
|
747
789
|
} while (0)
|
|
748
790
|
|
|
749
791
|
/* remove an item from a given bucket */
|
|
750
|
-
#define HASH_DEL_IN_BKT(
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
792
|
+
#define HASH_DEL_IN_BKT(head,delhh) \
|
|
793
|
+
do { \
|
|
794
|
+
UT_hash_bucket *_hd_head = &(head); \
|
|
795
|
+
_hd_head->count--; \
|
|
796
|
+
if (_hd_head->hh_head == (delhh)) { \
|
|
797
|
+
_hd_head->hh_head = (delhh)->hh_next; \
|
|
798
|
+
} \
|
|
799
|
+
if ((delhh)->hh_prev) { \
|
|
800
|
+
(delhh)->hh_prev->hh_next = (delhh)->hh_next; \
|
|
801
|
+
} \
|
|
802
|
+
if ((delhh)->hh_next) { \
|
|
803
|
+
(delhh)->hh_next->hh_prev = (delhh)->hh_prev; \
|
|
804
|
+
} \
|
|
805
|
+
} while (0)
|
|
761
806
|
|
|
762
807
|
/* Bucket expansion has the effect of doubling the number of buckets
|
|
763
808
|
* and redistributing the items into the new buckets. Ideally the
|
|
@@ -788,52 +833,56 @@ do {
|
|
|
788
833
|
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
|
|
789
834
|
*
|
|
790
835
|
*/
|
|
791
|
-
#define HASH_EXPAND_BUCKETS(tbl)
|
|
836
|
+
#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \
|
|
792
837
|
do { \
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
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; \
|
|
838
|
+
unsigned _he_bkt; \
|
|
839
|
+
unsigned _he_bkt_i; \
|
|
840
|
+
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
|
841
|
+
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
|
842
|
+
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
|
843
|
+
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
|
|
844
|
+
if (!_he_new_buckets) { \
|
|
845
|
+
HASH_RECORD_OOM(oomed); \
|
|
846
|
+
} else { \
|
|
847
|
+
uthash_bzero(_he_new_buckets, \
|
|
848
|
+
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
|
|
849
|
+
(tbl)->ideal_chain_maxlen = \
|
|
850
|
+
((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
|
|
851
|
+
((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
|
|
852
|
+
(tbl)->nonideal_items = 0; \
|
|
853
|
+
for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \
|
|
854
|
+
_he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \
|
|
855
|
+
while (_he_thh != NULL) { \
|
|
856
|
+
_he_hh_nxt = _he_thh->hh_next; \
|
|
857
|
+
HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \
|
|
858
|
+
_he_newbkt = &(_he_new_buckets[_he_bkt]); \
|
|
859
|
+
if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \
|
|
860
|
+
(tbl)->nonideal_items++; \
|
|
861
|
+
if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \
|
|
862
|
+
_he_newbkt->expand_mult++; \
|
|
863
|
+
} \
|
|
824
864
|
} \
|
|
865
|
+
_he_thh->hh_prev = NULL; \
|
|
866
|
+
_he_thh->hh_next = _he_newbkt->hh_head; \
|
|
867
|
+
if (_he_newbkt->hh_head != NULL) { \
|
|
868
|
+
_he_newbkt->hh_head->hh_prev = _he_thh; \
|
|
869
|
+
} \
|
|
870
|
+
_he_newbkt->hh_head = _he_thh; \
|
|
871
|
+
_he_thh = _he_hh_nxt; \
|
|
872
|
+
} \
|
|
825
873
|
} \
|
|
826
|
-
uthash_free(
|
|
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
|
-
|
|
834
|
-
|
|
874
|
+
uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
|
|
875
|
+
(tbl)->num_buckets *= 2U; \
|
|
876
|
+
(tbl)->log2_num_buckets++; \
|
|
877
|
+
(tbl)->buckets = _he_new_buckets; \
|
|
878
|
+
(tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \
|
|
879
|
+
((tbl)->ineff_expands+1U) : 0U; \
|
|
880
|
+
if ((tbl)->ineff_expands > 1U) { \
|
|
881
|
+
(tbl)->noexpand = 1; \
|
|
882
|
+
uthash_noexpand_fyi(tbl); \
|
|
835
883
|
} \
|
|
836
884
|
uthash_expand_fyi(tbl); \
|
|
885
|
+
} \
|
|
837
886
|
} while (0)
|
|
838
887
|
|
|
839
888
|
|
|
@@ -847,85 +896,82 @@ do {
|
|
|
847
896
|
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
|
|
848
897
|
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
|
|
849
898
|
if (head != NULL) { \
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
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; \
|
|
899
|
+
_hs_insize = 1; \
|
|
900
|
+
_hs_looping = 1; \
|
|
901
|
+
_hs_list = &((head)->hh); \
|
|
902
|
+
while (_hs_looping != 0U) { \
|
|
903
|
+
_hs_p = _hs_list; \
|
|
904
|
+
_hs_list = NULL; \
|
|
905
|
+
_hs_tail = NULL; \
|
|
906
|
+
_hs_nmerges = 0; \
|
|
907
|
+
while (_hs_p != NULL) { \
|
|
908
|
+
_hs_nmerges++; \
|
|
909
|
+
_hs_q = _hs_p; \
|
|
910
|
+
_hs_psize = 0; \
|
|
911
|
+
for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \
|
|
912
|
+
_hs_psize++; \
|
|
913
|
+
_hs_q = ((_hs_q->next != NULL) ? \
|
|
914
|
+
HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \
|
|
915
|
+
if (_hs_q == NULL) { \
|
|
916
|
+
break; \
|
|
916
917
|
} \
|
|
917
|
-
|
|
918
|
-
|
|
918
|
+
} \
|
|
919
|
+
_hs_qsize = _hs_insize; \
|
|
920
|
+
while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \
|
|
921
|
+
if (_hs_psize == 0U) { \
|
|
922
|
+
_hs_e = _hs_q; \
|
|
923
|
+
_hs_q = ((_hs_q->next != NULL) ? \
|
|
924
|
+
HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \
|
|
925
|
+
_hs_qsize--; \
|
|
926
|
+
} else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \
|
|
927
|
+
_hs_e = _hs_p; \
|
|
928
|
+
if (_hs_p != NULL) { \
|
|
929
|
+
_hs_p = ((_hs_p->next != NULL) ? \
|
|
930
|
+
HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \
|
|
931
|
+
} \
|
|
932
|
+
_hs_psize--; \
|
|
933
|
+
} else if ((cmpfcn( \
|
|
934
|
+
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \
|
|
935
|
+
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \
|
|
936
|
+
)) <= 0) { \
|
|
937
|
+
_hs_e = _hs_p; \
|
|
938
|
+
if (_hs_p != NULL) { \
|
|
939
|
+
_hs_p = ((_hs_p->next != NULL) ? \
|
|
940
|
+
HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \
|
|
941
|
+
} \
|
|
942
|
+
_hs_psize--; \
|
|
943
|
+
} else { \
|
|
944
|
+
_hs_e = _hs_q; \
|
|
945
|
+
_hs_q = ((_hs_q->next != NULL) ? \
|
|
946
|
+
HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \
|
|
947
|
+
_hs_qsize--; \
|
|
948
|
+
} \
|
|
949
|
+
if ( _hs_tail != NULL ) { \
|
|
950
|
+
_hs_tail->next = ((_hs_e != NULL) ? \
|
|
951
|
+
ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \
|
|
952
|
+
} else { \
|
|
953
|
+
_hs_list = _hs_e; \
|
|
919
954
|
} \
|
|
920
|
-
if (
|
|
921
|
-
|
|
922
|
-
(head)->hh.tbl
|
|
923
|
-
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
|
|
955
|
+
if (_hs_e != NULL) { \
|
|
956
|
+
_hs_e->prev = ((_hs_tail != NULL) ? \
|
|
957
|
+
ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \
|
|
924
958
|
} \
|
|
925
|
-
|
|
959
|
+
_hs_tail = _hs_e; \
|
|
960
|
+
} \
|
|
961
|
+
_hs_p = _hs_q; \
|
|
962
|
+
} \
|
|
963
|
+
if (_hs_tail != NULL) { \
|
|
964
|
+
_hs_tail->next = NULL; \
|
|
965
|
+
} \
|
|
966
|
+
if (_hs_nmerges <= 1U) { \
|
|
967
|
+
_hs_looping = 0; \
|
|
968
|
+
(head)->hh.tbl->tail = _hs_tail; \
|
|
969
|
+
DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
|
|
926
970
|
} \
|
|
927
|
-
|
|
928
|
-
|
|
971
|
+
_hs_insize *= 2U; \
|
|
972
|
+
} \
|
|
973
|
+
HASH_FSCK(hh, head, "HASH_SRT"); \
|
|
974
|
+
} \
|
|
929
975
|
} while (0)
|
|
930
976
|
|
|
931
977
|
/* This function selects items from one hash into another hash.
|
|
@@ -936,54 +982,74 @@ do {
|
|
|
936
982
|
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
|
|
937
983
|
do { \
|
|
938
984
|
unsigned _src_bkt, _dst_bkt; \
|
|
939
|
-
void *_last_elt=NULL, *_elt;
|
|
985
|
+
void *_last_elt = NULL, *_elt; \
|
|
940
986
|
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
|
|
941
987
|
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
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
988
|
+
if ((src) != NULL) { \
|
|
989
|
+
for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
|
|
990
|
+
for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
|
|
991
|
+
_src_hh != NULL; \
|
|
992
|
+
_src_hh = _src_hh->hh_next) { \
|
|
993
|
+
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
|
|
994
|
+
if (cond(_elt)) { \
|
|
995
|
+
IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \
|
|
996
|
+
_dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \
|
|
997
|
+
_dst_hh->key = _src_hh->key; \
|
|
998
|
+
_dst_hh->keylen = _src_hh->keylen; \
|
|
999
|
+
_dst_hh->hashv = _src_hh->hashv; \
|
|
1000
|
+
_dst_hh->prev = _last_elt; \
|
|
1001
|
+
_dst_hh->next = NULL; \
|
|
1002
|
+
if (_last_elt_hh != NULL) { \
|
|
1003
|
+
_last_elt_hh->next = _elt; \
|
|
1004
|
+
} \
|
|
1005
|
+
if ((dst) == NULL) { \
|
|
1006
|
+
DECLTYPE_ASSIGN(dst, _elt); \
|
|
1007
|
+
HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \
|
|
1008
|
+
IF_HASH_NONFATAL_OOM( \
|
|
1009
|
+
if (_hs_oomed) { \
|
|
1010
|
+
uthash_nonfatal_oom(_elt); \
|
|
1011
|
+
(dst) = NULL; \
|
|
1012
|
+
continue; \
|
|
1013
|
+
} \
|
|
1014
|
+
) \
|
|
1015
|
+
} else { \
|
|
1016
|
+
_dst_hh->tbl = (dst)->hh_dst.tbl; \
|
|
967
1017
|
} \
|
|
1018
|
+
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
|
|
1019
|
+
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \
|
|
1020
|
+
(dst)->hh_dst.tbl->num_items++; \
|
|
1021
|
+
IF_HASH_NONFATAL_OOM( \
|
|
1022
|
+
if (_hs_oomed) { \
|
|
1023
|
+
HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \
|
|
1024
|
+
HASH_DELETE_HH(hh_dst, dst, _dst_hh); \
|
|
1025
|
+
_dst_hh->tbl = NULL; \
|
|
1026
|
+
uthash_nonfatal_oom(_elt); \
|
|
1027
|
+
continue; \
|
|
1028
|
+
} \
|
|
1029
|
+
) \
|
|
1030
|
+
HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \
|
|
1031
|
+
_last_elt = _elt; \
|
|
1032
|
+
_last_elt_hh = _dst_hh; \
|
|
1033
|
+
} \
|
|
968
1034
|
} \
|
|
969
1035
|
} \
|
|
970
1036
|
} \
|
|
971
|
-
HASH_FSCK(hh_dst,dst);
|
|
1037
|
+
HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \
|
|
972
1038
|
} while (0)
|
|
973
1039
|
|
|
974
1040
|
#define HASH_CLEAR(hh,head) \
|
|
975
1041
|
do { \
|
|
976
|
-
if (head != NULL) {
|
|
1042
|
+
if ((head) != NULL) { \
|
|
1043
|
+
HASH_BLOOM_FREE((head)->hh.tbl); \
|
|
977
1044
|
uthash_free((head)->hh.tbl->buckets, \
|
|
978
1045
|
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
|
|
979
|
-
HASH_BLOOM_FREE((head)->hh.tbl); \
|
|
980
1046
|
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
|
981
|
-
(head)=NULL;
|
|
1047
|
+
(head) = NULL; \
|
|
982
1048
|
} \
|
|
983
1049
|
} while (0)
|
|
984
1050
|
|
|
985
1051
|
#define HASH_OVERHEAD(hh,head) \
|
|
986
|
-
((head != NULL) ? (
|
|
1052
|
+
(((head) != NULL) ? ( \
|
|
987
1053
|
(size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
|
|
988
1054
|
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
|
|
989
1055
|
sizeof(UT_hash_table) + \
|
|
@@ -1066,7 +1132,7 @@ typedef struct UT_hash_handle {
|
|
|
1066
1132
|
void *next; /* next element in app order */
|
|
1067
1133
|
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
|
1068
1134
|
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
|
1069
|
-
void *key;
|
|
1135
|
+
const void *key; /* ptr to enclosing struct's key */
|
|
1070
1136
|
unsigned keylen; /* enclosing struct's key len */
|
|
1071
1137
|
unsigned hashv; /* result of hash-fcn(key) */
|
|
1072
1138
|
} UT_hash_handle;
|