Freeciv21
Develop your civilization from humble roots to a global empire
iterator.h
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 #pragma once
14 /***********************************************************************
15  Iterator base class. "Derived" iterators must have this struct as
16  their first member (as a "vtable") and provide implementations of the
17  "pure virtual" member functions. See the function comment headers
18  below for the expected behaviour of these functions.
19 ***********************************************************************/
20 struct iterator {
21  void (*next)(struct iterator *it);
22  void *(*get)(const struct iterator *it);
23  bool (*valid)(const struct iterator *it);
24 };
25 
26 #define ITERATOR(p) ((struct iterator *) (p))
27 
28 /***********************************************************************
29  Advances the iterator to point to the next item in the sequence.
30 ***********************************************************************/
31 static inline void iterator_next(struct iterator *it) { it->next(it); }
32 
33 /***********************************************************************
34  Returns the item currently pointed to by the iterator. Note that the
35  iterator could point to an item whose value is nullptr; to actually test
36  whether the iterator is still valid (e.g. has not gone past the
37  end of the sequence), use iterator_valid().
38 ***********************************************************************/
39 static inline void *iterator_get(const struct iterator *it)
40 {
41  return it->get(it);
42 }
43 
44 /***********************************************************************
45  Returns TRUE if the iterator points to an item in the sequence.
46 ***********************************************************************/
47 static inline bool iterator_valid(const struct iterator *it)
48 {
49  return it->valid(it);
50 }
51 
52 /***************************************************************************
53  Iteration macro for iterators derived from the 'iterator' base class.
54  Usually you would define a specific iteration macro for each derived
55  iterator type. The meaning of the arguments is as follows:
56 
57  TYPE_it - The type of the derived iterator. E.g. 'struct foo_iter'.
58  TYPE_a - The real type of the items in the list. The variable with name
59  'NAME_a' will be cast to this.
60  NAME_a - The name of the variable that will be assigned the current item
61  in each iteration. It will be declared for you within the scope
62  of the iteration loop.
63  FUNC_size - A function that returns the total size in bytes of a
64  'TYPE_it'.
65  FUNC_init - A "construtor" for 'TYPE_it' objects. It returns a pointer to
66  a 'struct iterator' and takes as its first argument a pointer
67  to memory large enough to hold a 'TYPE_it' (this amount must
68  match the result of FUNC_size()). NB: This function must not
69  return nullptr; it must return a valid iterator pointing to the
70  first element in the sequence, or an invalid iterator.
71  ... - Zero or more extra arguments that 'FUNC_init' expects.
72 ***************************************************************************/
73 #define generic_iterate(TYPE_it, TYPE_a, NAME_a, FUNC_size, FUNC_init, ...) \
74  do { \
75  char MY_mem_##NAME_a[FUNC_size()]; \
76  struct iterator *MY_it_##NAME_a; \
77  TYPE_a NAME_a; \
78  MY_it_##NAME_a = \
79  FUNC_init((TYPE_it *) (void *) MY_mem_##NAME_a, ##__VA_ARGS__); \
80  for (; iterator_valid(MY_it_##NAME_a); iterator_next(MY_it_##NAME_a)) { \
81  NAME_a = (TYPE_a) iterator_get(MY_it_##NAME_a);
82 
83 #define generic_iterate_end \
84  } \
85  } \
86  while (false)
87 
88 /***************************************************************************
89  Iterator init functions cannot return nullptr, so this dummy helper
90 function can be used to return a "generic invalid iterator" that will just
91 exit out of generic_iterate. Its size is just sizeof(struct iterator), so it
92  will fit into any iterator's allocated stack memory.
93 ***************************************************************************/
94 struct iterator *invalid_iter_init(struct iterator *it);
static bool iterator_valid(const struct iterator *it)
Definition: iterator.h:47
static void * iterator_get(const struct iterator *it)
Definition: iterator.h:39
static void iterator_next(struct iterator *it)
Definition: iterator.h:31
struct iterator * invalid_iter_init(struct iterator *it)
Initializes the iterator vtable so that generic_iterate assumes that the iterator is invalid.
Definition: iterator.cpp:37
bool(* valid)(const struct iterator *it)
Definition: iterator.h:23
void *(* get)(const struct iterator *it)
Definition: iterator.h:22
void(* next)(struct iterator *it)
Definition: iterator.h:21