FreeRDP
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 
26 typedef struct s_wListDictionaryItem wListDictionaryItem;
27 
28 struct s_wListDictionaryItem
29 {
30  void* key;
31  void* value;
32 
33  wListDictionaryItem* next;
34 };
35 
36 struct s_wListDictionary
37 {
38  BOOL synchronized;
39  CRITICAL_SECTION lock;
40 
41  wListDictionaryItem* head;
42  wObject objectKey;
43  wObject objectValue;
44 };
45 
53 WINPR_API wObject* ListDictionary_KeyObject(wListDictionary* _dictionary)
54 {
55  WINPR_ASSERT(_dictionary);
56  return &_dictionary->objectKey;
57 }
58 
59 WINPR_API wObject* ListDictionary_ValueObject(wListDictionary* _dictionary)
60 {
61  WINPR_ASSERT(_dictionary);
62  return &_dictionary->objectValue;
63 }
64 
73 size_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 
103 void ListDictionary_Lock(wListDictionary* listDictionary)
104 {
105  WINPR_ASSERT(listDictionary);
106 
107  EnterCriticalSection(&listDictionary->lock);
108 }
109 
114 void ListDictionary_Unlock(wListDictionary* listDictionary)
115 {
116  WINPR_ASSERT(listDictionary);
117 
118  LeaveCriticalSection(&listDictionary->lock);
119 }
120 
129 size_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 -1;
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 
187 static 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 
201 static 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 
215 static 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 
235 fail:
236  item_free(listDictionary, item);
237  return NULL;
238 }
239 
244 BOOL 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;
273 out_error:
274 
275  if (listDictionary->synchronized)
276  LeaveCriticalSection(&listDictionary->lock);
277 
278  return ret;
279 }
280 
285 void 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 
318 BOOL 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 
349 static 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 
394 void ListDictionary_Remove(wListDictionary* listDictionary, const void* key)
395 {
396  ListDictionary_RemoveOrTake(listDictionary, key, FALSE);
397 }
398 
399 void* ListDictionary_Take(wListDictionary* listDictionary, const void* key)
400 {
401  return ListDictionary_RemoveOrTake(listDictionary, key, TRUE);
402 }
403 
408 static 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 
436 void ListDictionary_Remove_Head(wListDictionary* listDictionary)
437 {
438  ListDictionary_Remove_Or_Take_Head(listDictionary, FALSE);
439 }
440 
441 void* ListDictionary_Take_Head(wListDictionary* listDictionary)
442 {
443  return ListDictionary_Remove_Or_Take_Head(listDictionary, TRUE);
444 }
445 
450 void* 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 
488 BOOL 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 
526 static BOOL default_equal_function(const void* obj1, const void* obj2)
527 {
528  return (obj1 == obj2);
529 }
534 wListDictionary* 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 
554 void 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