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