From 5251aa9e82bdd9cfc1aff31aa07310b194289d3c Mon Sep 17 00:00:00 2001 From: Evan Burkey Date: Wed, 25 Oct 2023 07:56:41 -0700 Subject: [PATCH] implement vector --- CMakeLists.txt | 1 + include/utility.h | 8 ---- include/vector.h | 31 +++++++++++++++ src/vector.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ tests/tests.c | 60 ++++++++++++++++++++++++++++ 5 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 include/vector.h create mode 100644 src/vector.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5afca48..ac5b3f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ set(SOURCES src/binarytree.c src/input.c src/math.c + src/vector.c ) add_library(flint ${SOURCES}) diff --git a/include/utility.h b/include/utility.h index db08d6e..41d9b3e 100644 --- a/include/utility.h +++ b/include/utility.h @@ -1,14 +1,6 @@ #ifndef LIBFLINT_H_UTILITY #define LIBFLINT_H_UTILITY -/** - * \struct Point - * \brief Representation of a point on a two dimensional grid - * \var int x - * x point on the 2d grid - * \var int y - * y point on the 2d grid - */ typedef struct Point { int x; int y; diff --git a/include/vector.h b/include/vector.h new file mode 100644 index 0000000..0f055a3 --- /dev/null +++ b/include/vector.h @@ -0,0 +1,31 @@ +#ifndef LIBFLINT_H_VECTOR +#define LIBFLINT_H_VECTOR + +#include + +typedef struct Vector { + size_t capacity; + size_t length; + void **elements; + void (*destroy)(void *data); +} Vector; + +int vec_init(Vector *vec, void (*destroy)(void *data)); + +int vec_init_with_capacity(Vector *vec, void (*destroy)(void *data), size_t cap); + +void vec_destroy(Vector *vec); + +int vec_insert(Vector *vec, void *data, size_t index); + +int vec_push(Vector *vec, void *data); + +void *vec_safe_at(Vector *vec, size_t index); + +void *vec_remove(Vector *vec, size_t index); + +#define vec_at(v, i) (v)->elements[(i)] + +#define vec_len(v) (v)->length + +#endif // LIBFLINT_H_VECTOR diff --git a/src/vector.c b/src/vector.c new file mode 100644 index 0000000..2144f29 --- /dev/null +++ b/src/vector.c @@ -0,0 +1,99 @@ +#include +#include + +#include "vector.h" + +#define VEC_INIT_CAP 2 + +int vec_init(Vector *vec, void (*destroy)(void *data)) { + return vec_init_with_capacity(vec, destroy, VEC_INIT_CAP); +} + +int vec_init_with_capacity(Vector *vec, void (*destroy)(void *data), size_t capacity) { + if (vec == NULL) { + return -1; + } + vec->destroy = destroy; + vec_len(vec) = 0; + vec->capacity = capacity; + vec->elements = malloc(sizeof (void*) * capacity); + if (vec->elements == NULL) { + return -1; + } + memset(vec->elements, 0, vec->capacity * sizeof(void *)); + + return 0; +} + +static int vec_grow(Vector *const vec) { + vec->capacity *= 2; + vec->elements = reallocf(vec->elements, sizeof(void *) * vec->capacity); + if (vec->elements == NULL) { + return -1; + } + return 0; +} + +void vec_destroy(Vector *vec) { + if (vec->destroy) { + for (size_t i = 0; i < vec_len(vec); ++i) { + vec->destroy(vec->elements[i]); + } + } + free(vec); + vec = NULL; +} + +int vec_insert(Vector *vec, void *data, size_t index) { + if (vec_len(vec) + 1 >= vec->capacity) { + if (vec_grow(vec) != 0) { + return -1; + } + } + + if (index > vec_len(vec)) { + return -1; + } + + if (index < vec_len(vec)) { + void *a = vec->elements[index]; + vec->elements[index] = data; + + void *b = NULL; + for (size_t i = index + 1; i <= vec_len(vec); ++i) { + b = vec->elements[i]; + vec->elements[i] = a; + a = b; + } + } else /* index == vec_len(vec) */ { + vec->elements[index] = data; + } + + vec_len(vec) += 1; + return 0; +} + +int vec_push(Vector *vec, void *data) { + return vec_insert(vec, data, vec_len(vec)); +} + +void *vec_safe_at(Vector *vec, size_t index) { + if (index >= vec_len(vec)) { + return NULL; + } + return vec->elements[index]; +} + +void *vec_remove(Vector *vec, size_t index) { + if (index >= vec_len(vec)) { + return NULL; + } + + void *r = vec_at(vec, index); + for (size_t i = index + 1; i < vec_len(vec); ++i) { + vec->elements[i - 1] = vec->elements[i]; + } + vec->elements[vec_len(vec) - 1] = NULL; + vec->length -= 1; + return r; +} diff --git a/tests/tests.c b/tests/tests.c index 77b5a7a..0a01e41 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -1,10 +1,12 @@ #include #include +#include #include "linkedlist.h" #include "set.h" #include "stack.h" #include "binarytree.h" +#include "vector.h" #include "math.h" void print_ll(List *list) { @@ -158,6 +160,7 @@ void test_bintree() { void test_math() { printf("\n--- MATH TEST ---\n"); int i = 1, j = 2; + assert(max_int(i, j) == j); printf("Between %d and %d, %d is larger\n", i, j, max_int(i, j)); printf("Between %d and %d, %d is smaller\n", i, j, min_int(i, j)); @@ -179,11 +182,68 @@ void test_math() { free(line); } +void print_vector(Vector *vec) { + for (size_t i = 0; i < vec->length; ++i) { + int t = *(int*)vec_at(vec, i); + printf("%d ", t); + } + printf("\n"); +} + +void test_vector() { + printf("\n--- VECTOR TEST ---\n"); + Vector *v = malloc(sizeof(Vector)); + vec_init(v, NULL); + + int e0 = 0; + int e1 = 1; + int e2 = 2; + int e3 = 3; + int e4 = 4; + + vec_push(v, &e0); + assert(v->length == 1); + int *t = (int*)vec_at(v, 0); + assert(*t == 0); + + vec_push(v, &e1); + vec_push(v, &e2); + assert(v->length == 3); + + // test access outside bounds + t = (int*)vec_safe_at(v, 3); + assert(t == NULL); + + printf("Before insert: "); + print_vector(v); + vec_push(v, &e4); + vec_insert(v, &e3, 3); + printf("After insert: "); + print_vector(v); + + t = (int*)vec_at(v, 3); + assert(*t == e3); + t = (int*)vec_at(v, 4); + assert(*t == e4); + + t = (int*)vec_remove(v, 1); + assert(t != NULL); + assert(*t == 1); + printf("After removal: "); + print_vector(v); + + t = (int*)vec_remove(v, 10); + assert(t == NULL); + + vec_destroy(v); +} + int main() { test_ll(); test_set(); test_stack(); test_bintree(); test_math(); + test_vector(); return 0; } \ No newline at end of file