Now using 2 spaces instead of tabs. Fix copyright years. Improve documentation
[cgds.git] / src / List.c
1 /**
2 * @file List.c
3 */
4
5 #include "cgds/List.h"
6
7 ////////////////
8 // List logic //
9 ////////////////
10
11 void _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
19 List* _list_new(size_t dataSize)
20 {
21 List* list = (List*) safe_malloc(sizeof (List));
22 _list_init(list, dataSize);
23 return list;
24 }
25
26 List* 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
38 bool list_empty(List* list)
39 {
40 return (list->size == 0);
41 }
42
43 UInt list_size(List* list)
44 {
45 return list->size;
46 }
47
48 void* _list_get(ListCell* listCell)
49 {
50 return listCell->data;
51 }
52
53 void _list_set(List* list, ListCell* listCell, void* data)
54 {
55 memcpy(listCell->data, data, list->dataSize);
56 }
57
58 void _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
70 void _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
85 void _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
100 void _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
108 void _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
116 void 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
131 void list_remove_front(List* list)
132 {
133 list_remove(list, list->head);
134 }
135
136 void list_remove_back(List* list)
137 {
138 list_remove(list, list->tail);
139 }
140
141 void 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
154 void list_destroy(List* list)
155 {
156 list_clear(list);
157 safe_free(list);
158 }
159
160 ////////////////////
161 // Iterator logic //
162 ////////////////////
163
164 ListIterator* 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
173 void listI_reset_head(ListIterator* listI)
174 {
175 listI->current = listI->list->head;
176 }
177
178 void listI_reset_tail(ListIterator* listI)
179 {
180 listI->current = listI->list->tail;
181 }
182
183 bool listI_has_data(ListIterator* listI)
184 {
185 return (listI->current != NULL);
186 }
187
188 void 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
203 void listI_move_next(ListIterator* listI)
204 {
205 if (listI->current != NULL)
206 listI->current = listI->current->next;
207 }
208
209 void listI_move_prev(ListIterator* listI)
210 {
211 if (listI->current != NULL)
212 listI->current = listI->current->prev;
213 }
214
215 void listI_destroy(ListIterator* listI)
216 {
217 safe_free(listI);
218 }