222 lines
14 KiB
C
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 (u64)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 {
|
|
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
|