2 * shl - Dynamic Hashtable
4 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * A dynamic hash table implementation
30 #ifndef SHL_HASHTABLE_H
31 #define SHL_HASHTABLE_H
37 #include "external/htable.h"
41 typedef unsigned int (*shl_hash_cb) (const void *data);
42 typedef bool (*shl_equal_cb) (const void *data1, const void *data2);
43 typedef void (*shl_free_cb) (void *data);
45 struct shl_hashentry {
50 struct shl_hashtable {
53 shl_equal_cb equal_cb;
55 shl_free_cb free_value;
58 static inline unsigned int shl_direct_hash(const void *data)
60 return (unsigned int)(unsigned long)data;
63 static inline bool shl_direct_equal(const void *data1, const void *data2)
65 return data1 == data2;
68 static size_t shl_rehash(const void *ele, void *priv)
70 struct shl_hashtable *tbl = priv;
71 const struct shl_hashentry *ent = ele;
73 return tbl->hash_cb(ent->key);
76 static inline int shl_hashtable_new(struct shl_hashtable **out,
78 shl_equal_cb equal_cb,
80 shl_free_cb free_value)
82 struct shl_hashtable *tbl;
84 if (!out || !hash_cb || !equal_cb)
87 tbl = malloc(sizeof(*tbl));
90 memset(tbl, 0, sizeof(*tbl));
91 tbl->hash_cb = hash_cb;
92 tbl->equal_cb = equal_cb;
93 tbl->free_key = free_key;
94 tbl->free_value = free_value;
96 htable_init(&tbl->tbl, shl_rehash, tbl);
102 static inline void shl_hashtable_free(struct shl_hashtable *tbl)
104 struct htable_iter i;
105 struct shl_hashentry *entry;
110 for (entry = htable_first(&tbl->tbl, &i);
112 entry = htable_next(&tbl->tbl, &i)) {
113 htable_delval(&tbl->tbl, &i);
115 tbl->free_key(entry->key);
117 tbl->free_value(entry->value);
121 htable_clear(&tbl->tbl);
125 static inline int shl_hashtable_insert(struct shl_hashtable *tbl, void *key,
128 struct shl_hashentry *entry;
134 entry = malloc(sizeof(*entry));
138 entry->value = value;
140 hash = tbl->hash_cb(key);
142 if (!htable_add(&tbl->tbl, hash, entry)) {
150 static inline void shl_hashtable_remove(struct shl_hashtable *tbl, void *key)
152 struct htable_iter i;
153 struct shl_hashentry *entry;
159 hash = tbl->hash_cb(key);
161 for (entry = htable_firstval(&tbl->tbl, &i, hash);
163 entry = htable_nextval(&tbl->tbl, &i, hash)) {
164 if (tbl->equal_cb(key, entry->key)) {
165 htable_delval(&tbl->tbl, &i);
167 tbl->free_key(entry->key);
169 tbl->free_value(entry->value);
176 static inline bool shl_hashtable_find(struct shl_hashtable *tbl, void **out,
179 struct htable_iter i;
180 struct shl_hashentry *entry;
186 hash = tbl->hash_cb(key);
188 for (entry = htable_firstval(&tbl->tbl, &i, hash);
190 entry = htable_nextval(&tbl->tbl, &i, hash)) {
191 if (tbl->equal_cb(key, entry->key)) {
201 #endif /* SHL_HASHTABLE_H */