diff options
| author | Mistivia <i@mistivia.com> | 2025-06-08 18:11:12 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-06-08 18:11:12 +0800 |
| commit | 445fe6e07e3b8f5343f4a728d7ad96fbbfd0345e (patch) | |
| tree | 20021b181d1204f7577154e62dfe1f00ef5ee5f9 | |
| parent | acd6b6fffefc52414ccc8e983b5fe9909f332626 (diff) | |
add generic vector
| -rw-r--r-- | src/vec.c | 9 | ||||
| -rw-r--r-- | src/vec.h | 77 | ||||
| -rw-r--r-- | tests/test_vec.c | 22 |
3 files changed, 108 insertions, 0 deletions
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 <string.h> + +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 <stdlib.h> + +#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 <assert.h> +#include <stdio.h> + +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; +} |
