// 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 WAPP_PLATFORM_CPP BEGIN_C_LINKAGE #endif // !WAPP_PLATFORM_CPP #define WAPP_ARRAY_MAGIC (u64)0x57415f415252 #define _calc_array_count(TYPE, ...) wapp_misc_utils_va_args_count(TYPE, __VA_ARGS__) #define _calc_array_capacity(TYPE, ...) wapp_misc_utils_u64_round_up_pow2(_calc_array_count(TYPE, __VA_ARGS__) * 2) #define wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, FLAGS) \ ((TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(TYPE), FLAGS)) typedef struct Str8 Str8; // NOTE (Abdelrahman): Typedefs to distinguish arrays from regular pointers typedef void *GenericArray; typedef void **VoidPtrArray; typedef c8 *C8Array; typedef c16 *C16Array; typedef c32 *C32Array; typedef u8 *U8Array; typedef u16 *U16Array; typedef u32 *U32Array; typedef u64 *U64Array; typedef b8 *B8Array; typedef i8 *I8Array; typedef i16 *I16Array; typedef i32 *I32Array; typedef i64 *I64Array; typedef f32 *F32Array; typedef f64 *F64Array; typedef f128 *F128Array; typedef uptr *UptrArray; typedef iptr *IptrArray; typedef Str8 *Str8Array; typedef enum { ARRAY_INIT_NONE = 0, ARRAY_INIT_FILLED = 1 << 1, } ArrayInitFlags; #ifdef WAPP_PLATFORM_CPP #define wapp_array(TYPE, ...) ([&]() { \ u64 capacity = _calc_array_capacity(TYPE, __VA_ARGS__); \ \ TYPE items[_calc_array_capacity(TYPE, __VA_ARGS__)] = {__VA_ARGS__}; \ \ wapp_persist u8 array[ \ sizeof(ArrayHeader) + _calc_array_capacity(TYPE, __VA_ARGS__) * sizeof(TYPE) \ ] = {0}; \ ArrayHeader *header = (ArrayHeader *)array; \ header->magic = WAPP_ARRAY_MAGIC; \ header->count = _calc_array_count(TYPE, __VA_ARGS__); \ header->capacity = _calc_array_capacity(TYPE, __VA_ARGS__); \ header->item_size = sizeof(TYPE); \ \ u8 *buf = (u8 *)(header + 1); \ memcpy(buf, items, capacity * sizeof(TYPE)); \ return (TYPE *)buf; \ }()) #define wapp_array_with_capacity(TYPE, CAPACITY, FLAGS) ([&]() { \ wapp_persist u8 array[ \ sizeof(ArrayHeader) + CAPACITY * sizeof(TYPE) \ ] = {0}; \ ArrayHeader *header = (ArrayHeader *)array; \ header->magic = WAPP_ARRAY_MAGIC; \ header->count = (FLAGS & ARRAY_INIT_FILLED) ? CAPACITY : 0; \ header->capacity = CAPACITY; \ header->item_size = sizeof(TYPE); \ \ return (TYPE *)(header + 1); \ }()) #define wapp_array_pop(TYPE, ARRAY) ([&]() { \ if (ARRAY == NULL || _array_count((GenericArray)ARRAY) == 0) { \ TYPE result{}; \ return result; \ } \ \ return *((TYPE *)_array_pop((GenericArray)ARRAY, sizeof(TYPE))); \ }()) #else #define _stack_array(TYPE, SIZE) struct {ArrayHeader header; \ TYPE items[SIZE]; \ wapp_misc_utils_reserve_padding(sizeof(ArrayHeader) + \ sizeof(TYPE) * SIZE);} #define wapp_array(TYPE, ...) \ ((TYPE *)( \ (_stack_array(TYPE, _calc_array_capacity(TYPE, __VA_ARGS__))){ \ .header = { \ .magic = WAPP_ARRAY_MAGIC, \ .count = _calc_array_count(TYPE, __VA_ARGS__), \ .capacity = _calc_array_capacity(TYPE, __VA_ARGS__), \ .item_size = sizeof(TYPE), \ }, \ .items = {__VA_ARGS__}, \ }.items \ )) #define wapp_array_with_capacity(TYPE, CAPACITY, FLAGS) \ ((TYPE *)( \ (_stack_array(TYPE, CAPACITY)){ \ .header = { \ .magic = WAPP_ARRAY_MAGIC, \ .count = (FLAGS & ARRAY_INIT_FILLED) ? CAPACITY : 0, \ .capacity = CAPACITY, \ .item_size = sizeof(TYPE), \ }, \ .items = {0}, \ }.items \ )) #define wapp_array_pop(TYPE, ARRAY) \ (ARRAY == NULL || _array_count((GenericArray)ARRAY) == 0 ? \ (TYPE){0} : \ *((TYPE *)_array_pop((GenericArray)ARRAY, sizeof(TYPE))) \ ) #endif // !WAPP_PLATFORM_CPP #define wapp_array_count(ARRAY) \ (_array_count((GenericArray)ARRAY)) #define wapp_array_capacity(ARRAY) \ (_array_capacity((GenericArray)ARRAY)) #define wapp_array_item_size(ARRAY) \ (_array_item_size((GenericArray)ARRAY)) #define wapp_array_set_count(ARRAY, COUNT) \ (_array_set_count((GenericArray)ARRAY, COUNT)) #define wapp_array_get(TYPE, ARRAY, INDEX) \ ((TYPE *)_array_get((GenericArray)ARRAY, \ INDEX, \ sizeof(TYPE))) #define wapp_array_set(TYPE, ARRAY, INDEX, VALUE_PTR) \ (_array_set((GenericArray)ARRAY, \ INDEX, \ (u8 *)VALUE_PTR, \ sizeof(TYPE))) #define wapp_array_append_capped(TYPE, ARRAY, VALUE_PTR) \ (_array_append_capped((GenericArray)ARRAY, \ (u8 *)VALUE_PTR, \ sizeof(TYPE))) #define wapp_array_extend_capped(TYPE, DST_ARRAY, SRC_ARRAY) \ (_array_extend_capped((GenericArray)DST_ARRAY, \ (GenericArray)SRC_ARRAY, \ sizeof(TYPE))) #define wapp_array_copy_capped(TYPE, DST_ARRAY, SRC_ARRAY) \ (_array_copy_capped((GenericArray)DST_ARRAY, \ (GenericArray)SRC_ARRAY, \ sizeof(TYPE))) #define wapp_array_append_alloc(TYPE, ALLOCATOR_PTR, ARRAY, VALUE_PTR) \ ((TYPE *)_array_append_alloc(ALLOCATOR_PTR, \ (GenericArray)ARRAY, \ (u8 *)VALUE_PTR, \ sizeof(TYPE))) #define wapp_array_extend_alloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY) \ ((TYPE *)_array_extend_alloc(ALLOCATOR_PTR, \ (GenericArray)DST_ARRAY, \ (GenericArray)SRC_ARRAY, \ sizeof(TYPE))) #define wapp_array_copy_alloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY) \ ((TYPE *)_array_copy_alloc(ALLOCATOR_PTR, \ (GenericArray)DST_ARRAY, \ (GenericArray)SRC_ARRAY, \ sizeof(TYPE))) #define wapp_array_clear(TYPE, ARRAY) \ (_array_clear((GenericArray)ARRAY, \ sizeof(TYPE))) #define wapp_array_alloc_size(TYPE, CAPACITY) _array_alloc_size(CAPACITY, sizeof(TYPE)) typedef struct header ArrayHeader; struct header { u64 magic; u64 count; u64 capacity; u64 item_size; }; u64 _array_count(GenericArray array); u64 _array_capacity(GenericArray array); u64 _array_item_size(GenericArray array); void _array_set_count(GenericArray array, u64 count); void *_array_get(GenericArray array, u64 index, u64 item_size); void _array_set(GenericArray array, u64 index, void *value, u64 item_size); void _array_append_capped(GenericArray array, void *value, u64 item_size); void _array_extend_capped(GenericArray dst, const GenericArray src, u64 item_size); void _array_copy_capped(GenericArray dst, const GenericArray src, u64 item_size); GenericArray _array_append_alloc(const Allocator *allocator, GenericArray array, void *value, u64 item_size); GenericArray _array_extend_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src, u64 item_size); GenericArray _array_copy_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src, u64 item_size); void *_array_pop(GenericArray array, u64 item_size); void _array_clear(GenericArray array, u64 item_size); u64 _array_alloc_size(u64 capacity, u64 item_size); GenericArray _array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size, ArrayInitFlags flags); #ifdef WAPP_PLATFORM_CPP END_C_LINKAGE #endif // !WAPP_PLATFORM_CPP #endif // !ARRAY_H