1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: list.cpp
5 Desc: contains list handling functions.
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "main.hpp"
13 #include "entity.hpp"
14 #include "items.hpp"
15 #include "interface/interface.hpp"
16 /*-------------------------------------------------------------------------------
17
18 list_FreeAll
19
20 frees an entire list and all of its contents
21
22 -------------------------------------------------------------------------------*/
23
list_FreeAll(list_t * list)24 void list_FreeAll(list_t* list)
25 {
26 node_t* node, *nextnode;
27 if (list == map.entities)
28 map.entities_map.clear();
29 for ( node = list->first; node != NULL; node = nextnode )
30 {
31 nextnode = node->next;
32 list_RemoveNode(node);
33 }
34 list->first = NULL;
35 list->last = NULL;
36 }
37
38 /*-------------------------------------------------------------------------------
39
40 list_RemoveNode
41
42 removes a specific node from a list
43
44 -------------------------------------------------------------------------------*/
45
list_RemoveNode(node_t * node)46 void list_RemoveNode(node_t* node)
47 {
48 if ( !node )
49 {
50 return;
51 }
52 if (node->list && node->list == map.entities)
53 {
54 map.entities_map.erase(((Entity*)node->element)->getUID());
55 }
56 if ( stats[clientnum] && node->list && node->list == &stats[clientnum]->inventory )
57 {
58 Item* tmp = ((Item*)node->element);
59 if ( tmp )
60 {
61 if ( tmp == selectedItem )
62 {
63 selectedItem = nullptr; // important! crashes occur when deleting items you've selected...
64 // printlog("Reset selectedItem");
65 }
66 if ( GenericGUI.isItemUsedForCurrentGUI(*tmp) )
67 {
68 GenericGUI.clearCurrentGUIFromItem(*tmp);
69 }
70 }
71 }
72 if ( node->list && node->list->first )
73 {
74 // if this is the first node...
75 if ( node == node->list->first )
76 {
77 // is it also the last node?
78 if ( node->list->last == node )
79 {
80 node->list->first = NULL;
81 node->list->last = NULL;
82 }
83
84 // otherwise, the "first" pointer needs to point to the next node
85 else
86 {
87 node->next->prev = NULL;
88 node->list->first = node->next;
89 }
90 }
91
92 // if this is the last node, but not the first...
93 else if ( node == node->list->last )
94 {
95 node->prev->next = NULL;
96 node->list->last = node->prev; // the "last" pointer needs to point to the previous node
97 }
98
99 // if the node is neither first nor last, it is in the middle
100 else
101 {
102 // bridge the previous node and the first node together
103 node->prev->next = node->next;
104 node->next->prev = node->prev;
105 }
106 }
107
108 // once the node is removed from the list, delete it
109 // If a node has a deconstructor, then deconstruct it. Otherwise it's a class and we'll delete it (which calls the destructor)
110 if (*node->deconstructor)
111 {
112 (*node->deconstructor)(node->element);
113 }
114 else
115 {
116 free(node->element);
117 }
118 free(node);
119 }
120
121 /*-------------------------------------------------------------------------------
122
123 list_AddNodeFirst
124
125 inserts a new node at the beginning of a given list
126
127 warning: "element" and "deconstructor" elements are NULL when created!
128
129 -------------------------------------------------------------------------------*/
130
list_AddNodeFirst(list_t * list)131 node_t* list_AddNodeFirst(list_t* list)
132 {
133 node_t* node;
134
135 // allocate memory for node
136 if ( (node = (node_t*) malloc(sizeof(node_t))) == NULL )
137 {
138 printlog( "failed to allocate memory for new node!\n" );
139 exit(1);
140 }
141
142 // initialize data pointers to NULL
143 node->element = NULL;
144 node->deconstructor = NULL;
145 node->size = 0;
146 node->prev = NULL;
147
148 // integrate it into the list
149 node->list = list;
150 if ( list->first != NULL )
151 {
152 // there are prior nodes in the list
153 node->next = list->first;
154 list->first->prev = node;
155 }
156 else
157 {
158 // inserting into an empty list
159 node->next = NULL;
160 list->last = node;
161 }
162 list->first = node;
163
164 return node;
165 }
166
167 /*-------------------------------------------------------------------------------
168
169 list_AddNodeLast
170
171 inserts a new node at the end of a given list
172
173 warning: "element" and "deconstructor" elements are NULL when created!
174
175 -------------------------------------------------------------------------------*/
176
list_AddNodeLast(list_t * list)177 node_t* list_AddNodeLast(list_t* list)
178 {
179 node_t* node;
180
181 // allocate memory for node
182 if ( (node = (node_t*) malloc(sizeof(node_t))) == NULL )
183 {
184 printlog( "failed to allocate memory for new node!\n" );
185 exit(1);
186 }
187
188 // initialize data pointers to NULL
189 node->element = NULL;
190 node->deconstructor = NULL;
191 node->size = 0;
192 node->next = NULL;
193
194 // integrate it into the list
195 node->list = list;
196 if ( list->last != NULL )
197 {
198 // there are prior nodes in the list
199 node->prev = list->last;
200 list->last->next = node;
201 }
202 else
203 {
204 // inserting into an empty list
205 node->prev = NULL;
206 list->first = node;
207 }
208 list->last = node;
209
210 return node;
211 }
212
213 /*-------------------------------------------------------------------------------
214
215 list_AddNode
216
217 inserts a new node at the specified index of the given list, pushing
218 any existing nodes back to make room for it.
219
220 warning: "element" and "deconstructor" elements are NULL when created!
221
222 -------------------------------------------------------------------------------*/
223
list_AddNode(list_t * list,int index)224 node_t* list_AddNode(list_t* list, int index)
225 {
226 node_t* node;
227 if ( index < 0 || index > list_Size(list))
228 {
229 return NULL;
230 }
231
232 // allocate memory for node
233 if ( (node = (node_t*) malloc(sizeof(node_t))) == NULL )
234 {
235 printlog( "failed to allocate memory for new node!\n" );
236 exit(1);
237 }
238
239 // initialize data pointers to NULL
240 node->element = NULL;
241 node->deconstructor = NULL;
242 node->size = 0;
243 node->prev = NULL;
244 node->next = NULL;
245
246 // integrate it into the list
247 node->list = list;
248 node_t* oldnode = list_Node(list, index);
249 if ( oldnode )
250 {
251 // inserting at the beginning or middle of a list
252 node->prev = oldnode->prev;
253 node->next = oldnode;
254 if ( list->first == oldnode )
255 {
256 // inserting at the beginning
257 list->first = node;
258 }
259 else
260 {
261 // inserting in the middle
262 oldnode->prev->next = node;
263 }
264 oldnode->prev = node;
265 }
266 else
267 {
268 if ( list_Size(list) )
269 {
270 // inserting at the end of a list
271 node->prev = list->last;
272 node->next = NULL;
273 list->last->next = node;
274 list->last = node;
275 }
276 else
277 {
278 // inserting into an empty list
279 node->prev = NULL;
280 node->next = NULL;
281 list->first = node;
282 list->last = node;
283 }
284 }
285
286 return node;
287 }
288
289 /*-------------------------------------------------------------------------------
290
291 list_Size
292
293 returns the number of nodes in the given list
294
295 -------------------------------------------------------------------------------*/
296
list_Size(list_t * list)297 Uint32 list_Size(list_t* list)
298 {
299 node_t* node;
300 int c;
301
302 if ( !list )
303 {
304 return 0;
305 }
306
307 for ( c = 0, node = list->first; node != NULL; node = node->next, c++ );
308 return c;
309 }
310
311 /*-------------------------------------------------------------------------------
312
313 list_Copy
314
315 copies the contents of one list into another (appending any new nodes at
316 the end of destlist)
317
318 -------------------------------------------------------------------------------*/
319
list_Copy(list_t * destlist,list_t * srclist)320 list_t* list_Copy(list_t* destlist, list_t* srclist)
321 {
322 node_t* node;
323 for ( node = srclist->first; node != NULL; node = node->next )
324 {
325 if ( node->size == 0 )
326 {
327 printlog("error: attempted copy of node with size 0! Node not copied\n");
328 continue;
329 }
330 node_t* newnode = list_AddNodeLast(destlist);
331 newnode->deconstructor = node->deconstructor;
332 newnode->element = malloc(node->size);
333 newnode->size = node->size;
334 memcpy(newnode->element, node->element, node->size);
335 }
336
337 return destlist;
338 }
339
340 /*-------------------------------------------------------------------------------
341
342 list_CopyNew
343
344 copies the contents of one list into a new one which is subsequently
345 returned
346
347 -------------------------------------------------------------------------------*/
348
list_CopyNew(list_t * srclist)349 list_t* list_CopyNew(list_t* srclist)
350 {
351 if ( !srclist )
352 {
353 return NULL;
354 }
355 list_t* destlist = (list_t*) malloc(sizeof(list_t));
356 if ( !destlist )
357 {
358 printlog("critical error: list_CopyNew() failed to allocate memory for new list!\n");
359 return NULL;
360 }
361 destlist->first = NULL;
362 destlist->last = NULL;
363
364 node_t* node;
365 for ( node = srclist->first; node != NULL; node = node->next )
366 {
367 if ( node->size == 0 )
368 {
369 printlog("error: attempted copy of node with size 0! Node not copied\n");
370 continue;
371 }
372 node_t* newnode = list_AddNodeLast(destlist);
373 newnode->deconstructor = node->deconstructor;
374 newnode->element = malloc(node->size);
375 newnode->size = node->size;
376 memcpy(newnode->element, node->element, node->size);
377 }
378
379 return destlist;
380 }
381
382 /*-------------------------------------------------------------------------------
383
384 list_Index
385
386 returns the index number of a given node in its list.
387
388 -------------------------------------------------------------------------------*/
389
list_Index(node_t * node)390 Uint32 list_Index(node_t* node)
391 {
392 node_t* tempnode;
393 int i;
394
395 for ( i = 0, tempnode = node->list->first; tempnode != NULL; tempnode = tempnode->next, i++ )
396 {
397 if ( tempnode == node )
398 {
399 break;
400 }
401 }
402
403 return i;
404 }
405
406 /*-------------------------------------------------------------------------------
407
408 list_Node
409
410 returns the node with the given index number in the given list
411
412 -------------------------------------------------------------------------------*/
413
list_Node(list_t * list,int index)414 node_t* list_Node(list_t* list, int index)
415 {
416 if ( index < 0 || index >= list_Size(list) )
417 {
418 return NULL;
419 }
420
421 int i;
422 node_t* node = list->first;
423
424 for ( i = 0; i != index; node = node->next, i++ );
425 return node;
426 }
427