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 nullptr;
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 nullptr;
89}
90
99BOOL LinkedList_Contains(wLinkedList* list, const void* value)
100{
101 wLinkedListNode* item = nullptr;
102 OBJECT_EQUALS_FN keyEquals = nullptr;
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 != nullptr);
120}
121
122static wLinkedListNode* LinkedList_FreeNode(wLinkedList* list, wLinkedListNode* node)
123{
124 wLinkedListNode* next = nullptr;
125 wLinkedListNode* prev = nullptr;
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 (node == list->current)
145 {
146 /* Never leave the enumerator on a freed node: the next MoveNext continues after the removed
147 * node. */
148 list->current = prev;
149 if (!prev)
150 list->initial = 1;
151 }
152
153 if (list->object.fnObjectUninit)
154 list->object.fnObjectUninit(node);
155
156 if (list->object.fnObjectFree)
157 list->object.fnObjectFree(node);
158
159 free(node);
160 list->count--;
161 return next;
162}
163
168void LinkedList_Clear(wLinkedList* list)
169{
170 wLinkedListNode* node = nullptr;
171 WINPR_ASSERT(list);
172 if (!list->head)
173 return;
174
175 node = list->head;
176
177 while (node)
178 node = LinkedList_FreeNode(list, node);
179
180 list->head = list->tail = nullptr;
181 list->count = 0;
182}
183
184static wLinkedListNode* LinkedList_Create(wLinkedList* list, const void* value)
185{
186 wLinkedListNode* node = nullptr;
187
188 WINPR_ASSERT(list);
189 node = (wLinkedListNode*)calloc(1, sizeof(wLinkedListNode));
190
191 if (!node)
192 return nullptr;
193
194 if (list->object.fnObjectNew)
195 node->value = list->object.fnObjectNew(value);
196 else
197 {
198 union
199 {
200 const void* cpv;
201 void* pv;
202 } cnv;
203 cnv.cpv = value;
204 node->value = cnv.pv;
205 }
206
207 if (list->object.fnObjectInit)
208 list->object.fnObjectInit(node);
209
210 return node;
211}
216BOOL LinkedList_AddFirst(wLinkedList* list, const void* value)
217{
218 wLinkedListNode* node = LinkedList_Create(list, value);
219
220 if (!node)
221 return FALSE;
222
223 if (!list->head)
224 {
225 list->tail = list->head = node;
226 }
227 else
228 {
229 list->head->prev = node;
230 node->next = list->head;
231 list->head = node;
232 }
233
234 list->count++;
235 return TRUE;
236}
237
242BOOL LinkedList_AddLast(wLinkedList* list, const void* value)
243{
244 wLinkedListNode* node = LinkedList_Create(list, value);
245
246 if (!node)
247 return FALSE;
248
249 if (!list->tail)
250 {
251 list->head = list->tail = node;
252 }
253 else
254 {
255 list->tail->next = node;
256 node->prev = list->tail;
257 list->tail = node;
258 }
259
260 list->count++;
261 return TRUE;
262}
263
268BOOL LinkedList_Remove(wLinkedList* list, const void* value)
269{
270 wLinkedListNode* node = nullptr;
271 OBJECT_EQUALS_FN keyEquals = nullptr;
272 WINPR_ASSERT(list);
273
274 keyEquals = list->object.fnObjectEquals;
275 node = list->head;
276
277 while (node)
278 {
279 if (keyEquals(node->value, value))
280 {
281 LinkedList_FreeNode(list, node);
282 return TRUE;
283 }
284
285 node = node->next;
286 }
287
288 return FALSE;
289}
290
295void LinkedList_RemoveFirst(wLinkedList* list)
296{
297 WINPR_ASSERT(list);
298 if (list->head)
299 LinkedList_FreeNode(list, list->head);
300}
301
306void LinkedList_RemoveLast(wLinkedList* list)
307{
308 WINPR_ASSERT(list);
309 if (list->tail)
310 LinkedList_FreeNode(list, list->tail);
311}
312
317void LinkedList_Enumerator_Reset(wLinkedList* list)
318{
319 WINPR_ASSERT(list);
320 list->initial = 1;
321 list->current = nullptr;
322}
323
324/*
325 * Gets the element at the current position of the enumerator.
326 */
327
328void* LinkedList_Enumerator_Current(wLinkedList* list)
329{
330 WINPR_ASSERT(list);
331 if (list->initial)
332 return nullptr;
333
334 if (list->current)
335 return list->current->value;
336 else
337 return nullptr;
338}
339
340/*
341 * Advances the enumerator to the next element of the LinkedList.
342 */
343
344BOOL LinkedList_Enumerator_MoveNext(wLinkedList* list)
345{
346 WINPR_ASSERT(list);
347 if (list->initial)
348 {
349 list->initial = 0;
350 list->current = list->head;
351 }
352 else if (list->current)
353 list->current = list->current->next;
354
355 if (!list->current)
356 return FALSE;
357
358 return TRUE;
359}
360
361static BOOL default_equal_function(const void* objA, const void* objB)
362{
363 return objA == objB;
364}
365
370wLinkedList* LinkedList_New(void)
371{
372 wLinkedList* list = nullptr;
373 list = (wLinkedList*)calloc(1, sizeof(wLinkedList));
374
375 if (list)
376 {
377 list->object.fnObjectEquals = default_equal_function;
378 }
379
380 return list;
381}
382
383void LinkedList_Free(wLinkedList* list)
384{
385 if (list)
386 {
387 LinkedList_Clear(list);
388 free(list);
389 }
390}
391
392wObject* LinkedList_Object(wLinkedList* list)
393{
394 WINPR_ASSERT(list);
395
396 return &list->object;
397}
This struct contains function pointer to initialize/free objects.
Definition collections.h:52