Now using 2 spaces instead of tabs. Fix copyright years. Improve documentation
[cgds.git] / src / List.h
... / ...
CommitLineData
1/**
2 * @file List.h
3 */
4
5#ifndef CGDS_LIST_H
6#define CGDS_LIST_H
7
8#include <stdlib.h>
9#include <string.h>
10#include "cgds/safe_alloc.h"
11#include "cgds/types.h"
12
13////////////////
14// List logic //
15////////////////
16
17/**
18 * @brief Cell of a double-linked list.
19 */
20typedef struct ListCell {
21 void* data; ///< Generic data contained in this cell.
22 struct ListCell* prev; ///< Pointer to previous cell in the list.
23 struct ListCell* next; ///< Pointer to next cell in the list.
24} ListCell;
25
26/**
27 * @brief Double-linked list data structure.
28 */
29typedef struct List {
30 UInt size; ///< Count elements in the list.
31 size_t dataSize; ///< Size of a list cell element in bytes.
32 ListCell* head; ///< Pointer to the first cell in the list.
33 ListCell* tail; ///< Pointer to the last cell in the list.
34} List;
35
36/**
37 * @brief Initialize an empty list.
38 */
39void _list_init(
40 List* list, ///< "this" pointer.
41 size_t dataSize ///< Size of a list cell elements in bytes.
42);
43
44/**
45 * @brief Return an allocated and initialized list.
46 * @param dataSize Size in bytes of a list element.
47 */
48List* _list_new(
49 size_t dataSize ///< Size of a list cell elements in bytes.
50);
51
52/**
53 * @brief Return an allocated and initialized list.
54 * @param type Type of a list element (int, char*, ...).
55 *
56 * Usage: List* list_new(<Type> type)
57 */
58#define list_new(type) \
59{ \
60 _list_new(sizeof(type)); \
61}
62
63/**
64 * @brief Copy constructor (shallow copy, ok for basic types).
65 */
66List* list_copy(
67 List* list ///< "this" pointer.
68);
69
70/**
71 * @brief Check if the list is empty.
72 */
73bool list_empty(
74 List* list ///< "this" pointer.
75);
76
77/**
78 * @brief return the size of current list.
79 */
80UInt list_size(
81 List* list ///< "this" pointer.
82);
83
84/**
85 * @brief Get data at the given list cell argument.
86 */
87void* _list_get(
88 ListCell* listCell ///< Pointer to a cell inside "this" list.
89);
90
91/**
92 * @brief Get data at the given list cell argument.
93 * @param listCell Pointer to a cell inside "this" list.
94 * @param data Data to be assigned.
95 *
96 * Usage: void list_get(ListCell* listCell, void data)
97 */
98#define list_get(listCell, data) \
99{ \
100 void* pData = _list_get(listCell); \
101 data = *((typeof(&data))pData); \
102}
103
104/**
105 * @brief Set data at the given list cell argument.
106 */
107void _list_set(
108 List* list, ///< "this" pointer.
109 ListCell* listCell, ///< Pointer to a cell inside "this" list.
110 void* data ///< Pointer to data to be set.
111);
112
113/**
114 * @brief Set data at the given list cell argument.
115 * @param list "this" pointer.
116 * @param listCell Pointer to a cell inside "this" list.
117 * @param data Data to be set.
118 *
119 * Usage: void list_set(List* list, ListCell* listCell, void data);
120 */
121#define list_set(list, listCell, data) \
122{ \
123 typeof((data)) tmp = data; \
124 _list_set(list, listCell, &tmp); \
125}
126
127/**
128 * @brief Add data to the list when list is empty.
129 */
130void _list_insert_first_element(
131 List* list, ///< "this" pointer.
132 void* data ///< Pointer to data to be added
133);
134
135/**
136 * @brief Add data before list cell argument.
137 */
138void _list_insert_before(
139 List* list, ///< "this" pointer.
140 ListCell* listCell, ///< Pointer to a cell inside "this" list.
141 void* data ///< Pointer to data to be added.
142);
143
144/**
145 * @brief Add data before list cell argument.
146 * @param list "this" pointer.
147 * @param listCell Pointer to a cell inside "this" list.
148 * @param data Data to be inserted.
149 *
150 * Usage: void list_insert_before(List* list, ListCell* listCell, void data)
151 */
152#define list_insert_before(list, listCell, data) \
153{ \
154 typeof((data)) tmp = data; \
155 _list_insert_before(list, listCell, &tmp); \
156}
157
158/**
159 * @brief Add data after list cell argument.
160 */
161void _list_insert_after(
162 List* list, ///< "this" pointer.
163 ListCell* listCell, ///< Pointer to a cell inside "this" list.
164 void* data ///< Pointer to data to be inserted.
165);
166
167/**
168 * @brief Add data after list cell argument.
169 * @param list "this" pointer.
170 * @param listCell Pointer to a cell inside "this" list.
171 * @param data Data to be inserted.
172 *
173 * Usage: void list_insert_after(List* list, ListCell* listCell, void data)
174 */
175#define list_insert_after(list, listCell, data) \
176{ \
177 typeof((data)) tmp = data; \
178 _list_insert_after(list, listCell, &tmp); \
179}
180
181/**
182 * @brief Add data at the beginning of the list.
183 */
184void _list_insert_front(
185 List* list, ///< "this" pointer.
186 void* data ///< Pointer to data to be inserted.
187);
188
189/**
190 * @brief Add data at the beginning of the list.
191 * @param list "this" pointer.
192 * @param data Data to be inserted.
193 *
194 * Usage: void list_insert_front(List* list, void data)
195 */
196#define list_insert_front(list, data) \
197{ \
198 typeof((data)) tmp = data; \
199 _list_insert_front(list, &tmp); \
200}
201
202/**
203 * @brief Add data at the end of the list.
204 */
205void _list_insert_back(
206 List* list, ///< "this" pointer.
207 void* data ///< Pointer to data to be inserted.
208);
209
210/**
211 * @brief Add data at the end of the list.
212 * @param list "this" pointer.
213 * @param data Data to be inserted.
214 *
215 * Usage: void list_insert_back(List* list, void data)
216 */
217#define list_insert_back(list, data) \
218{ \
219 typeof((data)) tmp = data; \
220 _list_insert_back(list, &tmp); \
221}
222
223/**
224 * @brief Remove data at position given by 'listCell'.
225 */
226void list_remove(
227 List* list, ///< "this" pointer.
228 ListCell* listCell ///< Pointer to a cell inside "this" list.
229);
230
231/**
232 * @brief Remove data at the beginning of the list.
233 */
234void list_remove_front(
235 List* list ///< "this" pointer.
236);
237
238/**
239 * @brief Remove data at the end of the list.
240 */
241void list_remove_back(
242 List* list ///< "this" pointer.
243);
244
245/**
246 * @brief Clear the entire list.
247 */
248void list_clear(
249 List* list ///< "this" pointer.
250);
251
252/**
253 * @brief Destroy the list: clear it, and free 'list' pointer.
254 */
255void list_destroy(
256 List* list ///< "this" pointer.
257);
258
259////////////////////
260// Iterator logic //
261////////////////////
262
263/**
264 * @brief Iterator on a double-linked list.
265 */
266typedef struct ListIterator {
267 List* list; ///< The list to be iterate.
268 ListCell* current; ///< The current iterated list cell.
269} ListIterator;
270
271/**
272 * @brief Obtain an iterator object, starting at list beginning.
273 */
274ListIterator* list_get_iterator(
275 List* list ///< Pointer to the list to be iterated over.
276);
277
278/**
279 * @brief (Re)set current position inside list to head.
280 */
281void listI_reset_head(
282 ListIterator* listI ///< "this" pointer.
283);
284
285/**
286 * @brief (Re)set current position inside list to tail.
287 */
288void listI_reset_tail(
289 ListIterator* listI ///< "this" pointer.
290);
291
292/**
293 * @brief Tell if there is some data at the current index.
294 */
295bool listI_has_data(
296 ListIterator* listI ///< "this" pointer.
297);
298
299/**
300 * @brief Return data contained in the current list cell.
301 * @param listI "this" pointer.
302 * @param data Data to be assigned.
303 *
304 * Usage: void listI_get(ListIterator* listI, void data)
305 */
306#define listI_get(listI, data) \
307 list_get(listI->current, data)
308
309/**
310 * @brief Set data at the current iterator position.
311 * @param listI "this" pointer
312 * @param data Data to assign.
313 *
314 * Usage: void listI_set(ListIterator* listI, void data);
315 */
316#define listI_set(listI, data) \
317 list_set(listI->list, listI->current, data)
318
319/**
320 * @brief Add data before current list cell.
321 * @param listI "this" pointer
322 * @param data Data to be inserted.
323 *
324 * Usage: void listI_insert_before(ListIteratorI* listI, void data)
325 */
326#define listI_insert_before(listI, data) \
327 list_insert_before(listI->list, listI->current, data)
328
329/**
330 * @brief Add data after current list cell.
331 * @param listI "this" pointer
332 * @param data Data to be inserted.
333 *
334 * Usage: void listI_insert_after(ListIteratorI* listI, void data)
335 */
336#define listI_insert_after(listI, data) \
337 list_insert_after(listI->list, listI->current, data)
338
339/**
340 * @brief Type to encode a direction (forward / backward).
341 */
342typedef enum {
343 BACKWARD = -1, ///< Move toward head.
344 FORWARD = 1 ///< Move toward tail.
345} Direction;
346
347/**
348 * @brief Remove data at the current iterator position.
349 */
350void listI_remove(
351 ListIterator* listI, ///< "this" pointer.
352 Direction direction ///< Indicate the position of iterator after removal.
353);
354
355/**
356 * @brief Move current iterator position forward (toward tail).
357 */
358void listI_move_next(
359 ListIterator* listI ///< "this" pointer.
360);
361
362/**
363 * @brief Move current iterator position backward (toward head).
364 */
365void listI_move_prev(
366 ListIterator* listI ///< "this" pointer.
367);
368
369/**
370 * @brief Free memory allocated for the iterator.
371 */
372void listI_destroy(
373 ListIterator* listI ///< "this" pointer.
374);
375
376#endif