FreeRDP
Loading...
Searching...
No Matches
LinkedList.c
1
20#include <winpr/config.h>
21
22#include <winpr/collections.h>
23#include <winpr/assert.h>
24
25typedef struct s_wLinkedListItem wLinkedListNode;
26
27struct s_wLinkedListItem
28{
29 void* value;
30 wLinkedListNode* prev;
31 wLinkedListNode* next;
32};
33
34struct s_wLinkedList
35{
36 size_t count;
37 int initial;
38 wLinkedListNode* head;
39 wLinkedListNode* tail;
40 wLinkedListNode* current;
41 wObject object;
42};
43
59size_t LinkedList_Count(wLinkedList* list)
60{
61 WINPR_ASSERT(list);
62 return list->count;
63}
64
69void* LinkedList_First(wLinkedList* list)
70{
71 WINPR_ASSERT(list);
72 if (list->head)
73 return list->head->value;
74 else
75 return NULL;
76}
77
82void* LinkedList_Last(wLinkedList* list)
83{
84 WINPR_ASSERT(list);
85 if (list->tail)
86 return list->tail->value;
87 else
88 return NULL;
89}
90
99BOOL LinkedList_Contains(wLinkedList* list, const void* value)
100{
101 wLinkedListNode* item = NULL;
102 OBJECT_EQUALS_FN keyEquals = NULL;
103
104 WINPR_ASSERT(list);
105 if (!list->head)
106 return FALSE;
107
108 item = list->head;
109 keyEquals = list->object.fnObjectEquals;
110
111 while (item)
112 {
113 if (keyEquals(item->value, value))
114 break;
115
116 item = item->next;
117 }
118
119 return (item) ? TRUE : FALSE;
120}
121
122static wLinkedListNode* LinkedList_FreeNode(wLinkedList* list, wLinkedListNode* node)
123{
124 wLinkedListNode* next = NULL;
125 wLinkedListNode* prev = NULL;
126
127 WINPR_ASSERT(list);
128 WINPR_ASSERT(node);
129
130 next = node->next;
131 prev = node->prev;
132 if (prev)
133 prev->next = next;
134
135 if (next)
136 next->prev = prev;
137
138 if (node == list->head)
139 list->head = node->next;
140
141 if (node == list->tail)
142 list->tail = node->prev;
143
144 if (list->object.fnObjectUninit)
145 list->object.fnObjectUninit(node);
146
147 if (list->object.fnObjectFree)
148 list->object.fnObjectFree(node);
149
150 free(node);
151 list->count--;
152 return next;
153}
154
159void LinkedList_Clear(wLinkedList* list)
160{
161 wLinkedListNode* node = NULL;
162 WINPR_ASSERT(list);
163 if (!list->head)
164 return;
165
166 node = list->head;
167
168 while (node)
169 node = LinkedList_FreeNode(list, node);
170
171 list->head = list->tail = NULL;
172 list->count = 0;
173}
174
175static wLinkedListNode* LinkedList_Create(wLinkedList* list, const void* value)
176{
177 wLinkedListNode* node = NULL;
178
179 WINPR_ASSERT(list);
180 node = (wLinkedListNode*)calloc(1, sizeof(wLinkedListNode));
181
182 if (!node)
183 return NULL;
184
185 if (list->object.fnObjectNew)
186 node->value = list->object.fnObjectNew(value);
187 else
188 {
189 union
190 {
191 const void* cpv;
192 void* pv;
193 } cnv;
194 cnv.cpv = value;
195 node->value = cnv.pv;
196 }
197
198 if (list->object.fnObjectInit)
199 list->object.fnObjectInit(node);
200
201 return node;
202}
207BOOL LinkedList_AddFirst(wLinkedList* list, const void* value)
208{
209 wLinkedListNode* node = LinkedList_Create(list, value);
210
211 if (!node)
212 return FALSE;
213
214 if (!list->head)
215 {
216 list->tail = list->head = node;
217 }
218 else
219 {
220 list->head->prev = node;
221 node->next = list->head;
222 list->head = node;
223 }
224
225 list->count++;
226 return TRUE;
227}
228
233BOOL LinkedList_AddLast(wLinkedList* list, const void* value)
234{
235 wLinkedListNode* node = LinkedList_Create(list, value);
236
237 if (!node)
238 return FALSE;
239
240 if (!list->tail)
241 {
242 list->head = list->tail = node;
243 }
244 else
245 {
246 list->tail->next = node;
247 node->prev = list->tail;
248 list->tail = node;
249 }
250
251 list->count++;
252 return TRUE;
253}
254
259BOOL LinkedList_Remove(wLinkedList* list, const void* value)
260{
261 wLinkedListNode* node = NULL;
262 OBJECT_EQUALS_FN keyEquals = NULL;
263 WINPR_ASSERT(list);
264
265 keyEquals = list->object.fnObjectEquals;
266 node = list->head;
267
268 while (node)
269 {
270 if (keyEquals(node->value, value))
271 {
272 LinkedList_FreeNode(list, node);
273 return TRUE;
274 }
275
276 node = node->next;
277 }
278
279 return FALSE;
280}
281
286void LinkedList_RemoveFirst(wLinkedList* list)
287{
288 WINPR_ASSERT(list);
289 if (list->head)
290 LinkedList_FreeNode(list, list->head);
291}
292
297void LinkedList_RemoveLast(wLinkedList* list)
298{
299 WINPR_ASSERT(list);
300 if (list->tail)
301 LinkedList_FreeNode(list, list->tail);
302}
303
308void LinkedList_Enumerator_Reset(wLinkedList* list)
309{
310 WINPR_ASSERT(list);
311 list->initial = 1;
312 list->current = list->head;
313}
314
315/*
316 * Gets the element at the current position of the enumerator.
317 */
318
319void* LinkedList_Enumerator_Current(wLinkedList* list)
320{
321 WINPR_ASSERT(list);
322 if (list->initial)
323 return NULL;
324
325 if (list->current)
326 return list->current->value;
327 else
328 return NULL;
329}
330
331/*
332 * Advances the enumerator to the next element of the LinkedList.
333 */
334
335BOOL LinkedList_Enumerator_MoveNext(wLinkedList* list)
336{
337 WINPR_ASSERT(list);
338 if (list->initial)
339 list->initial = 0;
340 else if (list->current)
341 list->current = list->current->next;
342
343 if (!list->current)
344 return FALSE;
345
346 return TRUE;
347}
348
349static BOOL default_equal_function(const void* objA, const void* objB)
350{
351 return objA == objB;
352}
353
358wLinkedList* LinkedList_New(void)
359{
360 wLinkedList* list = NULL;
361 list = (wLinkedList*)calloc(1, sizeof(wLinkedList));
362
363 if (list)
364 {
365 list->object.fnObjectEquals = default_equal_function;
366 }
367
368 return list;
369}
370
371void LinkedList_Free(wLinkedList* list)
372{
373 if (list)
374 {
375 LinkedList_Clear(list);
376 free(list);
377 }
378}
379
380wObject* LinkedList_Object(wLinkedList* list)
381{
382 WINPR_ASSERT(list);
383
384 return &list->object;
385}
This struct contains function pointer to initialize/free objects.
Definition collections.h:57