1 
2 #include "taisei.h"
3 
4 #include "hashtable.h"
5 #include "list.h"
6 #include "util/stringops.h"
7 #include "util/assert.h"
8 #include "log.h"
9 
10 #include <SDL.h>
11 
12 /******************************************************************************\
13  *                                      ,.                                    *
14  *    ```             `.,:::,.    `;'';,;'.`                                  *
15  *   `,`,;'''''';.+###############''''''' ,.`                                 *
16  *  ,.''.:''''+@@####################'';,' `:                                 *
17  *  ,`',;'''+#@@#########################++;,                                 *
18  *   :,';+++@@#############################:,:                                *
19  *  .::,;++@@###############################;                                 *
20  *  .,:+;+,,,:+##@##########@##############+:,                                *
21  *   +,:+#@@##'::::++#######@###@##@##+'::,;'#`                               *
22  *   @++:@@@@@#@@@@###@#@##@##'@@##@@##@@@##@##                               *
23  *  .+'++@@@@##@@@@#@#@@#+#@@#:'@##@@@@@#@#@@##                               *
24  * .,+;+'+@@@##@@@@@+@+@@;';@@.`:#@;';@##@#@#@@#,                             *
25  * :#:+'+@@@#@@@@@:+;:@::':@,``.:@,+::@:@#@@#@#;                              *
26  *  '::+'@@@@@@@@#`,+`++';.`````:``+++,+:@@@.;@;                              *
27  *  +@'+;@@@@#:,;;,`, ''';`````````+''+:.';.: '`                              *
28  *  +@@@@@@@#:+',:`.,,.````````````.,,,.,:''.                                 *
29  *  '@@@@@@@':'+'+`....```````````````...:'+   Type-safe generics? In my C?   *
30  *  ;@@@@@@@':'+''`````````.`````````````,'+                                  *
31  *  :#@@@@@@@:'+''`````````::::''````````:;; It's more likely than you think. *
32  *  .;@@@@@@@@++,'`````````'::::.````````;:`:                                 *
33  *   .@@#@@@@#;'.:.`````````':'``````````@.:                                  *
34  *   ,#@,@@;@##@##``````````````````````@@#,        [FREE HEADER CHECK]       *
35  *   :.@ +# @##@@# :``````````````````;@:@@:                                  *
36  *     # '``.@:,##   :`````````````.+@#,..@:                                  *
37  *       `   '`  @      `::,,,:::` ` +; . ;'                                  *
38  *                :                        +                                  *
39 \******************************************************************************/
40 
41 /***********************\
42  * User-defined macros *
43 \***********************/
44 
45 /*
46  * HT_SUFFIX
47  *
48  * A name tag associated with your custom hashtable type.
49  * You must define this to a valid, unique identifier.
50  * Whenever you see XXX appear as part of an identifier in the documentation,
51  * substitute it for the value of HT_SUFFIX.
52  *
53  * Example:
54  *
55  *         #define HT_SUFFIX str2ptr
56  */
57 #ifndef HT_SUFFIX
58 	#error HT_SUFFIX not defined
59 #endif
60 
61 /*
62  * HT_KEY_TYPE
63  *
64  * The type of hashtable keys. This may be virtually anything, except for
65  * incomplete types. It is possible to use a pointer to a heap-allocated
66  * data structure here that is to be used as the actual key (see below). This
67  * is useful if you want to use strings, for example.
68  *
69  * Example:
70  *
71  *         #define HT_KEY_TYPE char*
72  */
73 #ifndef HT_KEY_TYPE
74 	#error HT_KEY_TYPE not defined
75 #endif
76 
77 /*
78  * HT_KEY_CONST
79  *
80  * Optional.
81  *
82  * If defined, the 'const' qualifier will be prepended to the key type where
83  * appropriate. Useful for pointer types.
84  */
85 #ifdef HT_KEY_CONST
86 	#undef HT_KEY_CONST
87 	#define HT_KEY_CONST const
88 #else
89 	#define HT_KEY_CONST
90 #endif
91 
92 /*
93  * HT_KEY_TYPE
94  *
95  * The type of hashtable keys. This must be a complete, non-array type.
96  *
97  * Example:
98  *
99  *         #define HT_VALUE_TYPE void*
100  */
101 #ifndef HT_VALUE_TYPE
102 	#error HT_VALUE_TYPE not defined
103 #endif
104 
105 /*
106  * HT_FUNC_HASH_KEY(key)
107  *
108  * A function-like macro used to compute an integer hash based on key. It must
109  * produce consistent results for every possible key, and collisions should be
110  * minimized to improve performance.
111  *
112  * Type of the key parameter is the same as HT_KEY_TYPE.
113  * Type of the result expression should be hash_t.
114  *
115  * Example:
116  *
117  *         #define HT_FUNC_HASH_KEY(key) htutil_hashfunc_string(key)
118  */
119 #ifndef HT_FUNC_HASH_KEY
120 	#error HT_FUNC_HASH_KEY not defined
121 #endif
122 
123 /*
124  * HT_FUNC_KEYS_EQUAL(key1, key2)
125  *
126  * Optional.
127  *
128  * A function-like macro used to test two keys for equality. Note that if two
129  * keys are considered equal, they must also hash to the same value. However,
130  * the converse doesn't apply: equality of hashes doesn't imply equality of keys.
131  *
132  * Type of the key1 and key2 parameters is the same as HT_KEY_TYPE.
133  * The result expression must be true if the keys are equal, false otherwise.
134  *
135  * If no definition is provided, the standard == operator is used.
136  *
137  * Example:
138  *
139  *         #define HT_FUNC_KEYS_EQUAL(key1, key2) (!strcmp(key1, key2))
140  */
141 #ifndef HT_FUNC_KEYS_EQUAL
142 	#define HT_FUNC_KEYS_EQUAL(key1, key2) ((key1) == (key2))
143 #endif
144 
145 /*
146  * HT_FUNC_COPY_KEY(dst, src)
147  *
148  * Optional.
149  *
150  * A function-like macro that specifies how copying a key should be handled.
151  * This is useful with pointers to variably-sized structures, such as strings.
152  *
153  * Type of src is the same as HT_KEY_TYPE.
154  * dst is a pointer to HT_KEY_TYPE.
155  * Type of the result expression is ignored.
156  *
157  * If no definition is provided, the key is simply copied by value.
158  *
159  * Example:
160  *
161  *        #define HT_FUNC_COPY_KEY(dst, src) (*(dst) = strdup(src))
162  */
163 #ifndef HT_FUNC_COPY_KEY
164 	#define HT_FUNC_COPY_KEY(dst, src) (*(dst) = (src))
165 #endif
166 
167 /*
168  * HT_FUNC_FREE_KEY(key)
169  *
170  * Optional.
171  *
172  * A function-like macro used to free any resources allocated for a key, if any.
173  * Use this to clean up after after any allocations done by HT_FUNC_COPY_KEY.
174  *
175  * Example:
176  *
177  *        #define HT_FUNC_FREE_KEY(key) free(key)
178  */
179 #ifndef HT_FUNC_FREE_KEY
180 	#define HT_FUNC_FREE_KEY(key) ((void)(key))
181 #endif
182 
183 /*
184  * HT_THREAD_SAFE
185  *
186  * Optional.
187  *
188  * If defined, most hashtable operations will be guarded by a readers-writer lock,
189  * protecting them from data races when used by multiple threads. This has some
190  * impact on performance and memory usage, however.
191  *
192  * Some additional APIs are provided in this mode, as well as unsafe versions of
193  * some of the core APIs. They are documented below.
194  *
195  * The unsafe variants behave identically to their core counterparts, but they
196  * completely bypass the locking mechanism, making them somewhat faster.
197  *
198  * Example:
199  *
200  *        #define HT_THREAD_SAFE
201  */
202 #ifndef HT_THREAD_SAFE
203 	// no default needed
204 #endif
205 
206 /*
207  * HT_DECL, HT_IMPL
208  *
209  * You must define at least one of these macros.
210  *
211  * If HT_DECL is defined, this header will generate declarations of the API types
212  * and functions. This should be used in headers.
213  *
214  * If HT_IMPL is defined, this header will generate definitions of the API functions.
215  *
216  *  * Example:
217  *
218  *        #define HT_IMPL
219  *        #include "hashtable.inc.h"
220  */
221 #if !defined(HT_DECL) && !defined(HT_IMPL)
222 	#error neither HT_DECL nor HT_IMPL defined
223 #endif
224 
225 /*
226  * HT_MIN_SIZE
227  *
228  * Optional.
229  *
230  * How many buckets to allocate initially. Higher values increase memory usage,
231  * but may improve performance. Must be a power of 2.
232  */
233 #ifndef HT_MIN_SIZE
234 	#define HT_MIN_SIZE 4
235 #endif
236 
237 static_assert((HT_MIN_SIZE & (~HT_MIN_SIZE + 1)) == HT_MIN_SIZE, "HT_MIN_SIZE must be power of two");
238 
239 /*
240  * The following macros comprise the core of the templating machinery.
241  * They are used to construct identifiers augmented with HT_SUFFIX.
242  */
243 
244 #define _HT_NAME_INNER1(suffix, name) ht_##suffix##name
245 #define _HT_NAME_INNER2(suffix, name) _HT_NAME_INNER1(suffix, name)
246 #define HT_NAME(name) _HT_NAME_INNER2(HT_SUFFIX, name)
247 
248 #define _HT_PRIV_NAME_INNER1(suffix, name) _ht_##suffix##name
249 #define _HT_PRIV_NAME_INNER2(suffix, name) _HT_PRIV_NAME_INNER1(suffix, name)
250 #define HT_PRIV_NAME(name) _HT_PRIV_NAME_INNER2(HT_SUFFIX, name)
251 
252 #define HT_TYPE(name) HT_NAME(_##name##_t)
253 #define HT_FUNC(name) HT_NAME(_##name)
254 #define HT_PRIV_FUNC(name) HT_PRIV_NAME(_##name)
255 #define HT_BASETYPE HT_NAME(_t)
256 
257 #define HT_DECLARE_FUNC(return_type, name, arguments) return_type HT_FUNC(name) arguments
258 #define HT_DECLARE_PRIV_FUNC(return_type, name, arguments) static return_type HT_PRIV_FUNC(name) arguments
259 
260 /****************\
261  * Declarations *
262 \****************/
263 #ifdef HT_DECL
264 
265 /*
266  * ht_XXX_t
267  *
268  * A structure representing a hash table.
269  * All its fields are considered private and should be left unmolested,
270  * please use the API functiosn instead of manipulating these directly.
271  */
272 typedef struct HT_BASETYPE HT_BASETYPE;
273 
274 /*
275  * ht_XXX_key_t
276  *
277  * An alias for the key type (HT_KEY_TYPE).
278  */
279 typedef HT_KEY_TYPE HT_TYPE(key);
280 
281 /*
282  * ht_XXX_const_key_t
283  *
284  * An alias for the key type (HT_KEY_TYPE).
285  *
286  * If HT_KEY_CONST is defined, this type has the 'const' qualifier.
287  */
288 typedef HT_KEY_CONST HT_KEY_TYPE HT_TYPE(const_key);
289 
290 /*
291  * ht_XXX_value_t
292  *
293  * An alias for the value type (HT_VALUE_TYPE).
294  */
295 typedef HT_VALUE_TYPE HT_TYPE(value);
296 
297 /*
298  * ht_XXX_key_list_t
299  *
300  * A list of keys.
301  */
302 typedef struct HT_TYPE(key_list) HT_TYPE(key_list);
303 
304 /*
305  * ht_XXX_foreach_callback_t
306  *
307  * Pointer to a callback function for use with ht_XXX_foreach().
308  */
309 typedef void* (*HT_TYPE(foreach_callback))(HT_TYPE(const_key) key, HT_TYPE(value) data, void *arg);
310 
311 /*
312  * ht_XXX_iter_t
313  *
314  * An iterator structure. See ht_XXX_iter_begin().
315  */
316 typedef struct HT_TYPE(iter) HT_TYPE(iter);
317 
318 /*
319  * Forward declaration of the private element struct.
320  */
321 typedef struct HT_TYPE(element) HT_TYPE(element);
322 
323 /*
324  * Definition for ht_XXX_key_list_t.
325  */
326 struct HT_TYPE(key_list) {
327 	LIST_INTERFACE(HT_TYPE(key_list));
328 	HT_TYPE(key) key;
329 };
330 
331 /*
332  * Definition for ht_XXX_t.
333  * All of these fields are to be considered private.
334  */
335 struct HT_BASETYPE {
336 	HT_TYPE(element) *elements;
337 	ht_size_t num_elements_occupied;
338 	ht_size_t num_elements_allocated;
339 	ht_size_t max_psl;
340 	hash_t hash_mask;
341 
342 #ifdef HT_THREAD_SAFE
343 	struct {
344 		SDL_mutex *mutex;
345 		SDL_cond *cond;
346 		uint readers;
347 		bool writing;
348 	} sync;
349 #endif
350 };
351 
352 /*
353  * Definition for ht_XXX_iter_t.
354  */
HT_TYPE(iter)355 struct HT_TYPE(iter) {
356 	HT_BASETYPE *hashtable;
357 	HT_TYPE(key) key;
358 	HT_TYPE(value) value;
359 	bool has_data;
360 
361 	struct {
362 		ht_size_t i;
363 		ht_size_t remaining;
364 	} private;
365 };
366 
367 /*
368  * void ht_XXX_create(ht_XXX_t *ht);
369  *
370  * Initialize a hashtable structure. Must be called before any other API function.
371  */
372 HT_DECLARE_FUNC(void, create, (HT_BASETYPE *ht))
373 	attr_nonnull(1);
374 
375 /*
376  * void ht_XXX_destroy(ht_XXX_t *ht);
377  *
378  * Destroy a hashtable, freeing all resources allocated to it.
379  * Other API functions, except for ht_XXX_create(), must not be called after this.
380  * Does not free the memory pointed to by [ht], as it's not necessarily heap-allocated.
381  */
382 HT_DECLARE_FUNC(void, destroy, (HT_BASETYPE *ht))
383 	attr_nonnull(1);
384 
385 /*
386  * ht_XXX_t* ht_XXX_new(void);
387  *
388  * Convenience function; allocates and initializes a new hashtable structure.
389  * You must free() it manually when you're done with it (but don't forget to
390  * ht_*_destroy() it as well).
391  *
392  * Returns the allocated hashtable structure.
393  */
394 INLINE attr_returns_allocated
395 HT_DECLARE_FUNC(HT_BASETYPE*, new, (void))  {
396 	HT_BASETYPE *ht = calloc(1, sizeof(HT_BASETYPE));
397 	HT_FUNC(create)(ht);
398 	return ht;
399 }
400 
401 #ifdef HT_THREAD_SAFE
402 
403 /*
404  * void ht_XXX_lock(ht_XXX_t *ht);
405  *
406  * Acquire a read lock on a hashtable. The hashtable is guarateed to stay unmodified
407  * while this lock is held. You must not try to modify it from the same thread; that
408  * will result in a deadlock. Other threads are able to read the hashtable while the
409  * lock is held.
410  */
411 HT_DECLARE_FUNC(void, lock, (HT_BASETYPE *ht))
412 	attr_nonnull(1);
413 
414 /*
415  * void ht_XXX_unlock(ht_XXX_t *ht);
416  *
417  * Release a read lock on a hashtable previously acquired via ht_XXX_unlock().
418  */
419 HT_DECLARE_FUNC(void, unlock, (HT_BASETYPE *ht))
420 	attr_nonnull(1);
421 
422 #endif // HT_THREAD_SAFE
423 
424 /*
425  * ht_XXX_value_t ht_XXX_get(ht_XXX_t *ht, ht_XXX_const_key_t key, ht_XXX_const_value_t fallback);
426  *
427  * Retrieve a value associated with [key]. If there is no association, [fallback] will
428  * be returned instead.
429  */
430 HT_DECLARE_FUNC(HT_TYPE(value), get_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) fallback))
431 	attr_nonnull(1);
432 
433 attr_nonnull(1)
HT_TYPE(value)434 INLINE HT_DECLARE_FUNC(HT_TYPE(value), get, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) fallback)) {
435 	return HT_FUNC(get_prehashed)(ht, key, HT_FUNC_HASH_KEY(key), fallback);
436 }
437 
438 #ifdef HT_THREAD_SAFE
439 /*
440  * ht_XXX_value_t ht_XXX_get_unsafe(ht_XXX_t *ht, ht_XXX_const_key_t key, ht_XXX_const_value_t fallback);
441  *
442  * A non-thread-safe version of ht_XXX_get().
443  */
444 HT_DECLARE_FUNC(HT_TYPE(value), get_unsafe_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) fallback))
445 	attr_nonnull(1);
446 
447 attr_nonnull(1)
HT_TYPE(value)448 INLINE HT_DECLARE_FUNC(HT_TYPE(value), get_unsafe, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) fallback)) {
449 	return HT_FUNC(get_unsafe_prehashed)(ht, key, HT_FUNC_HASH_KEY(key), fallback);
450 }
451 
452 #endif // HT_THREAD_SAFE
453 
454 /*
455  * bool ht_XXX_lookup(ht_XXX_t *ht, ht_XXX_const_key_t key, ht_XXX_value_t *out_value);
456  *
457  * Check whether a key exists in the hashtable. If it does and [out_value] is not NULL,
458  * then the value associated with it will be also copied into *out_value.
459  *
460  * Returns true if an entry is found, false otherwise.
461  */
462 HT_DECLARE_FUNC(bool, lookup_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) *out_value))
463 	attr_nonnull(1) attr_nodiscard;
464 
465 attr_nonnull(1) attr_nodiscard
466 INLINE HT_DECLARE_FUNC(bool, lookup, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) *out_value)) {
467 	return HT_FUNC(lookup_prehashed)(ht, key, HT_FUNC_HASH_KEY(key), out_value);
468 }
469 
470 #ifdef HT_THREAD_SAFE
471 /*
472  * bool ht_XXX_lookup_unsafe(ht_XXX_t *ht, ht_XXX_const_key_t key, ht_XXX_value_t *out_value);
473  *
474  * A non-thread-safe version of ht_XXX_lookup().
475  */
476 HT_DECLARE_FUNC(bool, lookup_unsafe_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) *out_value))
477 	attr_nonnull(1) attr_nodiscard;
478 
479 attr_nonnull(1) attr_nodiscard
480 INLINE HT_DECLARE_FUNC(bool, lookup_unsafe, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) *out_value)) {
481 	return HT_FUNC(lookup_unsafe_prehashed)(ht, key, HT_FUNC_HASH_KEY(key), out_value);
482 }
483 
484 #endif // HT_THREAD_SAFE
485 
486 /*
487  * void ht_XXX_set(ht_XXX_t *ht, ht_XXX_const_key_t key, ht_XXX_const_value_t value);
488  *
489  * Store a key-value pair in the hashtable.
490  * If this key already has a value associated with it, it will be overwritten.
491  *
492  * Returns true if a new key was inserted, false if a previous value was overwritten.
493  */
494 HT_DECLARE_FUNC(bool, set, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) value))
495 	attr_nonnull(1);
496 
497 /*
498  * bool ht_XXX_try_set(ht_XXX_t ht, ht_XXX_const_key_t key, ht_XXX_const_value_t value, ht_XXX_value_t (*value_transform)(ht_XXX_value_t), ht_XXX_value_t *out_value);
499  *
500  * See if [key] exists in the hashtable, and then:
501  *
502  * 	if key exists, then:
503  * 		if out_value is not NULL, then:
504  * 			store value associated with key in *out_value;
505  *
506  * 		return false;
507  * 	else:
508  * 		if value_transform is not NULL, then:
509  * 			newValue = value_transform(value);
510  * 		else
511  * 			newValue = value;
512  *
513  * 		if out_value is not NULL, then:
514  * 			store newValue in *out_value;
515  *
516  * 		associate key with newValue;
517  *
518  * 		return true;
519  *
520  * With HT_THREAD_SAFE defined, this is an atomic operation: the algorithm holds
521  * a write lock for its whole duration.
522  */
523 HT_DECLARE_FUNC(bool, try_set_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) value, HT_TYPE(value) (*value_transform)(HT_TYPE(value)), HT_TYPE(value) *out_value))
524 	attr_nonnull(1) attr_nodiscard;
525 
526 INLINE HT_DECLARE_FUNC(bool, try_set, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) value, HT_TYPE(value) (*value_transform)(HT_TYPE(value)), HT_TYPE(value) *out_value)) {
527 	return HT_FUNC(try_set_prehashed)(ht, key, HT_FUNC_HASH_KEY(key), value, value_transform, out_value);
528 }
529 
530 /*
531  * bool ht_XXX_unset(ht_XXX_t *ht, ht_XXX_const_key_t key);
532  *
533  * If there's a value associated with key, remove that association and return true.
534  * Otherwise, return false.
535  */
536 HT_DECLARE_FUNC(bool, unset, (HT_BASETYPE *ht, HT_TYPE(const_key) key))
537 	attr_nonnull(1);
538 
539 /*
540  * void ht_XXX_unset_list(ht_XXX_t *ht, const ht_XXX_key_list_t *keylist);
541  *
542  * Functionally equality to calling ht_XXX_unset() for every key in keylist, but
543  * more efficient.
544  */
545 HT_DECLARE_FUNC(void, unset_list, (HT_BASETYPE *ht, const HT_TYPE(key_list) *key_list))
546 	attr_nonnull(1);
547 
548 /*
549  * void ht_XXX_unset_all(ht_XXX_t *ht);
550  *
551  * Empty the hashtable completely.
552  * Functionally equivalent to calling ht_XXX_unset() for every key in the table,
553  * but more efficient.
554  */
555 HT_DECLARE_FUNC(void, unset_all, (HT_BASETYPE *ht))
556 	attr_nonnull(1);
557 
558 /*
559  * void* ht_XXX_foreach(ht_XXX_t *ht, ht_XXX_callback_t callback, void *arg);
560  *
561  * Call callback(key, value, arg) for each key-value pair in the hashtable.
562  *
563  * If the callback returns anything other than a NULL pointer, the loop is broken
564  * early, and this function returns whatever the callback returned.
565  *
566  * Otherwise, this function returns NULL once every pair has been processed.
567  *
568  * WARNING: Do not try to modify the hashtable from inside the callback.
569  */
570 HT_DECLARE_FUNC(void*, foreach, (HT_BASETYPE *ht, HT_TYPE(foreach_callback) callback, void *arg))
571 	attr_nonnull(1, 2);
572 
573 /*
574  * void ht_XXX_iter_begin(ht_XXX_t *ht, ht_XXX_iter_t *iter);
575  * void ht_XXX_iter_next(ht_XXX_iter_t *iter);
576  * void ht_XXX_iter_end(ht_XXX_iter_t *iter);
577  *
578  * These functions are used to iterate over the key-value pairs stored in the
579  * hashtable without having to provide a callback function.
580  *
581  * Declare a ht_XXX_iter_t structure and use ht_XXX_iter_begin() to initialize it.
582  * Then, if iter->has_data is true, iter->key and iter->value are set to the key
583  * and value of the first pair in the hashtable, respectively.
584  *
585  * While iter->has_data is true, you can call ht_XXX_iter_next() to advance the
586  * iterator to the next pair. If there are no more pairs, ht_XXX_iter_next() sets
587  * iter->has_data to false. Otherwise, iter->key and iter->data are updated.
588  * Calling ht_XXX_iter_next() has no effect if iter->has_data is already false.
589  *
590  * You must call ht_XXX_iter_end() when you are done iterating.
591  *
592  * Example:
593  *
594  * 		ht_XXX_iter_t iter;
595  * 		ht_XXX_iter_begin(&my_hashtable, &iter);
596  *
597  * 		while(iter.has_data) {
598  * 			do_something_with(iter.key, iter.value);
599  *
600  * 			if(some_condition) {
601  * 				break;
602  * 			}
603  *
604  * 			ht_XXX_iter_next(&iter);
605  * 		}
606  *
607  * 		ht_XXX_iter_end(&iter);
608  *
609  * WARNING: Do not try to modify the hashtable while iterating over its contents.
610  *
611  * If HT_THREAD_SAFE is defined, ht_XXX_iter_begin() acquires a read lock, and
612  * ht_XXX_iter_end() releases it. Thus, the hashtable is guarateed to stay
613  * unmodified while any threads have an iterator active.
614  */
615 HT_DECLARE_FUNC(void, iter_begin, (HT_BASETYPE *ht, HT_TYPE(iter) *iter))
616 	attr_nonnull(1, 2);
617 
618 HT_DECLARE_FUNC(void, iter_next, (HT_TYPE(iter) *iter))
619 	attr_nonnull(1);
620 
621 HT_DECLARE_FUNC(void, iter_end, (HT_TYPE(iter) *iter))
622 	attr_nonnull(1);
623 
624 /*
625  * hash_t ht_XXX_hash(ht_XXX_const_key_t key);
626  *
627  * Compute the key's hash, suitable to pass to _prehashed functions.
628  */
629 INLINE HT_DECLARE_FUNC(hash_t, hash, (HT_TYPE(const_key) key)) {
630 	return HT_FUNC_HASH_KEY(key);
631 }
632 
633 #endif // HT_DECL
634 
635 /*******************\
636  * Implementations *
637 \*******************/
638 
639 // #define HT_IMPL
640 #ifdef HT_IMPL
641 
HT_TYPE(element)642 struct HT_TYPE(element) {
643 	HT_TYPE(value) value;
644 	HT_TYPE(key) key;
645 	hash_t hash;
646 };
647 
648 inline
649 HT_DECLARE_PRIV_FUNC(ht_size_t, get_psl, (ht_size_t zero_idx, ht_size_t actual_idx, ht_size_t num_allocated)) {
650 	// returns the probe sequence length from zero_idx to actual_idx
651 
652 	if(actual_idx < zero_idx) {
653 		return num_allocated - zero_idx + actual_idx;
654 	}
655 
656 	return actual_idx - zero_idx;
657 }
658 
659 HT_DECLARE_PRIV_FUNC(ht_size_t, get_element_psl, (HT_BASETYPE *ht, HT_TYPE(element) *e)) {
660 	return HT_PRIV_FUNC(get_psl)(e->hash & ht->hash_mask, e - ht->elements, ht->num_elements_allocated);
661 }
662 
663 HT_DECLARE_PRIV_FUNC(void, dump, (HT_BASETYPE *ht)) {
664 #if 0
665 	log_debug(" -- begin dump of hashtable %p --", (void*)ht);
666 	for(ht_size_t i = 0; i < ht->num_elements_allocated; ++i) {
667 		HT_TYPE(element) *e = ht->elements + i;
668 
669 		if(e->hash & HT_HASH_LIVE_BIT) {
670 			ht_size_t psl = HT_PRIV_FUNC(get_element_psl)(ht, e);
671 			log_debug("%.4i. 0x%08x    [%"HT_KEY_FMT"]  ==>  [%"HT_VALUE_FMT"]    PSL: %u", i, e->hash, HT_KEY_PRINTABLE(e->key), HT_VALUE_PRINTABLE(e->value), psl);
672 			assert(psl <= ht->max_psl);
673 		} else {
674 			log_debug("%.4i. 0x%08x    -- empty --", i, e->hash);
675 		}
676 
677 	}
678 	log_debug("Max PSL: %u", ht->max_psl);
679 	log_debug(" -- end dump of hashtable %p --", (void*)ht);
680 #endif
681 }
682 
683 HT_DECLARE_PRIV_FUNC(void, begin_write, (HT_BASETYPE *ht)) {
684 	#ifdef HT_THREAD_SAFE
685 	SDL_LockMutex(ht->sync.mutex);
686 
687 	while(ht->sync.writing || ht->sync.readers) {
688 		SDL_CondWait(ht->sync.cond, ht->sync.mutex);
689 	}
690 
691 	ht->sync.writing = true;
692 	SDL_UnlockMutex(ht->sync.mutex);
693 	#endif
694 }
695 
696 HT_DECLARE_PRIV_FUNC(void, end_write, (HT_BASETYPE *ht)) {
697 	#ifdef HT_THREAD_SAFE
698 	SDL_LockMutex(ht->sync.mutex);
699 	ht->sync.writing = false;
700 	SDL_CondBroadcast(ht->sync.cond);
701 	SDL_UnlockMutex(ht->sync.mutex);
702 	#endif
703 }
704 
705 HT_DECLARE_PRIV_FUNC(void, begin_read, (HT_BASETYPE *ht)) {
706 	#ifdef HT_THREAD_SAFE
707 	SDL_LockMutex(ht->sync.mutex);
708 
709 	while(ht->sync.writing) {
710 		SDL_CondWait(ht->sync.cond, ht->sync.mutex);
711 	}
712 
713 	++ht->sync.readers;
714 	SDL_UnlockMutex(ht->sync.mutex);
715 	#endif
716 }
717 
718 HT_DECLARE_PRIV_FUNC(void, end_read, (HT_BASETYPE *ht)) {
719 	#ifdef HT_THREAD_SAFE
720 	SDL_LockMutex(ht->sync.mutex);
721 
722 	if(!--ht->sync.readers) {
723 		SDL_CondSignal(ht->sync.cond);
724 	}
725 
726 	SDL_UnlockMutex(ht->sync.mutex);
727 	#endif
728 }
729 
730 #ifdef HT_THREAD_SAFE
731 HT_DECLARE_FUNC(void, lock, (HT_BASETYPE *ht)) {
732 	HT_PRIV_FUNC(begin_read)(ht);
733 }
734 
735 HT_DECLARE_FUNC(void, unlock, (HT_BASETYPE *ht)) {
736 	HT_PRIV_FUNC(end_read)(ht);
737 }
738 #endif // HT_THREAD_SAFE
739 
740 HT_DECLARE_FUNC(void, create, (HT_BASETYPE *ht)) {
741 	ht_size_t size = HT_MIN_SIZE;
742 
743 	ht->elements = calloc(size, sizeof(*ht->elements));
744 	ht->num_elements_allocated = size;
745 	ht->num_elements_occupied = 0;
746 	ht->hash_mask = size - 1;
747 
748 	#ifdef HT_THREAD_SAFE
749 	ht->sync.writing = false;
750 	ht->sync.readers = 0;
751 	ht->sync.mutex = SDL_CreateMutex();
752 	ht->sync.cond = SDL_CreateCond();
753 	#endif
754 }
755 
756 HT_DECLARE_FUNC(void, destroy, (HT_BASETYPE *ht)) {
757 	HT_FUNC(unset_all)(ht);
758 	#ifdef HT_THREAD_SAFE
759 	SDL_DestroyCond(ht->sync.cond);
760 	SDL_DestroyMutex(ht->sync.mutex);
761 	#endif
762 	free(ht->elements);
763 }
764 
HT_TYPE(element)765 HT_DECLARE_PRIV_FUNC(HT_TYPE(element)*, find_element, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash)) {
766 	hash_t hash_mask = ht->hash_mask;
767 	ht_size_t i = hash & hash_mask;
768 	ht_size_t attr_unused zero_idx = i;
769 	ht_size_t probe_len = 0;
770 	ht_size_t max_probe_len = ht->max_psl;
771 	hash |= HT_HASH_LIVE_BIT;
772 
773 	HT_TYPE(element) *elements = ht->elements;
774 
775 	// log_debug("%p %08x [%"HT_KEY_FMT"]", (void*)ht, hash, HT_KEY_PRINTABLE(key));
776 
777 	for(;;) {
778 		HT_TYPE(element) *e = elements + i;
779 		hash_t e_hash = e->hash;
780 		// log_debug("i=%u :: %08x", i, e_hash);
781 
782 		if(e_hash == hash && HT_FUNC_KEYS_EQUAL(key, e->key)) {
783 			// log_debug("found at %u (probe_len = %u)", i, probe_len);
784 			assert(probe_len == HT_PRIV_FUNC(get_element_psl)(ht, e));
785 			return e;
786 		}
787 
788 		if(!(e_hash & HT_HASH_LIVE_BIT)) {
789 			// log_debug("not found (probe_len = %u)", probe_len);
790 			return NULL;
791 		}
792 
793 		ht_size_t e_probe_len = HT_PRIV_FUNC(get_element_psl)(ht, e);
794 		assert(probe_len == HT_PRIV_FUNC(get_psl)(zero_idx, i, ht->num_elements_allocated));
795 
796 		if(probe_len > e_probe_len) {
797 			// log_debug("[%"HT_KEY_FMT"] probe len at %u lower than current (%u < %u), bailing", HT_KEY_PRINTABLE(key), i, e_probe_len, probe_len);
798 			return NULL;
799 		}
800 
801 		if(++probe_len > max_probe_len) {
802 			// log_debug("max PSL reached, bailing (%u)", max_probe_len);
803 			return NULL;
804 		}
805 
806 		i = (i + 1) & hash_mask;
807 	}
808 }
809 
HT_TYPE(value)810 HT_DECLARE_FUNC(HT_TYPE(value), get_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) fallback)) {
811 	assert(hash == HT_FUNC_HASH_KEY(key));
812 	HT_TYPE(value) value;
813 
814 	HT_PRIV_FUNC(begin_read)(ht);
815 	HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, key, hash);
816 	value = e ? e->value : fallback;
817 	HT_PRIV_FUNC(end_read)(ht);
818 
819 	return value;
820 }
821 
822 #ifdef HT_THREAD_SAFE
HT_TYPE(value)823 HT_DECLARE_FUNC(HT_TYPE(value), get_unsafe_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) fallback)) {
824 	assert(hash == HT_FUNC_HASH_KEY(key));
825 	HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, key, hash);
826 	return e ? e->value : fallback;
827 }
828 #endif // HT_THREAD_SAFE
829 
830 HT_DECLARE_FUNC(bool, lookup_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) *out_value)) {
831 	assert(hash == HT_FUNC_HASH_KEY(key));
832 	bool found = false;
833 
834 	HT_PRIV_FUNC(begin_read)(ht);
835 	HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, key, hash);
836 
837 	if(e != NULL) {
838 		if(out_value != NULL) {
839 			*out_value = e->value;
840 		}
841 
842 		found = true;
843 	}
844 
845 	HT_PRIV_FUNC(end_read)(ht);
846 
847 	return found;
848 }
849 
850 #ifdef HT_THREAD_SAFE
851 HT_DECLARE_FUNC(bool, lookup_unsafe_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) *out_value)) {
852 	assert(hash == HT_FUNC_HASH_KEY(key));
853 	HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, key, hash);
854 
855 	if(e != NULL) {
856 		if(out_value != NULL) {
857 			*out_value = e->value;
858 		}
859 
860 		return true;
861 	}
862 
863 	return false;
864 }
865 #endif // HT_THREAD_SAFE
866 
867 HT_DECLARE_PRIV_FUNC(void, unset_all, (HT_BASETYPE *ht)) {
868 	for(ht_size_t i = 0; i < ht->num_elements_allocated; ++i) {
869 		HT_TYPE(element) *e = ht->elements + i;
870 		if(e->hash & HT_HASH_LIVE_BIT) {
871 			HT_FUNC_FREE_KEY(e->key);
872 			e->hash = 0;
873 
874 			if(--ht->num_elements_occupied == 0) {
875 				break;
876 			}
877 		}
878 	}
879 }
880 
881 HT_DECLARE_FUNC(void, unset_all, (HT_BASETYPE *ht)) {
882 	HT_PRIV_FUNC(begin_write)(ht);
883 	HT_PRIV_FUNC(unset_all)(ht);
884 	HT_PRIV_FUNC(end_write)(ht);
885 }
886 
887 HT_DECLARE_PRIV_FUNC(void, unset_with_backshift, (HT_BASETYPE *ht, HT_TYPE(element) *e)) {
888 	HT_TYPE(element) *elements = ht->elements;
889 	hash_t hash_mask = ht->hash_mask;
890 
891 	HT_FUNC_FREE_KEY(e->key);
892 	--ht->num_elements_occupied;
893 
894 	ht_size_t idx = e - elements;
895 	for(;;) {
896 		idx = (idx + 1) & hash_mask;
897 		HT_TYPE(element) *next_e = elements + idx;
898 
899 		if(HT_PRIV_FUNC(get_element_psl)(ht, next_e) < 1) {
900 			e->hash = 0;
901 			return;
902 		}
903 
904 		*e = *next_e;
905 		e = next_e;
906 	}
907 }
908 
909 HT_DECLARE_FUNC(bool, unset, (HT_BASETYPE *ht, HT_TYPE(const_key) key)) {
910 	hash_t hash = HT_FUNC_HASH_KEY(key);
911 	bool success = false;
912 
913 	HT_PRIV_FUNC(begin_write)(ht);
914 	HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, key, hash);
915 	if(e != NULL) {
916 		HT_PRIV_FUNC(unset_with_backshift)(ht, e);
917 		success = true;
918 	}
919 	HT_PRIV_FUNC(end_write)(ht);
920 
921 	return success;
922 }
923 
924 HT_DECLARE_FUNC(void, unset_list, (HT_BASETYPE *ht, const HT_TYPE(key_list) *key_list)) {
925 	HT_PRIV_FUNC(begin_write)(ht);
926 
927 	for(const HT_TYPE(key_list) *i = key_list; i; i = i->next) {
928 		hash_t hash = HT_FUNC_HASH_KEY(i->key);
929 		HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, i->key, hash);
930 
931 		if(e != NULL) {
932 			HT_PRIV_FUNC(unset_with_backshift)(ht, e);
933 		}
934 	}
935 
936 	HT_PRIV_FUNC(end_write)(ht);
937 }
938 
HT_TYPE(element)939 HT_DECLARE_PRIV_FUNC(HT_TYPE(element)*, insert, (
940 	HT_TYPE(element) *insertion_elem,
941 	HT_TYPE(element) *elements,
942 	hash_t hash_mask,
943 	ht_size_t *p_max_psl
944 )) {
945 	HT_TYPE(element) *e, *target = NULL, temp_elem;
946 	ht_size_t idx = insertion_elem->hash & hash_mask;
947 
948 	for(;;) {
949 		e = elements + idx;
950 
951 		if(!(e->hash & HT_HASH_LIVE_BIT)) {
952 			*e = *insertion_elem;
953 			if(target == NULL) {
954 				target = e;
955 			}
956 
957 			ht_size_t psl = HT_PRIV_FUNC(get_psl)(e->hash & hash_mask, idx, hash_mask + 1);
958 			if(*p_max_psl < psl) {
959 				*p_max_psl = psl;
960 			}
961 
962 			break;
963 		}
964 
965 		ht_size_t e_probe_len = HT_PRIV_FUNC(get_psl)(e->hash & hash_mask, idx, hash_mask + 1);
966 		ht_size_t i_probe_len = HT_PRIV_FUNC(get_psl)(insertion_elem->hash & hash_mask, idx, hash_mask + 1);
967 
968 		if(e_probe_len < i_probe_len) {
969 			// log_debug("SWAP %u (%u < %u)", idx, e_probe_len, i_probe_len);
970 			temp_elem = *e;
971 			*e = *insertion_elem;
972 			if(target == NULL) {
973 				target = e;
974 			}
975 			*insertion_elem = temp_elem;
976 
977 			ht_size_t psl = HT_PRIV_FUNC(get_psl)(e->hash & hash_mask, idx, hash_mask + 1);
978 			if(*p_max_psl < psl) {
979 				*p_max_psl = psl;
980 			}
981 		}
982 
983 		idx = (idx + 1) & hash_mask;
984 	}
985 
986 	return target;
987 }
988 
989 HT_DECLARE_PRIV_FUNC(bool, set, (
990 	HT_BASETYPE *ht,
991 	hash_t hash,
992 	HT_TYPE(const_key) key,
993 	HT_TYPE(value) value,
994 	HT_TYPE(value) (*transform_value)(HT_TYPE(value)),
995 	bool allow_overwrite,
996 	HT_TYPE(value) *out_value
997 )) {
998 	HT_TYPE(element) *e = HT_PRIV_FUNC(find_element)(ht, key, hash);
999 	if(e) {
1000 		if(!allow_overwrite) {
1001 			if(out_value != NULL) {
1002 				*out_value = e->value;
1003 			}
1004 
1005 			return false;
1006 		}
1007 
1008 		if(transform_value != NULL) {
1009 			value = transform_value(value);
1010 		}
1011 
1012 		if(out_value != NULL) {
1013 			*out_value = value;
1014 		}
1015 
1016 		e->value = value;
1017 
1018 		// log_debug("[%"HT_KEY_FMT"] ==> [%"HT_VALUE_FMT"] (replace)", HT_KEY_PRINTABLE(key), HT_VALUE_PRINTABLE(value));
1019 		return true;
1020 	}
1021 
1022 	// log_debug("[%"HT_KEY_FMT"] ==> [%"HT_VALUE_FMT"]", HT_KEY_PRINTABLE(key), HT_VALUE_PRINTABLE(value));
1023 
1024 	// log_debug(" *** BEFORE ***");
1025 	HT_PRIV_FUNC(dump)(ht);
1026 
1027 	if(transform_value != NULL) {
1028 		value = transform_value(value);
1029 	}
1030 
1031 	if(out_value != NULL) {
1032 		*out_value = value;
1033 	}
1034 
1035 	HT_TYPE(element) insertion_elem;
1036 	insertion_elem.value = value;
1037 	HT_FUNC_COPY_KEY(&insertion_elem.key, key);
1038 	insertion_elem.hash = hash | HT_HASH_LIVE_BIT;
1039 	e = HT_PRIV_FUNC(insert)(&insertion_elem, ht->elements, ht->hash_mask, &ht->max_psl);
1040 	assume(e != NULL);
1041 
1042 	++ht->num_elements_occupied;
1043 
1044 	// log_debug(" *** AFTER ***");
1045 	HT_PRIV_FUNC(dump)(ht);
1046 	// log_debug(" *** END SET ***");
1047 
1048 	assert(HT_PRIV_FUNC(find_element)(ht, key, hash) == e);
1049 	assert(e->value == value);
1050 	return true;
1051 }
1052 
1053 HT_DECLARE_PRIV_FUNC(void, check_elem_count, (HT_BASETYPE *ht)) {
1054 	#ifdef DEBUG
1055 	ht_size_t num_elements = 0;
1056 	for(ht_size_t i = 0; i < ht->num_elements_allocated; ++i) {
1057 		if(ht->elements[i].hash & HT_HASH_LIVE_BIT) {
1058 			++num_elements;
1059 		}
1060 	}
1061 	assert(num_elements == ht->num_elements_occupied);
1062 	#endif // DEBUG
1063 }
1064 
1065 HT_DECLARE_PRIV_FUNC(void, resize, (HT_BASETYPE *ht, size_t new_size)) {
1066 	assert(new_size != ht->num_elements_allocated);
1067 
1068 	HT_TYPE(element) *old_elements = ht->elements;
1069 	ht_size_t old_size = ht->num_elements_allocated;
1070 	HT_PRIV_FUNC(check_elem_count)(ht);
1071 
1072 	HT_TYPE(element) *new_elements = calloc(new_size, sizeof(*ht->elements));
1073 	ht->max_psl = 0;
1074 
1075 	for(ht_size_t i = 0; i < old_size; ++i) {
1076 		HT_TYPE(element) *e = old_elements + i;
1077 		if(e->hash & HT_HASH_LIVE_BIT) {
1078 			HT_PRIV_FUNC(insert)(e, new_elements, new_size - 1, &ht->max_psl);
1079 		}
1080 	}
1081 
1082 	ht->elements = new_elements;
1083 	ht->num_elements_allocated = new_size;
1084 	ht->hash_mask = new_size - 1;
1085 
1086 	free(old_elements);
1087 
1088 	/*
1089 	log_debug(
1090 		"Resized hashtable at %p: %"PRIuMAX" -> %"PRIuMAX"",
1091 		(void*)ht, (uintmax_t)old_size, (uintmax_t)new_size
1092 	);
1093 	*/
1094 
1095 	HT_PRIV_FUNC(dump)(ht);
1096 	HT_PRIV_FUNC(check_elem_count)(ht);
1097 }
1098 
1099 HT_DECLARE_PRIV_FUNC(bool, maybe_resize, (HT_BASETYPE *ht)) {
1100 	if(
1101 		ht->num_elements_occupied == ht->num_elements_allocated || ht->max_psl > 5
1102 	) {
1103 		HT_PRIV_FUNC(resize)(ht, ht->num_elements_allocated * 2);
1104 		return true;
1105 	}
1106 
1107 	return false;
1108 }
1109 
1110 HT_DECLARE_FUNC(bool, set, (HT_BASETYPE *ht, HT_TYPE(const_key) key, HT_TYPE(value) value)) {
1111 	hash_t hash = HT_FUNC_HASH_KEY(key);
1112 
1113 	HT_PRIV_FUNC(begin_write)(ht);
1114 	bool result = HT_PRIV_FUNC(set)(ht, hash, key, value, NULL, true, NULL);
1115 	HT_PRIV_FUNC(maybe_resize)(ht);
1116 	HT_PRIV_FUNC(end_write)(ht);
1117 
1118 	return result;
1119 }
1120 
1121 HT_DECLARE_FUNC(bool, try_set_prehashed, (HT_BASETYPE *ht, HT_TYPE(const_key) key, hash_t hash, HT_TYPE(value) value, HT_TYPE(value) (*value_transform)(HT_TYPE(value)), HT_TYPE(value) *out_value)) {
1122 	assert(hash == HT_FUNC_HASH_KEY(key));
1123 
1124 	HT_PRIV_FUNC(begin_write)(ht);
1125 	bool result = HT_PRIV_FUNC(set)(ht, hash, key, value, value_transform, false, out_value);
1126 	HT_PRIV_FUNC(maybe_resize)(ht);
1127 	HT_PRIV_FUNC(end_write)(ht);
1128 	return result;
1129 }
1130 
1131 HT_DECLARE_FUNC(void*, foreach, (HT_BASETYPE *ht, HT_TYPE(foreach_callback) callback, void *arg)) {
1132 	void *ret = NULL;
1133 
1134 	HT_PRIV_FUNC(begin_read)(ht);
1135 
1136 	for(ht_size_t i = 0, remaining = ht->num_elements_occupied; remaining; ++i) {
1137 		HT_TYPE(element) *e = ht->elements + i;
1138 		if(e->hash & HT_HASH_LIVE_BIT) {
1139 			if((ret = callback(e->key, e->value, arg))) {
1140 				break;
1141 			}
1142 			--remaining;
1143 		}
1144 	}
1145 
1146 	HT_PRIV_FUNC(end_read)(ht);
1147 	return ret;
1148 }
1149 
1150 HT_DECLARE_FUNC(void, iter_begin, (HT_BASETYPE *ht, HT_TYPE(iter) *iter)) {
1151 	HT_PRIV_FUNC(begin_read)(ht);
1152 	memset(iter, 0, sizeof(*iter));
1153 	iter->hashtable = ht;
1154 	iter->private.remaining = ht->num_elements_occupied;
1155 	iter->has_data = iter->private.remaining;
1156 	HT_FUNC(iter_next)(iter);
1157 }
1158 
1159 HT_DECLARE_FUNC(void, iter_next, (HT_TYPE(iter) *iter)) {
1160 	HT_BASETYPE *ht = iter->hashtable;
1161 
1162 	if(!iter->private.remaining) {
1163 		iter->has_data = false;
1164 		return;
1165 	}
1166 
1167 	for(;;) {
1168 		ht_size_t i = iter->private.i++;
1169 		assert(i < ht->num_elements_allocated);
1170 		HT_TYPE(element) *e = ht->elements + i;
1171 
1172 		if(e->hash & HT_HASH_LIVE_BIT) {
1173 			--iter->private.remaining;
1174 			iter->key = e->key;
1175 			iter->value = e->value;
1176 			return;
1177 		}
1178 	}
1179 
1180 	return;
1181 }
1182 
1183 HT_DECLARE_FUNC(void, iter_end, (HT_TYPE(iter) *iter)) {
1184 	HT_PRIV_FUNC(end_read)(iter->hashtable);
1185 }
1186 
1187 #endif // HT_IMPL
1188 
1189 /***********\
1190  * Cleanup *
1191 \***********/
1192 
1193 // Generated with:
1194 // $ sed -e 's/.*#define\s*//' -e 's/[^A-Z0-9_].*//' -e '/^$/d' -e 's/^/#undef /' hashtable.inc.h | sort -u
1195 // I'm sure this can be done much more efficiently, but I don't care to figure it out.
1196 
1197 // It is intentional that it also catches the examples in comments.
1198 // The user-supplied macros have to be #undef'd too.
1199 
1200 #undef HT_BASETYPE
1201 #undef HT_DECL
1202 #undef HT_DECLARE_FUNC
1203 #undef HT_DECLARE_PRIV_FUNC
1204 #undef HT_FUNC
1205 #undef HT_FUNC_COPY_KEY
1206 #undef HT_FUNC_FREE_KEY
1207 #undef HT_FUNC_HASH_KEY
1208 #undef HT_FUNC_KEYS_EQUAL
1209 #undef HT_IMPL
1210 #undef HT_KEY_CONST
1211 #undef HT_KEY_TYPE
1212 #undef HT_MIN_SIZE
1213 #undef HT_NAME
1214 #undef HT_PRIV_FUNC
1215 #undef HT_PRIV_NAME
1216 #undef HT_SUFFIX
1217 #undef HT_THREAD_SAFE
1218 #undef HT_TYPE
1219 #undef HT_VALUE_CONST
1220 #undef HT_VALUE_TYPE
1221 #undef _HT_NAME_INNER1
1222 #undef _HT_NAME_INNER2
1223 #undef _HT_PRIV_NAME_INNER1
1224 #undef _HT_PRIV_NAME_INNER2
1225 #undef HT_KEY_FMT
1226 #undef HT_KEY_PRINTABLE
1227 #undef HT_VALUE_FMT
1228 #undef HT_VALUE_PRINTABLE
1229