diff --git a/codegen/array/make_array.py b/codegen/array/make_array.py index 6b141a6..eaaed02 100644 --- a/codegen/array/make_array.py +++ b/codegen/array/make_array.py @@ -67,9 +67,8 @@ def make_array(user_datatypes: Dict[CDataType, ArrayData] = {}): common_decl_types: List[CStruct] = [] datatypes: dict[CDataType, ArrayData] = { - CType.VOID: ArrayData( - array_typename="GenericArray", - ), + CType.VOID: ArrayData(array_typename="GenericArray"), + "void *": ArrayData(array_typename="VoidPArray"), "Str8": ArrayData( array_typename="Str8Array", hdr_decl_types=[ diff --git a/codegen/dbl_list/make_dbl_list.py b/codegen/dbl_list/make_dbl_list.py index ba268b1..975cac7 100644 --- a/codegen/dbl_list/make_dbl_list.py +++ b/codegen/dbl_list/make_dbl_list.py @@ -59,10 +59,8 @@ def make_dbl_list(user_datatypes: Dict[CDataType, DblListData] = {}): common_decl_types: List[CStruct] = [] datatypes: dict[CDataType, DblListData] = { - CType.VOID: DblListData( - node_typename="GenericNode", - list_typename="GenericList", - ), + CType.VOID: DblListData(node_typename="GenericNode", list_typename="GenericList"), + "void *": DblListData(node_typename="VoidPNode", list_typename="VoidPList"), "Str8": DblListData( node_typename="Str8Node", list_typename="Str8List", diff --git a/src/primitives/array/array.c b/src/primitives/array/array.c index 2beec0c..b7b2176 100644 --- a/src/primitives/array/array.c +++ b/src/primitives/array/array.c @@ -10,6 +10,155 @@ #include "../../common/platform/platform.h" #include +void * *wapp_void_ptr_array_get(const VoidPArray *array, u64 index) { + wapp_debug_assert(array != NULL, "`array` should not be NULL"); + wapp_runtime_assert(index < array->count, "`index` is out of bounds"); + + u8 *ptr = (u8 *)(array->items) + (array->item_size * index); + return (void * *)ptr; +} + +void wapp_void_ptr_array_set(VoidPArray *array, u64 index, void * *item) { + void * *ptr = wapp_void_ptr_array_get(array, index); + + memcpy((void *)ptr, (void *)item, array->item_size); +} + +void wapp_void_ptr_array_append_capped(VoidPArray *array, void * *item) { + wapp_debug_assert(array != NULL, "`array` should not be NULL"); + wapp_runtime_assert(array->count < array->capacity, "`array` is full"); + + u64 index = (array->count)++; + wapp_void_ptr_array_set(array, index, item); +} + +void wapp_void_ptr_array_extend_capped(VoidPArray *array, const VoidPArray *other) { + wapp_debug_assert(array != NULL && other != NULL, "`array` and `other` should not be NULL"); + + u64 remaining_capacity = array->capacity - array->count; + wapp_runtime_assert(other->count < remaining_capacity, "`array` does not have enough capacity"); + + void * *item; + + // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of + // MSVC Spectre mitigation warnings + u64 items_to_add = other->count; + u64 item_index = 0; + b32 running = true; + while (running) { + item = wapp_void_ptr_array_get(other, item_index); + ++item_index; + running = item_index < items_to_add; + + if (!item) { + continue; + } + + wapp_void_ptr_array_append_capped(array, item); + } +} + +void wapp_void_ptr_array_clear(VoidPArray *array) { + wapp_debug_assert(array != NULL, "`array` should not be NULL"); + array->count = 0; +} + +void wapp_void_ptr_array_copy_capped(const VoidPArray *src, VoidPArray *dst) { + wapp_debug_assert(src != NULL && dst != NULL, "`src` and `dst` should not be NULL"); + + wapp_void_ptr_array_clear(dst); + + void * *item; + + // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of + // MSVC Spectre mitigation warnings + u64 to_copy = src->count < dst->capacity ? src->count : dst->capacity; + u64 item_index = 0; + b32 running = true; + while (running) { + item = wapp_void_ptr_array_get(src, item_index); + ++item_index; + running = item_index < to_copy; + + if (!item) { + continue; + } + + wapp_void_ptr_array_append_capped(dst, item); + } +} + +VoidPArray *wapp_void_ptr_array_append_alloc(const Allocator *allocator, VoidPArray *array, void * *item) { + wapp_debug_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL"); + + VoidPArray *output = array; + + if (array->count >= array->capacity) { + u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2); + output = (VoidPArray *)_array_alloc_capacity(allocator, new_capacity, array->item_size); + if (!output) { + output = array; + goto RETURN_VOID_PTR_ARRAY_APPEND_ALLOC; + } + wapp_void_ptr_array_copy_capped(array, output); + } + + wapp_void_ptr_array_append_capped(output, item); + +RETURN_VOID_PTR_ARRAY_APPEND_ALLOC: + return output; +} + +VoidPArray *wapp_void_ptr_array_extend_alloc(const Allocator *allocator, VoidPArray *array, const VoidPArray *other) { + wapp_debug_assert(allocator != NULL && array != NULL && other != NULL, "`allocator`, `array` and `other` should not be NULL"); + + VoidPArray *output = array; + + u64 remaining_capacity = array->capacity - array->count; + if (other->count >= remaining_capacity) { + u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2); + output = (VoidPArray *)_array_alloc_capacity(allocator, new_capacity, array->item_size); + if (!output) { + output = array; + goto RETURN_VOID_PTR_ARRAY_EXTEND_ALLOC; + } + wapp_void_ptr_array_copy_capped(array, output); + } + + wapp_void_ptr_array_extend_capped(output, other); + +RETURN_VOID_PTR_ARRAY_EXTEND_ALLOC: + return output; +} + +VoidPArray *wapp_void_ptr_array_copy_alloc(const Allocator *allocator, const VoidPArray *src, VoidPArray *dst) { + wapp_debug_assert(allocator != NULL && src != NULL && dst != NULL, "`allocator`, `src` and `dst` should not be NULL"); + + VoidPArray *output = dst; + + if (src->count >= dst->capacity) { + u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2); + output = (VoidPArray *)_array_alloc_capacity(allocator, new_capacity, src->item_size); + if (!output) { + output = dst; + goto RETURN_VOID_PTR_ARRAY_COPY_ALLOC; + } + } + + wapp_void_ptr_array_clear(output); + wapp_void_ptr_array_copy_capped(src, output); + +RETURN_VOID_PTR_ARRAY_COPY_ALLOC: + return output; +} + +void * *_void_ptr_array_pop(VoidPArray *array) { + u64 index = array->count - 1; + void * *out = wapp_void_ptr_array_get(array, index); + --(array->count); + return out; +} + Str8 *wapp_str8_array_get(const Str8Array *array, u64 index) { wapp_debug_assert(array != NULL, "`array` should not be NULL"); wapp_runtime_assert(index < array->count, "`index` is out of bounds"); diff --git a/src/primitives/array/array.h b/src/primitives/array/array.h index 3d5d66e..c0eb503 100644 --- a/src/primitives/array/array.h +++ b/src/primitives/array/array.h @@ -14,6 +14,7 @@ BEGIN_C_LINKAGE #endif // !WAPP_PLATFORM_CPP +#define wapp_void_ptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((VoidPArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(void *))) #define wapp_str8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((Str8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(Str8))) #define wapp_b32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((B32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(b32))) #define wapp_char_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((CharArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(char))) @@ -35,6 +36,23 @@ BEGIN_C_LINKAGE #define wapp_uptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((UptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(uptr))) #ifdef WAPP_PLATFORM_CPP +#define wapp_void_ptr_array(...) ([&]() { \ + persistent void * buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \ + return VoidPArray{ \ + buf, \ + wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \ + wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \ + sizeof(void *) \ + }; \ +}()) +#define wapp_void_ptr_array_with_capacity(CAPACITY) ([&]() { \ + persistent void * buf[CAPACITY] = {}; \ + return VoidPArray{buf, 0, CAPACITY, sizeof(void *)}; \ +}()) +#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \ + *_void_ptr_array_pop(ARRAY_PTR) : \ + void *{} \ +) #define wapp_str8_array(...) ([&]() { \ persistent Str8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \ return Str8Array{ \ @@ -359,6 +377,17 @@ BEGIN_C_LINKAGE uptr{} \ ) #else +#define wapp_void_ptr_array(...) ((VoidPArray){ \ + .items = (void *[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)]){__VA_ARGS__}, \ + .count = wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \ + .capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \ + .item_size = sizeof(void *) \ +}) +#define wapp_void_ptr_array_with_capacity(CAPACITY) ((VoidPArray){.items = (void *[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(void *)}) +#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \ + *_void_ptr_array_pop(ARRAY_PTR) : \ + (void *){0} \ +) #define wapp_str8_array(...) ((Str8Array){ \ .items = (Str8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \ .count = wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \ @@ -580,6 +609,14 @@ struct GenericArray { u64 item_size; }; +typedef struct VoidPArray VoidPArray; +struct VoidPArray { + void * *items; + u64 count; + u64 capacity; + u64 item_size; +}; + typedef struct Str8Array Str8Array; struct Str8Array { Str8 *items; @@ -732,6 +769,16 @@ struct UptrArray { u64 item_size; }; +void * *wapp_void_ptr_array_get(const VoidPArray *array, u64 index); +void wapp_void_ptr_array_set(VoidPArray *array, u64 index, void * *item); +void wapp_void_ptr_array_append_capped(VoidPArray *array, void * *item); +void wapp_void_ptr_array_extend_capped(VoidPArray *array, const VoidPArray *other); +void wapp_void_ptr_array_clear(VoidPArray *array); +void wapp_void_ptr_array_copy_capped(const VoidPArray *src, VoidPArray *dst); +VoidPArray *wapp_void_ptr_array_append_alloc(const Allocator *allocator, VoidPArray *array, void * *item); +VoidPArray *wapp_void_ptr_array_extend_alloc(const Allocator *allocator, VoidPArray *array, const VoidPArray *other); +VoidPArray *wapp_void_ptr_array_copy_alloc(const Allocator *allocator, const VoidPArray *src, VoidPArray *dst); +void * *_void_ptr_array_pop(VoidPArray *array); Str8 *wapp_str8_array_get(const Str8Array *array, u64 index); void wapp_str8_array_set(Str8Array *array, u64 index, Str8 *item); void wapp_str8_array_append_capped(Str8Array *array, Str8 *item); diff --git a/src/primitives/dbl_list/dbl_list.c b/src/primitives/dbl_list/dbl_list.c index db40e17..3cb9d5c 100644 --- a/src/primitives/dbl_list/dbl_list.c +++ b/src/primitives/dbl_list/dbl_list.c @@ -8,6 +8,7 @@ #include "../../common/platform/platform.h" #include +internal VoidPList void_ptr_node_to_list(VoidPNode *node); internal Str8List str8_node_to_list(Str8Node *node); internal B32List b32_node_to_list(B32Node *node); internal CharList char_node_to_list(CharNode *node); @@ -28,6 +29,179 @@ internal F128List f128_node_to_list(F128Node *node); internal IptrList iptr_node_to_list(IptrNode *node); internal UptrList uptr_node_to_list(UptrNode *node); +VoidPNode *wapp_void_ptr_list_get(const VoidPList *list, u64 index) { + wapp_runtime_assert(index < list->node_count, "`index` is out of bounds"); + + VoidPNode *output = NULL; + VoidPNode *current = list->first; + for (u64 i = 1; i <= index; ++i) { + current = current->next; + } + + output = current; + + return output; +} + +void wapp_void_ptr_list_push_front(VoidPList *list, VoidPNode *node) { + wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL"); + + VoidPList node_list = void_ptr_node_to_list(node); + + if (list->node_count == 0) { + *list = node_list; + return; + } + + list->node_count += node_list.node_count; + + VoidPNode *first = list->first; + if (first) { + first->prev = node_list.last; + } + + list->first = node_list.first; + node_list.last->next = first; +} + +void wapp_void_ptr_list_push_back(VoidPList *list, VoidPNode *node) { + wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL"); + + VoidPList node_list = void_ptr_node_to_list(node); + + if (list->node_count == 0) { + *list = node_list; + return; + } + + list->node_count += node_list.node_count; + + VoidPNode *last = list->last; + if (last) { + last->next = node_list.first; + } + + list->last = node_list.last; + node_list.first->prev = last; +} + +void wapp_void_ptr_list_insert(VoidPList *list, VoidPNode *node, u64 index) { + wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL"); + + if (index == 0) { + wapp_void_ptr_list_push_front(list, node); + return; + } else if (index == list->node_count) { + wapp_void_ptr_list_push_back(list, node); + return; + } + + VoidPNode *dst_node = wapp_void_ptr_list_get(list, index); + if (!dst_node) { + return; + } + + VoidPList node_list = void_ptr_node_to_list(node); + + list->node_count += node_list.node_count; + + VoidPNode *prev = dst_node->prev; + + dst_node->prev = node_list.last; + prev->next = node_list.first; + + node_list.first->prev = prev; + node_list.last->next = dst_node; +} + +VoidPNode *wapp_void_ptr_list_pop_front(VoidPList *list) { + wapp_debug_assert(list != NULL, "`list` should not be NULL"); + + VoidPNode *output = NULL; + + if (list->node_count == 0) { + goto RETURN_VOID_PTR_LIST_POP_FRONT; + } + + output = list->first; + + if (list->node_count == 1) { + *list = (VoidPList){0}; + goto RETURN_VOID_PTR_LIST_POP_FRONT; + } + + --(list->node_count); + list->first = output->next; + + output->prev = output->next = NULL; + +RETURN_VOID_PTR_LIST_POP_FRONT: + return output; +} + +VoidPNode *wapp_void_ptr_list_pop_back(VoidPList *list) { + wapp_debug_assert(list != NULL, "`list` should not be NULL"); + + VoidPNode *output = NULL; + + if (list->node_count == 0) { + goto RETURN_VOID_PTR_LIST_POP_BACK; + } + + output = list->last; + + if (list->node_count == 1) { + *list = (VoidPList){0}; + goto RETURN_VOID_PTR_LIST_POP_BACK; + } + + --(list->node_count); + list->last = output->prev; + + output->prev = output->next = NULL; + +RETURN_VOID_PTR_LIST_POP_BACK: + return output; +} + +VoidPNode *wapp_void_ptr_list_remove(VoidPList *list, u64 index) { + wapp_debug_assert(list != NULL, "`list` should not be NULL"); + + VoidPNode *output = NULL; + + if (index == 0) { + output = wapp_void_ptr_list_pop_front(list); + goto RETURN_VOID_PTR_LIST_REMOVE; + } else if (index == list->node_count) { + output = wapp_void_ptr_list_pop_back(list); + goto RETURN_VOID_PTR_LIST_REMOVE; + } + + output = wapp_void_ptr_list_get(list, index); + if (!output) { + goto RETURN_VOID_PTR_LIST_REMOVE; + } + + output->prev->next = output->next; + output->next->prev = output->prev; + + --(list->node_count); + + output->prev = output->next = NULL; + +RETURN_VOID_PTR_LIST_REMOVE: + return output; +} + +void wapp_void_ptr_list_empty(VoidPList *list) { + wapp_debug_assert(list != NULL, "`list` should not be NULL"); + + u64 count = list->node_count; + for (u64 i = 0; i < count; ++i) { + wapp_void_ptr_list_pop_back(list); + } +} + Str8Node *wapp_str8_list_get(const Str8List *list, u64 index) { wapp_runtime_assert(index < list->node_count, "`index` is out of bounds"); @@ -3315,6 +3489,22 @@ void wapp_uptr_list_empty(UptrList *list) { } } +internal VoidPList void_ptr_node_to_list(VoidPNode *node) { + VoidPList output = {.first = node, .last = node, .node_count = 1}; + + while (output.first->prev != NULL) { + output.first = output.first->prev; + ++(output.node_count); + } + + while (output.last->next != NULL) { + output.last = output.last->next; + ++(output.node_count); + } + + return output; +} + internal Str8List str8_node_to_list(Str8Node *node) { Str8List output = {.first = node, .last = node, .node_count = 1}; diff --git a/src/primitives/dbl_list/dbl_list.h b/src/primitives/dbl_list/dbl_list.h index 48ca496..c91543e 100644 --- a/src/primitives/dbl_list/dbl_list.h +++ b/src/primitives/dbl_list/dbl_list.h @@ -13,6 +13,7 @@ BEGIN_C_LINKAGE #endif // !WAPP_PLATFORM_CPP #ifdef WAPP_PLATFORM_CPP +#define wapp_void_ptr_list_node(ITEM_PTR) VoidPNode{ITEM_PTR, nullptr, nullptr} #define wapp_str8_list_node(ITEM_PTR) Str8Node{ITEM_PTR, nullptr, nullptr} #define wapp_b32_list_node(ITEM_PTR) B32Node{ITEM_PTR, nullptr, nullptr} #define wapp_char_list_node(ITEM_PTR) CharNode{ITEM_PTR, nullptr, nullptr} @@ -33,6 +34,7 @@ BEGIN_C_LINKAGE #define wapp_iptr_list_node(ITEM_PTR) IptrNode{ITEM_PTR, nullptr, nullptr} #define wapp_uptr_list_node(ITEM_PTR) UptrNode{ITEM_PTR, nullptr, nullptr} #else +#define wapp_void_ptr_list_node(ITEM_PTR) ((VoidPNode){.item = ITEM_PTR}) #define wapp_str8_list_node(ITEM_PTR) ((Str8Node){.item = ITEM_PTR}) #define wapp_b32_list_node(ITEM_PTR) ((B32Node){.item = ITEM_PTR}) #define wapp_char_list_node(ITEM_PTR) ((CharNode){.item = ITEM_PTR}) @@ -70,6 +72,20 @@ struct GenericList { u64 node_count; }; +typedef struct VoidPNode VoidPNode; +struct VoidPNode { + void * *item; + VoidPNode *prev; + VoidPNode *next; +}; + +typedef struct VoidPList VoidPList; +struct VoidPList { + VoidPNode *first; + VoidPNode *last; + u64 node_count; +}; + typedef struct Str8Node Str8Node; struct Str8Node { Str8 *item; @@ -336,6 +352,14 @@ struct UptrList { u64 node_count; }; +VoidPNode *wapp_void_ptr_list_get(const VoidPList *list, u64 index); +void wapp_void_ptr_list_push_front(VoidPList *list, VoidPNode *node); +void wapp_void_ptr_list_push_back(VoidPList *list, VoidPNode *node); +void wapp_void_ptr_list_insert(VoidPList *list, VoidPNode *node, u64 index); +VoidPNode *wapp_void_ptr_list_pop_front(VoidPList *list); +VoidPNode *wapp_void_ptr_list_pop_back(VoidPList *list); +VoidPNode *wapp_void_ptr_list_remove(VoidPList *list, u64 index); +void wapp_void_ptr_list_empty(VoidPList *list); Str8Node *wapp_str8_list_get(const Str8List *list, u64 index); void wapp_str8_list_push_front(Str8List *list, Str8Node *node); void wapp_str8_list_push_back(Str8List *list, Str8Node *node);