1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // https://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
13 * Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk>
15 * Permission is hereby granted, free of charge, to any person obtaining a copy
16 * of this software and associated documentation files (the "Software"), to
17 * deal in the Software without restriction, including without limitation the
18 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
19 * sell copies of the Software, and to permit persons to whom the Software is
20 * furnished to do so, subject to the following conditions:
22 * The above copyright notice and this permission notice shall be included in
23 * all copies of the Software and its documentation and acknowledgment shall be
24 * given in the documentation and software packages that this Software was
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
31 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 * struct hashtable *h;
43 * struct some_value *v;
45 * static unsigned int hash_from_key_fn( void *k );
46 * static int keys_equal_fn ( void *key1, void *key2 );
48 * h = create_hashtable(16, 0.75, hash_from_key_fn, keys_equal_fn, free, free);
49 * k = (struct some_key *) malloc(sizeof(struct some_key));
50 * v = (struct some_value *) malloc(sizeof(struct some_value));
52 * (initialise k and v to suitable values)
54 * if (! hashtable_insert(h,k,v) )
57 * if (NULL == (found = hashtable_search(h,k) ))
58 * { printf("not found!"); }
60 * if (NULL == (found = hashtable_remove(h,k) ))
61 * { printf("Not found\n"); }
65 /* Macros may be used to define type-safe(r) hashtable access functions, with
66 * methods specialized to take known key and value types as parameters.
70 * Insert this at the start of your file:
72 * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
73 * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
74 * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
76 * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
77 * These operate just like hashtable_insert etc., with the same parameters,
78 * but their function signatures have 'struct some_key *' rather than
79 * 'void *', and hence can generate compile time errors if your program is
80 * supplying incorrect data as a key (and similarly for value).
82 * Note that the hash and key equality functions passed to create_hashtable
83 * still take 'void *' parameters instead of 'some key *'. This shouldn't be
84 * a difficult issue as they're only defined and passed once, and the other
85 * functions will ensure that only valid keys are supplied to them.
87 * The cost for this checking is increased code size and runtime overhead
88 * - if performance is important, it may be worth switching back to the
89 * unsafe methods once your program has been debugged with the safe methods.
90 * This just requires switching to some simple alternative defines - eg:
91 * #define insert_some hashtable_insert
96 /*****************************************************************************/
106 unsigned int tablelength;
107 struct entry **table;
108 unsigned int entrycount;
109 unsigned int loadlimit;
110 unsigned int (*hashfn) (void *k);
111 int (*eqfn) (void *k1, void *k2);
112 void (*freekfn) (void *k);
113 void (*freevfn) (void *v);
116 /*****************************************************************************/
124 typedef struct hashtable HashTable;
127 /*****************************************************************************
128 * create_hashtable_ext
130 * @name create_hashtable
131 * @param minsize minimum initial size of hashtable
132 * @param maxloadfactor maximum ratio entries / tablesize
133 * @param hashfunction function for hashing keys
134 * @param key_eq_fn function for determining key equality
135 * @param key_free_fn function for freeing keys
136 * @param value_free_fn function for freeing values
137 * @return newly created hashtable or NULL on failure
141 create_hashtable_ext(unsigned int minsize, float maxloadfactor,
142 unsigned int (*hashfunction) (void*),
143 int (*key_eq_fn) (void*, void*),
144 void (*key_free_fn) (void*),
145 void (*value_free_fn) (void*));
147 /* wrapper function using reasonable default values for some parameters */
149 create_hashtable(unsigned int (*hashfunction) (void*),
150 int (*key_eq_fn) (void*, void*),
151 void (*key_free_fn) (void*),
152 void (*value_free_fn) (void*));
154 /*****************************************************************************
157 * @name hashtable_insert
158 * @param h the hashtable to insert into
159 * @param k the key - will be freed on removal if free function defined
160 * @param v the value - will be freed on removal if free function defined
161 * @return non-zero for successful insertion
163 * This function will cause the table to expand if the insertion would take
164 * the ratio of entries to table size over the maximum load factor.
166 * This function does not check for repeated insertions with a duplicate key.
167 * The value returned when using a duplicate key is undefined -- when
168 * the hashtable changes size, the order of retrieval of duplicate key
169 * entries is reversed.
170 * If in doubt, remove before insert.
174 hashtable_insert(struct hashtable *h, void *k, void *v);
176 #define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
177 static int fnname (struct hashtable *h, keytype *k, valuetype *v) \
179 return hashtable_insert(h, k, v); \
182 /*****************************************************************************
185 * @name hashtable_change
186 * @param h the hashtable to search
187 * @param k the key of the entry to change
188 * @param v the new value
189 * @return non-zero for successful change
193 hashtable_change(struct hashtable *h, void *k, void *v);
195 #define DEFINE_HASHTABLE_CHANGE(fnname, keytype, valuetype) \
196 static int fnname (struct hashtable *h, keytype *k, valuetype *v) \
198 return hashtable_change(h, k, v); \
201 /*****************************************************************************
204 * @name hashtable_exists
205 * @param h the hashtable to search
206 * @param k the key to search for
207 * @return non-zero if key exists, else zero
211 hashtable_exists(struct hashtable *h, void *k);
213 #define DEFINE_HASHTABLE_EXISTS(fnname, keytype, valuetype) \
214 static int fnname (struct hashtable *h, keytype *k) \
216 return hashtable_exists(h, k); \
219 /*****************************************************************************
222 * @name hashtable_search
223 * @param h the hashtable to search
224 * @param k the key to search for
225 * @return the value associated with the key, or NULL if none found
229 hashtable_search(struct hashtable *h, void *k);
231 #define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
232 static valuetype * fnname (struct hashtable *h, keytype *k) \
234 return (valuetype *) (hashtable_search(h, k)); \
237 /*****************************************************************************
240 * @name hashtable_remove
241 * @param h the hashtable to remove the item from
242 * @param k the key to search for
243 * @return the value associated with the key, or NULL if none found
246 void * /* returns value */
247 hashtable_remove(struct hashtable *h, void *k);
249 #define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
250 static valuetype * fnname (struct hashtable *h, keytype *k) \
252 return (valuetype *) (hashtable_remove(h, k)); \
256 /*****************************************************************************
259 * @name hashtable_count
260 * @return the number of items stored in the hashtable
263 hashtable_count(struct hashtable *h);
266 /*****************************************************************************
269 * @name hashtable_destroy
273 hashtable_destroy(struct hashtable *h);
276 /*****************************************************************************/
277 /* hashtable_iterator
280 struct hashtable_itr *
281 hashtable_iterator(struct hashtable *h);
283 /*****************************************************************************/
284 /* key - return the key of the (key, value) pair at the current position */
287 hashtable_iterator_key(struct hashtable_itr *i);
289 /*****************************************************************************/
290 /* value - return the value of the (key, value) pair at the current position */
293 hashtable_iterator_value(struct hashtable_itr *i);
295 /*****************************************************************************/
296 /* advance - advance the iterator to the next element
297 * returns zero if advanced to end of table */
300 hashtable_iterator_advance(struct hashtable_itr *itr);
303 /*****************************************************************************/
304 /* hashtable_fn - prototype of function to call for hashtable entry
307 * @param k the key of the current hash entry
308 * @param v the value of the current hash entry
309 * @param u additional user data
312 typedef void (*hashtable_fn) (void *k, void *v, void *u);
314 /*****************************************************************************/
315 /* hashtable_foreach - call function for all hashtable entries
317 * @name hashtable_foreach
318 * @param h the hashtable to iterate through
319 * @param fn the function to call for each entry
323 hashtable_foreach(struct hashtable *h, hashtable_fn fn, void *userdata);
325 /*****************************************************************************/
326 /* hashtable_remove_fn - prototype of function to call for hashtable entry
328 * @name hashtable_remove_fn
329 * @param k the key of the current hash entry
330 * @param v the value of the current hash entry
331 * @param u additional user data
332 * @return non-zero if entry should be removed, else zero
335 typedef int (*hashtable_remove_fn) (void *k, void *v, void *u);
337 /*****************************************************************************/
338 /* hashtable_foreach_remove - call function for all hashtable entries and remove them,
339 * if function returned 1
340 * returns the number of removed entries
342 * @name hashtable_foreach_remove
343 * @param h the hashtable to iterate through
344 * @param fn the function to call for each entry
345 * @return the number of removed entries
349 hashtable_foreach_remove(struct hashtable *h, hashtable_remove_fn fn, void *userdata);
351 /*****************************************************************************/
352 /* hashtable_remove_all - remove_all hashtable entries
354 * @name hashtable_remove
355 * @param h the hashtable to remove all entries from
356 * @return the number of removed entries
360 hashtable_remove_all(struct hashtable *h);