123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /*
- * category: [data structure]
- * apply status: log_mgr, sp_log, SpEntity, mod_evtconverter
- * edit status: not
- * build status:
- * description:
- */
- #ifndef HASHSET_H
- #define HASHSET_H
- #pragma once
- #include "config.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "list.h"
- #define HASH_DEFAULT_INIT_HASH_SIZE 15
- #define HASH_DEFAULT_LOAD_FACTOR 0.72f
- typedef struct hashset_t hashset_t;
- typedef struct hashset_iterator hashset_iterator;
- TOOLKIT_API int hash_get_prime(int min);
- typedef const void* (*hashset_getkey)(const void *obj);
- typedef unsigned int (*hashset_hash)(const void *key);
- typedef int (*hashset_cmpkey)(const void *key_x, const void *key_y);
- struct hashset_iterator {
- hashset_t *ht;
- int slot;
- struct hlist_node *pos, *pos_next;
- };
- struct hashset_t {
- struct hlist_head *buckets;
- int count;
- int size;
- int node_offset;
- float load_factor;
- hashset_getkey getkey_fn;
- hashset_hash hash_fn;
- hashset_cmpkey cmp_fn;
- hashset_iterator default_iterator;
- };
- /**
- * hash a set of object pointers
- * @param node_offset struct hlist_node offset in the structure, use offset_of macro
- * @param init_size initial size
- * @param getkey_fn get key from object
- * @param hash_fn get hashcode from key
- * @param cmp_fn compare key
- */
- TOOLKIT_API hashset_t *hashset_create2(int init_size,
- float load_factor,
- int node_offset,
- hashset_getkey getkey_fn,
- hashset_hash hash_fn,
- hashset_cmpkey cmp_fn);
- TOOLKIT_API hashset_t * hashset_create(int node_offset,
- hashset_getkey getkey_fn,
- hashset_hash hash_fn,
- hashset_cmpkey cmp_fn);
- /**
- * remove an object by key
- * @return NULL obj not find
- */
- TOOLKIT_API void* hashset_remove(hashset_t *ht, const void *key);
- /**
- * add an object to hashset
- */
- TOOLKIT_API int hashset_add(hashset_t *ht, void *obj);
- /**
- * find object by key
- * @return null failed
- */
- TOOLKIT_API void* hashset_find(hashset_t *ht, const void *key);
- /**
- * get the number of objects in the hashset
- */
- TOOLKIT_API int hashset_count(hashset_t *ht);
- /**
- * destroy hashset
- */
- TOOLKIT_API void hashset_destroy(hashset_t *ht);
- TOOLKIT_API hashset_iterator *hashset_default_iterator(hashset_t *ht);
- TOOLKIT_API hashset_iterator *hashset_iterator_create(hashset_t *ht);
- TOOLKIT_API void hashset_iterator_destroy(hashset_iterator *iter);
- TOOLKIT_API int hashset_iterator_next(hashset_iterator *iter);
- TOOLKIT_API void *hashset_iterator_get_object(hashset_iterator *iter);
- TOOLKIT_API hashset_iterator *hashset_iterator_reset(hashset_iterator *iter);
- static __inline struct hlist_node * __hashset_next_node(hashset_t *ht, struct hlist_node *pos, int *slot)
- {
- if (pos)
- pos = pos->next;
- while (*slot < ht->size && !pos) {
- pos = ht->buckets[*slot].first;
- *slot = *slot + 1;
- }
- return pos;
- }
- /**
- * walk through hashset
- * @param tpos pointer to type
- * @param pos temp pointer to struct hlist_node
- * @param slot temp int variable
- * @param ht hashtable pointer
- * @param type object type
- */
- #define hashset_for_each(tpos, pos, slot, ht, type) \
- for (slot = 0, pos = NULL; \
- pos = __hashset_next_node(ht, pos, &slot), tpos = pos ? (type*)((char*)pos-(ht)->node_offset) : NULL;)
- /**
- * walk through hashset, can remove tpos
- * @param pos temp pointer to struct hlist_node
- * @param n temp pointer to struct hlist_node
- */
- #define hashset_for_each_safe(tpos, pos, n, slot, ht, type) \
- for (slot = 0, pos = __hashset_next_node(ht, NULL, &slot), n = __hashset_next_node(ht, pos, &slot); \
- tpos = (pos) ? (type*)((char*)pos-(ht)->node_offset) : NULL; \
- pos = n, n = __hashset_next_node(ht, pos, &slot))
- /* string map(hash table) */
- typedef struct stringmap_t stringmap_t;
- TOOLKIT_API stringmap_t *stringmap_create(int init_size);
- TOOLKIT_API void stringmap_destroy(stringmap_t *map);
- typedef struct stringmap_kv_pair stringmap_kv_pair;
- TOOLKIT_API const char* stringmap_kv_pair_get_key(stringmap_kv_pair *kv);
- TOOLKIT_API void *stringmap_kv_pair_get_value(stringmap_kv_pair *kv);
- TOOLKIT_API void *stringmap_kv_pair_set_value(stringmap_kv_pair *kv, void *newval);
- TOOLKIT_API stringmap_kv_pair *stringmap_find(stringmap_t *map, const char *key);
- TOOLKIT_API int stringmap_add(stringmap_t *map, const char *key, void *value);
- TOOLKIT_API void *stringmap_remove(stringmap_t *map, const char *key);
- TOOLKIT_API int stringmap_count(stringmap_t *map);
- typedef struct stringmap_iterator stringmap_iterator;
- TOOLKIT_API stringmap_iterator *stringmap_default_iterator(stringmap_t *map);
- TOOLKIT_API stringmap_iterator *stringmap_iterator_create(stringmap_t *map);
- TOOLKIT_API void stringmap_iterator_destroy(stringmap_iterator *iter);
- TOOLKIT_API int stringmap_iterator_next(stringmap_iterator *iter);
- TOOLKIT_API const char *stringmap_iterator_get_key(stringmap_iterator *iter);
- TOOLKIT_API void *stringmap_iterator_get_value(stringmap_iterator *iter);
- TOOLKIT_API stringmap_iterator *stringmap_iterator_reset(stringmap_iterator *iter);
- // template version of hash table
- typedef unsigned int (*__htable_hash)(const void *key);
- typedef int (*__htable_compare)(const void *key1, const void *key2);
- typedef struct htable_t {
- struct hlist_head *buckets;
- int count;
- int size;
- }htable_t;
- TOOLKIT_API int htable_init(htable_t *ht, int init_size);
- TOOLKIT_API void htable_term(htable_t *ht);
- TOOLKIT_API htable_t *htable_create(int init_size);
- TOOLKIT_API void htable_destroy(htable_t *ht);
- static __inline int htable_get_count(htable_t *ht)
- {
- return ht->count;
- }
- #define __DECLARE_HTABLE(prefix, TKey, TObject, modifier) \
- modifier int prefix##_check_expand(htable_t *ht); \
- modifier TObject* prefix##_find(htable_t *ht, TKey* key); \
- modifier int prefix##_add(htable_t *ht, TObject* obj); \
- modifier void prefix##_remove(htable_t *ht, TObject* obj);
- #define __IMPLEMENT_HTABLE(prefix, TKey, TObject, member_key, member_node, fun_hash, fun_cmp, modifier) \
- modifier int prefix##_check_expand(htable_t *ht) \
- { \
- if ((ht->count+1)/(float)ht->size > HASH_DEFAULT_LOAD_FACTOR) { \
- int i; \
- int new_size = hash_get_prime(ht->size * 2); \
- struct hlist_head *new_buckets = (struct hlist_head *)ZALLOC(new_size*sizeof(struct hlist_head)); \
- if (!new_buckets) \
- return -1; \
- for (i = 0; i < ht->size; ++i) { \
- TObject *tpos; \
- struct hlist_node *pos, *n; \
- hlist_for_each_entry_safe(tpos, pos, n, &ht->buckets[i], TObject, member_node) { \
- unsigned int new_slot = fun_hash(&tpos->member_key) % new_size; \
- hlist_del(pos); \
- hlist_add_head(&tpos->member_node, &new_buckets[new_slot]); \
- } \
- } \
- FREE(ht->buckets); \
- ht->buckets = new_buckets; \
- ht->size = new_size; \
- } \
- return 0; \
- } \
- modifier TObject* prefix##_find_continue(htable_t *ht, struct hlist_node *position, TKey *key) \
- { \
- TObject *tpos; \
- struct hlist_node *pos = position; \
- hlist_for_each_entry_continue(tpos, pos, TObject, member_node) { \
- if (fun_cmp(&tpos->member_key, key) == 0) \
- return tpos; \
- } \
- return NULL; \
- } \
- modifier TObject* prefix##_find_from(htable_t *ht, struct hlist_node *position, TKey *key) \
- { \
- TObject *tpos; \
- struct hlist_node *pos = position; \
- hlist_for_each_entry_from(tpos, pos, TObject, member_node) { \
- if (fun_cmp(&tpos->member_key, key) == 0) \
- return tpos; \
- } \
- return NULL; \
- } \
- modifier TObject* prefix##_find(htable_t *ht, TKey *key) \
- { \
- unsigned int k = fun_hash(key); \
- int slot = k % ht->size; \
- TObject *tpos; \
- struct hlist_node *pos; \
- hlist_for_each_entry(tpos, pos, &ht->buckets[slot], TObject, member_node) { \
- if (fun_cmp(&tpos->member_key, key) == 0) \
- return tpos; \
- } \
- return NULL; \
- } \
- modifier int prefix##_add(htable_t *ht, TObject *obj) \
- { \
- int rc; \
- rc = prefix##_check_expand(ht); \
- if (rc == 0) { \
- unsigned int k = fun_hash(&obj->member_key); \
- int slot = k % ht->size; \
- hlist_add_head(&obj->member_node, &ht->buckets[slot]); \
- ht->count++; \
- } \
- return rc; \
- } \
- modifier void prefix##_remove(htable_t *ht, TObject* obj) \
- { \
- hlist_del_init(&obj->member_node); \
- ht->count --; \
- }
- #define __HTABLE_NOTHING
- #define __HTABLE_STATIC static
- #define DECLARE_HTABLE(prefix, TKey, TObject) __DECLARE_HTABLE(prefix, TKey, TObject, __HTABLE_NOTHING)
- #define DECLARE_HTABLE_STATIC(prefix, TKey, TObject) __DECLARE_HTABLE(prefix, TKey, TObject, __HTABLE_STATIC)
- #define IMPLEMENT_HTABLE(prefix, TKey, TObject, member_key, member_node, fun_hash, fun_cmp) __IMPLEMENT_HTABLE(prefix, TKey, TObject, member_key, member_node, fun_hash, fun_cmp, __HTABLE_NOTHING)
- #define IMPLEMENT_HTABLE_STATIC(prefix, TKey, TObject, member_key, member_node, fun_hash, fun_cmp) __IMPLEMENT_HTABLE(prefix, TKey, TObject, member_key, member_node, fun_hash, fun_cmp, __HTABLE_STATIC)
- #ifdef __cplusplus
- } // extern "C" {
- #endif
- #endif // HASHSET_H
|