// vim:fileencoding=utf-8:foldmethod=marker #ifndef ARRAY_H #define ARRAY_H #include "../mem/allocator/mem_allocator.h" #include "../../common/misc/misc_utils.h" #include "../../common/aliases/aliases.h" #include "../../common/platform/platform.h" #ifdef WP_PLATFORM_CPP BEGIN_C_LINKAGE #endif // !WP_PLATFORM_CPP #define WP_ARRAY_MAGIC wpU64Const(0x57415f415252) #define calcArrayCount(TYPE, ...) wpMiscUtilsVaArgsCount(TYPE, __VA_ARGS__) #define calcArrayCapacity(TYPE, ...) wpMiscUtilsU64RoundUpPow2(calcArrayCount(TYPE, __VA_ARGS__) * 2) typedef struct WpStr8 WpStr8; // NOTE (Abdelrahman): Typedefs to distinguish arrays from regular pointers typedef void *WpArray; typedef void **WpVoidPtrArray; typedef c8 *WpC8Array; typedef c16 *WpC16Array; typedef c32 *WpC32Array; typedef u8 *WpU8Array; typedef u16 *WpU16Array; typedef u32 *WpU32Array; typedef u64 *WpU64Array; typedef b8 *WpB8Array; typedef i8 *WpI8Array; typedef i16 *WpI16Array; typedef i32 *WpI32Array; typedef i64 *WpI64Array; typedef f32 *WpF32Array; typedef f64 *WpF64Array; typedef f128 *WpF128Array; typedef uptr *WpUptrArray; typedef iptr *WpIptrArray; typedef WpStr8 *WpStr8Array; typedef enum WpArrayInitFlags { WP_ARRAY_INIT_NONE = 0, WP_ARRAY_INIT_FILLED = 1 << 1, } WpArrayInitFlags; #ifdef WP_PLATFORM_CPP #define wpArray(TYPE, ...) ([&]() { \ u64 capacity = calcArrayCapacity(TYPE, __VA_ARGS__); \ \ TYPE items[calcArrayCapacity(TYPE, __VA_ARGS__)] = {__VA_ARGS__}; \ \ wp_persist u8 array[ \ sizeof(WpArrayHeader) + calcArrayCapacity(TYPE, __VA_ARGS__) * sizeof(TYPE) \ ] = {0}; \ WpArrayHeader *header = (WpArrayHeader *)array; \ header->magic = WP_ARRAY_MAGIC; \ header->count = calcArrayCount(TYPE, __VA_ARGS__); \ header->capacity = calcArrayCapacity(TYPE, __VA_ARGS__); \ header->item_size = sizeof(TYPE); \ \ u8 *buf = (u8 *)(header + 1); \ memcpy(buf, items, capacity * sizeof(TYPE)); \ return (TYPE *)buf; \ }()) #define wpArrayWithCapacity(TYPE, CAPACITY, FLAGS) ([&]() { \ wp_persist u8 array[ \ sizeof(WpArrayHeader) + CAPACITY * sizeof(TYPE) \ ] = {0}; \ WpArrayHeader *header = (WpArrayHeader *)array; \ header->magic = WP_ARRAY_MAGIC; \ header->count = (FLAGS & WP_ARRAY_INIT_FILLED) ? CAPACITY : 0; \ header->capacity = CAPACITY; \ header->item_size = sizeof(TYPE); \ \ return (TYPE *)(header + 1); \ }()) #define wpArrayPop(TYPE, ARRAY) ([&]() { \ if (ARRAY == NULL || arrayCount((WpArray)ARRAY) == 0) { \ TYPE result{}; \ return result; \ } \ \ return *((TYPE *)arrayPop((WpArray)ARRAY, sizeof(TYPE))); \ }()) #else #define stackArray(TYPE, SIZE) struct {WpArrayHeader header; \ TYPE items[SIZE]; \ wpMiscUtilsReservePadding(sizeof(WpArrayHeader) + \ sizeof(TYPE) * SIZE);} #define wpArray(TYPE, ...) \ ((TYPE *)( \ (stackArray(TYPE, calcArrayCapacity(TYPE, __VA_ARGS__))){ \ .header = { \ .magic = WP_ARRAY_MAGIC, \ .count = calcArrayCount(TYPE, __VA_ARGS__), \ .capacity = calcArrayCapacity(TYPE, __VA_ARGS__), \ .item_size = sizeof(TYPE), \ }, \ .items = {__VA_ARGS__}, \ }.items \ )) #define wpArrayWithCapacity(TYPE, CAPACITY, FLAGS) \ ((TYPE *)( \ (stackArray(TYPE, CAPACITY)){ \ .header = { \ .magic = WP_ARRAY_MAGIC, \ .count = (FLAGS & WP_ARRAY_INIT_FILLED) ? CAPACITY : 0, \ .capacity = CAPACITY, \ .item_size = sizeof(TYPE), \ }, \ .items = {0}, \ }.items \ )) #define wpArrayPop(TYPE, ARRAY) \ (ARRAY == NULL || arrayCount((WpArray)ARRAY) == 0 ? \ (TYPE){0} : \ *((TYPE *)arrayPop((WpArray)ARRAY, sizeof(TYPE))) \ ) #endif // !WP_PLATFORM_CPP #define wpArrayCount(ARRAY) \ (arrayCount((WpArray)ARRAY)) #define wpArrayCapacity(ARRAY) \ (arrayCapacity((WpArray)ARRAY)) #define wpArrayItemSize(ARRAY) \ (arrayItemSize((WpArray)ARRAY)) #define wpArraySetCount(ARRAY, COUNT) \ (arraySetCount((WpArray)ARRAY, COUNT)) #define wpArrayGet(TYPE, ARRAY, INDEX) \ ((TYPE *)arrayGet((WpArray)ARRAY, \ INDEX, \ sizeof(TYPE))) #define wpArraySet(TYPE, ARRAY, INDEX, VALUE_PTR) \ (arraySet((WpArray)ARRAY, \ INDEX, \ (u8 *)VALUE_PTR, \ sizeof(TYPE))) #define wpArrayAppendCapped(TYPE, ARRAY, VALUE_PTR) \ (arrayAppendCapped((WpArray)ARRAY, \ (u8 *)VALUE_PTR, \ sizeof(TYPE))) #define wpArrayExtendCapped(TYPE, DST_ARRAY, SRC_ARRAY) \ (arrayExtendCappend((WpArray)DST_ARRAY, \ (WpArray)SRC_ARRAY, \ sizeof(TYPE))) #define wpArrayCopyCapped(TYPE, DST_ARRAY, SRC_ARRAY) \ (arrayCopyCapped((WpArray)DST_ARRAY, \ (WpArray)SRC_ARRAY, \ sizeof(TYPE))) #define wpArrayAppendAlloc(TYPE, ALLOCATOR_PTR, ARRAY, VALUE_PTR, FLAGS) \ ((TYPE *)arrayAppendAlloc(ALLOCATOR_PTR, \ (WpArray)ARRAY, \ (u8 *)VALUE_PTR, \ FLAGS, \ sizeof(TYPE))) #define wpArrayExtendAlloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY, FLAGS) \ ((TYPE *)arrayExtendAlloc(ALLOCATOR_PTR, \ (WpArray)DST_ARRAY, \ (WpArray)SRC_ARRAY, \ FLAGS, \ sizeof(TYPE))) #define wpArrayCopyAlloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY, FLAGS) \ ((TYPE *)arrayCopyAlloc(ALLOCATOR_PTR, \ (WpArray)DST_ARRAY, \ (WpArray)SRC_ARRAY, \ FLAGS, \ sizeof(TYPE))) #define wpArrayClear(TYPE, ARRAY) \ (arrayClear((WpArray)ARRAY, \ sizeof(TYPE))) #define wpArrayCalcAllocSize(TYPE, CAPACITY) arrayCalcAllocSize(CAPACITY, sizeof(TYPE)) #define wpArrayAllocCapacity(TYPE, ALLOCATOR_PTR, CAPACITY, FLAGS) \ ((TYPE *)arrayAllocCapacity(ALLOCATOR_PTR, CAPACITY, FLAGS, sizeof(TYPE))) #define wpArrayFromPreallcatedBuffer(TYPE, BUFFER, BUFFER_SIZE) \ ((TYPE *)array_from_preallcated_buffer(BUFFER, BUFFER_SIZE, sizeof(TYPE))) // Only needed for allocators like malloc where each allocation has to be freed on its own. // No need to use it for allocators like Arena. #define wpArrayDealloc(TYPE, ALLOCATOR_PTR, ARRAY_DPTR) \ (arrayDealloc(ALLOCATOR_PTR, (WpArray *)ARRAY_DPTR, sizeof(TYPE))) typedef struct WpArrayHeader WpArrayHeader; struct WpArrayHeader { u64 magic; u64 count; u64 capacity; u64 item_size; }; u64 arrayCount(WpArray array); u64 arrayCapacity(WpArray array); u64 arrayItemSize(WpArray array); void arraySetCount(WpArray array, u64 count); void *arrayGet(WpArray array, u64 index, u64 item_size); void arraySet(WpArray array, u64 index, void *value, u64 item_size); void arrayAppendCapped(WpArray array, void *value, u64 item_size); void arrayExtendCappend(WpArray dst, const WpArray src, u64 item_size); void arrayCopyCapped(WpArray dst, const WpArray src, u64 item_size); WpArray arrayAppendAlloc(const WpAllocator *allocator, WpArray array, void *value, WpArrayInitFlags flags, u64 item_size); WpArray arrayExtendAlloc(const WpAllocator *allocator, WpArray dst, const WpArray src, WpArrayInitFlags flags, u64 item_size); WpArray arrayCopyAlloc(const WpAllocator *allocator, WpArray dst, const WpArray src, WpArrayInitFlags flags, u64 item_size); void *arrayPop(WpArray array, u64 item_size); void arrayClear(WpArray array, u64 item_size); u64 arrayCalcAllocSize(u64 capacity, u64 item_size); WpArray arrayAllocCapacity(const WpAllocator *allocator, u64 capacity, WpArrayInitFlags flags, u64 item_size); WpArray arrayFromPreallocatedBuffer(void *buffer, u64 buffer_size, WpArrayInitFlags flags, u64 item_size); void arrayDealloc(const WpAllocator *allocator, WpArray *array, u64 item_size); #ifdef WP_PLATFORM_CPP END_C_LINKAGE #endif // !WP_PLATFORM_CPP #endif // !ARRAY_H