#include "vector.h" #include #include #include struct vl__vector_tag { size_t cap, sz, len; void *data; /* cap * len */ }; vl_vector *vl_vector_new(size_t sz) { return vl_vector_new_ex(sz, 16); } vl_vector *vl_vector_new_ex(size_t sz, size_t init_cap) { vl_vector *vec = calloc(1, sizeof(vl_vector)); if (!vec) return NULL; if (init_cap < 16) init_cap = 16; vec->cap = init_cap; vec->len = 0; vec->sz = sz; void *data = calloc(init_cap, sz); if (!data) { free(vec); return NULL; } vec->data = data; return vec; } void vl_vector_free(vl_vector *vec) { if (!vec) return; free(vec->data); free(vec); } static int vec_grow(vl_vector *vec, size_t newlen) { void *temp = reallocarray(vec->data, newlen, vec->sz); if (!temp) return -1; vec->data = temp; return 0; } static size_t next_po2(size_t sz) { assert(sz > 0); return (size_t)(1 << (64 - __builtin_clzll((unsigned long long)sz))); } static int ensure_fits(vl_vector *vec, size_t toadd) { if (vec->len + toadd <= vec->cap) { return 0; } size_t newcap = next_po2(vec->len + toadd); return vec_grow(vec, newcap); } /* will abort if realloc fails to shrink the allocation (should never happen) */ void vl_vector_shrink_to_size(vl_vector *vec) { if (vec_grow(vec, vec->len) < 0) abort(); } #define vl_newvec(_t) vl_vector_new(sizeof(_t)) #define vl_newvec_ex(_t, _ic) vl_vector_new_ex(sizeof(_t), _ic) int vl_vector_push(vl_vector *vec, void *data) { return vl_vector_push_vec(vec, data, 1); } int vl_vector_push_vec(vl_vector *vec, void *data, size_t n) { if (ensure_fits(vec, n) < 0) { return -1; } unsigned char *d = vec->data; memcpy(d + (vec->len * vec->sz), data, n * vec->sz); vec->len += n; return 0; } int vl_vector_push_2d(vl_vector *vec, void **data, size_t n) { if (ensure_fits(vec, n) < 0) { return -1; } unsigned char *d = vec->data; for (size_t i = 0; i < n; ++i) { memcpy(d + ((vec->len + i) * vec->sz), data[i], vec->sz); } vec->len += n; return 0; } size_t vl_vector_size(const vl_vector *vec) { return vec->len; } void *vl_vector_values(const vl_vector *vec, size_t *psz) { if (psz) *psz = vec->len; return vec->data; }