From a02cce09668f29f2921cea9e1b57613d1f8077fa Mon Sep 17 00:00:00 2001 From: Klemen Plestenjak Date: Wed, 15 Nov 2023 16:13:26 +0100 Subject: [PATCH] Add dynamic arrays --- engine/CMakeLists.txt | 6 ++- engine/breeze.h | 1 + engine/breeze/utils/array.c | 97 +++++++++++++++++++++++++++++++++++++ engine/breeze/utils/array.h | 54 +++++++++++++++++++++ engine/tests/CMakeLists.txt | 5 +- engine/tests/array_test.c | 52 ++++++++++++++++++++ 6 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 engine/breeze/utils/array.c create mode 100644 engine/breeze/utils/array.h create mode 100644 engine/tests/array_test.c diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index ed6be43..c784446 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -32,10 +32,12 @@ set(BreezeSources breeze/core/memory.c breeze/core/module_system.c - breeze/utils/heap.c breeze/map/map.c breeze/map/tileset.c + breeze/utils/array.c + breeze/utils/object_pool.c + breeze/utils/heap.c breeze/utils/tokenizer.c ) @@ -48,6 +50,8 @@ set(BreezeHeaders breeze/map/map.h breeze/map/tileset.h + breeze/utils/array.h + breeze/utils/object_pool.h breeze/utils/heap.h breeze/utils/string.h breeze/utils/tokenizer.h diff --git a/engine/breeze.h b/engine/breeze.h index a8d1260..c7685a2 100644 --- a/engine/breeze.h +++ b/engine/breeze.h @@ -6,6 +6,7 @@ #include "breeze/math/vec2i.h" +#include "breeze/utils/array.h" #include "breeze/utils/heap.h" #include "breeze/utils/string.h" #include "breeze/utils/tokenizer.h" diff --git a/engine/breeze/utils/array.c b/engine/breeze/utils/array.c new file mode 100644 index 0000000..7031ed3 --- /dev/null +++ b/engine/breeze/utils/array.c @@ -0,0 +1,97 @@ +#include "array.h" + +#include "../core/memory.h" + +typedef struct BzArrayHead { + i32 capacity; + i32 size; + i32 stride; +} BzArrayHead; + +#define ARRAY_HEAD(array) (((BzArrayHead *) array) -1) + +void *_bzArrayNew(i32 startCapacity, i32 stride) { + BzArrayHead *head = bzAlloc(sizeof(*head) + startCapacity * stride); + BZ_ASSERT(startCapacity > 0); + head[0] = (BzArrayHead) { + .capacity=startCapacity, + .size=0, + .stride=stride + }; + return &head[1]; +} +void _bzArrayFree(void *arr) { + bzFree(ARRAY_HEAD(arr)); +} +void _bzArrayClear(void *arr) { + ARRAY_HEAD(arr)->size = 0; +} + +i32 _bzArraySize(void *arr) { + return ARRAY_HEAD(arr)->size; +} +i32 _bzArrayCapacity(void *arr) { + return ARRAY_HEAD(arr)->capacity; +} + +void *_bzArrayResize(void **arr, i32 newSize) { + BzArrayHead *old = ARRAY_HEAD(*arr); + BZ_ASSERT(newSize >= old->size); + if (newSize == old->capacity) return *arr; + + BzArrayHead *new = bzResize(old, sizeof(*new) + newSize * old->stride); + new[0].capacity = newSize; + return &new[1]; +} +void *_bzArrayEnsureCapacity(void **arr, i32 capacity) { + BzArrayHead *head = ARRAY_HEAD(*arr); + if (capacity > head->capacity) + return _bzArrayResize(arr, head->capacity << 1); + return *arr; +} + +i32 _bzArrayGet(void *arr, i32 idx) { + BzArrayHead *head = ARRAY_HEAD(arr); + BZ_ASSERT(idx >= 0 && idx < head->size); + return idx; +} +void _bzArrayDelN(void *arr, i32 idx, i32 n) { + BzArrayHead *head = ARRAY_HEAD(arr); + BZ_ASSERT(n <= head->size); + BZ_ASSERT(idx >= 0 && idx + n <= head->size); + + bzMemMove((u8 *) arr + idx * head->stride, + (u8 *) arr + (idx + n) * head->stride, + n * head->stride); + + head->size -= n; +} + +i32 _bzArrayPush(void *arr) { + BzArrayHead *head = ARRAY_HEAD(arr); + BZ_ASSERT(head->size < head->capacity); + i32 insertIdx = head->size; + head->size++; + return insertIdx; +} +i32 _bzArrayIns(void *arr, i32 idx) { + BzArrayHead *head = ARRAY_HEAD(arr); + BZ_ASSERT(idx >= 0 && idx <= head->size); + BZ_ASSERT(head->size + 1 <= head->capacity); + + bzMemMove((u8 *) arr + (idx + 1) * head->stride, + (u8 *) arr + idx * head->stride, head->stride); + head->size++; + return idx; +} +i32 _bzArraySet(void *arr, i32 idx) { + BzArrayHead *head = ARRAY_HEAD(arr); + BZ_ASSERT(idx >= 0 && idx < head->size); + return idx; +} +i32 _bzArrayPop(void *arr) { + BzArrayHead *head = ARRAY_HEAD(arr); + BZ_ASSERT(head->size > 0); + head->size--; + return head->size; +} diff --git a/engine/breeze/utils/array.h b/engine/breeze/utils/array.h new file mode 100644 index 0000000..aa98d27 --- /dev/null +++ b/engine/breeze/utils/array.h @@ -0,0 +1,54 @@ +#ifndef BREEZE_ARRAY_H +#define BREEZE_ARRAY_H + +#include "../defines.h" + +void *_bzArrayNew(i32 startCapacity, i32 stride); +void _bzArrayFree(void *arr); +void _bzArrayClear(void *arr); + +i32 _bzArraySize(void *arr); +i32 _bzArrayCapacity(void *arr); + +void *_bzArrayResize(void **arr, i32 newSize); +void *_bzArrayEnsureCapacity(void **arr, i32 capacity); + +i32 _bzArrayGet(void *arr, i32 idx); +void _bzArrayDelN(void *arr, i32 idx, i32 n); + +i32 _bzArrayPush(void *arr); +i32 _bzArrayIns(void *arr, i32 idx); +i32 _bzArraySet(void *arr, i32 idx); +i32 _bzArrayPop(void *arr); + +#define bzArrayNew(T, n) (T*) _bzArrayNew(n, sizeof(T)) +#define bzArrayFree(arr) do { \ + _bzArrayFree(arr); \ + arr = NULL; \ +} while(0) +#define bzArrayClear(arr) _bzArrayClear(arr) + +#define bzArraySize(arr) _bzArraySize(arr) +#define bzArrayCapacity(arr) _bzArrayCapacity(arr) + +#define bzArrayResize(arr, size) _bzArrayResize((void **) &arr, size) +#define bzArrayEnsureCapacity(arr, capacity) _bzArrayEnsureCapacity((void **) &arr, capacity) + +#define bzArrayGet(arr, idx) (arr)[_bzArrayGet(arr, idx)] +#define bzArrayDel(arr, idx) _bzArrayDelN(arr, idx, 1) +#define bzArrayDelN(arr, idx, n) _bzArrayDelN(arr, idx, n) + +#define bzArrayPush(arr, e) \ +do { \ + (arr) = bzArrayEnsureCapacity(arr, bzArraySize(arr) + 1); \ + (arr)[_bzArrayPush(arr)] = (e); \ +} while (0) +#define bzArrayIns(arr, idx, e) \ +do { \ + (arr) = bzArrayEnsureCapacity(arr, bzArraySize(arr) + 1); \ + (arr)[_bzArrayIns(arr, idx)] = (e); \ +} while (0) +#define bzArraySet(arr, idx, e) (arr)[_bzArraySet(arr, idx)] = e +#define bzArrayPop(arr) (arr)[_bzArrayPop(arr)] (arr)[_bzArrayPop(arr)] + +#endif //BREEZE_ARRAY_H diff --git a/engine/tests/CMakeLists.txt b/engine/tests/CMakeLists.txt index 0bb8758..58d6b16 100644 --- a/engine/tests/CMakeLists.txt +++ b/engine/tests/CMakeLists.txt @@ -9,4 +9,7 @@ add_executable(cute_tiled_test cute_tiled_test.c) target_link_libraries(cute_tiled_test LINK_PRIVATE Breeze) add_executable(heap_test heap_test.c) -target_link_libraries(heap_test LINK_PRIVATE Breeze) \ No newline at end of file +target_link_libraries(heap_test LINK_PRIVATE Breeze) + +add_executable(array_test array_test.c) +target_link_libraries(array_test LINK_PRIVATE Breeze) diff --git a/engine/tests/array_test.c b/engine/tests/array_test.c new file mode 100644 index 0000000..8164a34 --- /dev/null +++ b/engine/tests/array_test.c @@ -0,0 +1,52 @@ +#include + +#include + +int main(void) { + bzLoggerInit(); + int *arr = bzArrayNew(int, 5); + + int i, j; + + BZ_ASSERT(bzArraySize(arr) == 0); + for (i = 0; i < 20000; i += 50) { + for (j = 0; j < i; ++j) + bzArrayPush(arr, j); + bzArrayFree(arr); + arr = bzArrayNew(int, 5); + } + + for (i = 0; i < 4; ++i) { + bzArrayPush(arr, 1); + bzArrayPush(arr, 2); + bzArrayPush(arr, 3); + bzArrayPush(arr, 4); + bzArrayDel(arr, i); + bzArrayFree(arr); + arr = bzArrayNew(int, 5); + bzArrayPush(arr, 1); + bzArrayPush(arr, 2); + bzArrayPush(arr, 3); + bzArrayPush(arr, 4); + //darray_delswap(arr, i); + bzArrayFree(arr); + arr = bzArrayNew(int, 5); + } + + for (i = 0; i < 5; ++i) { + bzArrayPush(arr, 1); + bzArrayPush(arr, 2); + bzArrayPush(arr, 3); + bzArrayPush(arr, 4); + bzArrayIns(arr, i, 5); + BZ_ASSERT(arr[i] == 5); + if (i < 4) + BZ_ASSERT(arr[4] == 4); + bzArrayFree(arr); + arr = bzArrayNew(int, 5); + } + bzArrayFree(arr); + + + return 0; +}