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