summaryrefslogtreecommitdiff
path: root/vendors/uthash.h
diff options
context:
space:
mode:
Diffstat (limited to 'vendors/uthash.h')
-rw-r--r--vendors/uthash.h213
1 files changed, 212 insertions, 1 deletions
diff --git a/vendors/uthash.h b/vendors/uthash.h
index 2c00932..e3c235c 100644
--- a/vendors/uthash.h
+++ b/vendors/uthash.h
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h> /* memcmp, memset, strlen */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit */
+#include <stdio.h>
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
/* This codepath is provided for backward compatibility, but I plan to remove it. */
@@ -87,9 +88,86 @@ do {
#define uthash_strlen(s) strlen(s)
#endif
+#include "xxhash/xxhash.h"
+
+static uint32_t
+murmurhash (const char *key, uint32_t len, uint32_t seed) {
+ uint32_t c1 = 0xcc9e2d51;
+ uint32_t c2 = 0x1b873593;
+ uint32_t r1 = 15;
+ uint32_t r2 = 13;
+ uint32_t m = 5;
+ uint32_t n = 0xe6546b64;
+ uint32_t h = 0;
+ uint32_t k = 0;
+ uint8_t *d = (uint8_t *) key; // 32 bit extract from `key'
+ const uint32_t *chunks = NULL;
+ const uint8_t *tail = NULL; // tail - last 8 bytes
+ int i = 0;
+ int l = len / 4; // chunk length
+
+ h = seed;
+
+ chunks = (const uint32_t *) (d + l * 4); // body
+ tail = (const uint8_t *) (d + l * 4); // last 8 byte chunk of `key'
+
+ // for each 4 byte chunk of `key'
+ for (i = -l; i != 0; ++i) {
+ // next 4 byte chunk of `key'
+ k = chunks[i];
+
+ // encode next 4 byte chunk of `key'
+ k *= c1;
+ k = (k << r1) | (k >> (32 - r1));
+ k *= c2;
+
+ // append to hash
+ h ^= k;
+ h = (h << r2) | (h >> (32 - r2));
+ h = h * m + n;
+ }
+
+ k = 0;
+
+ // remainder
+ switch (len & 3) { // `len % 4'
+ case 3: k ^= (tail[2] << 16);
+ case 2: k ^= (tail[1] << 8);
+
+ case 1:
+ k ^= tail[0];
+ k *= c1;
+ k = (k << r1) | (k >> (32 - r1));
+ k *= c2;
+ h ^= k;
+ }
+
+ h ^= len;
+
+ h ^= (h >> 16);
+ h *= 0x85ebca6b;
+ h ^= (h >> 13);
+ h *= 0xc2b2ae35;
+ h ^= (h >> 16);
+
+ return h;
+}
+
+#define HASH_MUR(keyptr, keylen, hashv) \
+ do { \
+ hashv = murmurhash(keyptr, keylen, 0); \
+ } while (0)
+
+ #define HASH_XXH(keyptr, keylen, hashv) \
+ do { \
+ hashv = XXH3_64bits(keyptr, keylen); \
+ } while (0)
+
+
#ifndef HASH_FUNCTION
// #define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv)
-#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_SFH(keyptr, keylen, hashv)
+// #define HASH_FUNCTION(keyptr,keylen,hashv) HASH_SFH(keyptr, keylen, hashv)
+#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_MUR(keyptr, keylen, hashv)
// #define HASH_FUNCTION(keyptr,keylen,hashv) HASH_OAT(keyptr, keylen, hashv)
// #define HASH_FUNCTION(keyptr,keylen,hashv) HASH_SAX(keyptr, keylen, hashv)
// #define HASH_FUNCTION(keyptr,keylen,hashv) HASH_FNV(keyptr, keylen, hashv)
@@ -1142,4 +1220,137 @@ typedef struct UT_hash_handle {
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
+static inline unsigned hash_to_bkt_func(unsigned hashv, unsigned num_bkts) {
+ return hashv & (num_bkts - 1U);
+}
+
+static int my_key_cmp1(const void *a, const void *b, unsigned len) {
+ for (unsigned i = 0; i < len; i++) {
+ if (((char *)a)[i] != ((char *)b)[i]) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void* elmt_from_hh_func(struct UT_hash_table *tbl, struct UT_hash_handle *hhp) {
+ return (void*)((char*)hhp - tbl->hho);
+}
+
+static struct UT_hash_handle *things_in_while_find_hh(
+ struct UT_hash_table *tbl,
+ const void *keyptr,
+ unsigned keylen_in,
+ unsigned hashval,
+ struct UT_hash_handle *hh
+) {
+ while (hh != NULL) {
+ if (hh->hashv == hashval && hh->keylen == keylen_in &&
+ my_key_cmp1(hh->key, keyptr, keylen_in) == 0) {
+ // printf("while_cnt: %d before returning the value \n", while_cnt);
+ return hh;
+ }
+ hh = hh->hh_next;
+ }
+ return NULL;
+}
+
+/* 替换 HASH_FIND_IN_BKT */
+// static inline void *hash_find_in_bkt_func(
+// struct UT_hash_table *tbl,
+// unsigned bkt,
+// const void *keyptr,
+// unsigned keylen_in,
+// unsigned hashval
+// ) {
+// struct UT_hash_bucket *bucket = &(tbl->buckets[bkt]);
+// struct UT_hash_handle *hh = bucket->hh_head;
+// int while_cnt = 0;
+// while (hh != NULL) {
+// while_cnt++;
+// if (hh->hashv == hashval && hh->keylen == keylen_in &&
+// // HASH_KEYCMP(hh->key, keyptr, keylen_in) == 0) {
+// my_key_cmp1(hh->key, keyptr, keylen_in) == 0) {
+// // printf("while_cnt: %d before returning the value \n", while_cnt);
+// return elmt_from_hh_func(tbl, hh);
+// }
+// hh = hh->hh_next;
+// }
+// return NULL;
+// }
+
+static inline void *hash_find_in_bkt_func(
+ struct UT_hash_table *tbl,
+ unsigned bkt,
+ const void *keyptr,
+ unsigned keylen_in,
+ unsigned hashval
+) {
+ struct UT_hash_bucket *bucket = &(tbl->buckets[bkt]);
+ struct UT_hash_handle *hh = bucket->hh_head;
+
+ hh = things_in_while_find_hh(tbl, keyptr, keylen_in, hashval, hh);
+ if (hh != NULL) {
+ return elmt_from_hh_func(tbl, hh);
+ }
+ return NULL;
+}
+
+/* 替换 HASH_FIND_BYHASHVALUE */
+static inline void *hash_find_byhashvalue_func(
+ struct UT_hash_table *tbl,
+ const void *keyptr,
+ unsigned keylen,
+ unsigned hashval
+) {
+ unsigned bkt = hash_to_bkt_func(hashval, tbl->num_buckets);
+ if (HASH_BLOOM_TEST(tbl, hashval)) {
+ return hash_find_in_bkt_func(tbl, bkt, keyptr, keylen, hashval);
+ }
+ return NULL;
+}
+
+/* 替换 HASH_FIND */
+static inline void *hash_find_func(
+ struct UT_hash_table *tbl,
+ const void *keyptr,
+ unsigned keylen
+) {
+ unsigned hashv;
+ HASH_VALUE(keyptr, keylen, hashv);
+ return hash_find_byhashvalue_func(tbl, keyptr, keylen, hashv);
+}
+
+/* 2. 取消定义原有宏 */
+#undef HASH_TO_BKT
+#undef HASH_FIND_IN_BKT
+#undef HASH_FIND_BYHASHVALUE
+#undef HASH_FIND
+
+/* 3. 重定义宏以调用替代函数 */
+#define HASH_TO_BKT(hashv, num_bkts, bkt) \
+ do { \
+ (bkt) = hash_to_bkt_func((hashv), (num_bkts)); \
+ } while (0)
+
+#define HASH_FIND_IN_BKT(tbl, hh, head, keyptr, keylen_in, hashval, out) \
+ do { \
+ (out) = hash_find_in_bkt_func((tbl), (head), (keyptr), (keylen_in), (hashval)); \
+ } while (0)
+
+#define HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, hashval, out) \
+ do { \
+ (out) = hash_find_byhashvalue_func((head)->hh.tbl, (keyptr), (keylen), (hashval)); \
+ } while (0)
+
+#define HASH_FIND(hh, head, keyptr, keylen, out) \
+ do { \
+ if (!(head)) { \
+ (out) = NULL; \
+ } else { \
+ (out) = hash_find_func((head)->hh.tbl, (keyptr), (keylen)); \
+ } \
+ } while (0)
+
+
#endif /* UTHASH_H */