Freeciv-3.3
Loading...
Searching...
No Matches
iterator.h
Go to the documentation of this file.
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#ifndef FC__ITERATOR_H
14#define FC__ITERATOR_H
15
16#ifdef __cplusplus
17extern "C" {
18
19#include "mem.h"
20#endif /* __cplusplus */
21
22/* utility */
23#include "support.h" /* bool */
24
25/***********************************************************************
26 Iterator base class. "Derived" iterators must have this struct as
27 their first member (as a "vtable") and provide implementations of the
28 "pure virtual" member functions. See the function comment headers
29 below for the expected behaviour of these functions.
30***********************************************************************/
31struct iterator {
32 void (*next)(struct iterator *it);
33 void *(*get)(const struct iterator *it);
34 bool (*valid)(const struct iterator *it);
35};
36
37#define ITERATOR(p) ((struct iterator *)(p))
38
39/*******************************************************************/
42static inline void iterator_next(struct iterator *it)
43{
44 it->next(it);
45}
46
47/*******************************************************************/
53static inline void *iterator_get(const struct iterator *it)
54{
55 return it->get(it);
56}
57
58/*******************************************************************/
61static inline bool iterator_valid(const struct iterator *it)
62{
63 return it->valid(it);
64}
65
66/***************************************************************************
67 Iteration macro for iterators derived from the 'iterator' base class.
68 Usually you would define a specific iteration macro for each derived
69 iterator type. The meaning of the arguments is as follows:
70
71 TYPE_it - The type of the derived iterator. E.g. 'struct foo_iter'.
72 TYPE_a - The real type of the items in the list. The variable with name
73 'NAME_a' will be cast to this.
74 NAME_a - The name of the variable that will be assigned the current item
75 in each iteration. It will be declared for you within the scope
76 of the iteration loop.
77 FUNC_size - A function that returns the total size in bytes of a
78 'TYPE_it'.
79 FUNC_init - A "constructor" for 'TYPE_it' objects. It returns a pointer to
80 a 'struct iterator' and takes as its first argument a pointer
81 to memory large enough to hold a 'TYPE_it' (this amount must
82 match the result of FUNC_size()). NB: This function must not
83 return nullptr; it must return a valid iterator pointing to
84 the first element in the sequence, or an invalid iterator.
85 ... - Zero or more extra arguments that 'FUNC_init' expects.
86***************************************************************************/
87#ifdef __cplusplus
88
89/* C++ does not have VLA, except as compiler extension in case of
90 some compilers. Thus we need to fc_malloc() correct size array.
91 Wrap the allocated array within a class, so it will get freed
92 by the destructor when it goes out of scope. */
93class gi_mem
94{
95 public:
96 void *array;
97 gi_mem(int size) {
98 array = fc_malloc(size);
99 }
100 ~gi_mem() {
101 free(array);
102 }
103};
104
105#define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...) \
106do { \
107 gi_mem MY_mem_##NAME_a(FUNC_size()); \
108 struct iterator *MY_it_##NAME_a; \
109 TYPE_a NAME_a; \
110 MY_it_##NAME_a = \
111 FUNC_init((TYPE_it *) MY_mem_##NAME_a.array , ## __VA_ARGS__); \
112 for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) { \
113 NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);
114
115#else // __cplusplus
116
117#define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...) \
118do { \
119 char MY_mem_##NAME_a[FUNC_size()]; \
120 struct iterator *MY_it_##NAME_a; \
121 TYPE_a NAME_a; \
122 MY_it_##NAME_a = \
123 FUNC_init((TYPE_it *) (void *) MY_mem_##NAME_a , ## __VA_ARGS__); \
124 for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) { \
125 NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);
126
127#endif // __cplusplus
128
129#define generic_iterate_end \
130 } \
131} while (FALSE)
132
133/***************************************************************************
134 Iterator init functions cannot return nullptr, so this dummy helper
135 function can be used to return a "generic invalid iterator" that will
136 just exit out of generic_iterate. Its size is just sizeof(struct iterator),
137 so it will fit into any iterator's allocated stack memory.
138***************************************************************************/
139struct iterator *invalid_iter_init(struct iterator *it);
140
141#ifdef __cplusplus
142}
143#endif /* __cplusplus */
144
145#endif /* FC__ITERATOR_H */
char * incite_cost
Definition comments.c:76
static void * iterator_get(const struct iterator *it)
Definition iterator.h:53
static bool iterator_valid(const struct iterator *it)
Definition iterator.h:61
static void iterator_next(struct iterator *it)
Definition iterator.h:42
struct iterator * invalid_iter_init(struct iterator *it)
Definition iterator.c:51
#define fc_malloc(sz)
Definition mem.h:34
size_t size
Definition specvec.h:72
bool(* valid)(const struct iterator *it)
Definition iterator.h:34
void *(* get)(const struct iterator *it)
Definition iterator.h:33
void(* next)(struct iterator *it)
Definition iterator.h:32
#define bool
Definition support.h:71