Freeciv21
Develop your civilization from humble roots to a global empire
speclist.h
Go to the documentation of this file.
1 /**************************************************************************
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  __ __ part of Freeciv21. Freeciv21 is free software: you can
4 / \\..// \ redistribute it and/or modify it under the terms of the GNU
5  ( oo ) General Public License as published by the Free Software
6  \__/ Foundation, either version 3 of the License, or (at your
7  option) any later version. You should have received
8  a copy of the GNU General Public License along with Freeciv21. If not,
9  see https://www.gnu.org/licenses/.
10 **************************************************************************/
11 
12 /* speclists: "specific genlists", by dwp.
13  * (A generalisation of previous city_list and unit_list stuff.)
14  *
15  * This file is used to implement a "specific" genlist.
16  * That is, a (sometimes) type-checked genlist. (Or at least a
17  * genlist with related functions with distinctly typed parameters.)
18  * (Or, maybe, what you end up doing when you don't use C++ ?)
19  *
20  * Before including this file, you must define the following:
21  * SPECLIST_TAG - this tag will be used to form names for functions etc.
22  * You may also define:
23  * SPECLIST_TYPE - the typed genlist will contain pointers to this type;
24  * If SPECLIST_TYPE is not defined, then 'struct SPECLIST_TAG' is used.
25  * At the end of this file, these (and other defines) are undef-ed.
26  *
27  * Assuming SPECLIST_TAG were 'foo', and SPECLIST_TYPE were 'foo_t',
28  * including this file would provide a struct definition for:
29  * struct foo_list;
30  * struct foo_list_link;
31  *
32  * function typedefs:
33  * typedef void (*foo_list_free_fn_t) (foo_t *);
34  * typedef foo_t * (*foo_list_copy_fn_t) (const foo_t *);
35  * typedef bool (*foo_list_comp_fn_t) (const foo_t *, const foo_t *);
36  * typedef bool (*foo_list_cond_fn_t) (const foo_t *);
37  *
38  * and prototypes for the following functions:
39  * struct foo_list *foo_list_new(void);
40  * struct foo_list *foo_list_new_full(foo_list_free_fn_t free_data_func);
41  * void foo_list_destroy(struct foo_list *plist);
42  * struct foo_list *foo_list_copy(const struct foolist *plist);
43  * struct foo_list *foo_list_copy_full(const struct foolist *plist,
44  * foo_list_copy_fn_t copy_data_func,
45  * foo_list_free_fn_t free_data_func);
46  * void foo_list_clear(struct foo_list *plist);
47  * void foo_list_unique(struct foo_list *plist);
48  * void foo_list_unique_full(struct foo_list *plist,
49  * foo_list_comp_fn_t comp_data_func);
50  * void foo_list_append(struct foo_list *plist, foo_t *pfoo);
51  * void foo_list_prepend(struct foo_list *plist, foo_t *pfoo);
52  * void foo_list_insert(struct foo_list *plist, foo_t *pfoo, int idx);
53  * void foo_list_insert_after(struct foo_list *plist, foo_t *pfoo,
54  * struct foo_list_link *plink);
55  * void foo_list_insert_before(struct foo_list *plist, foo_t *pfoo,
56  * struct foo_list_link *plink);
57  * bool foo_list_remove(struct foo_list *plist, const foo_t *pfoo);
58  * bool foo_list_remove_if(struct foo_list *plist,
59  * foo_list_cond_fn_t cond_data_func);
60  * int foo_list_remove_all(struct foo_list *plist, const foo_t *pfoo);
61  * int foo_list_remove_all_if(struct foo_list *plist,
62  * foo_list_cond_fn_t cond_data_func);
63  * void foo_list_erase(struct foo_list *plist,
64  * struct foo_list_link *plink);
65  * void foo_list_pop_front(struct foo_list *plist);
66  * void foo_list_pop_back(struct foo_list *plist);
67  * int foo_list_size(const struct foo_list *plist);
68  * foo_t *foo_list_get(const struct foo_list *plist, int idx);
69  * foo_t *foo_list_front(const struct foo_list *plist);
70  * foo_t *foo_list_back(const struct foo_list *plist);
71  * struct foo_list_link *foo_list_link_get(const struct foo_list *plist,
72  * int idx);
73  * struct foo_list_link *foo_list_head(const struct foo_list *plist);
74  * struct foo_list_link *foo_list_tail(const struct foo_list *plist);
75  * struct foo_list_link *foo_list_search(const struct foo_list *plist,
76  * const void *data);
77  * struct foo_list_link *foo_list_search_if(const struct foo_list *plist,
78  * foo_list_cond_fn_t
79  * cond_data_func);
80  * void foo_list_sort(struct foo_list *plist,
81  * int (*compar) (const foo_t *const *, const foo_t *const *));
82  * void foo_list_shuffle(struct foo_list *plist);
83  * void foo_list_reverse(struct foo_list *plist);
84  * void foo_list_allocate_mutex(struct foo_list *plist);
85  * void foo_list_release_mutex(struct foo_list *plist);
86  * foo_t *foo_list_link_data(const struct foo_list_link *plink);
87  * struct foo_list_link *
88  * foo_list_link_prev(const struct foo_list_link *plink);
89  * struct foo_list_link *
90  * foo_list_link_next(const struct foo_list_link *plink);
91  *
92  * You should also define yourself (this file cannot do this for you):
93  * #define foo_list_iterate(foolist, pfoo) \
94  * TYPED_LIST_ITERATE(foo_t, foolist, pfoo)
95  * #define foo_list_iterate_end LIST_ITERATE_END
96  *
97  * #define foo_list_iterate_rev(foolist, pfoo) \
98  * TYPED_LIST_ITERATE_REV(foo_t, foolist, pfoo)
99  * #define foo_list_iterate_rev_end LIST_ITERATE_REV_END
100  *
101  * #define foo_list_link_iterate(foolist, plink) \
102  * TYPED_LIST_LINK_ITERATE(struct foo_list_link, foolist, plink)
103  * #define foo_list_link_iterate_end LIST_LINK_ITERATE_END
104  *
105  * #define foo_list_link_iterate_rev(foolist, plink) \
106  * TYPED_LIST_LINK_ITERATE_REV(struct foo_list_link, foolist, plink)
107  * #define foo_list_link_iterate_rev_end LIST_LINK_ITERATE_REV_END
108  *
109  * #define foo_list_both_iterate(foolist, plink, pfoo) \
110  * TYPED_LIST_BOTH_ITERATE(struct foo_list_link, foo_t, \
111  foolist, plink, pfoo)
112  * #define foo_list_both_iterate_end LIST_BOTH_ITERATE_END
113  *
114  * #define foo_list_both_iterate_rev(foolist, pfoo) \
115  * TYPED_LIST_BOTH_ITERATE_REV(struct foo_list_link, foo_t, \
116  foolist, plink, pfoo)
117  * #define foo_list_both_iterate_rev_end LIST_BOTH_ITERATE_REV_END
118  *
119  * Note this is not protected against multiple inclusions; this is so that
120  * you can have multiple different speclists. For each speclist, this file
121  * should be included _once_, inside a .h file which _is_ itself protected
122  * against multiple inclusions. */
123 
124 #include "genlist.h"
125 
126 #ifndef SPECLIST_TAG
127 #error Must define a SPECLIST_TAG to use this header
128 #endif
129 
130 #ifndef SPECLIST_TYPE
131 #define SPECLIST_TYPE struct SPECLIST_TAG
132 #endif
133 
134 #define SPECLIST_PASTE_(x, y) x##y
135 #define SPECLIST_PASTE(x, y) SPECLIST_PASTE_(x, y)
136 
137 #define SPECLIST_LIST struct SPECLIST_PASTE(SPECLIST_TAG, _list)
138 #define SPECLIST_LINK struct SPECLIST_PASTE(SPECLIST_TAG, _list_link)
139 #define SPECLIST_FOO(suffix) SPECLIST_PASTE(SPECLIST_TAG, suffix)
140 
141 // Dummy type. Actually a genlist, and not defined anywhere.
143 
144 // Dummy type. Actually a genlist_link, and not defined anywhere.
146 
147 // Function related typedefs.
148 typedef void (*SPECLIST_FOO(_list_free_fn_t))(SPECLIST_TYPE *);
149 typedef SPECLIST_TYPE *(*SPECLIST_FOO(_list_copy_fn_t))(
150  const SPECLIST_TYPE *);
151 typedef bool (*SPECLIST_FOO(_list_comp_fn_t))(const SPECLIST_TYPE *,
152  const SPECLIST_TYPE *);
153 typedef bool (*SPECLIST_FOO(_list_cond_fn_t))(const SPECLIST_TYPE *);
154 
155 /****************************************************************************
156  Create a new speclist.
157 ****************************************************************************/
158 static inline SPECLIST_LIST *
160 
162 {
163  return reinterpret_cast<SPECLIST_LIST *>(genlist_new());
164 }
165 
166 /****************************************************************************
167  Create a new speclist with a free callback.
168 ****************************************************************************/
169 static inline SPECLIST_LIST *
170  SPECLIST_FOO(_list_new_full)(SPECLIST_FOO(_list_free_fn_t)
171  free_data_func) fc__warn_unused_result;
172 
173 static inline SPECLIST_LIST *
175  free_data_func)
176 {
177  return (reinterpret_cast<SPECLIST_LIST *>(genlist_new_full(
178  reinterpret_cast<genlist_free_fn_t>(free_data_func))));
179 }
180 
181 /****************************************************************************
182  Free a speclist.
183 ****************************************************************************/
184 static inline void SPECLIST_FOO(_list_destroy)(SPECLIST_LIST *tthis)
185 {
186  genlist_destroy(reinterpret_cast<struct genlist *>(tthis));
187 }
188 
189 /****************************************************************************
190  Duplicate a speclist.
191 ****************************************************************************/
192 static inline SPECLIST_LIST *SPECLIST_FOO(_list_copy)(
194 
195 static inline SPECLIST_LIST *
197 {
198  return reinterpret_cast<SPECLIST_LIST *>(
199  genlist_copy(reinterpret_cast<const struct genlist *>(tthis)));
200 }
201 
202 /****************************************************************************
203  Duplicate a speclist with a free callback and a function to copy each
204  element.
205 ****************************************************************************/
207  const SPECLIST_LIST *tthis, SPECLIST_FOO(_list_copy_fn_t) copy_data_func,
208  SPECLIST_FOO(_list_free_fn_t) free_data_func) fc__warn_unused_result;
209 
211  const SPECLIST_LIST *tthis, SPECLIST_FOO(_list_copy_fn_t) copy_data_func,
212  SPECLIST_FOO(_list_free_fn_t) free_data_func)
213 {
214  return (reinterpret_cast<SPECLIST_LIST *>(genlist_copy_full(
215  reinterpret_cast<const struct genlist *>(tthis),
216  reinterpret_cast<genlist_copy_fn_t>(copy_data_func),
217  reinterpret_cast<genlist_free_fn_t>(free_data_func))));
218 }
219 
220 /****************************************************************************
221  Remove all elements from the speclist.
222 ****************************************************************************/
223 static inline void SPECLIST_FOO(_list_clear)(SPECLIST_LIST *tthis)
224 {
225  genlist_clear(reinterpret_cast<struct genlist *>(tthis));
226 }
227 
228 /****************************************************************************
229  Remove all element duplicates (the speclist must be sorted before).
230 ****************************************************************************/
231 static inline void SPECLIST_FOO(_list_unique)(SPECLIST_LIST *tthis)
232 {
233  genlist_unique(reinterpret_cast<struct genlist *>(tthis));
234 }
235 
236 /****************************************************************************
237  Remove all element duplicates (the speclist must be sorted before), using
238  'comp_data_func' to determine if the elements are equivalents.
239 ****************************************************************************/
240 static inline void SPECLIST_FOO(_list_unique_full)(
241  SPECLIST_LIST *tthis, SPECLIST_FOO(_list_comp_fn_t) comp_data_func)
242 {
243  genlist_unique_full(reinterpret_cast<struct genlist *>(tthis),
244  reinterpret_cast<genlist_comp_fn_t>(comp_data_func));
245 }
246 
247 /****************************************************************************
248  Push back an element into the speclist.
249 ****************************************************************************/
250 static inline void SPECLIST_FOO(_list_append)(SPECLIST_LIST *tthis,
251  SPECLIST_TYPE *pfoo)
252 {
253  genlist_append(reinterpret_cast<struct genlist *>(tthis), pfoo);
254 }
255 
256 /****************************************************************************
257  Push front an element into the speclist.
258 ****************************************************************************/
259 static inline void SPECLIST_FOO(_list_prepend)(SPECLIST_LIST *tthis,
260  SPECLIST_TYPE *pfoo)
261 {
262  genlist_prepend(reinterpret_cast<struct genlist *>(tthis), pfoo);
263 }
264 
265 /****************************************************************************
266  Insert an element into the speclist at the given position.
267 ****************************************************************************/
268 static inline void SPECLIST_FOO(_list_insert)(SPECLIST_LIST *tthis,
269  SPECLIST_TYPE *pfoo, int idx)
270 {
271  genlist_insert(reinterpret_cast<struct genlist *>(tthis), pfoo, idx);
272 }
273 
274 /****************************************************************************
275  Insert an element after the specified link.
276 ****************************************************************************/
277 static inline void SPECLIST_FOO(_list_insert_after)(SPECLIST_LIST *tthis,
278  SPECLIST_TYPE *pfoo,
279  SPECLIST_LINK *plink)
280 {
281  genlist_insert_after(reinterpret_cast<struct genlist *>(tthis), pfoo,
282  reinterpret_cast<struct genlist_link *>(plink));
283 }
284 
285 /****************************************************************************
286  Insert an element before the specified link.
287 ****************************************************************************/
288 static inline void SPECLIST_FOO(_list_insert_before)(SPECLIST_LIST *tthis,
289  SPECLIST_TYPE *pfoo,
290  SPECLIST_LINK *plink)
291 {
292  genlist_insert_before(reinterpret_cast<struct genlist *>(tthis), pfoo,
293  reinterpret_cast<struct genlist_link *>(plink));
294 }
295 
296 /****************************************************************************
297  Search 'pfoo' in the speclist, and remove it. Returns TRUE on success.
298 ****************************************************************************/
299 static inline bool SPECLIST_FOO(_list_remove)(SPECLIST_LIST *tthis,
300  const SPECLIST_TYPE *pfoo)
301 {
302  return genlist_remove(reinterpret_cast<struct genlist *>(tthis), pfoo);
303 }
304 
305 /****************************************************************************
306  Remove the first element which fit the conditional function. Returns
307  TRUE on success.
308 ****************************************************************************/
309 static inline bool SPECLIST_FOO(_list_remove_if)(
310  SPECLIST_LIST *tthis, SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
311 {
312  return genlist_remove_if(
313  reinterpret_cast<struct genlist *>(tthis),
314  reinterpret_cast<genlist_cond_fn_t>(cond_data_func));
315 }
316 
317 /****************************************************************************
318  Remove 'pfoo' of the whole list. Returns the number of removed elements.
319 ****************************************************************************/
320 static inline int SPECLIST_FOO(_list_remove_all)(SPECLIST_LIST *tthis,
321  const SPECLIST_TYPE *pfoo)
322 {
323  return genlist_remove_all(reinterpret_cast<struct genlist *>(tthis), pfoo);
324 }
325 
326 /****************************************************************************
327  Remove all elements which fit the conditional function. Returns the
328  number of removed elements.
329 ****************************************************************************/
330 static inline bool SPECLIST_FOO(_list_remove_all_if)(
331  SPECLIST_LIST *tthis, SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
332 {
333  return genlist_remove_all_if(
334  reinterpret_cast<struct genlist *>(tthis),
335  reinterpret_cast<genlist_cond_fn_t>(cond_data_func));
336 }
337 
338 /****************************************************************************
339  Remove the elements pointed by 'plink'. Returns the next element of the
340  speclist.
341 
342  NB: After calling this function 'plink' is no more usable. You should
343  have saved the next or previous link before.
344 ****************************************************************************/
345 static inline void SPECLIST_FOO(_list_erase)(SPECLIST_LIST *tthis,
346  SPECLIST_LINK *plink)
347 {
348  genlist_erase(reinterpret_cast<struct genlist *>(tthis),
349  reinterpret_cast<struct genlist_link *>(plink));
350 }
351 
352 /****************************************************************************
353  Remove the first element of the speclist.
354 ****************************************************************************/
355 static inline void SPECLIST_FOO(_list_pop_front)(SPECLIST_LIST *tthis)
356 {
357  genlist_pop_front(reinterpret_cast<struct genlist *>(tthis));
358 }
359 
360 /****************************************************************************
361  Remove the last element of the speclist.
362 ****************************************************************************/
363 static inline void SPECLIST_FOO(_list_pop_back)(SPECLIST_LIST *tthis)
364 {
365  genlist_pop_back(reinterpret_cast<struct genlist *>(tthis));
366 }
367 
368 /****************************************************************************
369  Return the number of elements inside the speclist.
370 ****************************************************************************/
371 static inline int SPECLIST_FOO(_list_size)(const SPECLIST_LIST *tthis)
372 {
373  return genlist_size(reinterpret_cast<const struct genlist *>(tthis));
374 }
375 
376 /****************************************************************************
377  Return the element at position in the speclist.
378 ****************************************************************************/
379 static inline SPECLIST_TYPE *
380  SPECLIST_FOO(_list_get)(const SPECLIST_LIST *tthis, int slindex)
381 {
382  return (static_cast<SPECLIST_TYPE *>(genlist_get(
383  reinterpret_cast<const struct genlist *>(tthis), slindex)));
384 }
385 
386 /****************************************************************************
387  Return the first element of the speclist.
388 ****************************************************************************/
389 static inline SPECLIST_TYPE *
391 {
392  return static_cast<SPECLIST_TYPE *>(
393  genlist_front(reinterpret_cast<const struct genlist *>(tthis)));
394 }
395 
396 /****************************************************************************
397  Return the last element of the speclist.
398 ****************************************************************************/
399 static inline SPECLIST_TYPE *
401 {
402  return static_cast<SPECLIST_TYPE *>(
403  genlist_back(reinterpret_cast<const struct genlist *>(tthis)));
404 }
405 
406 /****************************************************************************
407  Return the element at position in the speclist.
408 ****************************************************************************/
409 static inline SPECLIST_LINK *
410  SPECLIST_FOO(_list_link_get)(const SPECLIST_LIST *tthis, int slindex)
411 {
412  return (reinterpret_cast<SPECLIST_LINK *>(genlist_link_get(
413  reinterpret_cast<const struct genlist *>(tthis), slindex)));
414 }
415 
416 /****************************************************************************
417  Return the head link of the speclist.
418 ****************************************************************************/
419 static inline SPECLIST_LINK *
421 {
422  return reinterpret_cast<SPECLIST_LINK *>(
423  genlist_head(reinterpret_cast<const struct genlist *>(tthis)));
424 }
425 
426 /****************************************************************************
427  Return the tail link of the speclist.
428 ****************************************************************************/
429 static inline SPECLIST_LINK *
431 {
432  return reinterpret_cast<SPECLIST_LINK *>(
433  genlist_tail(reinterpret_cast<const struct genlist *>(tthis)));
434 }
435 
436 /****************************************************************************
437  Return the link of the first element which match the data 'pfoo'.
438 ****************************************************************************/
439 static inline SPECLIST_LINK *
441  const SPECLIST_TYPE *pfoo)
442 {
443  return (reinterpret_cast<SPECLIST_LINK *>(genlist_search(
444  reinterpret_cast<const struct genlist *>(tthis), pfoo)));
445 }
446 
447 /****************************************************************************
448  Return the link of the first element which match the conditional function.
449 ****************************************************************************/
451  const SPECLIST_LIST *tthis, SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
452 {
453  return (reinterpret_cast<SPECLIST_LINK *>(genlist_search_if(
454  reinterpret_cast<const struct genlist *>(tthis),
455  reinterpret_cast<genlist_cond_fn_t>(cond_data_func))));
456 }
457 
458 /****************************************************************************
459  Sort the speclist.
460 ****************************************************************************/
461 static inline void
463  int (*compar)(const SPECLIST_TYPE *const *,
464  const SPECLIST_TYPE *const *))
465 {
466  genlist_sort(
467  reinterpret_cast<struct genlist *>(tthis),
468  reinterpret_cast<int (*)(const void *, const void *)>(compar));
469 }
470 
471 /****************************************************************************
472  Shuffle the speclist.
473 ****************************************************************************/
474 static inline void SPECLIST_FOO(_list_shuffle)(SPECLIST_LIST *tthis)
475 {
476  genlist_shuffle(reinterpret_cast<struct genlist *>(tthis));
477 }
478 
479 /****************************************************************************
480  Reverse the order of the elements of the speclist.
481 ****************************************************************************/
482 static inline void SPECLIST_FOO(_list_reverse)(SPECLIST_LIST *tthis)
483 {
484  genlist_reverse(reinterpret_cast<struct genlist *>(tthis));
485 }
486 
487 /****************************************************************************
488  Allocate speclist mutex
489 ****************************************************************************/
491 {
492  genlist_allocate_mutex(reinterpret_cast<struct genlist *>(tthis));
493 }
494 
495 /****************************************************************************
496  Release speclist mutex
497 ****************************************************************************/
498 static inline void SPECLIST_FOO(_list_release_mutex)(SPECLIST_LIST *tthis)
499 {
500  genlist_release_mutex(reinterpret_cast<struct genlist *>(tthis));
501 }
502 
503 /****************************************************************************
504  Return the data of the link.
505 ****************************************************************************/
506 static inline SPECLIST_TYPE *
508 {
509  return (static_cast<SPECLIST_TYPE *>(genlist_link_data(
510  reinterpret_cast<const struct genlist_link *>(plink))));
511 }
512 
513 /****************************************************************************
514  Return the previous link.
515 ****************************************************************************/
518 
519 static inline SPECLIST_LINK *
521 {
522  return (reinterpret_cast<SPECLIST_LINK *>(genlist_link_prev(
523  reinterpret_cast<const struct genlist_link *>(plink))));
524 }
525 
526 /****************************************************************************
527  Return the next link.
528 ****************************************************************************/
531 
532 static inline SPECLIST_LINK *
534 {
535  return (reinterpret_cast<SPECLIST_LINK *>(genlist_link_next(
536  reinterpret_cast<const struct genlist_link *>(plink))));
537 }
538 
539 #undef SPECLIST_TAG
540 #undef SPECLIST_TYPE
541 #undef SPECLIST_PASTE_
542 #undef SPECLIST_PASTE
543 #undef SPECLIST_LIST
544 #undef SPECLIST_FOO
545 
546 // Base macros that the users can specialize.
547 #ifndef FC__SPECLIST_H /* Defines this only once, no multiple inclusions. \
548  */
549 #define FC__SPECLIST_H
550 
551 #ifdef FREECIV_DEBUG
552 #define TYPED_LIST_CHECK(ARG_list) \
553  fc_assert_action(nullptr != ARG_list, break)
554 #else
555 #define TYPED_LIST_CHECK(ARG_list) // Nothing.
556 #endif // FREECIV_DEBUG
557 
558 /* Speclist data iterator.
559  *
560  * Using *_list_remove(NAME_data) is safe in this loop (but it may be
561  * inefficient due to the linear research of the data, see also
562  * *_list_erase()).
563  * Using *_list_clear() will result to use freed data. It must be avoided!
564  *
565  * TYPE_data - The real type of the data in the genlist/speclist.
566  * ARG_list - The speclist to iterate.
567  * NAME_data - The name of the data iterator (defined inside the macro). */
568 #define TYPED_LIST_ITERATE(TYPE_data, ARG_list, NAME_data) \
569  do { \
570  const struct genlist_link *NAME_data##_iter; \
571  TYPE_data *NAME_data; \
572  TYPED_LIST_CHECK(ARG_list); \
573  NAME_data##_iter = genlist_head((const struct genlist *) ARG_list); \
574  while (nullptr != NAME_data##_iter) { \
575  NAME_data = (TYPE_data *) genlist_link_data(NAME_data##_iter); \
576  NAME_data##_iter = genlist_link_next(NAME_data##_iter);
577 
578 // Balance for above:
579 #define LIST_ITERATE_END \
580  } \
581  } \
582  while (false) \
583  ;
584 
585 /* Mutex protected speclist data iterator.
586  *
587  * Using *_list_remove(NAME_data) is safe in this loop (but it may be
588  * inefficient due to the linear research of the data, see also
589  * *_list_erase()).
590  * Using *_list_clear() will result to use freed data. It must be avoided!
591  *
592  * TYPE_data - The real type of the data in the genlist/speclist.
593  * LIST_tag - Tag of the speclist
594  * ARG_list - The speclist to iterate.
595  * NAME_data - The name of the data iterator (defined inside the macro). */
596 #define MUTEXED_LIST_ITERATE(TYPE_data, LIST_tag, ARG_list, NAME_data) \
597  do { \
598  const struct genlist_link *NAME_data##_iter; \
599  TYPE_data *NAME_data; \
600  LIST_tag##_list_allocate_mutex(ARG_list); \
601  TYPED_LIST_CHECK(ARG_list); \
602  NAME_data##_iter = genlist_head((const struct genlist *) ARG_list); \
603  while (nullptr != NAME_data##_iter) { \
604  NAME_data = (TYPE_data *) genlist_link_data(NAME_data##_iter); \
605  NAME_data##_iter = genlist_link_next(NAME_data##_iter);
606 
607 // Balance for above:
608 #define MUTEXED_ITERATE_END(LIST_tag, ARG_list) \
609  } \
610  LIST_tag##_list_release_mutex(ARG_list); \
611  } \
612  while (false) \
613  ;
614 
615 #define MUTEXED_ITERATE_BREAK(LIST_tag, ARG_list) \
616  do { \
617  LIST_tag##_list_release_mutex(ARG_list); \
618  } while (false);
619 
620 /* Same, but iterate backwards:
621  *
622  * TYPE_data - The real type of the data in the genlist/speclist.
623  * ARG_list - The speclist to iterate.
624  * NAME_data - The name of the data iterator (defined inside the macro). */
625 #define TYPED_LIST_ITERATE_REV(TYPE_data, ARG_list, NAME_data) \
626  do { \
627  const struct genlist_link *NAME_data##_iter; \
628  TYPE_data *NAME_data; \
629  TYPED_LIST_CHECK(ARG_list); \
630  NAME_data##_iter = genlist_tail((const struct genlist *) ARG_list); \
631  while (nullptr != NAME_data##_iter) { \
632  NAME_data = (TYPE_data *) genlist_link_data(NAME_data##_iter); \
633  NAME_data##_iter = genlist_link_prev(NAME_data##_iter);
634 
635 // Balance for above:
636 #define LIST_ITERATE_REV_END \
637  } \
638  } \
639  while (false) \
640  ;
641 
642 /* Speclist link iterator.
643  *
644  * Using *_list_erase(NAME_link) is safe in this loop.
645  * Using *_list_clear() will result to use freed data. It must be avoided!
646  *
647  * TYPE_link - The real type of the link.
648  * ARG_list - The speclist to iterate.
649  * NAME_link - The name of the link iterator (defined inside the macro). */
650 #define TYPED_LIST_LINK_ITERATE(TYPE_link, ARG_list, NAME_link) \
651  do { \
652  TYPE_link *NAME_link = \
653  ((TYPE_link *) genlist_head((const struct genlist *) ARG_list)); \
654  TYPE_link *NAME_link##_next; \
655  TYPED_LIST_CHECK(ARG_list); \
656  for (; nullptr != NAME_link; NAME_link = NAME_link##_next) { \
657  NAME_link##_next = ((TYPE_link *) genlist_link_next( \
658  (struct genlist_link *) NAME_link));
659 
660 // Balance for above:
661 #define LIST_LINK_ITERATE_END \
662  } \
663  } \
664  while (false) \
665  ;
666 
667 /* Same, but iterate backwards:
668  *
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 = \
675  ((TYPE_link *) genlist_tail((const struct genlist *) ARG_list)); \
676  TYPE_link *NAME_link##_prev; \
677  TYPED_LIST_CHECK(ARG_list); \
678  for (; nullptr != NAME_link; NAME_link = NAME_link##_prev) { \
679  NAME_link##_prev = ((TYPE_link *) genlist_link_prev( \
680  (struct genlist_link *) NAME_link));
681 
682 // Balance for above:
683 #define LIST_LINK_ITERATE_REV_END \
684  } \
685  } \
686  while (false) \
687  ;
688 
689 /* Speclist link and data iterator.
690  *
691  * Using *_list_erase(NAME_link) is safe in this loop.
692  * Using *_list_clear() will result to use freed data. It must be avoided!
693  *
694  * TYPE_link - The real type of the link.
695  * TYPE_data - The real type of the data in the genlist/speclist.
696  * ARG_list - The speclist to iterate.
697  * NAME_link - The name of the link iterator (defined inside the macro).
698  * NAME_data - The name of the data iterator (defined inside the macro). */
699 #define TYPED_LIST_BOTH_ITERATE(TYPE_link, TYPE_data, ARG_list, NAME_link, \
700  NAME_data) \
701  do { \
702  TYPE_link *NAME_link = \
703  ((TYPE_link *) genlist_head((const struct genlist *) ARG_list)); \
704  TYPE_link *NAME_link##_next; \
705  TYPE_data *NAME_data; \
706  TYPED_LIST_CHECK(ARG_list); \
707  for (; nullptr != NAME_link; NAME_link = NAME_link##_next) { \
708  NAME_link##_next = ((TYPE_link *) genlist_link_next( \
709  (struct genlist_link *) NAME_link)); \
710  NAME_data = ((TYPE_data *) genlist_link_data( \
711  (struct genlist_link *) NAME_link));
712 
713 // Balance for above:
714 #define LIST_BOTH_ITERATE_END \
715  } \
716  } \
717  while (false) \
718  ;
719 
720 /* Same, but iterate backwards:
721  *
722  * TYPE_link - The real type of the link.
723  * TYPE_data - The real type of the data in the genlist/speclist.
724  * ARG_list - The speclist to iterate.
725  * NAME_link - The name of the link iterator (defined inside the macro).
726  * NAME_data - The name of the data iterator (defined inside the macro). */
727 #define TYPED_LIST_BOTH_ITERATE_REV(TYPE_link, TYPE_data, ARG_list, \
728  NAME_link, NAME_data) \
729  do { \
730  TYPE_link *NAME_link = \
731  ((TYPE_link *) genlist_tail((const struct genlist *) ARG_list)); \
732  TYPE_link *NAME_link##_prev; \
733  TYPE_data *NAME_data; \
734  TYPED_LIST_CHECK(ARG_list); \
735  for (; nullptr != NAME_link; NAME_link = NAME_link##_prev) { \
736  NAME_link##_prev = ((TYPE_link *) genlist_link_prev( \
737  (struct genlist_link *) NAME_link)); \
738  NAME_data = ((TYPE_data *) genlist_link_data( \
739  (struct genlist_link *) NAME_link));
740 
741 // Balance for above:
742 #define LIST_BOTH_ITERATE_REV_END \
743  } \
744  } \
745  while (false) \
746  ;
747 
748 #endif // FC__SPECLIST_H
749 
750 /* This is after #endif FC__SPECLIST_H on purpose.
751  extern "C" portion begins well before latter part of the header
752  is guarded against multiple inclusions. */
bool genlist_remove(struct genlist *pgenlist, const void *punlink)
Remove an element of the genlist with the specified user-data pointer given by 'punlink'.
Definition: genlist.cpp:317
void genlist_allocate_mutex(struct genlist *pgenlist)
Allocates list mutex.
Definition: genlist.cpp:676
void genlist_insert(struct genlist *pgenlist, void *data, int pos)
Insert a new element in the list, at position 'pos', with the specified user-data pointer 'data'.
Definition: genlist.cpp:465
void genlist_release_mutex(struct genlist *pgenlist)
Releases list mutex.
Definition: genlist.cpp:684
void * genlist_get(const struct genlist *pgenlist, int idx)
Returns the user-data pointer stored in the genlist at the position given by 'idx'.
Definition: genlist.cpp:212
struct genlist_link * genlist_search_if(const struct genlist *pgenlist, genlist_cond_fn_t cond_data_func)
Return the link which fit the conditional function.
Definition: genlist.cpp:558
void * genlist_back(const struct genlist *pgenlist)
Returns the user-data pointer stored in the last element of the genlist.
Definition: genlist.cpp:228
int genlist_remove_all(struct genlist *pgenlist, const void *punlink)
Remove all elements of the genlist with the specified user-data pointer given by 'punlink'.
Definition: genlist.cpp:339
void genlist_erase(struct genlist *pgenlist, struct genlist_link *plink)
Remove the element pointed to plink.
Definition: genlist.cpp:424
void genlist_clear(struct genlist *pgenlist)
Frees all the internal data used by the genlist (but doesn't touch the user-data).
Definition: genlist.cpp:238
void genlist_prepend(struct genlist *pgenlist, void *data)
Insert an item at the start of the list.
Definition: genlist.cpp:515
bool genlist_remove_if(struct genlist *pgenlist, genlist_cond_fn_t cond_data_func)
Remove the first element of the genlist which fit the function (the function return TRUE).
Definition: genlist.cpp:367
void genlist_append(struct genlist *pgenlist, void *data)
Insert an item at the end of the list.
Definition: genlist.cpp:525
void genlist_unique_full(struct genlist *pgenlist, genlist_comp_fn_t comp_data_func)
Remove all duplicates of element from every consecutive group of equal elements in the list (equality...
Definition: genlist.cpp:280
struct genlist_link * genlist_tail(const struct genlist *pgenlist)
Returns the tail link of the genlist.
Definition: genlist.cpp:201
struct genlist_link * genlist_link_get(const struct genlist *pgenlist, int idx)
Returns the link in the genlist at the position given by 'idx'.
Definition: genlist.cpp:190
void genlist_destroy(struct genlist *pgenlist)
Destroys the genlist.
Definition: genlist.cpp:45
void genlist_pop_front(struct genlist *pgenlist)
Remove the first element of the genlist.
Definition: genlist.cpp:436
void * genlist_front(const struct genlist *pgenlist)
Returns the user-data pointer stored in the first element of the genlist.
Definition: genlist.cpp:220
void genlist_insert_before(struct genlist *pgenlist, void *data, struct genlist_link *plink)
Insert an item before the link.
Definition: genlist.cpp:502
int genlist_remove_all_if(struct genlist *pgenlist, genlist_cond_fn_t cond_data_func)
Remove all elements of the genlist which fit the function (the function return TRUE).
Definition: genlist.cpp:392
void genlist_unique(struct genlist *pgenlist)
Remove all duplicates of element from every consecutive group of equal elements in the list.
Definition: genlist.cpp:270
void genlist_insert_after(struct genlist *pgenlist, void *data, struct genlist_link *plink)
Insert an item after the link.
Definition: genlist.cpp:490
struct genlist * genlist_copy(const struct genlist *pgenlist)
Returns a new genlist that's a copy of the existing one.
Definition: genlist.cpp:144
void genlist_sort(struct genlist *pgenlist, int(*compar)(const void *, const void *))
Sort the elements of a genlist.
Definition: genlist.cpp:587
void genlist_reverse(struct genlist *pgenlist)
Reverse the order of the elements in the genlist.
Definition: genlist.cpp:653
struct genlist_link * genlist_search(const struct genlist *pgenlist, const void *data)
Return the link where data is equal to 'data'.
Definition: genlist.cpp:538
void genlist_pop_back(struct genlist *pgenlist)
Remove the last element of the genlist.
Definition: genlist.cpp:448
struct genlist * genlist_new()
Create a new empty genlist.
Definition: genlist.cpp:25
struct genlist * genlist_new_full(genlist_free_fn_t free_data_func)
Create a new empty genlist with a free data function.
Definition: genlist.cpp:30
struct genlist * genlist_copy_full(const struct genlist *pgenlist, genlist_copy_fn_t copy_data_func, genlist_free_fn_t free_data_func)
Returns a new genlist that's a copy of the existing one.
Definition: genlist.cpp:152
int genlist_size(const struct genlist *pgenlist)
Returns the number of elements stored in the genlist.
Definition: genlist.cpp:179
void genlist_shuffle(struct genlist *pgenlist)
Randomize the elements of a genlist using the Fisher-Yates shuffle.
Definition: genlist.cpp:619
static struct genlist_link * genlist_head(const struct genlist *pgenlist)
Definition: genlist.h:104
static void * genlist_link_data(const struct genlist_link *plink)
Definition: genlist.h:133
bool(* genlist_cond_fn_t)(const void *)
Definition: genlist.h:47
static fc__warn_unused_result struct genlist_link * genlist_link_next(const struct genlist_link *plink)
Definition: genlist.h:151
bool(* genlist_comp_fn_t)(const void *, const void *)
Definition: genlist.h:48
static fc__warn_unused_result struct genlist_link * genlist_link_prev(const struct genlist_link *plink)
Definition: genlist.h:142
void(* genlist_free_fn_t)(void *)
Definition: genlist.h:45
void *(* genlist_copy_fn_t)(const void *)
Definition: genlist.h:46
static void SPECLIST_FOO() _list_sort(SPECLIST_LIST *tthis, int(*compar)(const SPECLIST_TYPE *const *, const SPECLIST_TYPE *const *))
Definition: speclist.h:462
static void SPECLIST_FOO() _list_append(SPECLIST_LIST *tthis, SPECLIST_TYPE *pfoo)
Definition: speclist.h:250
static SPECLIST_LIST *SPECLIST_FOO() _list_new_full(SPECLIST_FOO(_list_free_fn_t) free_data_func) fc__warn_unused_result
Definition: speclist.h:174
static int SPECLIST_FOO() _list_size(const SPECLIST_LIST *tthis)
Definition: speclist.h:371
static SPECLIST_LINK *SPECLIST_FOO() _list_search_if(const SPECLIST_LIST *tthis, SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
Definition: speclist.h:450
static void SPECLIST_FOO() _list_erase(SPECLIST_LIST *tthis, SPECLIST_LINK *plink)
Definition: speclist.h:345
static SPECLIST_TYPE *SPECLIST_FOO() _list_get(const SPECLIST_LIST *tthis, int slindex)
Definition: speclist.h:380
static bool SPECLIST_FOO() _list_remove(SPECLIST_LIST *tthis, const SPECLIST_TYPE *pfoo)
Definition: speclist.h:299
static void SPECLIST_FOO() _list_prepend(SPECLIST_LIST *tthis, SPECLIST_TYPE *pfoo)
Definition: speclist.h:259
static void SPECLIST_FOO() _list_pop_front(SPECLIST_LIST *tthis)
Definition: speclist.h:355
static void SPECLIST_FOO() _list_pop_back(SPECLIST_LIST *tthis)
Definition: speclist.h:363
static void SPECLIST_FOO() _list_insert_before(SPECLIST_LIST *tthis, SPECLIST_TYPE *pfoo, SPECLIST_LINK *plink)
Definition: speclist.h:288
static bool SPECLIST_FOO() _list_remove_if(SPECLIST_LIST *tthis, SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
Definition: speclist.h:309
#define SPECLIST_LINK
Definition: speclist.h:138
static SPECLIST_TYPE *SPECLIST_FOO() _list_back(const SPECLIST_LIST *tthis)
Definition: speclist.h:400
static SPECLIST_LIST *SPECLIST_FOO() _list_new() fc__warn_unused_result
Definition: speclist.h:161
static void SPECLIST_FOO() _list_clear(SPECLIST_LIST *tthis)
Definition: speclist.h:223
static void SPECLIST_FOO() _list_reverse(SPECLIST_LIST *tthis)
Definition: speclist.h:482
static void SPECLIST_FOO() _list_insert_after(SPECLIST_LIST *tthis, SPECLIST_TYPE *pfoo, SPECLIST_LINK *plink)
Definition: speclist.h:277
static SPECLIST_LINK *SPECLIST_FOO() _list_head(const SPECLIST_LIST *tthis)
Definition: speclist.h:420
static void SPECLIST_FOO() _list_allocate_mutex(SPECLIST_LIST *tthis)
Definition: speclist.h:490
static void SPECLIST_FOO() _list_shuffle(SPECLIST_LIST *tthis)
Definition: speclist.h:474
static void SPECLIST_FOO() _list_insert(SPECLIST_LIST *tthis, SPECLIST_TYPE *pfoo, int idx)
Definition: speclist.h:268
static SPECLIST_LINK *SPECLIST_FOO() _list_tail(const SPECLIST_LIST *tthis)
Definition: speclist.h:430
static SPECLIST_LINK *SPECLIST_FOO() _list_link_get(const SPECLIST_LIST *tthis, int slindex)
Definition: speclist.h:410
static SPECLIST_LIST *SPECLIST_FOO() _list_copy(const SPECLIST_LIST *tthis) fc__warn_unused_result
Definition: speclist.h:196
static bool SPECLIST_FOO() _list_remove_all_if(SPECLIST_LIST *tthis, SPECLIST_FOO(_list_cond_fn_t) cond_data_func)
Definition: speclist.h:330
static SPECLIST_LINK *SPECLIST_FOO() _list_search(const SPECLIST_LIST *tthis, const SPECLIST_TYPE *pfoo)
Definition: speclist.h:440
static SPECLIST_LINK *SPECLIST_FOO() _list_link_prev(const SPECLIST_LINK *plink) fc__warn_unused_result
Definition: speclist.h:520
static void SPECLIST_FOO() _list_unique(SPECLIST_LIST *tthis)
Definition: speclist.h:231
static SPECLIST_TYPE *SPECLIST_FOO() _list_link_data(const SPECLIST_LINK *plink)
Definition: speclist.h:507
static void SPECLIST_FOO() _list_release_mutex(SPECLIST_LIST *tthis)
Definition: speclist.h:498
#define SPECLIST_LIST
Definition: speclist.h:137
static void SPECLIST_FOO() _list_unique_full(SPECLIST_LIST *tthis, SPECLIST_FOO(_list_comp_fn_t) comp_data_func)
Definition: speclist.h:240
static void SPECLIST_FOO() _list_destroy(SPECLIST_LIST *tthis)
Definition: speclist.h:184
static SPECLIST_LINK *SPECLIST_FOO() _list_link_next(const SPECLIST_LINK *plink) fc__warn_unused_result
Definition: speclist.h:533
#define SPECLIST_TYPE
Definition: speclist.h:131
#define SPECLIST_FOO(suffix)
Definition: speclist.h:139
static SPECLIST_TYPE *SPECLIST_FOO() _list_front(const SPECLIST_LIST *tthis)
Definition: speclist.h:390
static SPECLIST_LIST *SPECLIST_FOO() _list_copy_full(const SPECLIST_LIST *tthis, SPECLIST_FOO(_list_copy_fn_t) copy_data_func, SPECLIST_FOO(_list_free_fn_t) free_data_func) fc__warn_unused_result
Definition: speclist.h:210
static int SPECLIST_FOO() _list_remove_all(SPECLIST_LIST *tthis, const SPECLIST_TYPE *pfoo)
Definition: speclist.h:320
#define fc__warn_unused_result
Definition: support.h:41