summaryrefslogtreecommitdiffstats
path: root/lib/vector.c
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <bigfoot@figboot.dev>2026-01-12 16:30:37 -0600
committerLibravatar bigfoot547 <bigfoot@figboot.dev>2026-01-12 16:30:37 -0600
commit2016dceaa9cfc65ee80ee7e433331390f4263744 (patch)
treed0c97b2ab5fc1933298a050f167b6a68fff08c89 /lib/vector.c
parentadd support for verified files (diff)
download jobs
Diffstat (limited to 'lib/vector.c')
-rw-r--r--lib/vector.c122
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;
+}