Support changing players' science box in the editor.
[freeciv.git] / utility / iterator.h
blobe399e4e811e82195736a7c423c5d3e85f371b3ce
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 ***********************************************************************/
13 #ifndef FC__ITERATOR_H
14 #define FC__ITERATOR_H
16 #ifdef __cplusplus
17 extern "C" {
18 #endif /* __cplusplus */
20 #include "support.h" /* bool */
22 /***********************************************************************
23 Iterator base class. "Derived" iterators must have this struct as
24 their first member (as a "vtable") and provide implementations of the
25 "pure virtual" member functions. See the function comment headers
26 below for the expected behaviour of these functions.
27 ***********************************************************************/
28 struct iterator {
29 void (*next)(struct iterator *it);
30 void *(*get)(const struct iterator *it);
31 bool (*valid)(const struct iterator *it);
34 #define ITERATOR(p) ((struct iterator *)(p))
36 /***********************************************************************
37 Advances the iterator to point to the next item in the sequence.
38 ***********************************************************************/
39 static inline void iterator_next(struct iterator *it) {
40 it->next(it);
43 /***********************************************************************
44 Returns the item currently pointed to by the iterator. Note that the
45 iterator could point to an item whose value is NULL; to actually test
46 whether the iterator is still valid (e.g. has not gone past the
47 end of the sequence), use iterator_valid().
48 ***********************************************************************/
49 static inline void *iterator_get(const struct iterator *it) {
50 return it->get(it);
53 /***********************************************************************
54 Returns TRUE if the iterator points to an item in the sequence.
55 ***********************************************************************/
56 static inline bool iterator_valid(const struct iterator *it) {
57 return it->valid(it);
60 /***************************************************************************
61 Iteration macro for iterators derived from the 'iterator' base class.
62 Usually you would define a specific iteration macro for each derived
63 iterator type. The meaning of the arguments is as follows:
65 TYPE_it - The type of the derived iterator. E.g. 'struct foo_iter'.
66 TYPE_a - The real type of the items in the list. The variable with name
67 'NAME_a' will be cast to this.
68 NAME_a - The name of the variable that will be assigned the current item
69 in each iteration. It will be declared for you within the scope
70 of the iteration loop.
71 FUNC_size - A function that returns the total size in bytes of a
72 'TYPE_it'.
73 FUNC_init - A "construtor" for 'TYPE_it' objects. It returns a pointer to
74 a 'struct iterator' and takes as its first argument a pointer
75 to memory large enough to hold a 'TYPE_it' (this amount must
76 match the result of FUNC_size()). NB: This function must not
77 return NULL; it must return a valid iterator pointing to the
78 first element in the sequence, or an invalid iterator.
79 ... - Zero or more extra arguments that 'FUNC_init' expects.
80 ***************************************************************************/
81 #define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...)\
82 do {\
83 char MY_mem_##NAME_a[FUNC_size()];\
84 struct iterator *MY_it_##NAME_a;\
85 TYPE_a NAME_a;\
86 MY_it_##NAME_a =\
87 FUNC_init((TYPE_it *) (void *) MY_mem_##NAME_a , ## __VA_ARGS__);\
88 for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) {\
89 NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);\
91 #define generic_iterate_end\
93 } while (FALSE)
95 /***************************************************************************
96 Iterator init functions cannot return NULL, so this dummy helper function
97 can be used to return a "generic invalid iterator" that will just exit
98 out of generic_iterate. Its size is just sizeof(struct iterator), so it
99 will fit into any iterator's allocated stack memory.
100 ***************************************************************************/
101 struct iterator *invalid_iter_init(struct iterator *it);
103 #ifdef __cplusplus
105 #endif /* __cplusplus */
107 #endif /* FC__ITERATOR_H */