Commit | Line | Data |
---|---|---|
a7868768 BA |
1 | /** |
2 | * @file Vector.h | |
3 | */ | |
4 | ||
5 | #ifndef CGDS_VECTOR_H | |
6 | #define CGDS_VECTOR_H | |
7 | ||
8 | #include <stdlib.h> | |
9 | #include <string.h> | |
10 | #include "cgds/safe_alloc.h" | |
11 | #include "cgds/types.h" | |
12 | ||
13 | //************* | |
14 | // Vector logic | |
15 | //************* | |
16 | ||
17 | /** | |
18 | * @brief Generic resizable array. | |
19 | */ | |
20 | typedef struct Vector { | |
1d60b10a | 21 | void* datas; ///< Data array of fixed length (reallocated if needed). |
e45132ac BA |
22 | size_t dataSize; ///< Size in bytes of a vector element. |
23 | UInt size; ///< Count elements in the vector. | |
24 | UInt capacity; ///< Current maximal capacity; always larger than size. | |
a7868768 BA |
25 | } Vector; |
26 | ||
27 | /** | |
28 | * @brief Initialize an empty vector. | |
29 | */ | |
30 | void _vector_init( | |
e45132ac BA |
31 | Vector* vector, ///< "this" pointer. |
32 | size_t dataSize ///< Size in bytes of a vector element. | |
a7868768 BA |
33 | ); |
34 | ||
35 | /** | |
36 | * @brief Return an allocated and initialized vector. | |
37 | */ | |
38 | Vector* _vector_new( | |
e45132ac | 39 | size_t dataSize ///< Size in bytes of a vector element. |
a7868768 BA |
40 | ); |
41 | ||
42 | /** | |
43 | * @brief Return an allocated and initialized vector. | |
44 | * @param type Type of a vector element (int, char*, ...). | |
1ff641f9 | 45 | * |
a7868768 BA |
46 | * Usage: Vector* vector_new(<Type> type) |
47 | */ | |
48 | #define vector_new(type) \ | |
eed1b5d2 | 49 | _vector_new(sizeof(type)) |
a7868768 BA |
50 | |
51 | /** | |
1ff641f9 | 52 | * @brief Copy constructor (shallow copy, ok for basic types). |
a7868768 BA |
53 | */ |
54 | Vector* vector_copy( | |
e45132ac | 55 | Vector* vector ///< "this" pointer. |
a7868768 BA |
56 | ); |
57 | ||
58 | /** | |
59 | * @brief Check if the vector is empty. | |
60 | */ | |
1ff641f9 | 61 | bool vector_empty( |
e45132ac | 62 | Vector* vector ///< "this" pointer. |
a7868768 BA |
63 | ); |
64 | ||
65 | /** | |
66 | * @brief Return current size. | |
67 | */ | |
68 | UInt vector_size( | |
e45132ac | 69 | Vector* vector ///< "this" pointer. |
a7868768 BA |
70 | ); |
71 | ||
72 | /** | |
73 | * @brief Reallocate internal array. | |
74 | */ | |
75 | void _vector_realloc( | |
e45132ac BA |
76 | Vector* vector, ///< "this" pointer. |
77 | UInt newCapacity ///< New capacity of the vector (in number of elements). | |
a7868768 BA |
78 | ); |
79 | ||
80 | /** | |
81 | * @brief Add data at the end. | |
82 | */ | |
83 | void _vector_push( | |
e45132ac BA |
84 | Vector* vector, ///< "this" pointer. |
85 | void* data ///< Data to be added. | |
a7868768 BA |
86 | ); |
87 | ||
88 | /** | |
89 | * @brief Add data at the end. | |
90 | * @param vector "this" pointer. | |
91 | * @param data Data to be added. | |
1ff641f9 | 92 | * |
a7868768 BA |
93 | * Usage: void vector_push(Vector* vector, void data) |
94 | */ | |
95 | #define vector_push(vector, data) \ | |
96 | { \ | |
eed1b5d2 BA |
97 | typeof(data) tmp = data; \ |
98 | _vector_push(vector, &tmp); \ | |
a7868768 BA |
99 | } |
100 | ||
101 | /** | |
102 | * @brief Remove the last pushed element. | |
103 | */ | |
104 | void vector_pop( | |
e45132ac | 105 | Vector* vector ///< "this" pointer. |
a7868768 BA |
106 | ); |
107 | ||
108 | /** | |
109 | * @brief Get the element at given index. | |
110 | */ | |
111 | void* _vector_get( | |
e45132ac BA |
112 | Vector* vector, ///< "this" pointer. |
113 | UInt index ///< Index of the element to retrieve. | |
a7868768 BA |
114 | ); |
115 | ||
116 | /** | |
117 | * @brief Get the element at given index. | |
118 | * @param vector "this" pointer. | |
119 | * @param index Index of the element to retrieve. | |
120 | * @param data 'out' variable to contain the result. | |
1ff641f9 | 121 | * |
a7868768 BA |
122 | * Usage: void vector_get(Vector* vector, size_t index, void data) |
123 | */ | |
124 | #define vector_get(vector, index, data) \ | |
125 | { \ | |
e45132ac BA |
126 | void* pData = _vector_get(vector,index); \ |
127 | data = *((typeof(&data))pData); \ | |
a7868768 BA |
128 | } |
129 | ||
130 | /** | |
131 | * @brief Set the element at given index. | |
132 | */ | |
133 | void _vector_set( | |
e45132ac BA |
134 | Vector* vector, ///< "this" pointer. |
135 | UInt index, ///< Index of the element to be modified. | |
136 | void* data ///< Pointer to new data at given index. | |
a7868768 BA |
137 | ); |
138 | ||
139 | /** | |
140 | * @brief Set the element at given index. | |
141 | * @param vector "this" pointer. | |
142 | * @param index Index of the element to be modified. | |
143 | * @param data New data at given index. | |
1ff641f9 | 144 | * |
a7868768 BA |
145 | * Usage: void vector_set(Vector* vector, size_t index, void data) |
146 | */ | |
147 | #define vector_set(vector, index, data) \ | |
148 | { \ | |
eed1b5d2 BA |
149 | typeof(data) tmp = data; \ |
150 | _vector_set(vector, index, &tmp); \ | |
a7868768 BA |
151 | } |
152 | ||
153 | /** | |
154 | * @brief Clear the entire vector. | |
155 | */ | |
156 | void vector_clear( | |
e45132ac | 157 | Vector* vector ///< "this" pointer. |
a7868768 BA |
158 | ); |
159 | ||
160 | /** | |
161 | * @brief Destroy the vector: clear it, and free 'vector' pointer. | |
162 | */ | |
163 | void vector_destroy( | |
e45132ac | 164 | Vector* vector ///< "this" pointer. |
a7868768 BA |
165 | ); |
166 | ||
167 | //*************** | |
168 | // Iterator logic | |
169 | //*************** | |
170 | ||
171 | /** | |
172 | * @brief Iterator on a generic vector. | |
173 | */ | |
174 | typedef struct VectorIterator { | |
e45132ac | 175 | Vector* vector; ///< Vector to be iterated. |
1d60b10a | 176 | void* current; ///< Current vector element. |
a7868768 BA |
177 | } VectorIterator; |
178 | ||
179 | /** | |
180 | * @brief Obtain an iterator object, starting at vector beginning (index 0). | |
181 | */ | |
182 | VectorIterator* vector_get_iterator( | |
e45132ac | 183 | Vector* vector ///< Pointer to the vector to iterate over. |
a7868768 BA |
184 | ); |
185 | ||
186 | /** | |
187 | * @brief (Re)set current position inside vector to beginning (0). | |
188 | */ | |
189 | void vectorI_reset_begin( | |
e45132ac | 190 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
191 | ); |
192 | ||
193 | /** | |
194 | * @brief (Re)set current position inside vector to end (vector->size-1). | |
195 | */ | |
196 | void vectorI_reset_end( | |
e45132ac | 197 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
198 | ); |
199 | ||
200 | /** | |
201 | * @brief Tell if there is some data at the current index. | |
202 | */ | |
1ff641f9 | 203 | bool vectorI_has_data( |
e45132ac | 204 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
205 | ); |
206 | ||
207 | /** | |
208 | * @brief Get data contained at the current index. | |
209 | */ | |
210 | void* _vectorI_get( | |
e45132ac | 211 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
212 | ); |
213 | ||
214 | /** | |
215 | * @brief Get data contained at the current index. | |
216 | * @param vectorI "this" pointer. | |
217 | * @param data 'out' variable to contain the result. | |
1ff641f9 | 218 | * |
a7868768 BA |
219 | * Usage: void vectorI_get(VectorIterator* vectorI, void data); |
220 | */ | |
221 | #define vectorI_get(vectorI, data) \ | |
222 | { \ | |
e45132ac BA |
223 | void* pData = _vectorI_get(vectorI); \ |
224 | data = *((typeof(&data))pData); \ | |
a7868768 BA |
225 | } |
226 | ||
227 | /** | |
228 | * @brief Set the element at current index. | |
229 | */ | |
230 | void _vectorI_set( | |
e45132ac BA |
231 | VectorIterator* vectorI, ///< "this" pointer. |
232 | void* data ///< Data to be assigned. | |
a7868768 BA |
233 | ); |
234 | ||
235 | /** | |
236 | * @brief Set the element at current index. | |
237 | * @param vectorI "this" pointer. | |
238 | * @param data Data to be assigned. | |
1ff641f9 | 239 | * |
a7868768 BA |
240 | * Usage: void vectorI_set(VectorIterator* vectorI, void data) |
241 | */ | |
242 | #define vectorI_set(vectorI, data) \ | |
243 | { \ | |
eed1b5d2 BA |
244 | typeof(data) tmp = data; \ |
245 | _vectorI_set(vectorI, &tmp); \ | |
a7868768 BA |
246 | } |
247 | ||
248 | /** | |
249 | * @brief Move current iterator position forward (toward last index). | |
250 | */ | |
251 | void vectorI_move_next( | |
e45132ac | 252 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
253 | ); |
254 | ||
255 | /** | |
256 | * @brief Move current iterator position backward (toward first index). | |
257 | */ | |
258 | void vectorI_move_prev( | |
e45132ac | 259 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
260 | ); |
261 | ||
262 | /** | |
263 | * @brief Free memory allocated for the iterator. | |
264 | */ | |
265 | void vectorI_destroy( | |
e45132ac | 266 | VectorIterator* vectorI ///< "this" pointer. |
a7868768 BA |
267 | ); |
268 | ||
269 | #endif |