20 #include <winpr/config.h>
24 #include <winpr/crt.h>
25 #include <winpr/assert.h>
26 #include <winpr/collections.h>
28 #if defined(_WIN32) && (_MSC_VER < 1800) && !defined(__MINGW32__)
29 #define va_copy(dest, src) (dest = src)
58 size_t ArrayList_Capacity(wArrayList* arrayList)
60 WINPR_ASSERT(arrayList);
61 return arrayList->capacity;
68 size_t ArrayList_Count(wArrayList* arrayList)
70 WINPR_ASSERT(arrayList);
71 return arrayList->size;
78 size_t ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems)
80 WINPR_ASSERT(arrayList);
81 *ppItems = (ULONG_PTR*)arrayList->array;
82 return arrayList->size;
89 BOOL ArrayList_IsFixedSized(wArrayList* arrayList)
91 WINPR_ASSERT(arrayList);
99 BOOL ArrayList_IsReadOnly(wArrayList* arrayList)
101 WINPR_ASSERT(arrayList);
109 BOOL ArrayList_IsSynchronized(wArrayList* arrayList)
111 WINPR_ASSERT(arrayList);
112 return arrayList->synchronized;
119 static void ArrayList_Lock_Conditional(wArrayList* arrayList)
121 WINPR_ASSERT(arrayList);
122 if (arrayList->synchronized)
123 EnterCriticalSection(&arrayList->lock);
126 void ArrayList_Lock(wArrayList* arrayList)
128 WINPR_ASSERT(arrayList);
129 EnterCriticalSection(&arrayList->lock);
136 static void ArrayList_Unlock_Conditional(wArrayList* arrayList)
138 WINPR_ASSERT(arrayList);
139 if (arrayList->synchronized)
140 LeaveCriticalSection(&arrayList->lock);
143 void ArrayList_Unlock(wArrayList* arrayList)
145 WINPR_ASSERT(arrayList);
146 LeaveCriticalSection(&arrayList->lock);
153 void* ArrayList_GetItem(wArrayList* arrayList,
size_t index)
157 WINPR_ASSERT(arrayList);
158 if (index < arrayList->size)
160 obj = arrayList->array[index];
170 BOOL ArrayList_SetItem(wArrayList* arrayList,
size_t index,
const void* obj)
172 WINPR_ASSERT(arrayList);
173 if (index >= arrayList->size)
176 if (arrayList->object.fnObjectNew)
178 arrayList->array[index] = arrayList->object.fnObjectNew(obj);
179 if (obj && !arrayList->array[index])
190 arrayList->array[index] = cnv.pv;
198 static BOOL ArrayList_EnsureCapacity(wArrayList* arrayList,
size_t count)
200 WINPR_ASSERT(arrayList);
201 WINPR_ASSERT(count > 0);
203 if (arrayList->size + count > arrayList->capacity)
205 void** newArray = NULL;
206 size_t newCapacity = arrayList->capacity * arrayList->growthFactor;
207 if (newCapacity < arrayList->size + count)
208 newCapacity = arrayList->size + count;
210 newArray = (
void**)realloc(arrayList->array,
sizeof(
void*) * newCapacity);
215 arrayList->array = newArray;
216 arrayList->capacity = newCapacity;
225 static BOOL ArrayList_Shift(wArrayList* arrayList,
size_t index, SSIZE_T count)
227 WINPR_ASSERT(arrayList);
230 if (!ArrayList_EnsureCapacity(arrayList, count))
233 MoveMemory(&arrayList->array[index + count], &arrayList->array[index],
234 (arrayList->size - index) *
sizeof(
void*));
235 arrayList->size += count;
239 const size_t off = index + (size_t)(-1 * count);
240 if (off < arrayList->size)
242 const size_t chunk = arrayList->size - off;
243 MoveMemory(&arrayList->array[index], &arrayList->array[index - count],
244 chunk *
sizeof(
void*));
247 arrayList->size += count;
257 void ArrayList_Clear(wArrayList* arrayList)
259 WINPR_ASSERT(arrayList);
260 ArrayList_Lock_Conditional(arrayList);
262 for (
size_t index = 0; index < arrayList->size; index++)
264 if (arrayList->object.fnObjectFree)
265 arrayList->object.fnObjectFree(arrayList->array[index]);
267 arrayList->array[index] = NULL;
272 ArrayList_Unlock_Conditional(arrayList);
279 BOOL ArrayList_Contains(wArrayList* arrayList,
const void* obj)
283 WINPR_ASSERT(arrayList);
284 ArrayList_Lock_Conditional(arrayList);
286 for (
size_t index = 0; index < arrayList->size; index++)
288 rc = arrayList->object.fnObjectEquals(arrayList->array[index], obj);
294 ArrayList_Unlock_Conditional(arrayList);
299 #if defined(WITH_WINPR_DEPRECATED)
300 int ArrayList_Add(wArrayList* arrayList,
const void* obj)
302 WINPR_ASSERT(arrayList);
303 if (!ArrayList_Append(arrayList, obj))
305 return (
int)ArrayList_Count(arrayList) - 1;
313 BOOL ArrayList_Append(wArrayList* arrayList,
const void* obj)
318 WINPR_ASSERT(arrayList);
319 ArrayList_Lock_Conditional(arrayList);
321 if (!ArrayList_EnsureCapacity(arrayList, 1))
324 index = arrayList->size++;
325 rc = ArrayList_SetItem(arrayList, index, obj);
328 ArrayList_Unlock_Conditional(arrayList);
337 BOOL ArrayList_Insert(wArrayList* arrayList,
size_t index,
const void* obj)
341 WINPR_ASSERT(arrayList);
342 ArrayList_Lock_Conditional(arrayList);
344 if (index < arrayList->size)
346 if (!ArrayList_Shift(arrayList, index, 1))
352 ArrayList_SetItem(arrayList, index, obj);
356 ArrayList_Unlock_Conditional(arrayList);
365 BOOL ArrayList_Remove(wArrayList* arrayList,
const void* obj)
370 WINPR_ASSERT(arrayList);
371 ArrayList_Lock_Conditional(arrayList);
374 for (; index < arrayList->size; index++)
376 if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
385 if (arrayList->object.fnObjectFree)
386 arrayList->object.fnObjectFree(arrayList->array[index]);
388 ret = ArrayList_Shift(arrayList, index, -1);
391 ArrayList_Unlock_Conditional(arrayList);
400 BOOL ArrayList_RemoveAt(wArrayList* arrayList,
size_t index)
404 WINPR_ASSERT(arrayList);
405 ArrayList_Lock_Conditional(arrayList);
407 if (index < arrayList->size)
409 if (arrayList->object.fnObjectFree)
410 arrayList->object.fnObjectFree(arrayList->array[index]);
412 ret = ArrayList_Shift(arrayList, index, -1);
415 ArrayList_Unlock_Conditional(arrayList);
433 SSIZE_T ArrayList_IndexOf(wArrayList* arrayList,
const void* obj, SSIZE_T startIndex, SSIZE_T count)
437 WINPR_ASSERT(arrayList);
438 ArrayList_Lock_Conditional(arrayList);
440 SSIZE_T sindex = startIndex;
444 SSIZE_T index = sindex;
445 SSIZE_T cindex = count;
448 if (arrayList->size > SSIZE_MAX)
450 cindex = (SSIZE_T)arrayList->size;
453 for (; index < sindex + cindex; index++)
455 if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
466 ArrayList_Unlock_Conditional(arrayList);
484 SSIZE_T ArrayList_LastIndexOf(wArrayList* arrayList,
const void* obj, SSIZE_T startIndex,
491 WINPR_ASSERT(arrayList);
492 ArrayList_Lock_Conditional(arrayList);
501 WINPR_ASSERT(arrayList->size <= SSIZE_MAX);
502 cindex = (SSIZE_T)arrayList->size;
505 SSIZE_T index = sindex + cindex;
506 for (; index > sindex; index--)
508 if (arrayList->object.fnObjectEquals(arrayList->array[index - 1], obj))
518 ArrayList_Unlock_Conditional(arrayList);
523 static BOOL ArrayList_DefaultCompare(
const void* objA,
const void* objB)
525 return objA == objB ? TRUE : FALSE;
528 wObject* ArrayList_Object(wArrayList* arrayList)
530 WINPR_ASSERT(arrayList);
531 return &arrayList->object;
534 BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...)
539 rc = ArrayList_ForEachAP(arrayList, fkt, ap);
545 BOOL ArrayList_ForEachAP(wArrayList* arrayList, ArrayList_ForEachFkt fkt, va_list ap)
550 WINPR_ASSERT(arrayList);
553 ArrayList_Lock_Conditional(arrayList);
554 size_t count = ArrayList_Count(arrayList);
555 for (
size_t index = 0; index < count; index++)
558 void* obj = ArrayList_GetItem(arrayList, index);
560 rs = fkt(obj, index, cap);
567 ArrayList_Unlock_Conditional(arrayList);
575 wArrayList* ArrayList_New(BOOL
synchronized)
578 wArrayList* arrayList = NULL;
579 arrayList = (wArrayList*)calloc(1,
sizeof(wArrayList));
584 arrayList->synchronized =
synchronized;
585 arrayList->growthFactor = 2;
586 obj = ArrayList_Object(arrayList);
589 obj->fnObjectEquals = ArrayList_DefaultCompare;
590 if (!ArrayList_EnsureCapacity(arrayList, 32))
593 InitializeCriticalSectionAndSpinCount(&arrayList->lock, 4000);
596 WINPR_PRAGMA_DIAG_PUSH
597 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
598 ArrayList_Free(arrayList);
599 WINPR_PRAGMA_DIAG_POP
603 void ArrayList_Free(wArrayList* arrayList)
608 ArrayList_Clear(arrayList);
609 DeleteCriticalSection(&arrayList->lock);
610 free(arrayList->array);
This struct contains function pointer to initialize/free objects.