Freeciv21
Develop your civilization from humble roots to a global empire
specvec.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 /* specvectors: "specific vectors".
13 
14  This file is used to implement resizable arrays.
15 
16  Before including this file, you must define the following:
17  SPECVEC_TAG - this tag will be used to form names for functions etc.
18  You may also define:
19  SPECVEC_TYPE - the typed vector will contain pointers to this type;
20  If SPECVEC_TYPE is not defined, then 'struct SPECVEC_TAG' is used.
21  At the end of this file, these (and other defines) are undef-ed.
22 
23  Assuming SPECVEC_TAG were 'foo', and SPECVEC_TYPE were 'foo_t',
24  including this file would provide a struct definition for:
25  struct foo_vector;
26  and prototypes for the following functions:
27  void foo_vector_init(struct foo_vector *tthis);
28  void foo_vector_reserve(struct foo_vector *tthis, int n);
29  int foo_vector_size(const struct foo_vector *tthis);
30  foo_t *foo_vector_get(struct foo_vector *tthis, int svindex);
31  void foo_vector_copy(struct foo_vector *to,
32  const struct foo_vector *from);
33  void foo_vector_free(struct foo_vector *tthis);
34  void foo_vector_append(struct foo_vector *tthis, foo_t pfoo);
35  void foo_vector_remove(struct foo_vector *tthis, int svindex);
36 
37  Note this is not protected against multiple inclusions; this is
38  so that you can have multiple different specvectors. For each
39  specvector, this file should be included _once_, inside a .h file
40  which _is_ itself protected against multiple inclusions.
41 */
42 
43 #include <cstring> // for memcpy
44 
45 #ifndef SPECVEC_TAG
46 #error Must define a SPECVEC_TAG to use this header
47 #endif
48 #ifndef SPECVEC_TYPE
49 #define SPECVEC_TYPE struct SPECVEC_TAG
50 #endif
51 
52 #define SPECVEC_PASTE_(x, y) x##y
53 #define SPECVEC_PASTE(x, y) SPECVEC_PASTE_(x, y)
54 
55 #define SPECVEC_VECTOR struct SPECVEC_PASTE(SPECVEC_TAG, _vector)
56 
57 #define SPECVEC_FOO(suffix) SPECVEC_PASTE(SPECVEC_TAG, suffix)
58 
60 {
61  // Users are allowed to access the data pointer directly.
62  SPECVEC_TYPE *p;
63 
64  size_t size, size_alloc;
65 };
66 
67 static inline void SPECVEC_FOO(_vector_init)(SPECVEC_VECTOR *tthis)
68 {
69  tthis->p = nullptr;
70  tthis->size = tthis->size_alloc = 0;
71 }
72 
73 static inline void SPECVEC_FOO(_vector_reserve)(SPECVEC_VECTOR *tthis,
74  size_t size)
75 {
76  if (size > tthis->size_alloc) {
77  size_t new_size = MAX(size, tthis->size_alloc * 2);
78 
79  tthis->p = static_cast<SPECVEC_TYPE *>(
80  fc_realloc(tthis->p, new_size * sizeof(*tthis->p)));
81  tthis->size_alloc = new_size;
82  }
83  tthis->size = size;
84 }
85 
86 static inline size_t SPECVEC_FOO(_vector_size)(const SPECVEC_VECTOR *tthis)
87 {
88  return tthis->size;
89 }
90 
91 static inline SPECVEC_TYPE *
92  SPECVEC_FOO(_vector_get)(const SPECVEC_VECTOR *tthis, int svindex)
93 {
94  if (svindex == -1 && tthis->size > 0) {
95  return tthis->p + tthis->size - 1;
96  } else if (svindex >= 0 && static_cast<size_t>(svindex) < tthis->size) {
97  return tthis->p + svindex;
98  } else {
99  return nullptr;
100  }
101 }
102 
103 // You must _init "*to" before using this function
104 static inline void SPECVEC_FOO(_vector_copy)(SPECVEC_VECTOR *to,
105  const SPECVEC_VECTOR *from)
106 {
107  SPECVEC_FOO(_vector_reserve)(to, from->size);
108  if (from->size > 0) {
109  memcpy(to->p, from->p, from->size * sizeof(*to->p));
110  }
111 }
112 
113 static inline void SPECVEC_FOO(_vector_free)(SPECVEC_VECTOR *tthis)
114 {
115  if (tthis->p) {
116  free(tthis->p);
117  }
118  SPECVEC_FOO(_vector_init)(tthis);
119 }
120 
121 static inline void SPECVEC_FOO(_vector_append)(SPECVEC_VECTOR *tthis,
122  SPECVEC_TYPE const &pfoo)
123 {
124  SPECVEC_FOO(_vector_reserve)(tthis, tthis->size + 1);
125  tthis->p[tthis->size - 1] = pfoo;
126 }
127 
128 /**************************************************************************
129  Remove element number svindex from the vector.
130 **************************************************************************/
131 static inline void SPECVEC_FOO(_vector_remove)(SPECVEC_VECTOR *tthis,
132  const int svindex)
133 {
134  size_t i;
135 
136  /* Be consistent with SPECVEC_FOO_vector_get(): Allow negative element
137  * number. */
138  const size_t rmpos =
139  (svindex < 0 ? SPECVEC_FOO(_vector_size)(tthis) - svindex
140  : static_cast<size_t>(svindex));
141 
142  fc_assert_ret(rmpos < SPECVEC_FOO(_vector_size)(tthis));
143 
144  for (i = rmpos; (i + 1) < SPECVEC_FOO(_vector_size)(tthis); i++) {
145  // Relocate the elements following the deleted element.
146  tthis->p[i] = tthis->p[i + 1];
147  }
148 
150 }
151 
152 #define TYPED_VECTOR_ITERATE(atype, vector, var) \
153  { \
154  unsigned int myiter##var; \
155  atype *var; \
156  for (myiter##var = 0; myiter##var < (vector)->size; myiter##var++) { \
157  var = &(vector)->p[myiter##var];
158 
159 // Balance for above:
160 #define VECTOR_ITERATE_END \
161  } \
162  }
163 
164 #undef SPECVEC_TAG
165 #undef SPECVEC_TYPE
166 #undef SPECVEC_PASTE_
167 #undef SPECVEC_PASTE
168 #undef SPECVEC_VECTOR
169 #undef SPECVEC_FOO
#define fc_assert_ret(condition)
Definition: log.h:112
#define MAX(x, y)
Definition: shared.h:48
static void SPECVEC_FOO() _vector_free(SPECVEC_VECTOR *tthis)
Definition: specvec.h:113
static void SPECVEC_FOO() _vector_init(SPECVEC_VECTOR *tthis)
Definition: specvec.h:67
static void SPECVEC_FOO() _vector_remove(SPECVEC_VECTOR *tthis, const int svindex)
Definition: specvec.h:131
#define SPECVEC_FOO(suffix)
Definition: specvec.h:57
static void SPECVEC_FOO() _vector_copy(SPECVEC_VECTOR *to, const SPECVEC_VECTOR *from)
Definition: specvec.h:104
static size_t SPECVEC_FOO() _vector_size(const SPECVEC_VECTOR *tthis)
Definition: specvec.h:86
static void SPECVEC_FOO() _vector_append(SPECVEC_VECTOR *tthis, SPECVEC_TYPE const &pfoo)
Definition: specvec.h:121
size_t size
Definition: specvec.h:64
size_t size_alloc
Definition: specvec.h:64
#define SPECVEC_VECTOR
Definition: specvec.h:55
static void SPECVEC_FOO() _vector_reserve(SPECVEC_VECTOR *tthis, size_t size)
Definition: specvec.h:73
#define SPECVEC_TYPE
Definition: specvec.h:49
static SPECVEC_TYPE *SPECVEC_FOO() _vector_get(const SPECVEC_VECTOR *tthis, int svindex)
Definition: specvec.h:92
#define fc_realloc(ptr, sz)
Definition: support.h:59