diff options
| author | 2026-01-12 16:30:37 -0600 | |
|---|---|---|
| committer | 2026-01-12 16:30:37 -0600 | |
| commit | 2016dceaa9cfc65ee80ee7e433331390f4263744 (patch) | |
| tree | d0c97b2ab5fc1933298a050f167b6a68fff08c89 /lib/vector.c | |
| parent | add support for verified files (diff) | |
download jobs
Diffstat (limited to 'lib/vector.c')
| -rw-r--r-- | lib/vector.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/vector.c b/lib/vector.c new file mode 100644 index 0000000..eb7233c --- /dev/null +++ b/lib/vector.c @@ -0,0 +1,122 @@ +#include "vector.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +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; +} |
