aboutsummaryrefslogtreecommitdiff
path: root/Vector.c
diff options
context:
space:
mode:
authorSyndamia <kamen@syndamia.com>2026-04-28 14:06:44 +0300
committerSyndamia <kamen@syndamia.com>2026-05-12 07:08:56 +0300
commit0d249b1d47a7f84cfe5f09ad070d1affd26566da (patch)
treef395f67eecb27daea3fc4a9ad8e59bf40f988984 /Vector.c
parent5c36b582ad60a569ed996fe188ed92ef6bd7fc5f (diff)
downloadfoollib-0d249b1d47a7f84cfe5f09ad070d1affd26566da.tar
foollib-0d249b1d47a7f84cfe5f09ad070d1affd26566da.tar.gz
foollib-0d249b1d47a7f84cfe5f09ad070d1affd26566da.zip
feat!: Refactor using MemoryManager
The idea is to provide a universal memory management "API", through which you allocate and deallocate. This allows our implementations (for String and Vector) to be more generic. It does also allow usage of different allocators depending on situation.
Diffstat (limited to 'Vector.c')
-rw-r--r--Vector.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/Vector.c b/Vector.c
new file mode 100644
index 0000000..2236c64
--- /dev/null
+++ b/Vector.c
@@ -0,0 +1,117 @@
+#include "Vector.h"
+#include "Types.h"
+#include <string.h>
+
+struct VectorMeta {
+ MemoryManager *mm;
+ usize element_size;
+ usize count;
+ usize length;
+};
+
+static inline struct VectorMeta*
+V_metadata(void *arr) {
+ return arr - sizeof(struct VectorMeta);
+}
+
+Vector
+V_new(MemoryManager *mm, usize element_size, usize length) {
+ if (NULL == mm)
+ return NULL;
+
+ struct VectorMeta vm = {
+ .mm = mm,
+ .element_size = element_size,
+ .count = 0,
+ .length = length,
+ };
+
+ void* start = NULL;
+ if (R_Ok != mm->alloc(*mm, &start, sizeof(vm) + element_size * length) ||
+ NULL == start)
+ {
+ return NULL;
+ }
+
+ memcpy(start, &vm, sizeof(vm));
+ return start + sizeof(vm);
+}
+
+usize
+V_length(Vector arr) {
+ if (NULL == arr)
+ return 0;
+ return V_metadata(arr)->length;
+}
+
+usize
+V_count(Vector arr) {
+ if (NULL == arr)
+ return 0;
+ return V_metadata(arr)->count;
+}
+
+void*
+V_top(Vector arr) {
+ if (NULL == arr)
+ return NULL;
+
+ struct VectorMeta *vm = V_metadata(arr);
+
+ if (0 == vm->count)
+ return NULL;
+
+ return arr + (vm->count - 1) * vm->element_size;
+}
+
+Result
+V_push(Vector *arr, void *pvalue) {
+ if (NULL == arr || NULL == *arr)
+ return R_Uninitialized;
+
+ struct VectorMeta *vm = V_metadata(*arr);
+
+ if (vm->count >= vm->length) {
+ void *start = vm;
+ RETURN_NOTOK(
+ vm->mm->realloc(*vm->mm, &start, sizeof(*vm) + vm->element_size * (vm->length << 1)));
+
+ vm = start;
+ *arr = start + sizeof(*vm);
+ vm->length <<= 1;
+ }
+
+ memcpy(*arr + vm->count++ * vm->element_size, pvalue, vm->element_size);
+
+ return R_Ok;
+}
+
+Result
+V_pushp(Vector* *arr, void *value) {
+ void *temp = value;
+ return V_push((void**)arr, &temp);
+}
+
+Result
+V_pop(Vector *arr) {
+ if (NULL == arr || NULL == *arr)
+ return R_NullArgument;
+
+ struct VectorMeta *vm = V_metadata(arr);
+
+ if (vm->count == 0)
+ return R_OutOfBounds;
+
+ --vm->count;
+ return R_Ok;
+}
+
+Result
+V_free(Vector *arr) {
+ if (NULL == arr || NULL == *arr)
+ return R_NullArgument;
+
+ struct VectorMeta *vm = V_metadata(*arr);
+ *arr = vm;
+ return vm->mm->free(*vm->mm, arr);
+}