1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, 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 (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * General purpose hash table implementation.
32 * Just uses the util_hash for now, but it might be better switch to a linear
33 * probing hash table implementation at some point -- as it is said they have
34 * better lookup and cache performance and it appears to be possible to write
35 * a lock-free implementation of such hash tables .
37 * @author José Fonseca <jfonseca@vmware.com>
42 #include "util_hash_table.h"
43 #include "util_hash.h"
48 struct util_hash_table
50 struct util_hash *head;
53 unsigned (*make_hash)(void *key);
55 /** Compare two keys */
56 int (*compare)(void *key1, void *key2);
59 struct util_hash_table_item
66 static struct util_hash_table_item *
67 util_hash_table_item(struct util_hash_iter iter)
69 return (struct util_hash_table_item *)util_hash_iter_data(iter);
72 struct util_hash_table *util_hash_table_create(unsigned (*hash)(void *key),
73 int (*compare)(void *key1, void *key2))
75 struct util_hash_table *ht;
77 ht = malloc(sizeof(struct util_hash_table));
81 ht->head = util_hash_create();
88 ht->compare = compare;
93 static struct util_hash_iter
94 util_hash_table_find_iter(struct util_hash_table *ht,
95 void *key, unsigned key_hash)
97 struct util_hash_iter iter;
98 struct util_hash_table_item *item;
100 iter = util_hash_find(ht->head, key_hash);
101 while (!util_hash_iter_is_null(iter)) {
102 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
103 if (!ht->compare(item->key, key))
105 iter = util_hash_iter_next(iter);
111 static struct util_hash_table_item *
112 util_hash_table_find_item(struct util_hash_table *ht,
113 void *key, unsigned key_hash)
115 struct util_hash_iter iter;
116 struct util_hash_table_item *item;
118 iter = util_hash_find(ht->head, key_hash);
119 while (!util_hash_iter_is_null(iter)) {
120 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
121 if (!ht->compare(item->key, key))
123 iter = util_hash_iter_next(iter);
129 void util_hash_table_set(struct util_hash_table *ht, void *key, void *value)
132 struct util_hash_table_item *item;
133 struct util_hash_iter iter;
139 key_hash = ht->make_hash(key);
141 item = util_hash_table_find_item(ht, key, key_hash);
143 /* TODO: key/value destruction? */
148 item = malloc(sizeof(struct util_hash_table_item));
155 iter = util_hash_insert(ht->head, key_hash, item);
156 if(util_hash_iter_is_null(iter)) {
162 void *util_hash_table_get(struct util_hash_table *ht, void *key)
165 struct util_hash_table_item *item;
171 key_hash = ht->make_hash(key);
173 item = util_hash_table_find_item(ht, key, key_hash);
180 void util_hash_table_remove(struct util_hash_table *ht, void *key)
183 struct util_hash_iter iter;
184 struct util_hash_table_item *item;
190 key_hash = ht->make_hash(key);
192 iter = util_hash_table_find_iter(ht, key, key_hash);
193 if(util_hash_iter_is_null(iter))
196 item = util_hash_table_item(iter);
200 util_hash_erase(ht->head, iter);
203 void util_hash_table_clear(struct util_hash_table *ht)
205 struct util_hash_iter iter;
206 struct util_hash_table_item *item;
212 iter = util_hash_first_node(ht->head);
213 while (!util_hash_iter_is_null(iter)) {
214 item = (struct util_hash_table_item *)util_hash_take(ht->head, util_hash_iter_key(iter));
216 iter = util_hash_first_node(ht->head);
220 void util_hash_table_foreach(struct util_hash_table *ht,
221 void (*callback)(void *key, void *value, void *data),
224 struct util_hash_iter iter;
225 struct util_hash_table_item *item;
231 iter = util_hash_first_node(ht->head);
232 while (!util_hash_iter_is_null(iter)) {
233 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
234 callback(item->key, item->value, data);
235 iter = util_hash_iter_next(iter);
239 void util_hash_table_destroy(struct util_hash_table *ht)
241 struct util_hash_iter iter;
242 struct util_hash_table_item *item;
248 iter = util_hash_first_node(ht->head);
249 while (!util_hash_iter_is_null(iter)) {
250 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
252 iter = util_hash_iter_next(iter);
255 util_hash_delete(ht->head);