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