diff options
Diffstat (limited to 'Vector.c')
| -rw-r--r-- | Vector.c | 117 |
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); +} |
