From 445fe6e07e3b8f5343f4a728d7ad96fbbfd0345e Mon Sep 17 00:00:00 2001 From: Mistivia Date: Sun, 8 Jun 2025 18:11:12 +0800 Subject: add generic vector --- src/vec.c | 9 +++++++ src/vec.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test_vec.c | 22 ++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/vec.c create mode 100644 src/vec.h create mode 100644 tests/test_vec.c diff --git a/src/vec.c b/src/vec.c new file mode 100644 index 0000000..318d328 --- /dev/null +++ b/src/vec.c @@ -0,0 +1,9 @@ +#include "vec.h" + +#include + +VECTOR_IMPL(Char); +VECTOR_IMPL(Int); +VECTOR_IMPL(Long); +VECTOR_IMPL(Float); +VECTOR_IMPL(Double); diff --git a/src/vec.h b/src/vec.h new file mode 100644 index 0000000..3bb4014 --- /dev/null +++ b/src/vec.h @@ -0,0 +1,77 @@ +#ifndef ALGDS_VEC_H_ +#define ALGDS_VEC_H_ + +#include + +#include "type_alias.h" + +#define VECTOR_DEF(T) \ + typedef struct { \ + T* buffer; \ + int size; \ + int cap; \ + } T##Vector; \ + \ + void T##Vector_init(T##Vector *self); \ + void T##Vector_push_back(T##Vector *self, T *elem); \ + void T##Vector_insert_before(T##Vector *self, int n, T *elem); \ + void T##Vector_pop(T##Vector *self); \ + void T##Vector_remove(T##Vector *self, size_t n); \ + size_t T##Vector_len(T##Vector *self); \ + T* T##Vector_begin(T##Vector *self); \ + T* T##Vector_end(T##Vector *self); \ + T* T##Vector_ref(T##Vector *self, size_t n); \ + void T##Vector_free(T##Vector *self); + +#define VECTOR_IMPL(T) \ + void T##Vector_init(T##Vector *self) { \ + self->buffer = (T*)malloc(sizeof(T) * 16); \ + self->cap = 16; \ + self->size = 0; \ + } \ + \ + void T##Vector_push_back(T##Vector *self, T *elem) { \ + if (self->size + 1 > self->cap) { \ + self->buffer = realloc(self->buffer, sizeof(T) * self->cap * 2); \ + self->cap *= 2; \ + } \ + memmove(self->buffer + self->size, elem, sizeof(T)); \ + self->size += 1; \ + } \ + void T##Vector_insert_before(T##Vector *self, int n, T *elem) { \ + if (n < 0 || n > self->size) { \ + return; \ + } \ + if (self->size + 1 > self->cap) { \ + self->buffer = malloc(sizeof(T) * self->cap * 2); \ + self->cap *= 2; \ + } \ + if (n != self->size) { \ + memmove(self->buffer + n + 1, \ + self->buffer + n, \ + sizeof(T) * (self->size - n)); \ + memmove(self->buffer + n, elem, sizeof(T)); \ + } \ + } \ + void T##Vector_pop(T##Vector *self) { \ + self->size -= 1; \ + } \ + void T##Vector_remove(T##Vector *self, size_t n) { \ + if (n < 0 || n >= self->size) return; \ + memmove(self->buffer + n, \ + self->buffer + n + 1, \ + sizeof(T) * self->size - n - 1); \ + self->size -= 1; \ + } \ + T* T##Vector_begin(T##Vector *self) { return self->buffer; } \ + T* T##Vector_end(T##Vector *self) { return self->buffer + self->size; } \ + T* T##Vector_ref(T##Vector *self, size_t n) { return self->buffer + n; } \ + void T##Vector_free(T##Vector *self) { free(self->buffer); } + +VECTOR_DEF(Char); +VECTOR_DEF(Int); +VECTOR_DEF(Long); +VECTOR_DEF(Float); +VECTOR_DEF(Double); + +#endif diff --git a/tests/test_vec.c b/tests/test_vec.c new file mode 100644 index 0000000..4cbc96f --- /dev/null +++ b/tests/test_vec.c @@ -0,0 +1,22 @@ +#include "vec.h" + +#include +#include + +int main() { + printf("[TEST] vec\n"); + + IntVector vec; + IntVector_init(&vec); + + for (int i = 0; i < 1000; i++) { + assert(vec.size == i); + IntVector_push_back(&vec, &i); + assert(*(IntVector_end(&vec) - 1) == i); + } + assert(*IntVector_begin(&vec) == 0); + + IntVector_free(&vec); + printf("[PASS] vec\n"); + return 0; +} -- cgit v1.0