README.html
[cgds.git] / src / List.c
CommitLineData
a7868768
BA
1/**
2 * @file List.c
3 */
4
5#include "cgds/List.h"
6
7////////////////
8// List logic //
9////////////////
10
11void _list_init(List* list, size_t dataSize)
12{
13 list->size = 0;
14 list->dataSize = dataSize;
15 list->head = NULL;
16 list->tail = NULL;
17}
18
19List* _list_new(size_t dataSize)
20{
21 List* list = (List*) safe_malloc(sizeof (List));
22 _list_init(list, dataSize);
23 return list;
24}
25
26List* list_copy(List* list)
27{
28 List* listCopy = _list_new(list->dataSize);
29 ListCell* listCell = list->head;
30 while (listCell != NULL)
31 {
32 _list_insert_back(listCopy, listCell->data);
33 listCell = listCell->next;
34 }
35 return listCopy;
36}
37
38Bool list_empty(List* list)
39{
40 return (list->size == 0);
41}
42
43UInt list_size(List* list)
44{
45 return list->size;
46}
47
48void* _list_get(ListCell* listCell)
49{
50 return listCell->data;
51}
52
53void _list_set(List* list, ListCell* listCell, void* data)
54{
55 memcpy(listCell->data, data, list->dataSize);
56}
57
58void _list_insert_first_element(List* list, void* data)
59{
60 ListCell* newListCell = (ListCell*) safe_malloc(sizeof (ListCell));
61 newListCell->data = safe_malloc(list->dataSize);
62 memcpy(newListCell->data, data, list->dataSize);
63 newListCell->prev = NULL;
64 newListCell->next = NULL;
65 list->head = newListCell;
66 list->tail = newListCell;
67 list->size = 1;
68}
69
70void _list_insert_before(List* list, ListCell* listCell, void* data)
71{
72 ListCell* newListCell = (ListCell*) safe_malloc(sizeof (ListCell));
73 newListCell->data = safe_malloc(list->dataSize);
74 memcpy(newListCell->data, data, list->dataSize);
75 newListCell->prev = listCell->prev;
76 newListCell->next = listCell;
77 if (listCell->prev != NULL)
78 listCell->prev->next = newListCell;
79 else
80 list->head = newListCell;
81 listCell->prev = newListCell;
82 list->size++;
83}
84
85void _list_insert_after(List* list, ListCell* listCell, void* data)
86{
87 ListCell* newListCell = (ListCell*) safe_malloc(sizeof (ListCell));
88 newListCell->data = safe_malloc(list->dataSize);
89 memcpy(newListCell->data, data, list->dataSize);
90 newListCell->prev = listCell;
91 newListCell->next = listCell->next;
92 if (listCell->next != NULL)
93 listCell->next->prev = newListCell;
94 else
95 list->tail = newListCell;
96 listCell->next = newListCell;
97 list->size++;
98}
99
100void _list_insert_front(List* list, void* data)
101{
102 if (list->head != NULL)
103 _list_insert_before(list, list->head, data);
104 else
105 _list_insert_first_element(list, data);
106}
107
108void _list_insert_back(List* list, void* data)
109{
110 if (list->tail != NULL)
111 _list_insert_after(list, list->tail, data);
112 else
113 _list_insert_first_element(list, data);
114}
115
116void list_remove(List* list, ListCell* listCell)
117{
118 if (listCell->prev != NULL)
119 listCell->prev->next = listCell->next;
120 else
121 list->head = listCell->next;
122 if (listCell->next != NULL)
123 listCell->next->prev = listCell->prev;
124 else
125 list->tail = listCell->prev;
126 safe_free(listCell->data);
127 safe_free(listCell);
128 list->size--;
129}
130
131void list_remove_front(List* list)
132{
133 list_remove(list, list->head);
134}
135
136void list_remove_back(List* list)
137{
138 list_remove(list, list->tail);
139}
140
141void list_clear(List* list)
142{
143 ListCell* current = list->head;
144 while (current != NULL)
145 {
146 safe_free(current->data);
147 ListCell* nextListCell = current->next;
148 safe_free(current);
149 current = nextListCell;
150 }
151 _list_init(list, list->dataSize);
152}
153
154void list_destroy(List* list)
155{
156 list_clear(list);
157 safe_free(list);
158}
159
160////////////////////
161// Iterator logic //
162////////////////////
163
164ListIterator* list_get_iterator(List* list)
165{
166 ListIterator* listI = (ListIterator*) safe_malloc(sizeof (ListIterator));
167 listI->list = list;
168 listI->current = NULL;
169 listI_reset_head(listI);
170 return listI;
171}
172
173void listI_reset_head(ListIterator* listI)
174{
175 listI->current = listI->list->head;
176}
177
178void listI_reset_tail(ListIterator* listI)
179{
180 listI->current = listI->list->tail;
181}
182
183Bool listI_has_data(ListIterator* listI)
184{
185 return (listI->current != NULL);
186}
187
188void listI_remove(ListIterator* listI, Direction direction)
189{
190 ListCell* toTrash = listI->current;
191 switch (direction)
192 {
193 case FORWARD:
194 listI->current = listI->current->next;
195 break;
196 case BACKWARD:
197 listI->current = listI->current->prev;
198 break;
199 }
200 list_remove(listI->list, toTrash);
201}
202
203void listI_move_next(ListIterator* listI)
204{
205 if (listI->current != NULL)
206 listI->current = listI->current->next;
207}
208
209void listI_move_prev(ListIterator* listI)
210{
211 if (listI->current != NULL)
212 listI->current = listI->current->prev;
213}
214
215void listI_destroy(ListIterator* listI)
216{
217 safe_free(listI);
218}