Removed silencing of gtk warning logs from gtk3.22-client.
[freeciv.git] / utility / speclist.h
blob3c489eb64d057fecd9ad820ee353f8637022d560
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.
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 ***********************************************************************/
14 /* speclists: "specific genlists", by dwp.
15 * (A generalisation of previous city_list and unit_list stuff.)
17 * This file is used to implement a "specific" genlist.
18 * That is, a (sometimes) type-checked genlist. (Or at least a
19 * genlist with related functions with distinctly typed parameters.)
20 * (Or, maybe, what you end up doing when you don't use C++ ?)
22 * Before including this file, you must define the following:
23 * SPECLIST_TAG - this tag will be used to form names for functions etc.
24 * You may also define:
25 * SPECLIST_TYPE - the typed genlist will contain pointers to this type;
26 * If SPECLIST_TYPE is not defined, then 'struct SPECLIST_TAG' is used.
27 * At the end of this file, these (and other defines) are undef-ed.
29 * Assuming SPECLIST_TAG were 'foo', and SPECLIST_TYPE were 'foo_t',
30 * including this file would provide a struct definition for:
31 * struct foo_list;
32 * struct foo_list_link;
34 * function typedefs:
35 * typedef void (*foo_list_free_fn_t) (foo_t *);
36 * typedef foo_t * (*foo_list_copy_fn_t) (const foo_t *);
37 * typedef bool (*foo_list_comp_fn_t) (const foo_t *, const foo_t *);
38 * typedef bool (*foo_list_cond_fn_t) (const foo_t *);
40 * and prototypes for the following functions:
41 * struct foo_list *foo_list_new(void);
42 * struct foo_list *foo_list_new_full(foo_list_free_fn_t free_data_func);
43 * void foo_list_destroy(struct foo_list *plist);
44 * struct foo_list *foo_list_copy(const struct foolist *plist);
45 * struct foo_list *foo_list_copy_full(const struct foolist *plist,
46 * foo_list_copy_fn_t copy_data_func,
47 * foo_list_free_fn_t free_data_func);
48 * void foo_list_clear(struct foo_list *plist);
49 * void foo_list_unique(struct foo_list *plist);
50 * void foo_list_unique_full(struct foo_list *plist,
51 * foo_list_comp_fn_t comp_data_func);
52 * void foo_list_append(struct foo_list *plist, foo_t *pfoo);
53 * void foo_list_prepend(struct foo_list *plist, foo_t *pfoo);
54 * void foo_list_insert(struct foo_list *plist, foo_t *pfoo, int idx);
55 * void foo_list_insert_after(struct foo_list *plist, foo_t *pfoo,
56 * struct foo_list_link *plink);
57 * void foo_list_insert_before(struct foo_list *plist, foo_t *pfoo,
58 * struct foo_list_link *plink);
59 * bool foo_list_remove(struct foo_list *plist, const foo_t *pfoo);
60 * bool foo_list_remove_if(struct foo_list *plist,
61 * foo_list_cond_fn_t cond_data_func);
62 * int foo_list_remove_all(struct foo_list *plist, const foo_t *pfoo);
63 * int foo_list_remove_all_if(struct foo_list *plist,
64 * foo_list_cond_fn_t cond_data_func);
65 * void foo_list_erase(struct foo_list *plist,
66 * struct foo_list_link *plink);
67 * void foo_list_pop_front(struct foo_list *plist);
68 * void foo_list_pop_back(struct foo_list *plist);
69 * int foo_list_size(const struct foo_list *plist);
70 * foo_t *foo_list_get(const struct foo_list *plist, int idx);
71 * foo_t *foo_list_front(const struct foo_list *plist);
72 * foo_t *foo_list_back(const struct foo_list *plist);
73 * struct foo_list_link *foo_list_link_get(const struct foo_list *plist,
74 * int idx);
75 * struct foo_list_link *foo_list_head(const struct foo_list *plist);
76 * struct foo_list_link *foo_list_tail(const struct foo_list *plist);
77 * struct foo_list_link *foo_list_search(const struct foo_list *plist,
78 * const void *data);
79 * struct foo_list_link *foo_list_search_if(const struct foo_list *plist,
80 * foo_list_cond_fn_t
81 * cond_data_func);
82 * void foo_list_sort(struct foo_list *plist,
83 * int (*compar) (const foo_t *const *, const foo_t *const *));
84 * void foo_list_shuffle(struct foo_list *plist);
85 * void foo_list_reverse(struct foo_list *plist);
86 * void foo_list_allocate_mutex(struct foo_list *plist);
87 * void foo_list_release_mutex(struct foo_list *plist);
88 * foo_t *foo_list_link_data(const struct foo_list_link *plink);
89 * struct foo_list_link *
90 * foo_list_link_prev(const struct foo_list_link *plink);
91 * struct foo_list_link *
92 * foo_list_link_next(const struct foo_list_link *plink);
94 * You should also define yourself (this file cannot do this for you):
95 * #define foo_list_iterate(foolist, pfoo) \
96 * TYPED_LIST_ITERATE(foo_t, foolist, pfoo)
97 * #define foo_list_iterate_end LIST_ITERATE_END
99 * #define foo_list_iterate_rev(foolist, pfoo) \
100 * TYPED_LIST_ITERATE_REV(foo_t, foolist, pfoo)
101 * #define foo_list_iterate_rev_end LIST_ITERATE_REV_END
103 * #define foo_list_link_iterate(foolist, plink) \
104 * TYPED_LIST_LINK_ITERATE(struct foo_list_link, foolist, plink)
105 * #define foo_list_link_iterate_end LIST_LINK_ITERATE_END
107 * #define foo_list_link_iterate_rev(foolist, plink) \
108 * TYPED_LIST_LINK_ITERATE_REV(struct foo_list_link, foolist, plink)
109 * #define foo_list_link_iterate_rev_end LIST_LINK_ITERATE_REV_END
111 * #define foo_list_both_iterate(foolist, plink, pfoo) \
112 * TYPED_LIST_BOTH_ITERATE(struct foo_list_link, foo_t, \
113 foolist, plink, pfoo)
114 * #define foo_list_both_iterate_end LIST_BOTH_ITERATE_END
116 * #define foo_list_both_iterate_rev(foolist, pfoo) \
117 * TYPED_LIST_BOTH_ITERATE_REV(struct foo_list_link, foo_t, \
118 foolist, plink, pfoo)
119 * #define foo_list_both_iterate_rev_end LIST_BOTH_ITERATE_REV_END
121 * Note this is not protected against multiple inclusions; this is so that
122 * you can have multiple different speclists. For each speclist, this file
123 * should be included _once_, inside a .h file which _is_ itself protected
124 * against multiple inclusions. */
126 #ifdef __cplusplus
127 extern "C" {
128 #endif /* __cplusplus */
130 #include "genlist.h"
132 #ifndef SPECLIST_TAG
133 #error Must define a SPECLIST_TAG to use this header
134 #endif
136 #ifndef SPECLIST_TYPE
137 #define SPECLIST_TYPE struct SPECLIST_TAG
138 #endif
140 #define SPECLIST_PASTE_(x, y) x ## y
141 #define SPECLIST_PASTE(x, y) SPECLIST_PASTE_(x,y)
143 #define SPECLIST_LIST struct SPECLIST_PASTE(SPECLIST_TAG, _list)
144 #define SPECLIST_LINK struct SPECLIST_PASTE(SPECLIST_TAG, _list_link)
145 #define SPECLIST_FOO(suffix) SPECLIST_PASTE(SPECLIST_TAG, suffix)
147 /* Dummy type. Actually a genlist, and not defined anywhere. */
148 SPECLIST_LIST;
150 /* Dummy type. Actually a genlist_link, and not defined anywhere. */
151 SPECLIST_LINK;
153 /* Function related typedefs. */
154 typedef void (*SPECLIST_FOO(_list_free_fn_t)) (SPECLIST_TYPE *);
155 typedef SPECLIST_TYPE *
156 (*SPECLIST_FOO(_list_copy_fn_t)) (const SPECLIST_TYPE *);
157 typedef bool (*SPECLIST_FOO(_list_comp_fn_t)) (const SPECLIST_TYPE *,
158 const SPECLIST_TYPE *);
159 typedef bool (*SPECLIST_FOO(_list_cond_fn_t)) (const SPECLIST_TYPE *);
162 /****************************************************************************
163 Create a new speclist.
164 ****************************************************************************/
165 static inline SPECLIST_LIST *SPECLIST_FOO(_list_new) (void)
166 fc__warn_unused_result;
168 static inline SPECLIST_LIST *SPECLIST_FOO(_list_new) (void)
170 return (SPECLIST_LIST *) genlist_new();
173 /****************************************************************************
174 Create a new speclist with a free callback.
175 ****************************************************************************/
176 static inline SPECLIST_LIST *
177 SPECLIST_FOO(_list_new_full) (SPECLIST_FOO(_list_free_fn_t) free_data_func)
178 fc__warn_unused_result;
180 static inline SPECLIST_LIST *
181 SPECLIST_FOO(_list_new_full) (SPECLIST_FOO(_list_free_fn_t) free_data_func)
183 return ((SPECLIST_LIST *)
184 genlist_new_full((genlist_free_fn_t) free_data_func));
187 /****************************************************************************
188 Free a speclist.
189 ****************************************************************************/
190 static inline void SPECLIST_FOO(_list_destroy) (SPECLIST_LIST *tthis)
192 genlist_destroy((struct genlist *) tthis);
195 /****************************************************************************
196 Duplicate a speclist.
197 ****************************************************************************/
198 static inline SPECLIST_LIST *
199 SPECLIST_FOO(_list_copy) (const SPECLIST_LIST *tthis)
200 fc__warn_unused_result;
202 static inline SPECLIST_LIST *
203 SPECLIST_FOO(_list_copy) (const SPECLIST_LIST *tthis)
205 return (SPECLIST_LIST *) genlist_copy((const struct genlist *) tthis);
208 /****************************************************************************
209 Duplicate a speclist with a free callback and a function to copy each
210 element.
211 ****************************************************************************/
212 static inline SPECLIST_LIST *
213 SPECLIST_FOO(_list_copy_full) (const SPECLIST_LIST *tthis,
214 SPECLIST_FOO(_list_copy_fn_t) copy_data_func,
215 SPECLIST_FOO(_list_free_fn_t) free_data_func)
216 fc__warn_unused_result;
218 static inline SPECLIST_LIST *
219 SPECLIST_FOO(_list_copy_full) (const SPECLIST_LIST *tthis,
220 SPECLIST_FOO(_list_copy_fn_t) copy_data_func,
221 SPECLIST_FOO(_list_free_fn_t) free_data_func)
223 return ((SPECLIST_LIST *)
224 genlist_copy_full((const struct genlist *) tthis,
225 (genlist_copy_fn_t) copy_data_func,
226 (genlist_free_fn_t) free_data_func));
229 /****************************************************************************
230 Remove all elements from the speclist.
231 ****************************************************************************/
232 static inline void SPECLIST_FOO(_list_clear) (SPECLIST_LIST *tthis)
234 genlist_clear((struct genlist *) tthis);
237 /****************************************************************************
238 Remove all element duplicates (the speclist must be sorted before).
239 ****************************************************************************/
240 static inline void SPECLIST_FOO(_list_unique) (SPECLIST_LIST *tthis)
242 genlist_unique((struct genlist *) tthis);
245 /****************************************************************************
246 Remove all element duplicates (the speclist must be sorted before), using
247 'comp_data_func' to determine if the elements are equivalents.
248 ****************************************************************************/
249 static inline void
250 SPECLIST_FOO(_list_unique_full) (SPECLIST_LIST *tthis,
251 SPECLIST_FOO(_list_comp_fn_t) comp_data_func)
253 genlist_unique_full((struct genlist *) tthis,
254 (genlist_comp_fn_t) comp_data_func);
257 /****************************************************************************
258 Push back an element into the speclist.
259 ****************************************************************************/
260 static inline void SPECLIST_FOO(_list_append) (SPECLIST_LIST *tthis,
261 SPECLIST_TYPE *pfoo)
263 genlist_append((struct genlist *) tthis, pfoo);
266 /****************************************************************************
267 Push front an element into the speclist.
268 ****************************************************************************/
269 static inline void SPECLIST_FOO(_list_prepend) (SPECLIST_LIST *tthis,
270 SPECLIST_TYPE *pfoo)
272 genlist_prepend((struct genlist *) tthis, pfoo);
275 /****************************************************************************
276 Insert an element into the speclist at the given position.
277 ****************************************************************************/
278 static inline void SPECLIST_FOO(_list_insert) (SPECLIST_LIST *tthis,
279 SPECLIST_TYPE *pfoo, int idx)
281 genlist_insert((struct genlist *) tthis, pfoo, idx);
284 /****************************************************************************
285 Insert an element after the specified link.
286 ****************************************************************************/
287 static inline void SPECLIST_FOO(_list_insert_after) (SPECLIST_LIST *tthis,
288 SPECLIST_TYPE *pfoo,
289 SPECLIST_LINK *plink)
291 genlist_insert_after((struct genlist *) tthis, pfoo,
292 (struct genlist_link *) plink);
295 /****************************************************************************
296 Insert an element before the specified link.
297 ****************************************************************************/
298 static inline void SPECLIST_FOO(_list_insert_before) (SPECLIST_LIST *tthis,
299 SPECLIST_TYPE *pfoo,
300 SPECLIST_LINK *plink)
302 genlist_insert_before((struct genlist *) tthis, pfoo,
303 (struct genlist_link *) plink);
306 /****************************************************************************
307 Search 'pfoo' in the speclist, and remove it. Returns TRUE on success.
308 ****************************************************************************/
309 static inline bool SPECLIST_FOO(_list_remove) (SPECLIST_LIST *tthis,
310 const SPECLIST_TYPE *pfoo)
312 return genlist_remove((struct genlist *) tthis, pfoo);
315 /****************************************************************************
316 Remove the first element which fit the conditional function. Returns
317 TRUE on success.
318 ****************************************************************************/
319 static inline bool
320 SPECLIST_FOO(_list_remove_if) (SPECLIST_LIST *tthis,
321 SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
323 return genlist_remove_if((struct genlist *) tthis,
324 (genlist_cond_fn_t) cond_data_func);
327 /****************************************************************************
328 Remove 'pfoo' of the whole list. Returns the number of removed elements.
329 ****************************************************************************/
330 static inline int SPECLIST_FOO(_list_remove_all) (SPECLIST_LIST *tthis,
331 const SPECLIST_TYPE *pfoo)
333 return genlist_remove_all((struct genlist *) tthis, pfoo);
336 /****************************************************************************
337 Remove all elements which fit the conditional function. Returns the
338 number of removed elements.
339 ****************************************************************************/
340 static inline bool
341 SPECLIST_FOO(_list_remove_all_if) (SPECLIST_LIST *tthis,
342 SPECLIST_FOO(_list_cond_fn_t)
343 cond_data_func)
345 return genlist_remove_all_if((struct genlist *) tthis,
346 (genlist_cond_fn_t) cond_data_func);
349 /****************************************************************************
350 Remove the elements pointed by 'plink'. Returns the next element of the
351 speclist.
353 NB: After calling this function 'plink' is no more usable. You should
354 have saved the next or previous link before.
355 ****************************************************************************/
356 static inline void SPECLIST_FOO(_list_erase) (SPECLIST_LIST *tthis,
357 SPECLIST_LINK *plink)
359 genlist_erase((struct genlist *) tthis, (struct genlist_link *) plink);
362 /****************************************************************************
363 Remove the first element of the speclist.
364 ****************************************************************************/
365 static inline void SPECLIST_FOO(_list_pop_front) (SPECLIST_LIST *tthis)
367 genlist_pop_front((struct genlist *) tthis);
370 /****************************************************************************
371 Remove the last element of the speclist.
372 ****************************************************************************/
373 static inline void SPECLIST_FOO(_list_pop_back) (SPECLIST_LIST *tthis)
375 genlist_pop_back((struct genlist *) tthis);
378 /****************************************************************************
379 Return the number of elements inside the speclist.
380 ****************************************************************************/
381 static inline int SPECLIST_FOO(_list_size) (const SPECLIST_LIST *tthis)
383 return genlist_size((const struct genlist *) tthis);
386 /****************************************************************************
387 Return the element at position in the speclist.
388 ****************************************************************************/
389 static inline SPECLIST_TYPE *
390 SPECLIST_FOO(_list_get) (const SPECLIST_LIST *tthis, int slindex)
392 return ((SPECLIST_TYPE *)
393 genlist_get((const struct genlist *) tthis, slindex));
396 /****************************************************************************
397 Return the first element of the speclist.
398 ****************************************************************************/
399 static inline SPECLIST_TYPE *
400 SPECLIST_FOO(_list_front) (const SPECLIST_LIST *tthis)
402 return (SPECLIST_TYPE *) genlist_front((const struct genlist *) tthis);
405 /****************************************************************************
406 Return the last element of the speclist.
407 ****************************************************************************/
408 static inline SPECLIST_TYPE *
409 SPECLIST_FOO(_list_back) (const SPECLIST_LIST *tthis)
411 return (SPECLIST_TYPE *) genlist_back((const struct genlist *) tthis);
414 /****************************************************************************
415 Return the element at position in the speclist.
416 ****************************************************************************/
417 static inline SPECLIST_LINK *
418 SPECLIST_FOO(_list_link_get) (const SPECLIST_LIST *tthis, int slindex)
420 return ((SPECLIST_LINK *)
421 genlist_link_get((const struct genlist *) tthis, slindex));
424 /****************************************************************************
425 Return the head link of the speclist.
426 ****************************************************************************/
427 static inline SPECLIST_LINK *
428 SPECLIST_FOO(_list_head) (const SPECLIST_LIST *tthis)
430 return (SPECLIST_LINK *) genlist_head((const struct genlist *) tthis);
433 /****************************************************************************
434 Return the tail link of the speclist.
435 ****************************************************************************/
436 static inline SPECLIST_LINK *
437 SPECLIST_FOO(_list_tail) (const SPECLIST_LIST *tthis)
439 return (SPECLIST_LINK *) genlist_tail((const struct genlist *) tthis);
442 /****************************************************************************
443 Return the link of the first element which match the data 'pfoo'.
444 ****************************************************************************/
445 static inline SPECLIST_LINK *
446 SPECLIST_FOO(_list_search) (const SPECLIST_LIST *tthis,
447 const SPECLIST_TYPE *pfoo)
449 return ((SPECLIST_LINK *)
450 genlist_search((const struct genlist *) tthis, pfoo));
453 /****************************************************************************
454 Return the link of the first element which match the conditional function.
455 ****************************************************************************/
456 static inline SPECLIST_LINK *
457 SPECLIST_FOO(_list_search_if) (const SPECLIST_LIST *tthis,
458 SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
460 return ((SPECLIST_LINK *)
461 genlist_search_if((const struct genlist *) tthis,
462 (genlist_cond_fn_t) cond_data_func));
465 /****************************************************************************
466 Sort the speclist.
467 ****************************************************************************/
468 static inline void
469 SPECLIST_FOO(_list_sort) (SPECLIST_LIST * tthis,
470 int (*compar) (const SPECLIST_TYPE *const *,
471 const SPECLIST_TYPE *const *))
473 genlist_sort((struct genlist *) tthis,
474 (int (*)(const void *, const void *)) compar);
477 /****************************************************************************
478 Shuffle the speclist.
479 ****************************************************************************/
480 static inline void SPECLIST_FOO(_list_shuffle) (SPECLIST_LIST *tthis)
482 genlist_shuffle((struct genlist *) tthis);
485 /****************************************************************************
486 Reverse the order of the elements of the speclist.
487 ****************************************************************************/
488 static inline void SPECLIST_FOO(_list_reverse) (SPECLIST_LIST *tthis)
490 genlist_reverse((struct genlist *) tthis);
493 /****************************************************************************
494 Allocate speclist mutex
495 ****************************************************************************/
496 static inline void SPECLIST_FOO(_list_allocate_mutex) (SPECLIST_LIST *tthis)
498 genlist_allocate_mutex((struct genlist *) tthis);
501 /****************************************************************************
502 Release speclist mutex
503 ****************************************************************************/
504 static inline void SPECLIST_FOO(_list_release_mutex) (SPECLIST_LIST *tthis)
506 genlist_release_mutex((struct genlist *) tthis);
509 /****************************************************************************
510 Return the data of the link.
511 ****************************************************************************/
512 static inline SPECLIST_TYPE *
513 SPECLIST_FOO(_list_link_data) (const SPECLIST_LINK *plink)
515 return ((SPECLIST_TYPE *)
516 genlist_link_data((const struct genlist_link *) plink));
519 /****************************************************************************
520 Return the previous link.
521 ****************************************************************************/
522 static inline SPECLIST_LINK *
523 SPECLIST_FOO(_list_link_prev) (const SPECLIST_LINK *plink)
524 fc__warn_unused_result;
526 static inline SPECLIST_LINK *
527 SPECLIST_FOO(_list_link_prev) (const SPECLIST_LINK *plink)
529 return ((SPECLIST_LINK *)
530 genlist_link_prev((const struct genlist_link *) plink));
533 /****************************************************************************
534 Return the next link.
535 ****************************************************************************/
536 static inline SPECLIST_LINK *
537 SPECLIST_FOO(_list_link_next) (const SPECLIST_LINK *plink)
538 fc__warn_unused_result;
540 static inline SPECLIST_LINK *
541 SPECLIST_FOO(_list_link_next) (const SPECLIST_LINK *plink)
543 return ((SPECLIST_LINK *)
544 genlist_link_next((const struct genlist_link *) plink));
547 #undef SPECLIST_TAG
548 #undef SPECLIST_TYPE
549 #undef SPECLIST_PASTE_
550 #undef SPECLIST_PASTE
551 #undef SPECLIST_LIST
552 #undef SPECLIST_FOO
554 /* Base macros that the users can specialize. */
555 #ifndef FC__SPECLIST_H /* Defines this only once, no multiple inclusions. */
556 #define FC__SPECLIST_H
558 #ifdef FREECIV_DEBUG
559 # define TYPED_LIST_CHECK(ARG_list) \
560 fc_assert_action(NULL != ARG_list, break)
561 #else
562 # define TYPED_LIST_CHECK(ARG_list) /* Nothing. */
563 #endif /* FREECIV_DEBUG */
565 /* Speclist data iterator.
567 * Using *_list_remove(NAME_data) is safe in this loop (but it may be
568 * inefficient due to the linear research of the data, see also
569 * *_list_erase()).
570 * Using *_list_clear() will result to use freed data. It must be avoided!
572 * TYPE_data - The real type of the data in the genlist/speclist.
573 * ARG_list - The speclist to iterate.
574 * NAME_data - The name of the data iterator (defined inside the macro). */
575 #define TYPED_LIST_ITERATE(TYPE_data, ARG_list, NAME_data) \
576 do { \
577 const struct genlist_link *NAME_data##_iter; \
578 TYPE_data *NAME_data; \
579 TYPED_LIST_CHECK(ARG_list); \
580 NAME_data##_iter = genlist_head((const struct genlist *) ARG_list); \
581 while (NULL != NAME_data##_iter) { \
582 NAME_data = (TYPE_data *) genlist_link_data(NAME_data##_iter); \
583 NAME_data##_iter = genlist_link_next(NAME_data##_iter);
585 /* Balance for above: */
586 #define LIST_ITERATE_END \
588 } while (FALSE);
590 /* Mutex protected speclist data iterator.
592 * Using *_list_remove(NAME_data) is safe in this loop (but it may be
593 * inefficient due to the linear research of the data, see also
594 * *_list_erase()).
595 * Using *_list_clear() will result to use freed data. It must be avoided!
597 * TYPE_data - The real type of the data in the genlist/speclist.
598 * LIST_tag - Tag of the speclist
599 * ARG_list - The speclist to iterate.
600 * NAME_data - The name of the data iterator (defined inside the macro). */
601 #define MUTEXED_LIST_ITERATE(TYPE_data, LIST_tag, ARG_list, NAME_data) \
602 do { \
603 const struct genlist_link *NAME_data##_iter; \
604 TYPE_data *NAME_data; \
605 LIST_tag##_list_allocate_mutex(ARG_list); \
606 TYPED_LIST_CHECK(ARG_list); \
607 NAME_data##_iter = genlist_head((const struct genlist *) ARG_list); \
608 while (NULL != NAME_data##_iter) { \
609 NAME_data = (TYPE_data *) genlist_link_data(NAME_data##_iter); \
610 NAME_data##_iter = genlist_link_next(NAME_data##_iter);
612 /* Balance for above: */
613 #define MUTEXED_ITERATE_END(LIST_tag, ARG_list) \
615 LIST_tag##_list_release_mutex(ARG_list); \
616 } while (FALSE);
618 #define MUTEXED_ITERATE_BREAK(LIST_tag, ARG_list) \
619 do { \
620 LIST_tag##_list_release_mutex(ARG_list); \
621 } while (FALSE);
623 /* Same, but iterate backwards:
625 * TYPE_data - The real type of the data in the genlist/speclist.
626 * ARG_list - The speclist to iterate.
627 * NAME_data - The name of the data iterator (defined inside the macro). */
628 #define TYPED_LIST_ITERATE_REV(TYPE_data, ARG_list, NAME_data) \
629 do { \
630 const struct genlist_link *NAME_data##_iter; \
631 TYPE_data *NAME_data; \
632 TYPED_LIST_CHECK(ARG_list); \
633 NAME_data##_iter = genlist_tail((const struct genlist *) ARG_list); \
634 while (NULL != NAME_data##_iter) { \
635 NAME_data = (TYPE_data *) genlist_link_data(NAME_data##_iter); \
636 NAME_data##_iter = genlist_link_prev(NAME_data##_iter);
638 /* Balance for above: */
639 #define LIST_ITERATE_REV_END \
641 } while (FALSE);
643 /* Speclist link iterator.
645 * Using *_list_erase(NAME_link) is safe in this loop.
646 * Using *_list_clear() will result to use freed data. It must be avoided!
648 * TYPE_link - The real type of the link.
649 * ARG_list - The speclist to iterate.
650 * NAME_link - The name of the link iterator (defined inside the macro). */
651 #define TYPED_LIST_LINK_ITERATE(TYPE_link, ARG_list, NAME_link) \
652 do { \
653 TYPE_link *NAME_link = ((TYPE_link *) \
654 genlist_head((const struct genlist *) ARG_list)); \
655 TYPE_link *NAME_link##_next; \
656 TYPED_LIST_CHECK(ARG_list); \
657 for (; NULL != NAME_link; NAME_link = NAME_link##_next) { \
658 NAME_link##_next = ((TYPE_link *) \
659 genlist_link_next((struct genlist_link *) \
660 NAME_link));
662 /* Balance for above: */
663 #define LIST_LINK_ITERATE_END \
665 } while (FALSE);
667 /* Same, but iterate backwards:
669 * TYPE_link - The real type of the link.
670 * ARG_list - The speclist to iterate.
671 * NAME_link - The name of the link iterator (defined inside the macro). */
672 #define TYPED_LIST_LINK_ITERATE_REV(TYPE_link, ARG_list, NAME_link) \
673 do { \
674 TYPE_link *NAME_link = ((TYPE_link *) \
675 genlist_tail((const struct genlist *) ARG_list)); \
676 TYPE_link *NAME_link##_prev; \
677 TYPED_LIST_CHECK(ARG_list); \
678 for (; NULL != NAME_link; NAME_link = NAME_link##_prev) { \
679 NAME_link##_prev = ((TYPE_link *) \
680 genlist_link_prev((struct genlist_link *) \
681 NAME_link));
683 /* Balance for above: */
684 #define LIST_LINK_ITERATE_REV_END \
686 } while (FALSE);
688 /* Speclist link and data iterator.
690 * Using *_list_erase(NAME_link) is safe in this loop.
691 * Using *_list_clear() will result to use freed data. It must be avoided!
693 * TYPE_link - The real type of the link.
694 * TYPE_data - The real type of the data in the genlist/speclist.
695 * ARG_list - The speclist to iterate.
696 * NAME_link - The name of the link iterator (defined inside the macro).
697 * NAME_data - The name of the data iterator (defined inside the macro). */
698 #define TYPED_LIST_BOTH_ITERATE(TYPE_link, TYPE_data, \
699 ARG_list, NAME_link, NAME_data) \
700 do { \
701 TYPE_link *NAME_link = ((TYPE_link *) \
702 genlist_head((const struct genlist *) ARG_list)); \
703 TYPE_link *NAME_link##_next; \
704 TYPE_data *NAME_data; \
705 TYPED_LIST_CHECK(ARG_list); \
706 for (; NULL != NAME_link; NAME_link = NAME_link##_next) { \
707 NAME_link##_next = ((TYPE_link *) \
708 genlist_link_next((struct genlist_link *) \
709 NAME_link)); \
710 NAME_data = ((TYPE_data *) \
711 genlist_link_data((struct genlist_link *) NAME_link));
713 /* Balance for above: */
714 #define LIST_BOTH_ITERATE_END \
716 } while (FALSE);
718 /* Same, but iterate backwards:
720 * TYPE_link - The real type of the link.
721 * TYPE_data - The real type of the data in the genlist/speclist.
722 * ARG_list - The speclist to iterate.
723 * NAME_link - The name of the link iterator (defined inside the macro).
724 * NAME_data - The name of the data iterator (defined inside the macro). */
725 #define TYPED_LIST_BOTH_ITERATE_REV(TYPE_link, TYPE_data, \
726 ARG_list, NAME_link, NAME_data) \
727 do { \
728 TYPE_link *NAME_link = ((TYPE_link *) \
729 genlist_tail((const struct genlist *) ARG_list)); \
730 TYPE_link *NAME_link##_prev; \
731 TYPE_data *NAME_data; \
732 TYPED_LIST_CHECK(ARG_list); \
733 for (; NULL != NAME_link; NAME_link = NAME_link##_prev) { \
734 NAME_link##_prev = ((TYPE_link *) \
735 genlist_link_prev((struct genlist_link *) \
736 NAME_link)); \
737 NAME_data = ((TYPE_data *) \
738 genlist_link_data((struct genlist_link *) NAME_link));
740 /* Balance for above: */
741 #define LIST_BOTH_ITERATE_REV_END \
743 } while (FALSE);
745 #endif /* FC__SPECLIST_H */
747 /* This is after #endif FC__SPECLIST_H on purpose.
748 extern "C" portion begins well before latter part of the header
749 is guarded against multiple inclusions. */
750 #ifdef __cplusplus
752 #endif /* __cplusplus */