bfe221b242f472771565faccad3a52db68e5ab03
[mesa.git] / src / mesa / program / hash_table.h
1 /*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file hash_table.h
26 * \brief Implementation of a generic, opaque hash table data type.
27 *
28 * \author Ian Romanick <ian.d.romanick@intel.com>
29 */
30
31 #ifndef HASH_TABLE_H
32 #define HASH_TABLE_H
33
34 #include <string.h>
35 #include <stdint.h>
36 #include <limits.h>
37 #include <assert.h>
38
39 struct hash_table;
40 struct string_to_uint_map;
41
42 typedef unsigned (*hash_func_t)(const void *key);
43 typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
44
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48
49 /**
50 * Hash table constructor
51 *
52 * Creates a hash table with the specified number of buckets. The supplied
53 * \c hash and \c compare routines are used when adding elements to the table
54 * and when searching for elements in the table.
55 *
56 * \param num_buckets Number of buckets (bins) in the hash table.
57 * \param hash Function used to compute hash value of input keys.
58 * \param compare Function used to compare keys.
59 */
60 extern struct hash_table *hash_table_ctor(unsigned num_buckets,
61 hash_func_t hash, hash_compare_func_t compare);
62
63
64 /**
65 * Release all memory associated with a hash table
66 *
67 * \warning
68 * This function cannot release memory occupied either by keys or data.
69 */
70 extern void hash_table_dtor(struct hash_table *ht);
71
72
73 /**
74 * Flush all entries from a hash table
75 *
76 * \param ht Table to be cleared of its entries.
77 */
78 extern void hash_table_clear(struct hash_table *ht);
79
80
81 /**
82 * Search a hash table for a specific element
83 *
84 * \param ht Table to be searched
85 * \param key Key of the desired element
86 *
87 * \return
88 * The \c data value supplied to \c hash_table_insert when the element with
89 * the matching key was added. If no matching key exists in the table,
90 * \c NULL is returned.
91 */
92 extern void *hash_table_find(struct hash_table *ht, const void *key);
93
94
95 /**
96 * Add an element to a hash table
97 *
98 * \warning
99 * If \c key is already in the hash table, it will be added again. Future
100 * calls to \c hash_table_find and \c hash_table_remove will return or remove,
101 * repsectively, the most recently added instance of \c key.
102 *
103 * \sa hash_table_replace
104 */
105 extern void hash_table_insert(struct hash_table *ht, void *data,
106 const void *key);
107
108 /**
109 * Add an element to a hash table with replacement
110 *
111 * \warning
112 * If \c key is already in the hash table, \c data will \b replace the most
113 * recently inserted \c data (see the warning in \c hash_table_insert) for
114 * that key.
115 *
116 * \sa hash_table_insert
117 */
118 extern void hash_table_replace(struct hash_table *ht, void *data,
119 const void *key);
120
121 /**
122 * Remove a specific element from a hash table.
123 */
124 extern void hash_table_remove(struct hash_table *ht, const void *key);
125
126 /**
127 * Compute hash value of a string
128 *
129 * Computes the hash value of a string using the DJB2 algorithm developed by
130 * Professor Daniel J. Bernstein. It was published on comp.lang.c once upon
131 * a time. I was unable to find the original posting in the archives.
132 *
133 * \param key Pointer to a NUL terminated string to be hashed.
134 *
135 * \sa hash_table_string_compare
136 */
137 extern unsigned hash_table_string_hash(const void *key);
138
139
140 /**
141 * Compare two strings used as keys
142 *
143 * This is just a macro wrapper around \c strcmp.
144 *
145 * \sa hash_table_string_hash
146 */
147 #define hash_table_string_compare ((hash_compare_func_t) strcmp)
148
149
150 /**
151 * Compute hash value of a pointer
152 *
153 * \param key Pointer to be used as a hash key
154 *
155 * \note
156 * The memory pointed to by \c key is \b never accessed. The value of \c key
157 * itself is used as the hash key
158 *
159 * \sa hash_table_pointer_compare
160 */
161 unsigned
162 hash_table_pointer_hash(const void *key);
163
164
165 /**
166 * Compare two pointers used as keys
167 *
168 * \sa hash_table_pointer_hash
169 */
170 int
171 hash_table_pointer_compare(const void *key1, const void *key2);
172
173 void
174 hash_table_call_foreach(struct hash_table *ht,
175 void (*callback)(const void *key,
176 void *data,
177 void *closure),
178 void *closure);
179
180 struct string_to_uint_map *
181 string_to_uint_map_ctor();
182
183 void
184 string_to_uint_map_dtor(struct string_to_uint_map *);
185
186
187 #ifdef __cplusplus
188 }
189
190 /**
191 * Map from a string (name) to an unsigned integer value
192 *
193 * \note
194 * Because of the way this class interacts with the \c hash_table
195 * implementation, values of \c UINT_MAX cannot be stored in the map.
196 */
197 struct string_to_uint_map {
198 public:
199 string_to_uint_map()
200 {
201 this->ht = hash_table_ctor(0, hash_table_string_hash,
202 hash_table_string_compare);
203 }
204
205 ~string_to_uint_map()
206 {
207 hash_table_dtor(this->ht);
208 }
209
210 /**
211 * Get the value associated with a particular key
212 *
213 * \return
214 * If \c key is found in the map, \c true is returned. Otherwise \c false
215 * is returned.
216 *
217 * \note
218 * If \c key is not found in the table, \c value is not modified.
219 */
220 bool get(unsigned &value, const char *key)
221 {
222 const intptr_t v =
223 (intptr_t) hash_table_find(this->ht, (const void *) key);
224
225 if (v == 0)
226 return false;
227
228 value = (unsigned)(v - 1);
229 return true;
230 }
231
232 void put(unsigned value, const char *key)
233 {
234 /* The low-level hash table structure returns NULL if key is not in the
235 * hash table. However, users of this map might want to store zero as a
236 * valid value in the table. Bias the value by +1 so that a
237 * user-specified zero is stored as 1. This enables ::get to tell the
238 * difference between a user-specified zero (returned as 1 by
239 * hash_table_find) and the key not in the table (returned as 0 by
240 * hash_table_find).
241 *
242 * The net effect is that we can't store UINT_MAX in the table. This is
243 * because UINT_MAX+1 = 0.
244 */
245 assert(value != UINT_MAX);
246 hash_table_replace(ht, (void *) (intptr_t) (value + 1), key);
247 }
248
249 private:
250 struct hash_table *ht;
251 };
252
253 #endif /* __cplusplus */
254 #endif /* HASH_TABLE_H */