Files
wizapp-stdlib/src/base/array/array.h
T
abdelrahman 9226891bb9
Release / release (push) Successful in 3s
wpArrayClear memsets members to 0
2026-09-13 21:14:11 +01:00

222 lines
14 KiB
C

// 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