/* radare2 - BSD 3 Clause License - 2016-2022 - crowell, pancake */ #ifdef __cplusplus extern "C" { #endif #ifndef HT_TYPE #error HT_TYPE should be defined before including this header #endif #undef HtName_ #undef Ht_ #undef HT_ #undef KEY_TYPE #undef VALUE_TYPE #undef KEY_TO_HASH #undef HT_NULL_VALUE #if HT_TYPE == 1 #define HtName_(name) name##PP #define Ht_(name) ht_pp_##name #define HT_(name) HtPP##name #define KEY_TYPE void * #define VALUE_TYPE void * #define KEY_TO_HASH(x) ((ut32)(uintptr_t)(x)) #define HT_NULL_VALUE NULL #elif HT_TYPE == 2 #define HtName_(name) name##UP #define Ht_(name) ht_up_##name #define HT_(name) HtUP##name #define KEY_TYPE ut64 #define VALUE_TYPE void * #define KEY_TO_HASH(x) ((ut32)(x)) #define HT_NULL_VALUE 0 #elif HT_TYPE == 3 #define HtName_(name) name##UU #define Ht_(name) ht_uu_##name #define HT_(name) HtUU##name #define KEY_TYPE ut64 #define VALUE_TYPE ut64 #define KEY_TO_HASH(x) ((ut32)(x)) #define HT_NULL_VALUE 0 #else #define HtName_(name) name##PU #define Ht_(name) ht_pu_##name #define HT_(name) HtPU##name #define KEY_TYPE void * #define VALUE_TYPE ut64 #define KEY_TO_HASH(x) ((ut32)(uintptr_t)(x)) #define HT_NULL_VALUE 0 #endif #include "ls.h" #include "types.h" /* Kv represents a single key/value element in the hashtable */ typedef struct Ht_(kv) { KEY_TYPE key; VALUE_TYPE value; ut32 key_len; ut32 value_len; } HT_(Kv); /* * Free resources owned by kv, but do not free kv itself. * Hashtable entries live inline inside bucket arrays. */ typedef void (*HT_(KvFreeFunc))(HT_(Kv) *); typedef KEY_TYPE (*HT_(DupKey))(const KEY_TYPE); typedef VALUE_TYPE (*HT_(DupValue))(const VALUE_TYPE); typedef ut32 (*HT_(CalcSizeK))(const KEY_TYPE); typedef ut32 (*HT_(CalcSizeV))(const VALUE_TYPE); typedef ut32 (*HT_(HashFunction))(const KEY_TYPE); typedef int (*HT_(ListComparator))(const KEY_TYPE, const KEY_TYPE); typedef bool (*HT_(ForeachCallback))(void *user, const KEY_TYPE, const VALUE_TYPE); typedef struct Ht_(bucket_t) { HT_(Kv) *arr; ut32 count; ut32 size; } HT_(Bucket); /* Options contain all the settings of the hashtable */ typedef struct Ht_(options_t) { HT_(ListComparator) cmp; // Function for comparing values. Returns 0 if eq. HT_(HashFunction) hashfn; // Function for hashing items in the hash table. HT_(DupKey) dupkey; // Function for making a copy of key HT_(DupValue) dupvalue; // Function for making a copy of value HT_(CalcSizeK) calcsizeK; // Function to determine the key's size HT_(CalcSizeV) calcsizeV; // Function to determine the value's size HT_(KvFreeFunc) freefn; // Function to free the keyvalue store size_t elem_size; // Size of each HtKv element (useful for subclassing like SdbKv) } HT_(Options); /* Ht is the hashtable structure */ typedef struct Ht_(t) { HT_(Bucket) *table; // Actual table. HT_(Options) opt; ut32 size; // size of the hash table in buckets. ut32 count; // number of stored elements. ut32 prime_idx; } HtName_(Ht); // Create a new Ht with the provided Options SDB_API HtName_(Ht)* Ht_(new_opt)(HT_(Options) *opt); // Destroy a hashtable and all of its entries. SDB_API void Ht_(free)(HtName_(Ht)* ht); // Insert a new Key-Value pair into the hashtable. If the key already exists, returns false. SDB_API bool Ht_(insert)(HtName_(Ht)* ht, const KEY_TYPE key, VALUE_TYPE value); // Insert a new Key-Value pair into the hashtable, or updates the value if the key already exists. SDB_API bool Ht_(update)(HtName_(Ht)* ht, const KEY_TYPE key, VALUE_TYPE value); // Update the key of an element in the hashtable SDB_API bool Ht_(update_key)(HtName_(Ht)* ht, const KEY_TYPE old_key, const KEY_TYPE new_key); // Delete a key from the hashtable. SDB_API bool Ht_(delete)(HtName_(Ht)* ht, const KEY_TYPE key); // Find the value corresponding to the matching key. SDB_API VALUE_TYPE Ht_(find)(HtName_(Ht)* ht, const KEY_TYPE key, bool* found); // Iterates over all elements in the hashtable, calling the cb function on each Kv. // If the cb returns false, the iteration is stopped. // cb should not modify the hashtable. // NOTE: cb can delete the current element, but it should be avoided SDB_API void Ht_(foreach)(HtName_(Ht) *ht, HT_(ForeachCallback) cb, void *user); SDB_API HT_(Kv)* Ht_(find_kv)(HtName_(Ht)* ht, const KEY_TYPE key, bool* found); SDB_API bool Ht_(insert_kv)(HtName_(Ht) *ht, HT_(Kv) *kv, bool update); #ifdef __cplusplus } #endif #undef HT_TYPE