diff --git a/include/vector.h b/include/vector.h new file mode 100644 index 0000000..f722ead --- /dev/null +++ b/include/vector.h @@ -0,0 +1,26 @@ +#ifndef _VECTOR_H +#define _VECTOR_H + +#include +#include + +typedef struct { + size_t len, cap; + + size_t element, scap; + + void* ptr; +} vec_t; + +#define VEC_DEFAULT_CAP 16 + +vec_t vec_new_with_cap(size_t elem, size_t cap); +void vec_push(vec_t* restrict self, const void* restrict item); +bool vec_pop(vec_t* restrict self, void* restrict item); +void* vec_index(const vec_t* restrict self, size_t i); +vec_t vec_clone(const vec_t* restrict self); + +__attribute__((gnu_inline)) inline extern vec_t vec_new(size_t elem) { return vec_new_with_cap(elem, VEC_DEFAULT_CAP); } +__attribute__((gnu_inline)) inline extern void vec_free(vec_t v) { free(v.ptr); } + +#endif /* _VECTOR_H */ diff --git a/src/vector.c b/src/vector.c new file mode 100644 index 0000000..f8f8ec3 --- /dev/null +++ b/src/vector.c @@ -0,0 +1,61 @@ +#include +#include +#include + +#include + +__attribute__((gnu_inline)) inline static void* die_if_null(void* ptr) +{ + if (!ptr) abort(); + return ptr; +} + +vec_t vec_new_with_cap(size_t elem, size_t cap) { + return (vec_t){ + .len =0, + .cap = cap, + .scap = cap, + .element = elem, + .ptr = die_if_null(calloc(elem, cap)), + }; +} + +static inline void vec_extend_one(vec_t* restrict self) +{ + self->ptr = die_if_null(reallocarray(self->ptr, self->element, (self->cap+=self->scap))); +} + +void* vec_index(const vec_t* restrict self, size_t i) +{ + if (i >= self->len) return NULL; + return (void*)(((uintptr_t)self->ptr)+ (self->element*i)); +} + +void vec_push(vec_t* restrict self, const void* restrict item) +{ + if (self->len >= self->cap) { + vec_extend_one(self); + } + memcpy(die_if_null(vec_index(self, self->len++)), item, self->element); +} + +bool vec_pop(vec_t* restrict self, void* restrict item) +{ + if (self->len>0) { + memcpy(item, die_if_null(vec_index(self, self->len--)), self->element); + return true; + } else return false; +} + +vec_t vec_clone(const vec_t* restrict self) +{ + register vec_t new = { + .len = self->len, + .cap = self->cap, + .element = self->element, + .scap = self->scap, + .ptr = die_if_null(calloc(self->element, self->cap)), + }; + memcpy(self->ptr, new.ptr, new.len * new.element); + return new; +}