You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.4 KiB
123 lines
3.4 KiB
#ifndef HASHMAP_H |
|
#define HASHMAP_H |
|
|
|
/* |
|
* Generic implementation of hash-based key-value mappings. |
|
* See Documentation/technical/api-hashmap.txt. |
|
*/ |
|
|
|
/* FNV-1 functions */ |
|
|
|
extern unsigned int strhash(const char *buf); |
|
extern unsigned int strihash(const char *buf); |
|
extern unsigned int memhash(const void *buf, size_t len); |
|
extern unsigned int memihash(const void *buf, size_t len); |
|
extern unsigned int memihash_cont(unsigned int hash_seed, const void *buf, size_t len); |
|
|
|
static inline unsigned int sha1hash(const unsigned char *sha1) |
|
{ |
|
/* |
|
* Equivalent to 'return *(unsigned int *)sha1;', but safe on |
|
* platforms that don't support unaligned reads. |
|
*/ |
|
unsigned int hash; |
|
memcpy(&hash, sha1, sizeof(hash)); |
|
return hash; |
|
} |
|
|
|
/* data structures */ |
|
|
|
struct hashmap_entry { |
|
struct hashmap_entry *next; |
|
unsigned int hash; |
|
}; |
|
|
|
typedef int (*hashmap_cmp_fn)(const void *entry, const void *entry_or_key, |
|
const void *keydata); |
|
|
|
struct hashmap { |
|
struct hashmap_entry **table; |
|
hashmap_cmp_fn cmpfn; |
|
unsigned int size, tablesize, grow_at, shrink_at; |
|
unsigned disallow_rehash : 1; |
|
}; |
|
|
|
struct hashmap_iter { |
|
struct hashmap *map; |
|
struct hashmap_entry *next; |
|
unsigned int tablepos; |
|
}; |
|
|
|
/* hashmap functions */ |
|
|
|
extern void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, |
|
size_t initial_size); |
|
extern void hashmap_free(struct hashmap *map, int free_entries); |
|
|
|
/* hashmap_entry functions */ |
|
|
|
static inline void hashmap_entry_init(void *entry, unsigned int hash) |
|
{ |
|
struct hashmap_entry *e = entry; |
|
e->hash = hash; |
|
e->next = NULL; |
|
} |
|
extern void *hashmap_get(const struct hashmap *map, const void *key, |
|
const void *keydata); |
|
extern void *hashmap_get_next(const struct hashmap *map, const void *entry); |
|
extern void hashmap_add(struct hashmap *map, void *entry); |
|
extern void *hashmap_put(struct hashmap *map, void *entry); |
|
extern void *hashmap_remove(struct hashmap *map, const void *key, |
|
const void *keydata); |
|
|
|
static inline void *hashmap_get_from_hash(const struct hashmap *map, |
|
unsigned int hash, const void *keydata) |
|
{ |
|
struct hashmap_entry key; |
|
hashmap_entry_init(&key, hash); |
|
return hashmap_get(map, &key, keydata); |
|
} |
|
|
|
int hashmap_bucket(const struct hashmap *map, unsigned int hash); |
|
|
|
/* |
|
* Disallow/allow rehashing of the hashmap. |
|
* This is useful if the caller knows that the hashmap |
|
* needs multi-threaded access. The caller is still |
|
* required to guard/lock searches and inserts in a |
|
* manner appropriate to their usage. This simply |
|
* prevents the table from being unexpectedly re-mapped. |
|
* |
|
* If is up to the caller to ensure that the hashmap is |
|
* initialized to a reasonable size to prevent poor |
|
* performance. |
|
* |
|
* When value=1, prevent future rehashes on adds and deleted. |
|
* When value=0, allow future rehahses. This DOES NOT force |
|
* a rehash now. |
|
*/ |
|
static inline void hashmap_disallow_rehash(struct hashmap *map, unsigned value) |
|
{ |
|
map->disallow_rehash = value; |
|
} |
|
|
|
/* hashmap_iter functions */ |
|
|
|
extern void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter); |
|
extern void *hashmap_iter_next(struct hashmap_iter *iter); |
|
static inline void *hashmap_iter_first(struct hashmap *map, |
|
struct hashmap_iter *iter) |
|
{ |
|
hashmap_iter_init(map, iter); |
|
return hashmap_iter_next(iter); |
|
} |
|
|
|
/* string interning */ |
|
|
|
extern const void *memintern(const void *data, size_t len); |
|
static inline const char *strintern(const char *string) |
|
{ |
|
return memintern(string, strlen(string)); |
|
} |
|
|
|
#endif
|
|
|