diff --git a/vector.c b/vector.c new file mode 100644 index 0000000..9dfb4bb --- /dev/null +++ b/vector.c @@ -0,0 +1,71 @@ +#include + +#include "error.h" +#include "vector.h" + +#define DEFAULT_CAP 16 + +VECTOR_GEN_SOURCE(Char, char) + +Vector *vector_new(size_t size, size_t cap) +{ + Vector *v; + + if (cap == 0) + cap = DEFAULT_CAP; + + if (!(v = malloc(sizeof(*v)))) { + PRINTINTERR(FUNCFAILED("malloc"), ERRNOS); + abort(); + } + + if (!(v->buf = malloc(size * cap))) { + PRINTINTERR(FUNCFAILED("malloc"), ERRNOS); + abort(); + } + + v->size = size; + v->cap = cap; + v->len = 0; + + return v; +} + +void vector_free(Vector *vec) +{ + free(vec->buf); + free(vec); +} + +void vector_append_arr(Vector *vec, void *arr, size_t len) +{ + void *p; + size_t cap = vec->cap; + + while (cap < vec->len + len) + cap *= 2; + + if (cap != vec->cap) { + if (!(p = realloc(vec->buf, vec->size * cap))) { + vector_free(vec); + PRINTINTERR(FUNCFAILED("realloc"), ERRNOS); + abort(); + } + + vec->buf = p; + vec->cap = cap; + } + + memcpy(vec->buf + vec->len * vec->size, arr, len * vec->size); + vec->len += len; +} + +void vector_append(Vector *vec, void *val) +{ + vector_append_arr(vec, val, 1); +} + +void *vector_get(Vector *vec, size_t i) +{ + return vec->buf + i * vec->size; +} diff --git a/vector.h b/vector.h new file mode 100644 index 0000000..531de92 --- /dev/null +++ b/vector.h @@ -0,0 +1,69 @@ +#ifndef VECTOR_H +#define VECTOR_H + +#include + +#define VECTOR_TYPE(name, type) \ + typedef struct { \ + size_t len, cap, size; \ + type *buf; \ + } Vector##name + +#define VECTOR_SIGN(name, type, func, ret, ...) \ + ret vector_##func##_##type(__VA_ARGS__) + +#define VECTOR_SIGN_V(name, type, func, ret, ...) \ + ret vector_##func##_##type(Vector##name *v __VA_OPT__(,) __VA_ARGS__) + +#define VECTOR_SIGN_NEW(name, type) VECTOR_SIGN(name, type, new, Vector##name *, size_t cap) +#define VECTOR_SIGN_FREE(name, type) VECTOR_SIGN_V(name, type, free, void) +#define VECTOR_SIGN_APPEND_ARR(name, type) VECTOR_SIGN_V(name, type, append_arr, void, type *arr, size_t len) +#define VECTOR_SIGN_APPEND(name, type) VECTOR_SIGN_V(name, type, append, void, type val) +#define VECTOR_SIGN_GET(name, type) VECTOR_SIGN_V(name, type, get, type, size_t i) + +#define VECTOR_GEN_SOURCE_(name, type, spec) \ + spec VECTOR_SIGN_NEW(name, type) \ + { \ + return (Vector##name *)vector_new(sizeof(type), cap); \ + } \ + spec VECTOR_SIGN_FREE(name, type) \ + { \ + vector_free((Vector *)v); \ + } \ + spec VECTOR_SIGN_APPEND_ARR(name, type) \ + { \ + vector_append_arr((Vector *)v, arr, len); \ + } \ + spec VECTOR_SIGN_APPEND(name, type) \ + { \ + vector_append((Vector *)v, &val); \ + } \ + spec VECTOR_SIGN_GET(name, type) \ + { \ + return *(type *)vector_get((Vector *)v, i); \ + } + +#define VECTOR_GEN_SOURCE(name, type) VECTOR_GEN_SOURCE_(name, type, ) +#define VECTOR_GEN_SOURCE_STATIC(name, type) \ + VECTOR_TYPE(name, type); \ + VECTOR_GEN_SOURCE_(name, type, static __attribute__((unused))) + +#define VECTOR_GEN_HEADER(name, type) \ + VECTOR_TYPE(name, type); \ + VECTOR_SIGN_NEW(name, type); \ + VECTOR_SIGN_APPEND_ARR(name, type); \ + VECTOR_SIGN_APPEND(name, type); \ + VECTOR_SIGN_FREE(name, type); \ + VECTOR_SIGN_GET(name, type); + +VECTOR_TYPE(, void); + +Vector *vector_new(size_t size, size_t cap); +void vector_free(Vector *vec); +void vector_append_arr(Vector *vec, void *arr, size_t len); +void vector_append(Vector *vec, void *arr); +void *vector_get(Vector *vec, size_t i); + +VECTOR_GEN_HEADER(Char, char) + +#endif