FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
ListDictionary.c
1
20#include <winpr/config.h>
21#include <winpr/assert.h>
22#include <winpr/crt.h>
23
24#include <winpr/collections.h>
25
26typedef struct s_wListDictionaryItem wListDictionaryItem;
27
28struct s_wListDictionaryItem
29{
30 void* key;
31 void* value;
32
33 wListDictionaryItem* next;
34};
35
36struct s_wListDictionary
37{
38 BOOL synchronized;
40
41 wListDictionaryItem* head;
42 wObject objectKey;
43 wObject objectValue;
44};
45
53WINPR_API wObject* ListDictionary_KeyObject(wListDictionary* listDictionary)
54{
55 WINPR_ASSERT(listDictionary);
56 return &listDictionary->objectKey;
57}
58
59WINPR_API wObject* ListDictionary_ValueObject(wListDictionary* listDictionary)
60{
61 WINPR_ASSERT(listDictionary);
62 return &listDictionary->objectValue;
63}
64
73size_t ListDictionary_Count(wListDictionary* listDictionary)
74{
75 size_t count = 0;
76
77 WINPR_ASSERT(listDictionary);
78
79 if (listDictionary->synchronized)
80 EnterCriticalSection(&listDictionary->lock);
81
82 if (listDictionary->head)
83 {
84 wListDictionaryItem* item = listDictionary->head;
85
86 while (item)
87 {
88 count++;
89 item = item->next;
90 }
91 }
92
93 if (listDictionary->synchronized)
94 LeaveCriticalSection(&listDictionary->lock);
95
96 return count;
97}
98
103void ListDictionary_Lock(wListDictionary* listDictionary)
104{
105 WINPR_ASSERT(listDictionary);
106
107 EnterCriticalSection(&listDictionary->lock);
108}
109
114void ListDictionary_Unlock(wListDictionary* listDictionary)
115{
116 WINPR_ASSERT(listDictionary);
117
118 LeaveCriticalSection(&listDictionary->lock);
119}
120
129size_t ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys)
130{
131 ULONG_PTR* pKeys = NULL;
132
133 WINPR_ASSERT(listDictionary);
134 if (!ppKeys)
135 return 0;
136
137 if (listDictionary->synchronized)
138 EnterCriticalSection(&listDictionary->lock);
139
140 size_t count = 0;
141
142 if (listDictionary->head)
143 {
144 wListDictionaryItem* item = listDictionary->head;
145
146 while (item)
147 {
148 count++;
149 item = item->next;
150 }
151 }
152
153 if (count > 0)
154 {
155 pKeys = (ULONG_PTR*)calloc(count, sizeof(ULONG_PTR));
156
157 if (!pKeys)
158 {
159 if (listDictionary->synchronized)
160 LeaveCriticalSection(&listDictionary->lock);
161
162 return 0;
163 }
164 }
165
166 size_t index = 0;
167
168 if (listDictionary->head)
169 {
170 wListDictionaryItem* item = listDictionary->head;
171
172 while (item)
173 {
174 pKeys[index++] = (ULONG_PTR)item->key;
175 item = item->next;
176 }
177 }
178
179 *ppKeys = pKeys;
180
181 if (listDictionary->synchronized)
182 LeaveCriticalSection(&listDictionary->lock);
183
184 return count;
185}
186
187static void item_free(wListDictionary* listDictionary, wListDictionaryItem* item)
188{
189 WINPR_ASSERT(listDictionary);
190
191 if (item)
192 {
193 if (listDictionary->objectKey.fnObjectFree)
194 listDictionary->objectKey.fnObjectFree(item->key);
195 if (listDictionary->objectValue.fnObjectFree)
196 listDictionary->objectValue.fnObjectFree(item->value);
197 }
198 free(item);
199}
200
201static void item_set(wListDictionary* listDictionary, wListDictionaryItem* item, const void* value)
202{
203 WINPR_ASSERT(listDictionary);
204 WINPR_ASSERT(item);
205
206 if (listDictionary->objectValue.fnObjectFree)
207 listDictionary->objectValue.fnObjectFree(item->value);
208
209 if (listDictionary->objectValue.fnObjectNew)
210 item->value = listDictionary->objectValue.fnObjectNew(value);
211 else
212 item->value = (void*)(uintptr_t)value;
213}
214
215static wListDictionaryItem* new_item(wListDictionary* listDictionary, const void* key,
216 const void* value)
217{
218 wListDictionaryItem* item = (wListDictionaryItem*)calloc(1, sizeof(wListDictionaryItem));
219 if (!item)
220 return NULL;
221
222 if (listDictionary->objectKey.fnObjectNew)
223 item->key = listDictionary->objectKey.fnObjectNew(key);
224 else
225 item->key = (void*)(uintptr_t)key;
226 if (!item->key)
227 goto fail;
228
229 item_set(listDictionary, item, value);
230 if (value && !item->value)
231 goto fail;
232
233 return item;
234
235fail:
236 item_free(listDictionary, item);
237 return NULL;
238}
239
244BOOL ListDictionary_Add(wListDictionary* listDictionary, const void* key, const void* value)
245{
246 BOOL ret = FALSE;
247
248 WINPR_ASSERT(listDictionary);
249
250 if (listDictionary->synchronized)
251 EnterCriticalSection(&listDictionary->lock);
252
253 wListDictionaryItem* item = new_item(listDictionary, key, value);
254
255 if (!item)
256 goto out_error;
257
258 if (!listDictionary->head)
259 {
260 listDictionary->head = item;
261 }
262 else
263 {
264 wListDictionaryItem* lastItem = listDictionary->head;
265
266 while (lastItem->next)
267 lastItem = lastItem->next;
268
269 lastItem->next = item;
270 }
271
272 ret = TRUE;
273out_error:
274
275 if (listDictionary->synchronized)
276 LeaveCriticalSection(&listDictionary->lock);
277
278 return ret;
279}
280
285void ListDictionary_Clear(wListDictionary* listDictionary)
286{
287 wListDictionaryItem* item = NULL;
288 wListDictionaryItem* nextItem = NULL;
289
290 WINPR_ASSERT(listDictionary);
291
292 if (listDictionary->synchronized)
293 EnterCriticalSection(&listDictionary->lock);
294
295 if (listDictionary->head)
296 {
297 item = listDictionary->head;
298
299 while (item)
300 {
301 nextItem = item->next;
302
303 item_free(listDictionary, item);
304 item = nextItem;
305 }
306
307 listDictionary->head = NULL;
308 }
309
310 if (listDictionary->synchronized)
311 LeaveCriticalSection(&listDictionary->lock);
312}
313
318BOOL ListDictionary_Contains(wListDictionary* listDictionary, const void* key)
319{
320 wListDictionaryItem* item = NULL;
321 OBJECT_EQUALS_FN keyEquals = NULL;
322
323 WINPR_ASSERT(listDictionary);
324
325 if (listDictionary->synchronized)
326 EnterCriticalSection(&(listDictionary->lock));
327
328 keyEquals = listDictionary->objectKey.fnObjectEquals;
329 item = listDictionary->head;
330
331 while (item)
332 {
333 if (keyEquals(item->key, key))
334 break;
335
336 item = item->next;
337 }
338
339 if (listDictionary->synchronized)
340 LeaveCriticalSection(&(listDictionary->lock));
341
342 return (item) ? TRUE : FALSE;
343}
344
349static void* ListDictionary_RemoveOrTake(wListDictionary* listDictionary, const void* key,
350 BOOL take)
351{
352 void* value = NULL;
353 wListDictionaryItem* item = NULL;
354 wListDictionaryItem* prevItem = NULL;
355 OBJECT_EQUALS_FN keyEquals = NULL;
356
357 WINPR_ASSERT(listDictionary);
358
359 if (listDictionary->synchronized)
360 EnterCriticalSection(&listDictionary->lock);
361
362 keyEquals = listDictionary->objectKey.fnObjectEquals;
363 item = listDictionary->head;
364 prevItem = NULL;
365
366 while (item)
367 {
368 if (keyEquals(item->key, key))
369 {
370 if (!prevItem)
371 listDictionary->head = item->next;
372 else
373 prevItem->next = item->next;
374
375 if (take)
376 {
377 value = item->value;
378 item->value = NULL;
379 }
380 item_free(listDictionary, item);
381 break;
382 }
383
384 prevItem = item;
385 item = item->next;
386 }
387
388 if (listDictionary->synchronized)
389 LeaveCriticalSection(&listDictionary->lock);
390
391 return value;
392}
393
394void ListDictionary_Remove(wListDictionary* listDictionary, const void* key)
395{
396 ListDictionary_RemoveOrTake(listDictionary, key, FALSE);
397}
398
399void* ListDictionary_Take(wListDictionary* listDictionary, const void* key)
400{
401 return ListDictionary_RemoveOrTake(listDictionary, key, TRUE);
402}
403
408static void* ListDictionary_Remove_Or_Take_Head(wListDictionary* listDictionary, BOOL take)
409{
410 wListDictionaryItem* item = NULL;
411 void* value = NULL;
412
413 WINPR_ASSERT(listDictionary);
414
415 if (listDictionary->synchronized)
416 EnterCriticalSection(&listDictionary->lock);
417
418 if (listDictionary->head)
419 {
420 item = listDictionary->head;
421 listDictionary->head = listDictionary->head->next;
422 if (take)
423 {
424 value = item->value;
425 item->value = NULL;
426 }
427 item_free(listDictionary, item);
428 }
429
430 if (listDictionary->synchronized)
431 LeaveCriticalSection(&listDictionary->lock);
432
433 return value;
434}
435
436void ListDictionary_Remove_Head(wListDictionary* listDictionary)
437{
438 ListDictionary_Remove_Or_Take_Head(listDictionary, FALSE);
439}
440
441void* ListDictionary_Take_Head(wListDictionary* listDictionary)
442{
443 return ListDictionary_Remove_Or_Take_Head(listDictionary, TRUE);
444}
445
450void* ListDictionary_GetItemValue(wListDictionary* listDictionary, const void* key)
451{
452 void* value = NULL;
453 wListDictionaryItem* item = NULL;
454 OBJECT_EQUALS_FN keyEquals = NULL;
455
456 WINPR_ASSERT(listDictionary);
457
458 if (listDictionary->synchronized)
459 EnterCriticalSection(&listDictionary->lock);
460
461 keyEquals = listDictionary->objectKey.fnObjectEquals;
462
463 if (listDictionary->head)
464 {
465 item = listDictionary->head;
466
467 while (item)
468 {
469 if (keyEquals(item->key, key))
470 break;
471
472 item = item->next;
473 }
474 }
475
476 value = (item) ? item->value : NULL;
477
478 if (listDictionary->synchronized)
479 LeaveCriticalSection(&listDictionary->lock);
480
481 return value;
482}
483
488BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, const void* key,
489 const void* value)
490{
491 BOOL status = FALSE;
492 wListDictionaryItem* item = NULL;
493 OBJECT_EQUALS_FN keyEquals = NULL;
494
495 WINPR_ASSERT(listDictionary);
496
497 if (listDictionary->synchronized)
498 EnterCriticalSection(&listDictionary->lock);
499
500 keyEquals = listDictionary->objectKey.fnObjectEquals;
501
502 if (listDictionary->head)
503 {
504 item = listDictionary->head;
505
506 while (item)
507 {
508 if (keyEquals(item->key, key))
509 break;
510
511 item = item->next;
512 }
513
514 if (item)
515 item_set(listDictionary, item, value);
516
517 status = (item) ? TRUE : FALSE;
518 }
519
520 if (listDictionary->synchronized)
521 LeaveCriticalSection(&listDictionary->lock);
522
523 return status;
524}
525
526static BOOL default_equal_function(const void* obj1, const void* obj2)
527{
528 return (obj1 == obj2);
529}
534wListDictionary* ListDictionary_New(BOOL synchronized)
535{
536 wListDictionary* listDictionary = (wListDictionary*)calloc(1, sizeof(wListDictionary));
537
538 if (!listDictionary)
539 return NULL;
540
541 listDictionary->synchronized = synchronized;
542
543 if (!InitializeCriticalSectionAndSpinCount(&(listDictionary->lock), 4000))
544 {
545 free(listDictionary);
546 return NULL;
547 }
548
549 listDictionary->objectKey.fnObjectEquals = default_equal_function;
550 listDictionary->objectValue.fnObjectEquals = default_equal_function;
551 return listDictionary;
552}
553
554void ListDictionary_Free(wListDictionary* listDictionary)
555{
556 if (listDictionary)
557 {
558 ListDictionary_Clear(listDictionary);
559 DeleteCriticalSection(&listDictionary->lock);
560 free(listDictionary);
561 }
562}
This struct contains function pointer to initialize/free objects.
Definition collections.h:57