Mercurial > almixer_isolated
comparison LinkedList.c @ 13:54aa96ae8912
Added LinkedList class to project.
ALmixer now saves ALmixer_Data instances in a private linked list so when Quit is called, this memory can be cleaned up.
This is meant to deal with two problems. First, SDL_sound does something similar which means since I wrap SDL_sound structures, I may be left with dangling pointers if. Second is the obvious auto-cleanup when quiting which is convenient for resetting.
author | Eric Wing <ewing . public |-at-| gmail . com> |
---|---|
date | Sat, 06 Nov 2010 00:37:29 -0700 |
parents | |
children | b27f7ff5e44b |
comparison
equal
deleted
inserted
replaced
12:bfe90b4f3d87 | 13:54aa96ae8912 |
---|---|
1 #include "LinkedList.h" | |
2 #include <stddef.h> /* for NULL */ | |
3 #include <stdlib.h> /* for malloc/free */ | |
4 #include <stdio.h> /* for debugging */ | |
5 | |
6 struct LinkedListNode | |
7 { | |
8 LinkedListNode* nextNode; | |
9 LinkedListNode* previousNode; | |
10 void* dataPtr; | |
11 }; | |
12 | |
13 struct LinkedList | |
14 { | |
15 size_t currentSize; | |
16 LinkedListNode* headPtr; | |
17 LinkedListNode* tailPtr; | |
18 }; | |
19 | |
20 | |
21 LinkedListNode* LinkedListNode_Create() | |
22 { | |
23 LinkedListNode* list_node; | |
24 list_node = (LinkedListNode*)calloc(1, sizeof(LinkedListNode)); | |
25 if(NULL == list_node) | |
26 { | |
27 /* Very bad, but not sure what to do here. */ | |
28 return NULL; | |
29 } | |
30 | |
31 return list_node; | |
32 } | |
33 | |
34 | |
35 void LinkedListNode_Free(LinkedListNode* list_node) | |
36 { | |
37 if(NULL == list_node) | |
38 { | |
39 return; | |
40 } | |
41 free(list_node); | |
42 } | |
43 | |
44 | |
45 LinkedList* LinkedList_Create() | |
46 { | |
47 LinkedList* linked_list; | |
48 linked_list = (LinkedList*)calloc(1, sizeof(LinkedList)); | |
49 if(NULL == linked_list) | |
50 { | |
51 /* Very bad, but not sure what to do here. */ | |
52 return NULL; | |
53 } | |
54 | |
55 return linked_list; | |
56 } | |
57 | |
58 void LinkedList_Free(LinkedList* linked_list) | |
59 { | |
60 /* Both functions check for NULL */ | |
61 LinkedList_Clear(linked_list); | |
62 free(linked_list); | |
63 } | |
64 | |
65 | |
66 /** | |
67 * Returns 1 if successful, 0 if failure. | |
68 */ | |
69 unsigned int LinkedList_PushFront(LinkedList* linked_list, void* new_item) | |
70 { | |
71 LinkedListNode* new_node; | |
72 | |
73 if(NULL == linked_list) | |
74 { | |
75 return 0; | |
76 } | |
77 | |
78 new_node = LinkedListNode_Create(); | |
79 if(NULL == new_node) | |
80 { | |
81 return 0; | |
82 } | |
83 | |
84 new_node->dataPtr = new_item; | |
85 | |
86 if(0 == linked_list->currentSize) | |
87 { | |
88 linked_list->tailPtr = new_node; | |
89 } | |
90 else | |
91 { | |
92 LinkedListNode* head_node = linked_list->headPtr; | |
93 new_node->nextNode = head_node; | |
94 head_node->previousNode = new_node; | |
95 } | |
96 | |
97 linked_list->headPtr = new_node; | |
98 linked_list->currentSize++; | |
99 return 1; | |
100 } | |
101 | |
102 unsigned int LinkedList_PushBack(LinkedList* linked_list, void* new_item) | |
103 { | |
104 LinkedListNode* new_node; | |
105 | |
106 if(NULL == linked_list) | |
107 { | |
108 return 0; | |
109 } | |
110 | |
111 new_node = LinkedListNode_Create(); | |
112 if(NULL == new_node) | |
113 { | |
114 return 0; | |
115 } | |
116 | |
117 new_node->dataPtr = new_item; | |
118 | |
119 if(0 == linked_list->currentSize) | |
120 { | |
121 linked_list->headPtr = new_node; | |
122 } | |
123 else | |
124 { | |
125 LinkedListNode* tail_node = linked_list->tailPtr; | |
126 new_node->previousNode = tail_node; | |
127 tail_node->nextNode = new_node; | |
128 } | |
129 | |
130 linked_list->tailPtr = new_node; | |
131 linked_list->currentSize++; | |
132 return 1; | |
133 | |
134 } | |
135 | |
136 void* LinkedList_PopFront(LinkedList* linked_list) | |
137 { | |
138 LinkedListNode* head_node; | |
139 void* return_data; | |
140 | |
141 if(NULL == linked_list) | |
142 { | |
143 return 0; | |
144 } | |
145 if(0 == linked_list->currentSize) | |
146 { | |
147 return NULL; | |
148 } | |
149 | |
150 head_node = linked_list->headPtr; | |
151 return_data = head_node->dataPtr; | |
152 | |
153 if(1 == linked_list->currentSize) | |
154 { | |
155 LinkedList_Clear(linked_list); | |
156 } | |
157 else | |
158 { | |
159 LinkedListNode* next_node = head_node->nextNode; | |
160 next_node->previousNode = NULL; | |
161 LinkedListNode_Free(head_node); | |
162 linked_list->headPtr = next_node; | |
163 linked_list->currentSize = linked_list->currentSize - 1; | |
164 | |
165 } | |
166 return return_data; | |
167 } | |
168 | |
169 void* LinkedList_PopBack(LinkedList* linked_list) | |
170 { | |
171 LinkedListNode* tail_node; | |
172 void* return_data; | |
173 | |
174 if(NULL == linked_list) | |
175 { | |
176 return NULL; | |
177 } | |
178 if(0 == linked_list->currentSize) | |
179 { | |
180 return NULL; | |
181 } | |
182 | |
183 tail_node = linked_list->tailPtr; | |
184 return_data = tail_node->dataPtr; | |
185 | |
186 if(1 == linked_list->currentSize) | |
187 { | |
188 LinkedList_Clear(linked_list); | |
189 } | |
190 else | |
191 { | |
192 LinkedListNode* previous_node = tail_node->previousNode; | |
193 previous_node->nextNode = NULL; | |
194 LinkedListNode_Free(tail_node); | |
195 linked_list->tailPtr = previous_node; | |
196 linked_list->currentSize = linked_list->currentSize - 1; | |
197 } | |
198 return return_data; | |
199 } | |
200 | |
201 size_t LinkedList_Size(LinkedList* linked_list) | |
202 { | |
203 if(NULL == linked_list) | |
204 { | |
205 return 0; | |
206 } | |
207 return linked_list->currentSize; | |
208 } | |
209 | |
210 void LinkedList_Clear(LinkedList* linked_list) | |
211 { | |
212 if(NULL == linked_list) | |
213 { | |
214 return; | |
215 } | |
216 | |
217 LinkedListNode* current_node = linked_list->headPtr; | |
218 LinkedListNode* next_node; | |
219 while(NULL != current_node) | |
220 { | |
221 next_node = current_node->nextNode; | |
222 LinkedListNode_Free(current_node); | |
223 current_node = next_node; | |
224 } | |
225 linked_list->headPtr = NULL; | |
226 linked_list->tailPtr = NULL; | |
227 linked_list->currentSize = 0; | |
228 } | |
229 | |
230 void* LinkedListNode_GetData(LinkedListNode* list_node) | |
231 { | |
232 if(NULL == list_node) | |
233 { | |
234 return NULL; | |
235 } | |
236 return list_node->dataPtr; | |
237 } | |
238 | |
239 LinkedListNode* LinkedList_Find(LinkedList* linked_list, void* the_data, LinkedListNode* start_node) | |
240 { | |
241 LinkedListNode* current_node; | |
242 if(NULL == linked_list) | |
243 { | |
244 return; | |
245 } | |
246 if(NULL == start_node) | |
247 { | |
248 start_node = linked_list->headPtr; | |
249 } | |
250 | |
251 for(current_node = start_node; NULL != current_node; current_node = current_node->nextNode) | |
252 { | |
253 if(current_node->dataPtr == the_data) | |
254 { | |
255 return current_node; | |
256 } | |
257 } | |
258 return current_node; | |
259 } | |
260 | |
261 /* Make sure your LinkedListNode is actually connected to the | |
262 * LinkedList instance you pass. | |
263 */ | |
264 unsigned int LinkedList_Remove(LinkedList* linked_list, LinkedListNode* list_node) | |
265 { | |
266 LinkedListNode* previous_node; | |
267 LinkedListNode* next_node; | |
268 if(NULL == linked_list) | |
269 { | |
270 return 0; | |
271 } | |
272 if(NULL == list_node) | |
273 { | |
274 return 0; | |
275 } | |
276 | |
277 if(1 == linked_list->currentSize) | |
278 { | |
279 LinkedList_Clear(linked_list); | |
280 } | |
281 else if(list_node == linked_list->headPtr) | |
282 { | |
283 LinkedList_PopFront(linked_list); | |
284 } | |
285 else if(list_node == linked_list->tailPtr) | |
286 { | |
287 LinkedList_PopBack(linked_list); | |
288 } | |
289 else | |
290 { | |
291 previous_node = list_node->previousNode; | |
292 next_node = list_node->nextNode; | |
293 | |
294 previous_node->nextNode = next_node; | |
295 next_node->previousNode = previous_node; | |
296 LinkedListNode_Free(list_node); | |
297 | |
298 linked_list->currentSize = linked_list->currentSize - 1; | |
299 } | |
300 | |
301 return 1; | |
302 | |
303 } | |
304 | |
305 | |
306 |