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((
void*)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, (
size_t)count))
233 MoveMemory((
void*)&arrayList->array[index + (
size_t)count], (
void*)&arrayList->array[index],
234 (arrayList->size - index) *
sizeof(
void*));
235 arrayList->size += (size_t)count;
239 const size_t scount = WINPR_ASSERTING_INT_CAST(
size_t, -count);
240 const size_t off = index + scount;
241 if (off < arrayList->size)
243 const size_t chunk = arrayList->size - off;
244 MoveMemory((
void*)&arrayList->array[index], (
void*)&arrayList->array[off],
245 chunk *
sizeof(
void*));
248 arrayList->size -= scount;
258 void ArrayList_Clear(wArrayList* arrayList)
260 WINPR_ASSERT(arrayList);
261 ArrayList_Lock_Conditional(arrayList);
263 for (
size_t index = 0; index < arrayList->size; index++)
265 if (arrayList->object.fnObjectFree)
266 arrayList->object.fnObjectFree(arrayList->array[index]);
268 arrayList->array[index] = NULL;
273 ArrayList_Unlock_Conditional(arrayList);
280 BOOL ArrayList_Contains(wArrayList* arrayList,
const void* obj)
284 WINPR_ASSERT(arrayList);
285 ArrayList_Lock_Conditional(arrayList);
287 for (
size_t index = 0; index < arrayList->size; index++)
289 rc = arrayList->object.fnObjectEquals(arrayList->array[index], obj);
295 ArrayList_Unlock_Conditional(arrayList);
300 #if defined(WITH_WINPR_DEPRECATED)
301 int ArrayList_Add(wArrayList* arrayList,
const void* obj)
303 WINPR_ASSERT(arrayList);
304 if (!ArrayList_Append(arrayList, obj))
306 return (
int)ArrayList_Count(arrayList) - 1;
314 BOOL ArrayList_Append(wArrayList* arrayList,
const void* obj)
319 WINPR_ASSERT(arrayList);
320 ArrayList_Lock_Conditional(arrayList);
322 if (!ArrayList_EnsureCapacity(arrayList, 1))
325 index = arrayList->size++;
326 rc = ArrayList_SetItem(arrayList, index, obj);
329 ArrayList_Unlock_Conditional(arrayList);
338 BOOL ArrayList_Insert(wArrayList* arrayList,
size_t index,
const void* obj)
342 WINPR_ASSERT(arrayList);
343 ArrayList_Lock_Conditional(arrayList);
345 if (index < arrayList->size)
347 if (!ArrayList_Shift(arrayList, index, 1))
353 ArrayList_SetItem(arrayList, index, obj);
357 ArrayList_Unlock_Conditional(arrayList);
366 BOOL ArrayList_Remove(wArrayList* arrayList,
const void* obj)
371 WINPR_ASSERT(arrayList);
372 ArrayList_Lock_Conditional(arrayList);
375 for (; index < arrayList->size; index++)
377 if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
386 if (arrayList->object.fnObjectFree)
387 arrayList->object.fnObjectFree(arrayList->array[index]);
389 ret = ArrayList_Shift(arrayList, index, -1);
392 ArrayList_Unlock_Conditional(arrayList);
401 BOOL ArrayList_RemoveAt(wArrayList* arrayList,
size_t index)
405 WINPR_ASSERT(arrayList);
406 ArrayList_Lock_Conditional(arrayList);
408 if (index < arrayList->size)
410 if (arrayList->object.fnObjectFree)
411 arrayList->object.fnObjectFree(arrayList->array[index]);
413 ret = ArrayList_Shift(arrayList, index, -1);
416 ArrayList_Unlock_Conditional(arrayList);
434 SSIZE_T ArrayList_IndexOf(wArrayList* arrayList,
const void* obj, SSIZE_T startIndex, SSIZE_T count)
438 WINPR_ASSERT(arrayList);
439 ArrayList_Lock_Conditional(arrayList);
441 SSIZE_T sindex = startIndex;
445 SSIZE_T index = sindex;
446 SSIZE_T cindex = count;
449 if (arrayList->size > SSIZE_MAX)
451 cindex = (SSIZE_T)arrayList->size;
454 for (; index < sindex + cindex; index++)
456 if (arrayList->object.fnObjectEquals(arrayList->array[index], obj))
467 ArrayList_Unlock_Conditional(arrayList);
485 SSIZE_T ArrayList_LastIndexOf(wArrayList* arrayList,
const void* obj, SSIZE_T startIndex,
492 WINPR_ASSERT(arrayList);
493 ArrayList_Lock_Conditional(arrayList);
502 WINPR_ASSERT(arrayList->size <= SSIZE_MAX);
503 cindex = (SSIZE_T)arrayList->size;
506 SSIZE_T index = sindex + cindex;
507 for (; index > sindex; index--)
509 if (arrayList->object.fnObjectEquals(arrayList->array[index - 1], obj))
519 ArrayList_Unlock_Conditional(arrayList);
524 static BOOL ArrayList_DefaultCompare(
const void* objA,
const void* objB)
526 return objA == objB ? TRUE : FALSE;
529 wObject* ArrayList_Object(wArrayList* arrayList)
531 WINPR_ASSERT(arrayList);
532 return &arrayList->object;
535 BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...)
540 rc = ArrayList_ForEachAP(arrayList, fkt, ap);
546 BOOL ArrayList_ForEachAP(wArrayList* arrayList, ArrayList_ForEachFkt fkt, va_list ap)
551 WINPR_ASSERT(arrayList);
554 ArrayList_Lock_Conditional(arrayList);
555 size_t count = ArrayList_Count(arrayList);
556 for (
size_t index = 0; index < count; index++)
559 void* obj = ArrayList_GetItem(arrayList, index);
561 rs = fkt(obj, index, cap);
568 ArrayList_Unlock_Conditional(arrayList);
576 wArrayList* ArrayList_New(BOOL
synchronized)
579 wArrayList* arrayList = NULL;
580 arrayList = (wArrayList*)calloc(1,
sizeof(wArrayList));
585 arrayList->synchronized =
synchronized;
586 arrayList->growthFactor = 2;
587 obj = ArrayList_Object(arrayList);
590 obj->fnObjectEquals = ArrayList_DefaultCompare;
591 if (!ArrayList_EnsureCapacity(arrayList, 32))
594 InitializeCriticalSectionAndSpinCount(&arrayList->lock, 4000);
597 WINPR_PRAGMA_DIAG_PUSH
598 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
599 ArrayList_Free(arrayList);
600 WINPR_PRAGMA_DIAG_POP
604 void ArrayList_Free(wArrayList* arrayList)
609 ArrayList_Clear(arrayList);
610 DeleteCriticalSection(&arrayList->lock);
611 free((
void*)arrayList->array);
This struct contains function pointer to initialize/free objects.