#ifndef LIBGE_GEVECTOR_H #define LIBGE_GEVECTOR_H #include #include #define GEVECTOR_DEF(t, n) \ GEVECTOR_DEF_API(t, n) \ GEVECTOR_DEF_IMPL(t, n) #define GEVECTOR_DEF_API(t, n) GEVECTOR_DEF_API_HELPER(t, n, n##_t) #define GEVECTOR_DEF_API_HELPER(t, n, n_t) \ typedef struct { \ double gfac; \ size_t cap; \ size_t len; \ t *data; \ } n_t; \ \ int n##_new(n_t *, size_t, double); \ int n##_push(n_t *, t); \ int n##_insert(n_t *, t, size_t); \ void n##_remove(n_t *, size_t); \ int n##_resize(n_t *, size_t); #define GEVECTOR_DEF_IMPL(t, n) GEVECTOR_DEF_IMPL_HELPER(t, n, n##_t) #define GEVECTOR_DEF_IMPL_HELPER(t, n, n_t) \ int \ n##_new(n_t *vec, size_t cap, double gfac) \ { \ *vec = (n_t) { \ .gfac = gfac == 0 ? 1.5f : gfac, \ .cap = cap == 0 ? 16 : cap, \ .len = 0, \ .data = calloc(cap == 0 ? 16 : cap, sizeof(t)) \ }; \ return vec->data == NULL ? -1 : 0; \ } \ \ int \ n##_push(n_t *vec, t elem) \ { \ return n##_insert(vec, elem, vec->len); \ } \ \ int \ n##_insert(n_t *vec, t elem, size_t i) \ { \ if (vec->len == vec->cap) { \ size_t ncap = (size_t) (vec->cap * vec->gfac); \ if (ncap == vec->cap) \ ncap++; \ if (n##_resize(vec, ncap) == -1) \ return -1; \ } \ for (size_t j = vec->len; j > i; j--) \ vec->data[j] = vec->data[j - 1]; \ vec->data[i] = elem; \ vec->len++; \ return 0; \ } \ \ void \ n##_remove(n_t *vec, size_t i) \ { \ for (size_t j = i; j < vec->len - 1; j++) \ vec->data[j] = vec->data[j + 1]; \ vec->len--; \ } \ \ int \ n##_resize(n_t *vec, size_t ncap) \ { \ vec->data = realloc(vec->data, sizeof(t) * ncap); \ if (vec->data == NULL) \ return -1; \ vec->cap = ncap; \ return 0; \ } #define GEVECTOR_ENUMERATE(t, i, e, v) \ for (bool __ge_c = true; __ge_c; __ge_c = false) \ for (t e = (v).data[0]; __ge_c; __ge_c = false) \ for (size_t i = 0; i < (v).len; e = (v).data[++i]) #define GEVECTOR_FOREACH(t, e, v) GEVECTOR_ENUMERATE(t, __ge_i, e, v) #endif /* !LIBGE_GEVECTOR_H */