1 /**********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 /* spechashs: "specific genhash".
15  *
16  * This file is used to implement a "specific" genhash.
17  * That is, a (sometimes) type-checked genhash. (Or at least a
18  * genhash with related functions with distinctly typed parameters.)
19  *
20  * Before including this file, you must define the following:
21  *   SPECHASH_TAG - this tag will be used to form names for functions etc.
22  *   SPECHASH_IKEY_TYPE - the typed genhash will use this type as key.
23  *     (genhash internal usage). You may omit this setting defining
24  *     SPECHASH_INT_KEY_TYPE, SPECHASH_ENUM_KEY_TYPE,
25  *     SPECHASH_ASTR_KEY_TYPE, or SPECHASH_CSTR_KEY_TYPE, by convenience
26  *     for integer, enumerators, or strings.
27  *   SPECHASH_IDATA_TYPE - the typed genhash will use this type as data.
28  *     (genhash internal usage). You may omit this setting defining
29  *     SPECHASH_INT_DATA_TYPE, SPECHASH_ENUM_DATA_TYPE,
30  *     SPECHASH_ASTR_DATA_TYPE, or SPECHASH_CSTR_DATA_TYPE, by convenience
31  *     for integers, enumerators, or strings.
32  * You may also define:
33  *   SPECHASH_UKEY_TYPE - the typed genhash will use this as key.
34  *     (external user usage, see SPECHASH_UKEY_TO_IKEY and
35  *      SPECHASH_IKEY_TO_UKEY convertors).
36  *   SPECHASH_UDATA_TYPE - the typed genhash will use this type as data.
37  *     (external user usage, see SPECHASH_IDATA_TO_UDATA and
38  *      SPECHASH_UDATA_TO_IDATA convertos).
39  *   SPECHASH_IKEY_VAL - The default hash function.
40  *   SPECHASH_IKEY_COMP - The default hash key comparator function.
41  *   SPECHASH_IKEY_COPY - The default key copy function.
42  *   SPECHASH_IKEY_FREE - The default key free function.
43  *   SPECHASH_IDATA_COMP - The default data comparator function.
44  *   SPECHASH_IDATA_COPY - The default data copy function.
45  *   SPECHASH_IDATA_FREE - The default data free function.
46  *   SPECHASH_UKEY_TO_IKEY - A function or macro to convert a key to
47  *     pointer.
48  *   SPECHASH_IKEY_TO_UKEY - A function or macro to convert a pointer to
49  *     key.
50  *   SPECHASH_IDATA_TO_UDATA - A function or macro to convert a data to
51  *     pointer.
52  *   SPECHASH_UDATA_TO_IDATA - A function or macro to convert a pointer
53  *     to data.
54  * At the end of this file, these (and other defines) are undef-ed.
55  *
56  * Assuming SPECHASH_TAG were 'foo', SPECHASH_IKEY_TYPE were 'key_t', and
57  * SPECHASH_IDATA_TYPE were 'data_t'.
58  * including this file would provide a struct definition for:
59  *    struct foo_hash;
60  *    struct foo_hash_iter;
61  *
62  * function typedefs:
63  *    typedef genhash_val_t (*foo_hash_key_val_fn_t) (const key_t);
64  *    typedef bool (*foo_hash_key_comp_fn_t) (const key_t, const key_t);
65  *    typedef key_t (*foo_hash_key_copy_fn_t) (const key_t);
66  *    typedef void (*foo_hash_key_free_fn_t) (key_t);
67  *    typedef bool (*foo_hash_data_comp_fn_t) (const data_t, const data_t);
68  *    typedef data_t (*foo_hash_data_copy_fn_t) (const data_t);
69  *    typedef void (*foo_hash_data_free_fn_t) (data_t);
70  *
71  * and prototypes for the following functions:
72  *    struct foo_hash *foo_hash_new(void);
73  *    struct foo_hash *foo_hash_new_full(foo_hash_key_val_fn_t key_val,
74  *                                       foo_hash_key_comp_fn_t key_comp,
75  *                                       foo_hash_key_copy_fn_t key_copy,
76  *                                       foo_hash_key_free_fn_t key_free,
77  *                                       foo_hash_data_copy_fn_t data_val,
78  *                                       foo_hash_data_free_fn_t data_free);
79  *    struct foo_hash *foo_hash_new_nentries(size_t nentries);
80  *    struct foo_hash *
81  *    foo_hash_new_nentries_full(foo_hash_key_val_fn_t key_val,
82  *                               foo_hash_key_comp_fn_t key_comp,
83  *                               foo_hash_key_copy_fn_t key_copy,
84  *                               foo_hash_key_free_fn_t key_free,
85  *                               foo_hash_data_copy_fn_t data_val,
86  *                               foo_hash_data_free_fn_t data_free,
87  *                               size_t nentries);
88  *    void foo_hash_destroy(struct foo_hash *phash);
89  *    bool foo_hash_set_no_shrink(struct foo_hash *phash, bool no_shrink);
90  *    size_t foo_hash_size(const struct foo_hash *phash);
91  *    size_t foo_hash_capacity(const struct foo_hash *phash);
92  *    struct foo_hash *foo_hash_copy(const struct foo_hash *phash);
93  *    void foo_hash_clear(struct foo_hash *phash);
94  *    bool foo_hash_insert(struct foo_hash *phash, const key_t key,
95  *                         const data_t data);
96  *    bool foo_hash_replace(struct foo_hash *phash, const key_t key,
97  *                          const data_t data);
98  *    bool foo_hash_replace_full(struct foo_hash *phash, const key_t key,
99  *                               const data_t data, key_t *old_pkey,
100  *                               data_t *old_pdata);
101  *    bool foo_hash_lookup(const struct foo_hash *phash, const key_t key,
102  *                         data_t *pdata);
103  *    bool foo_hash_remove(struct foo_hash *phash, const key_t key);
104  *    bool foo_hash_remove_full(struct foo_hash *phash, const key_t key,
105  *                              key_t *deleted_pkey, data_t *deleted_pdata);
106  *
107  *    bool foo_hashs_are_equal(const struct foo_hash *phash1,
108  *                             const struct foo_hash *phash2);
109  *    bool foo_hashs_are_equal_full(const struct foo_hash *phash1,
110  *                                  const struct foo_hash *phash2,
111  *                                  foo_hash_data_comp_fn_t data_comp_func);
112  *
113  *    size_t foo_hash_iter_sizeof(void);
114  *    struct iterator *foo_hash_iter_init(struct foo_hash_iter *iter,
115  *                                        const struct foo_hash *phash);
116  *    struct iterator *foo_hash_key_iter_init(struct foo_hash_iter *iter,
117  *                                        const struct foo_hash *phash);
118  *    struct iterator *foo_hash_value_init(struct foo_hash_iter *iter,
119  *                                         const struct foo_hash *phash);
120  *
121  * You should also define yourself (this file cannot do this for you):
122  * #define foo_hash_data_iterate(phash, data)                               \
123  *   TYPED_HASH_DATA_ITERATE(data_t, phash, data)
124  * #define foo_hash_data_iterate_end HASH_DATA_ITERATE_END
125  *
126  * #define foo_hash_keys_iterate(phash, key)                                \
127  *   TYPED_HASH_KEYS_ITERATE(key_t, phash, key)
128  * #define foo_hash_keys_iterate_end HASH_KEYS_ITERATE_END
129  *
130  * #define foo_hash_iterate(phash, key, data)                               \
131  *   TYPED_HASH_ITERATE(key_t, data_t, phash, key, data)
132  * #define foo_hash_iterate_end HASH_ITERATE_END
133  *
134  * Note this is not protected against multiple inclusions; this is so that
135  * you can have multiple different speclists. For each speclist, this file
136  * should be included _once_, inside a .h file which _is_ itself protected
137  * against multiple inclusions. */
138 
139 #ifdef __cplusplus
140 extern "C" {
141 #endif /* __cplusplus */
142 
143 /* utility */
144 #include "genhash.h"
145 #include "iterator.h"
146 #include "support.h"
147 
148 /* Pre-defined cases for convenience. */
149 #ifdef SPECHASH_INT_KEY_TYPE
150 #undef SPECHASH_INT_KEY_TYPE
151 #define SPECHASH_UKEY_TYPE int
152 #define SPECHASH_IKEY_TYPE void *
153 #define SPECHASH_IKEY_TO_UKEY FC_PTR_TO_INT
154 #define SPECHASH_UKEY_TO_IKEY FC_INT_TO_PTR
155 #define SPECHASH_IKEY_VAL NULL
156 #define SPECHASH_IKEY_COMP NULL
157 #define SPECHASH_IKEY_COPY NULL
158 #define SPECHASH_IKEY_FREE NULL
159 #endif/* SPECHASH_INT_KEY_TYPE */
160 #ifdef SPECHASH_INT_DATA_TYPE
161 #undef SPECHASH_INT_DATA_TYPE
162 #define SPECHASH_UDATA_TYPE int
163 #define SPECHASH_IDATA_TYPE void *
164 #define SPECHASH_IDATA_TO_UDATA FC_PTR_TO_INT
165 #define SPECHASH_UDATA_TO_IDATA FC_INT_TO_PTR
166 #define SPECHASH_IDATA_COMP NULL
167 #define SPECHASH_IDATA_COPY NULL
168 #define SPECHASH_IDATA_FREE NULL
169 #endif/* SPECHASH_INT_DATA_TYPE */
170 #ifdef SPECHASH_ENUM_KEY_TYPE
171 #define SPECHASH_UKEY_TYPE enum SPECHASH_ENUM_KEY_TYPE
172 #define SPECHASH_IKEY_TYPE void *
173 #define SPECHASH_IKEY_TO_UKEY FC_PTR_TO_INT
174 #define SPECHASH_UKEY_TO_IKEY FC_INT_TO_PTR
175 #define SPECHASH_IKEY_VAL NULL
176 #define SPECHASH_IKEY_COMP NULL
177 #define SPECHASH_IKEY_COPY NULL
178 #define SPECHASH_IKEY_FREE NULL
179 #endif/* SPECHASH_ENUM_KEY_TYPE */
180 #ifdef SPECHASH_ENUM_DATA_TYPE
181 #define SPECHASH_UDATA_TYPE enum SPECHASH_ENUM_DATA_TYPE
182 #define SPECHASH_IDATA_TYPE void *
183 #define SPECHASH_IDATA_TO_UDATA FC_PTR_TO_INT
184 #define SPECHASH_UDATA_TO_IDATA FC_INT_TO_PTR
185 #define SPECHASH_IDATA_COMP NULL
186 #define SPECHASH_IDATA_COPY NULL
187 #define SPECHASH_IDATA_FREE NULL
188 #endif/* SPECHASH_ENUM_DATA_TYPE */
189 #ifdef SPECHASH_ASTR_KEY_TYPE
190 #undef SPECHASH_ASTR_KEY_TYPE
191 #define SPECHASH_IKEY_TYPE char *
192 #define SPECHASH_IKEY_VAL genhash_str_val_func
193 #define SPECHASH_IKEY_COMP genhash_str_comp_func
194 #define SPECHASH_IKEY_COPY genhash_str_copy_func
195 #define SPECHASH_IKEY_FREE genhash_str_free_func
196 #endif /* SPECHASH_ASTR_KEY_TYPE */
197 #ifdef SPECHASH_ASTR_DATA_TYPE
198 #undef SPECHASH_ASTR_DATA_TYPE
199 #define SPECHASH_IDATA_TYPE char *
200 #define SPECHASH_IDATA_COMP genhash_str_comp_func
201 #define SPECHASH_IDATA_COPY genhash_str_copy_func
202 #define SPECHASH_IDATA_FREE genhash_str_free_func
203 #endif /* SPECHASH_ASTR_DATA_TYPE */
204 #ifdef SPECHASH_CSTR_KEY_TYPE
205 #undef SPECHASH_CSTR_KEY_TYPE
206 #define SPECHASH_IKEY_TYPE char *
207 #define SPECHASH_IKEY_VAL genhash_str_val_func
208 #define SPECHASH_IKEY_COMP genhash_str_comp_func
209 #define SPECHASH_IKEY_COPY NULL
210 #define SPECHASH_IKEY_FREE NULL
211 #endif /* SPECHASH_CSTR_KEY_TYPE */
212 #ifdef SPECHASH_CSTR_DATA_TYPE
213 #undef SPECHASH_CSTR_DATA_TYPE
214 #define SPECHASH_IDATA_TYPE char *
215 #define SPECHASH_IDATA_COMP genhash_str_comp_func
216 #define SPECHASH_IDATA_COPY NULL
217 #define SPECHASH_IDATA_FREE NULL
218 #endif /* SPECHASH_CSTR_DATA_TYPE */
219 
220 #ifndef SPECHASH_TAG
221 #error Must define a SPECHASH_TAG to use this header
222 #endif
223 #ifndef SPECHASH_IKEY_TYPE
224 #error Must define a SPECHASH_IKEY_TYPE to use this header
225 #endif
226 #ifndef SPECHASH_UKEY_TYPE
227 #define SPECHASH_UKEY_TYPE SPECHASH_IKEY_TYPE
228 #endif
229 #ifndef SPECHASH_IDATA_TYPE
230 #error Must define a SPECHASH_IDATA_TYPE to use this header
231 #endif
232 #ifndef SPECHASH_UDATA_TYPE
233 #define SPECHASH_UDATA_TYPE SPECHASH_IDATA_TYPE
234 #endif
235 
236 /* Default functions. */
237 #ifndef SPECHASH_IKEY_VAL
238 #define SPECHASH_IKEY_VAL NULL
239 #endif
240 #ifndef SPECHASH_IKEY_COMP
241 #define SPECHASH_IKEY_COMP NULL
242 #endif
243 #ifndef SPECHASH_IKEY_COPY
244 #define SPECHASH_IKEY_COPY NULL
245 #endif
246 #ifndef SPECHASH_IKEY_FREE
247 #define SPECHASH_IKEY_FREE NULL
248 #endif
249 #ifndef SPECHASH_IDATA_COMP
250 #define SPECHASH_IDATA_COMP NULL
251 #endif
252 #ifndef SPECHASH_IDATA_COPY
253 #define SPECHASH_IDATA_COPY NULL
254 #endif
255 #ifndef SPECHASH_IDATA_FREE
256 #define SPECHASH_IDATA_FREE NULL
257 #endif
258 
259 /* Other functions or macros. */
260 #ifndef SPECHASH_UKEY_TO_IKEY
261 #define SPECHASH_UKEY_TO_IKEY(ukey) ((SPECHASH_IKEY_TYPE) (ukey))
262 #endif
263 #ifndef SPECHASH_IKEY_TO_UKEY
264 #define SPECHASH_IKEY_TO_UKEY(ikey) ((SPECHASH_UKEY_TYPE) (ikey))
265 #endif
266 #ifndef SPECHASH_UDATA_TO_IDATA
267 #define SPECHASH_UDATA_TO_IDATA(udata) ((SPECHASH_IDATA_TYPE) (udata))
268 #endif
269 #ifndef SPECHASH_IDATA_TO_UDATA
270 #define SPECHASH_IDATA_TO_UDATA(idata) ((SPECHASH_UDATA_TYPE) (idata))
271 #endif
272 
273 #define SPECHASH_PASTE_(x, y) x ## y
274 #define SPECHASH_PASTE(x, y) SPECHASH_PASTE_(x, y)
275 
276 #define SPECHASH_HASH struct SPECHASH_PASTE(SPECHASH_TAG, _hash)
277 #define SPECHASH_ITER struct SPECHASH_PASTE(SPECHASH_TAG, _hash_iter)
278 #define SPECHASH_FOO(suffix) SPECHASH_PASTE(SPECHASH_TAG, suffix)
279 
280 /* Dummy type. Actually a genhash, and not defined anywhere. */
281 SPECHASH_HASH;
282 
283 /* Dummy type. Actually a genhash_iter, and not defined anywhere. */
284 SPECHASH_ITER;
285 
286 /* Function related typedefs. */
287 typedef genhash_val_t
288 (*SPECHASH_FOO(_hash_key_val_fn_t)) (const SPECHASH_IKEY_TYPE);
289 typedef bool (*SPECHASH_FOO(_hash_key_comp_fn_t)) (const SPECHASH_IKEY_TYPE,
290                                                    const SPECHASH_IKEY_TYPE);
291 typedef SPECHASH_IKEY_TYPE
292 (*SPECHASH_FOO(_hash_key_copy_fn_t)) (const SPECHASH_IKEY_TYPE);
293 typedef void (*SPECHASH_FOO(_hash_key_free_fn_t)) (SPECHASH_IKEY_TYPE);
294 typedef bool
295 (*SPECHASH_FOO(_hash_data_comp_fn_t)) (const SPECHASH_IDATA_TYPE,
296                                        const SPECHASH_IDATA_TYPE);
297 typedef SPECHASH_IDATA_TYPE
298 (*SPECHASH_FOO(_hash_data_copy_fn_t)) (const SPECHASH_IDATA_TYPE);
299 typedef void (*SPECHASH_FOO(_hash_data_free_fn_t)) (SPECHASH_IDATA_TYPE);
300 
301 static inline SPECHASH_HASH *SPECHASH_FOO(_hash_new) (void)
302 fc__warn_unused_result;
303 static inline SPECHASH_HASH *
304 SPECHASH_FOO(_hash_new_full) (SPECHASH_FOO(_hash_key_val_fn_t) key_val_func,
305                               SPECHASH_FOO(_hash_key_comp_fn_t)
306                               key_comp_func,
307                               SPECHASH_FOO(_hash_key_copy_fn_t)
308                               key_copy_func,
309                               SPECHASH_FOO(_hash_key_free_fn_t)
310                               key_free_func,
311                               SPECHASH_FOO(_hash_data_copy_fn_t)
312                               data_copy_func,
313                               SPECHASH_FOO(_hash_data_free_fn_t)
314                               data_free_func)
315 fc__warn_unused_result;
316 static inline SPECHASH_HASH *
317 SPECHASH_FOO(_hash_new_nentries) (size_t nentries)
318 fc__warn_unused_result;
319 static inline SPECHASH_HASH *
320 SPECHASH_FOO(_hash_new_nentries_full) (SPECHASH_FOO(_hash_key_val_fn_t)
321                                        key_val_func,
322                                        SPECHASH_FOO(_hash_key_comp_fn_t)
323                                        key_comp_func,
324                                        SPECHASH_FOO(_hash_key_copy_fn_t)
325                                        key_copy_func,
326                                        SPECHASH_FOO(_hash_key_free_fn_t)
327                                        key_free_func,
328                                        SPECHASH_FOO(_hash_data_copy_fn_t)
329                                        data_copy_func,
330                                        SPECHASH_FOO(_hash_data_free_fn_t)
331                                        data_free_func, size_t nentries)
332 fc__warn_unused_result;
333 
334 /****************************************************************************
335   Create a new spechash.
336 ****************************************************************************/
SPECHASH_FOO(_hash_new)337 static inline SPECHASH_HASH *SPECHASH_FOO(_hash_new) (void)
338 {
339   return SPECHASH_FOO(_hash_new_full) (SPECHASH_IKEY_VAL,
340                                        SPECHASH_IKEY_COMP,
341                                        SPECHASH_IKEY_COPY,
342                                        SPECHASH_IKEY_FREE,
343                                        SPECHASH_IDATA_COPY,
344                                        SPECHASH_IDATA_FREE);
345 }
346 
347 /****************************************************************************
348   Create a new spechash with a set of control functions.
349 ****************************************************************************/
350 static inline SPECHASH_HASH *
SPECHASH_FOO(_hash_new_full)351 SPECHASH_FOO(_hash_new_full) (SPECHASH_FOO(_hash_key_val_fn_t) key_val_func,
352                               SPECHASH_FOO(_hash_key_comp_fn_t)
353                               key_comp_func,
354                               SPECHASH_FOO(_hash_key_copy_fn_t)
355                               key_copy_func,
356                               SPECHASH_FOO(_hash_key_free_fn_t)
357                               key_free_func,
358                               SPECHASH_FOO(_hash_data_copy_fn_t)
359                               data_copy_func,
360                               SPECHASH_FOO(_hash_data_free_fn_t)
361                               data_free_func)
362 {
363   return ((SPECHASH_HASH *)
364           genhash_new_full((genhash_val_fn_t) key_val_func,
365                            (genhash_comp_fn_t) key_comp_func,
366                            (genhash_copy_fn_t) key_copy_func,
367                            (genhash_free_fn_t) key_free_func,
368                            (genhash_copy_fn_t) data_copy_func,
369                            (genhash_free_fn_t) data_free_func));
370 }
371 
372 /****************************************************************************
373   Create a new spechash with n entries.
374 ****************************************************************************/
375 static inline SPECHASH_HASH *
SPECHASH_FOO(_hash_new_nentries)376 SPECHASH_FOO(_hash_new_nentries) (size_t nentries)
377 {
378   return SPECHASH_FOO(_hash_new_nentries_full) (SPECHASH_IKEY_VAL,
379                                                 SPECHASH_IKEY_COMP,
380                                                 SPECHASH_IKEY_COPY,
381                                                 SPECHASH_IKEY_FREE,
382                                                 SPECHASH_IDATA_COPY,
383                                                 SPECHASH_IDATA_FREE,
384                                                 nentries);
385 }
386 
387 /****************************************************************************
388   Create a new spechash with n entries and a set of control functions.
389 ****************************************************************************/
390 static inline SPECHASH_HASH *
SPECHASH_FOO(_hash_new_nentries_full)391 SPECHASH_FOO(_hash_new_nentries_full) (SPECHASH_FOO(_hash_key_val_fn_t)
392                                        key_val_func,
393                                        SPECHASH_FOO(_hash_key_comp_fn_t)
394                                        key_comp_func,
395                                        SPECHASH_FOO(_hash_key_copy_fn_t)
396                                        key_copy_func,
397                                        SPECHASH_FOO(_hash_key_free_fn_t)
398                                        key_free_func,
399                                        SPECHASH_FOO(_hash_data_copy_fn_t)
400                                        data_copy_func,
401                                        SPECHASH_FOO(_hash_data_free_fn_t)
402                                        data_free_func, size_t nentries)
403 {
404   return ((SPECHASH_HASH *)
405           genhash_new_nentries_full((genhash_val_fn_t) key_val_func,
406                                     (genhash_comp_fn_t) key_comp_func,
407                                     (genhash_copy_fn_t) key_copy_func,
408                                     (genhash_free_fn_t) key_free_func,
409                                     (genhash_copy_fn_t) data_copy_func,
410                                     (genhash_free_fn_t) data_free_func,
411                                     nentries));
412 }
413 
414 /****************************************************************************
415   Free a spechash.
416 ****************************************************************************/
SPECHASH_FOO(_hash_destroy)417 static inline void SPECHASH_FOO(_hash_destroy) (SPECHASH_HASH *tthis)
418 {
419   genhash_destroy((struct genhash *) tthis);
420 }
421 
422 /****************************************************************************
423   Enable/Disable shrinking.
424 ****************************************************************************/
SPECHASH_FOO(_hash_set_no_shrink)425 static inline bool SPECHASH_FOO(_hash_set_no_shrink) (SPECHASH_HASH *tthis,
426                                                       bool no_shrink)
427 {
428   return genhash_set_no_shrink((struct genhash *) tthis, no_shrink);
429 }
430 
431 /****************************************************************************
432   Return the number of elements.
433 ****************************************************************************/
SPECHASH_FOO(_hash_size)434 static inline size_t SPECHASH_FOO(_hash_size) (const SPECHASH_HASH *tthis)
435 {
436   return genhash_size((const struct genhash *) tthis);
437 }
438 
439 /****************************************************************************
440   Return the real number of buckets.
441 ****************************************************************************/
442 static inline size_t
SPECHASH_FOO(_hash_capacity)443 SPECHASH_FOO(_hash_capacity) (const SPECHASH_HASH *tthis)
444 {
445   return genhash_capacity((const struct genhash *) tthis);
446 }
447 
448 /****************************************************************************
449   Duplicate the spechash.
450 ****************************************************************************/
451 static inline SPECHASH_HASH *
452 SPECHASH_FOO(_hash_copy) (const SPECHASH_HASH *tthis)
453 fc__warn_unused_result;
454 
455 static inline SPECHASH_HASH *
SPECHASH_FOO(_hash_copy)456 SPECHASH_FOO(_hash_copy) (const SPECHASH_HASH *tthis)
457 {
458   return (SPECHASH_HASH *) genhash_copy((const struct genhash *) tthis);
459 }
460 
461 /****************************************************************************
462   Remove all elements of the spechash.
463 ****************************************************************************/
SPECHASH_FOO(_hash_clear)464 static inline void SPECHASH_FOO(_hash_clear) (SPECHASH_HASH *tthis)
465 {
466   genhash_clear((struct genhash *) tthis);
467 }
468 
469 /****************************************************************************
470   Insert an element into the spechash. Returns TRUE on success (if no
471   collision).
472 ****************************************************************************/
473 static inline bool
SPECHASH_FOO(_hash_insert)474 SPECHASH_FOO(_hash_insert) (SPECHASH_HASH *tthis,
475                             const SPECHASH_UKEY_TYPE ukey,
476                             const SPECHASH_UDATA_TYPE udata)
477 {
478   return genhash_insert((struct genhash *) tthis,
479                         SPECHASH_UKEY_TO_IKEY(ukey),
480                         SPECHASH_UDATA_TO_IDATA(udata));
481 }
482 
483 /****************************************************************************
484   Replace an element into the spechash. Returns TRUE if it replaced an old
485   element.
486 ****************************************************************************/
487 static inline bool
SPECHASH_FOO(_hash_replace)488 SPECHASH_FOO(_hash_replace) (SPECHASH_HASH *tthis,
489                              const SPECHASH_UKEY_TYPE ukey,
490                              const SPECHASH_UDATA_TYPE udata)
491 {
492   return genhash_replace((struct genhash *) tthis,
493                          SPECHASH_UKEY_TO_IKEY(ukey),
494                          SPECHASH_UDATA_TO_IDATA(udata));
495 }
496 
497 /****************************************************************************
498   Replace an element into the spechash. Returns TRUE if it replaced an old
499   element.
500 ****************************************************************************/
501 static inline bool
SPECHASH_FOO(_hash_replace_full)502 SPECHASH_FOO(_hash_replace_full) (SPECHASH_HASH *tthis,
503                                   const SPECHASH_UKEY_TYPE ukey,
504                                   const SPECHASH_UDATA_TYPE udata,
505                                   SPECHASH_UKEY_TYPE *old_pukey,
506                                   SPECHASH_UDATA_TYPE *old_pudata)
507 {
508   void *key_ptr, *data_ptr;
509   bool ret = genhash_replace_full((struct genhash *) tthis,
510                                   SPECHASH_UKEY_TO_IKEY(ukey),
511                                   SPECHASH_UDATA_TO_IDATA(udata),
512                                   &key_ptr, &data_ptr);
513 
514   if (NULL != old_pukey) {
515     *old_pukey = SPECHASH_IKEY_TO_UKEY((SPECHASH_IKEY_TYPE) key_ptr);
516   }
517   if (NULL != old_pudata) {
518     *old_pudata = SPECHASH_IDATA_TO_UDATA((SPECHASH_IDATA_TYPE) data_ptr);
519   }
520   return ret;
521 }
522 
523 /****************************************************************************
524   Lookup an element. Returns TRUE if found.
525 ****************************************************************************/
526 static inline bool
SPECHASH_FOO(_hash_lookup)527 SPECHASH_FOO(_hash_lookup) (const SPECHASH_HASH *tthis,
528                             const SPECHASH_UKEY_TYPE ukey,
529                             SPECHASH_UDATA_TYPE *pudata)
530 {
531   void *data_ptr;
532   bool ret = genhash_lookup((const struct genhash *) tthis,
533                             SPECHASH_UKEY_TO_IKEY(ukey), &data_ptr);
534 
535   if (NULL != pudata) {
536     *pudata = SPECHASH_IDATA_TO_UDATA((SPECHASH_IDATA_TYPE) data_ptr);
537   }
538   return ret;
539 }
540 
541 /****************************************************************************
542   Remove an element. Returns TRUE on success.
543 ****************************************************************************/
544 static inline bool
SPECHASH_FOO(_hash_remove)545 SPECHASH_FOO(_hash_remove) (SPECHASH_HASH *tthis,
546                             const SPECHASH_UKEY_TYPE ukey)
547 {
548   return genhash_remove((struct genhash *) tthis,
549                         SPECHASH_UKEY_TO_IKEY(ukey));
550 }
551 
552 /****************************************************************************
553   Remove an element. Returns TRUE on success.
554 ****************************************************************************/
555 static inline bool
SPECHASH_FOO(_hash_remove_full)556 SPECHASH_FOO(_hash_remove_full) (SPECHASH_HASH *tthis,
557                                  const SPECHASH_UKEY_TYPE ukey,
558                                  SPECHASH_UKEY_TYPE *deleted_pukey,
559                                  SPECHASH_UDATA_TYPE *deleted_pudata)
560 {
561   void *key_ptr, *data_ptr;
562   bool ret = genhash_remove_full((struct genhash *) tthis,
563                                  SPECHASH_UKEY_TO_IKEY(ukey),
564                                  &key_ptr, &data_ptr);
565 
566   if (NULL != deleted_pukey) {
567     *deleted_pukey = SPECHASH_IKEY_TO_UKEY((SPECHASH_IKEY_TYPE) key_ptr);
568   }
569   if (NULL != deleted_pudata) {
570     *deleted_pudata = SPECHASH_IDATA_TO_UDATA((SPECHASH_IDATA_TYPE)
571                                                  data_ptr);
572   }
573   return ret;
574 }
575 
576 
577 /****************************************************************************
578   Compare the specific hash tables.
579 ****************************************************************************/
580 static inline bool
SPECHASH_FOO(_hashs_are_equal_full)581 SPECHASH_FOO(_hashs_are_equal_full) (const SPECHASH_HASH *phash1,
582                                      const SPECHASH_HASH *phash2,
583                                      SPECHASH_FOO(_hash_data_comp_fn_t)
584                                      data_comp_func)
585 {
586   return genhashs_are_equal_full((const struct genhash *) phash1,
587                                  (const struct genhash *) phash2,
588                                  (genhash_comp_fn_t) data_comp_func);
589 }
590 
591 /****************************************************************************
592   Compare the specific hash tables.
593 ****************************************************************************/
594 static inline bool
SPECHASH_FOO(_hashs_are_equal)595 SPECHASH_FOO(_hashs_are_equal) (const SPECHASH_HASH *phash1,
596                                 const SPECHASH_HASH *phash2)
597 {
598   return SPECHASH_FOO(_hashs_are_equal_full) (phash1, phash2,
599                                               SPECHASH_IDATA_COMP);
600 }
601 
602 
603 /****************************************************************************
604   Remove the size of the iterator type.
605 ****************************************************************************/
SPECHASH_FOO(_hash_iter_sizeof)606 static inline size_t SPECHASH_FOO(_hash_iter_sizeof) (void)
607 {
608   return genhash_iter_sizeof();
609 }
610 
611 /****************************************************************************
612   Initialize an iterator.
613 ****************************************************************************/
614 static inline struct iterator *
SPECHASH_FOO(_hash_iter_init)615 SPECHASH_FOO(_hash_iter_init) (SPECHASH_ITER *iter,
616                                const SPECHASH_HASH *tthis)
617 {
618   return genhash_iter_init((struct genhash_iter *) iter,
619                            (const struct genhash *) tthis);
620 }
621 
622 /****************************************************************************
623   Initialize a key iterator.
624 ****************************************************************************/
625 static inline struct iterator *
SPECHASH_FOO(_hash_key_iter_init)626 SPECHASH_FOO(_hash_key_iter_init) (SPECHASH_ITER *iter,
627                                    const SPECHASH_HASH *tthis)
628 {
629   return genhash_key_iter_init((struct genhash_iter *) iter,
630                                (const struct genhash *) tthis);
631 }
632 
633 /****************************************************************************
634   Initialize a value iterator.
635 ****************************************************************************/
636 static inline struct iterator *
SPECHASH_FOO(_hash_value_iter_init)637 SPECHASH_FOO(_hash_value_iter_init) (SPECHASH_ITER *iter,
638                                      const SPECHASH_HASH *tthis)
639 {
640   return genhash_value_iter_init((struct genhash_iter *) iter,
641                                  (const struct genhash *) tthis);
642 }
643 
644 #undef SPECHASH_TAG
645 #undef SPECHASH_IKEY_TYPE
646 #undef SPECHASH_UKEY_TYPE
647 #undef SPECHASH_IDATA_TYPE
648 #undef SPECHASH_UDATA_TYPE
649 #undef SPECHASH_IKEY_VAL
650 #undef SPECHASH_IKEY_COMP
651 #undef SPECHASH_IKEY_COPY
652 #undef SPECHASH_IKEY_FREE
653 #undef SPECHASH_IDATA_COMP
654 #undef SPECHASH_IDATA_COPY
655 #undef SPECHASH_IDATA_FREE
656 #undef SPECHASH_UKEY_TO_IKEY
657 #undef SPECHASH_IKEY_TO_UKEY
658 #undef SPECHASH_UDATA_TO_IDATA
659 #undef SPECHASH_IDATA_TO_UDATA
660 #undef SPECHASH_PASTE_
661 #undef SPECHASH_PASTE
662 #undef SPECHASH_HASH
663 #undef SPECHASH_ITER
664 #undef SPECHASH_FOO
665 #ifdef SPECHASH_ENUM_KEY_TYPE
666 #undef SPECHASH_ENUM_KEY_TYPE
667 #endif
668 #ifdef SPECHASH_ENUM_DATA_TYPE
669 #undef SPECHASH_ENUM_DATA_TYPE
670 #endif
671 
672 
673 /* Base macros that the users can specialize. */
674 #ifndef FC__SPECHASH_H  /* Defines this only once, no multiple inclusions. */
675 #define FC__SPECHASH_H
676 
677 /* Spechash value iterator.
678  *
679  * TYPE_data - The real type of the data in the genhash.
680  * ARG_ht - The genhash to iterate.
681  * NAME_data - The name of the data iterator (defined inside the macro). */
682 #define TYPED_HASH_DATA_ITERATE(TYPE_data, ARG_ht, NAME_data)               \
683   generic_iterate(struct genhash_iter, TYPE_data, NAME_data,                \
684                   genhash_iter_sizeof, genhash_value_iter_init,             \
685                   (const struct genhash *) (ARG_ht))
686 
687 /* Balance for above: */
688 #define HASH_DATA_ITERATE_END generic_iterate_end
689 
690 /* Spechash key iterator.
691  *
692  * TYPE_key - The real type of the key in the genhash.
693  * ARG_ht - The genhash to iterate.
694  * NAME_key - The name of the key iterator (defined inside the macro). */
695 #define TYPED_HASH_KEYS_ITERATE(TYPE_key, ARG_ht, NAME_key)                 \
696   generic_iterate(struct genhash_iter, TYPE_key, NAME_key,                  \
697                   genhash_iter_sizeof, genhash_key_iter_init,               \
698                   (const struct genhash *) (ARG_ht))
699 
700 /* Balance for above: */
701 #define HASH_KEYS_ITERATE_END                                               \
702   }                                                                         \
703 } while (FALSE);
704 
705 /* Spechash key and values iterator.
706  *
707  * TYPE_key - The real type of the key in the genhash.
708  * TYPE_data - The real type of the key in the genhash.
709  * ARG_ht - The genhash to iterate.
710  * NAME_key - The name of the key iterator (defined inside the macro).
711  * NAME_data - The name of the data iterator (defined inside the macro). */
712 #define TYPED_HASH_ITERATE(TYPE_key, TYPE_data, ARG_ht, NAME_key, NAME_data)\
713   genhash_iterate((const struct genhash *) (ARG_ht), MY_iter) {             \
714     TYPE_key NAME_key = (TYPE_key) genhash_iter_key(MY_iter);               \
715     TYPE_data NAME_data = (TYPE_data) genhash_iter_value(MY_iter);
716 
717 /* Balance for above: */
718 #define HASH_ITERATE_END                                                    \
719   } genhash_iterate_end;
720 
721 #endif /* FC__SPECHASH_H */
722 
723 /* This is after #endif FC__SPECHASH_H on purpose.
724    extern "C" portion begins well before latter part of the header
725    is guarded against multiple inclusions. */
726 #ifdef __cplusplus
727 }
728 #endif /* __cplusplus */
729