|
@@ -102,6 +102,8 @@ typedef unsigned char uint8_t;
|
|
|
|
|
|
/* calculate the element whose hash handle address is hhe */
|
|
/* calculate the element whose hash handle address is hhe */
|
|
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
|
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
|
|
|
+/* calculate the hash handle from element address elp */
|
|
|
|
+#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho)))
|
|
|
|
|
|
#define HASH_VALUE(keyptr,keylen,hashv) \
|
|
#define HASH_VALUE(keyptr,keylen,hashv) \
|
|
do { \
|
|
do { \
|
|
@@ -122,7 +124,7 @@ do {
|
|
} \
|
|
} \
|
|
} while (0)
|
|
} while (0)
|
|
|
|
|
|
-#define HASH_FIND_BY_HASH_VALUE(hh,head,keyptr,keylen,_hf_hashv,out) \
|
|
|
|
|
|
+#define HASH_FIND_BY_HVAL(hh,head,keyptr,keylen,_hf_hashv,out) \
|
|
do { \
|
|
do { \
|
|
out=NULL; \
|
|
out=NULL; \
|
|
if (head != NULL) { \
|
|
if (head != NULL) { \
|
|
@@ -188,79 +190,117 @@ do {
|
|
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
|
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
|
} while(0)
|
|
} while(0)
|
|
|
|
|
|
-#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
|
|
|
- HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
|
|
|
|
|
|
+#define HASH_SADD(hh,head,fieldname,keylen_in,add,cmpfcn) \
|
|
|
|
+ HASH_SADD_KEYPTR(hh,(head),&((add)->fieldname),(keylen_in),(add),cmpfcn)
|
|
|
|
+
|
|
|
|
+#define HASH_SADD_BY_HVAL(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \
|
|
|
|
+ HASH_SADD_KEYPTR_BY_HVAL(hh,(head),&((add)->fieldname), \
|
|
|
|
+ (keylen_in),(add),cmpfcn)
|
|
|
|
|
|
-#define HASH_ADD_BY_HASH_VALUE(hh,head,fieldname,keylen_in,hashval,add) \
|
|
|
|
- HASH_ADD_KEYPTR_BY_HASH_VALUE(hh,head,&((add)->fieldname),keylen_in,hashval,add)
|
|
|
|
|
|
+#define HASH_ADD_BY_HVAL(hh,head,fieldname,keylen_in,hashval,add) \
|
|
|
|
+ HASH_ADD_KEYPTR_BY_HVAL(hh,head,&((add)->fieldname), \
|
|
|
|
+ keylen_in,hashval,add)
|
|
|
|
|
|
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
|
|
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
|
|
do { \
|
|
do { \
|
|
unsigned _hr_hashv; \
|
|
unsigned _hr_hashv; \
|
|
- HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \
|
|
|
|
- HASH_REPLACE_BY_HASH_VALUE(hh,head,fieldname,keylen_in,_hr_hashv,add,replaced);\
|
|
|
|
|
|
+ HASH_VALUE(&((add)->fieldname), (keylen_in), _hr_hashv); \
|
|
|
|
+ HASH_REPLACE_BY_HVAL(hh,(head),fieldname,(keylen_in), \
|
|
|
|
+ _hr_hashv,(add),(replaced)); \
|
|
} while(0)
|
|
} while(0)
|
|
|
|
|
|
-#define HASH_REPLACE_BY_HASH_VALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \
|
|
|
|
|
|
+#define HASH_REPLACE_BY_HVAL(hh,head,fieldname,keylen_in,hashval,add,replaced) \
|
|
do { \
|
|
do { \
|
|
replaced=NULL; \
|
|
replaced=NULL; \
|
|
- HASH_FIND_BY_HASH_VALUE(hh,head,&((add)->fieldname),keylen_in,hashval,replaced); \
|
|
|
|
- if (replaced!=NULL) { \
|
|
|
|
- HASH_DELETE(hh,head,replaced); \
|
|
|
|
|
|
+ HASH_FIND_BY_HVAL(hh,(head),&((add)->fieldname), \
|
|
|
|
+ (keylen_in),(hashval),(replaced)); \
|
|
|
|
+ if ((replaced)!=NULL) { \
|
|
|
|
+ HASH_DELETE(hh,(head),(replaced)); \
|
|
} \
|
|
} \
|
|
- HASH_ADD_BY_HASH_VALUE(hh,head,fieldname,keylen_in,hashval,add); \
|
|
|
|
|
|
+ HASH_ADD_BY_HVAL(hh,(head),fieldname,(keylen_in),(hashval),(add)); \
|
|
} while(0)
|
|
} while(0)
|
|
|
|
|
|
-#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
|
|
|
|
|
+#define HASH_APPEND_LIST(hh, head, add) \
|
|
do { \
|
|
do { \
|
|
- unsigned _ha_bkt; \
|
|
|
|
- (add)->hh.next = NULL; \
|
|
|
|
- (add)->hh.key = (char*)(keyptr); \
|
|
|
|
- (add)->hh.keylen = (unsigned)(keylen_in); \
|
|
|
|
- if (!(head)) { \
|
|
|
|
- head = (add); \
|
|
|
|
- (head)->hh.prev = NULL; \
|
|
|
|
- HASH_MAKE_TABLE(hh,head); \
|
|
|
|
- } else { \
|
|
|
|
- (head)->hh.tbl->tail->next = (add); \
|
|
|
|
- (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
|
|
|
- (head)->hh.tbl->tail = &((add)->hh); \
|
|
|
|
- } \
|
|
|
|
- (head)->hh.tbl->num_items++; \
|
|
|
|
- (add)->hh.tbl = (head)->hh.tbl; \
|
|
|
|
- HASH_FCN(keyptr, keylen_in, (add)->hh.hashv); \
|
|
|
|
- HASH_TO_BKT((add)->hh.hashv, (head)->hh.tbl->num_buckets, _ha_bkt); \
|
|
|
|
- HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
|
|
|
- HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
|
|
|
|
- HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
|
|
|
- HASH_FSCK(hh,head); \
|
|
|
|
|
|
+ (add)->hh.next = NULL; \
|
|
|
|
+ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
|
|
|
+ (head)->hh.tbl->tail->next = (add); \
|
|
|
|
+ (head)->hh.tbl->tail = &((add)->hh); \
|
|
} while(0)
|
|
} while(0)
|
|
|
|
|
|
-#define HASH_ADD_KEYPTR_BY_HASH_VALUE(hh,head,keyptr,keylen_in,hashval,add) \
|
|
|
|
-do { \
|
|
|
|
- unsigned _ha_bkt; \
|
|
|
|
- (add)->hh.next = NULL; \
|
|
|
|
- (add)->hh.key = (char*)(keyptr); \
|
|
|
|
- (add)->hh.keylen = (unsigned)(keylen_in); \
|
|
|
|
- if (!(head)) { \
|
|
|
|
- head = (add); \
|
|
|
|
- (head)->hh.prev = NULL; \
|
|
|
|
|
|
+
|
|
|
|
+#define HASH_ADD_PROLOGUE(hh,head,keyptr,keylen_in,add) \
|
|
|
|
+ add->hh.key = (char*) keyptr; \
|
|
|
|
+ add->hh.keylen = (unsigned) keylen_in; \
|
|
|
|
+ if (!head) { \
|
|
|
|
+ add->hh.next = NULL; \
|
|
|
|
+ add->hh.prev = NULL; \
|
|
|
|
+ head = add; \
|
|
HASH_MAKE_TABLE(hh,head); \
|
|
HASH_MAKE_TABLE(hh,head); \
|
|
- } else { \
|
|
|
|
- (head)->hh.tbl->tail->next = (add); \
|
|
|
|
- (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
|
|
|
- (head)->hh.tbl->tail = &((add)->hh); \
|
|
|
|
- } \
|
|
|
|
- (head)->hh.tbl->num_items++; \
|
|
|
|
- (add)->hh.tbl = (head)->hh.tbl; \
|
|
|
|
- (add)->hh.hashv = hashval; \
|
|
|
|
- HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \
|
|
|
|
- HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
|
|
|
- HASH_BLOOM_ADD((head)->hh.tbl,hashval); \
|
|
|
|
- HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
|
|
|
- HASH_FSCK(hh,head); \
|
|
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+#define HASH_ADD_EPILOGUE(hh,head,keyptr,keylen_in,hashval,add) \
|
|
|
|
+ HASH_APPEND_LIST(hh, head, add); \
|
|
|
|
+ } \
|
|
|
|
+ head->hh.tbl->num_items++; \
|
|
|
|
+ HASH_TO_BKT((hashval), (head)->hh.tbl->num_buckets, _ha_bkt); \
|
|
|
|
+ HASH_ADD_TO_BKT(head->hh.tbl->buckets[_ha_bkt],&add->hh); \
|
|
|
|
+ HASH_BLOOM_ADD(head->hh.tbl,add->hh.hashv); \
|
|
|
|
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
|
|
|
+ HASH_FSCK(hh,head); \
|
|
} while(0)
|
|
} while(0)
|
|
|
|
|
|
|
|
+#define HASH_GHV_DIRECT(hh, add, hashval) \
|
|
|
|
+ (add)->hh.hashv = (hashval)
|
|
|
|
+#define HASH_GHV_COMPUTE(hh, keyptr, keylen_in, add) \
|
|
|
|
+ HASH_FCN((keyptr), (keylen_in), (add)->hh.hashv)
|
|
|
|
+
|
|
|
|
+#define HASH_ADD_SORTED(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \
|
|
|
|
+ HASH_ADD_PROLOGUE(hh,(head),(keyptr),(keylen_in),(add)) \
|
|
|
|
+ struct UT_hash_handle *iter = &(head)->hh; \
|
|
|
|
+ (add)->hh.tbl = (head)->hh.tbl; \
|
|
|
|
+ do { \
|
|
|
|
+ if(cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, iter), add) > 0) \
|
|
|
|
+ break; \
|
|
|
|
+ } while((iter = iter->next)); \
|
|
|
|
+ if(iter) { \
|
|
|
|
+ (add)->hh.next = iter; \
|
|
|
|
+ if(((add)->hh.prev = iter->prev)) \
|
|
|
|
+ HH_FROM_ELMT((head)->hh.tbl, iter->prev)->next = add; \
|
|
|
|
+ else \
|
|
|
|
+ (head) = (add); \
|
|
|
|
+ iter->prev = add; \
|
|
|
|
+ } \
|
|
|
|
+ else \
|
|
|
|
+ HASH_ADD_EPILOGUE(hh,(head),(keyptr),(keylen_in),(hashval),(add))
|
|
|
|
+
|
|
|
|
+#define HASH_SADD_KEYPTR_BY_HVAL(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \
|
|
|
|
+do { unsigned _ha_bkt; \
|
|
|
|
+ HASH_GHV_DIRECT(hh, add, hashval); \
|
|
|
|
+ HASH_ADD_SORTED(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \
|
|
|
|
+
|
|
|
|
+#define HASH_SADD_KEYPTR(hh,head,keyptr,keylen_in,add,cmpfcn) \
|
|
|
|
+do { unsigned _ha_bkt; \
|
|
|
|
+ HASH_GHV_COMPUTE(hh, keyptr, keylen_in, add); \
|
|
|
|
+ HASH_ADD_SORTED(hh,head,keyptr,keylen_in,(add)->hh.hashv,add,cmpfcn)
|
|
|
|
+
|
|
|
|
+#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
|
|
|
+ HASH_ADD_KEYPTR(hh,(head),&((add)->fieldname),(keylen_in),(add))
|
|
|
|
+
|
|
|
|
+#define HASH_ADD_KEYPTR_BY_HVAL(hh,head,keyptr,keylen_in,hashval,add) \
|
|
|
|
+do { unsigned _ha_bkt; \
|
|
|
|
+ HASH_GHV_DIRECT(hh, add, hashval); \
|
|
|
|
+ HASH_ADD_PROLOGUE(hh,(head),(keyptr),(keylen_in),(add)) \
|
|
|
|
+ (add)->hh.tbl = (head)->hh.tbl; \
|
|
|
|
+ HASH_ADD_EPILOGUE(hh,(head),(keyptr),(keylen_in),hashval,(add))
|
|
|
|
+
|
|
|
|
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
|
|
|
+do { unsigned _ha_bkt; \
|
|
|
|
+ HASH_GHV_COMPUTE(hh, keyptr, keylen_in, add); \
|
|
|
|
+ HASH_ADD_PROLOGUE(hh,(head),(keyptr),(keylen_in),(add)) \
|
|
|
|
+ (add)->hh.tbl = (head)->hh.tbl; \
|
|
|
|
+ HASH_ADD_EPILOGUE(hh,(head),(keyptr),(keylen_in),(add)->hh.hashv,(add))
|
|
|
|
+
|
|
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
|
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
|
do { \
|
|
do { \
|
|
bkt = ((hashv) & ((num_bkts) - 1U)); \
|
|
bkt = ((hashv) & ((num_bkts) - 1U)); \
|