commit f7cdc492f86eee1740d7c40c00e31c9dafd51ff6
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 12 Feb 2022 15:54:35 +0100
Core functionality
Diffstat:
6 files changed, 286 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,5 @@
+compile_commands.json
+build
+.cache
+vgcore*
+test
diff --git a/Makefile b/Makefile
@@ -0,0 +1,42 @@
+CFLAGS = -I include
+LDLIBS =
+DEPFLAGS = -MT $@ -MMD -MP -MF build/$*.d
+
+_SRCS = vec.c
+SRCS = $(_SRCS:%.c=src/%.c)
+OBJS = $(_SRCS:%.c=build/%.o)
+DEPS = $(_SRCS:%.c=build/%.d)
+PI_OBJS = $(_SRCS:%.c=build/%.pi.o)
+
+.PHONY: all clean
+
+all: build/libvec.so build/libvec.a build/test
+
+clean:
+ rm -rf build
+
+build:
+ mkdir build
+
+build/%.o: src/%.c build/%.d | build
+ $(CC) -c -o $@ $< $(DEPFLAGS) $(CFLAGS)
+
+build/%.pi.o: src/%.c build/%.d | build
+ $(CC) -c -o $@ $< $(DEPFLAGS) $(CFLAGS) -fPIC
+
+build/%.d: | build;
+
+include $(DEPS)
+
+build/libvec.a: $(OBJS) | build
+ $(CC) -o build/tmp.o $^ $(CFLAGS) -r
+ objcopy --keep-global-symbols=libvec.abi build/tmp.o build/fixed.o
+ ar rcs $@ build/fixed.o
+
+build/libvec.so: $(PI_OBJS) | build
+ $(CC) -o build/tmp.so $(PI_OBJS) $(CFLAGS) -shared
+ objcopy --keep-global-symbols=libvec.abi build/tmp.so $@
+
+build/test: src/test.c build/libvec.a | build
+ $(CC) -o $@ $^ -I include
+
diff --git a/include/vec.h b/include/vec.h
@@ -0,0 +1,22 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+struct vec;
+
+struct vec *vec_alloc(size_t dsize, size_t cap);
+void vec_free(struct vec *vec);
+
+void vec_clear(struct vec *vec);
+void vec_resize(struct vec *vec, size_t cap);
+
+void vec_push(struct vec *vec, const void *data);
+void *vec_pop(struct vec *vec);
+
+void *vec_at(struct vec *vec, size_t index);
+bool vec_iter(struct vec *vec, void *p);
+
+void vec_set(struct vec *vec, size_t index, const void *data);
+void vec_rm(struct vec *vec, size_t index);
+
+int vec_empty(struct vec *vec);
+int vec_len(struct vec *vec);
diff --git a/libvec.abi b/libvec.abi
@@ -0,0 +1,17 @@
+vec_alloc
+vec_free
+
+vec_clear
+vec_resize
+
+vec_push
+vec_pop
+
+vec_at
+vec_iter
+
+vec_set
+vec_rm
+
+vec_empty
+vec_len
diff --git a/src/test.c b/src/test.c
@@ -0,0 +1,27 @@
+#include "vec.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main(int argc, const char **argv)
+{
+ struct vec *vec;
+ int *num;
+ int i, val;
+
+ vec = vec_alloc(sizeof(int), 10);
+
+ for (i = 1; i < argc; i++) {
+ val = atoi(argv[i]);
+ vec_push(vec, &val);
+ }
+
+ num = NULL;
+ while (vec_iter(vec, &num)) {
+ printf("%i\n", *num);
+ }
+
+ vec_free(vec);
+}
diff --git a/src/vec.c b/src/vec.c
@@ -0,0 +1,173 @@
+#include "vec.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define ASSERT(x) assert((x), __FILE__, __LINE__, #x)
+#define OOM_CHECK(x) assert((x) != NULL, __FILE__, __LINE__, "Out of Memory")
+
+struct vec {
+ size_t dsize;
+ size_t count, cap;
+
+ char data[];
+};
+
+static void assert(int cond, const char *file, int line, const char *condstr);
+
+static const size_t vec_data_offset = sizeof(size_t) * 3;
+
+void
+assert(int cond, const char *file, int line, const char *condstr)
+{
+ if (cond) return;
+
+ fprintf(stderr, "CVEC: Assertion failed at %s:%i (%s)\n",
+ file, line, condstr);
+ exit(1);
+}
+
+struct vec *
+vec_alloc(size_t dsize, size_t cap)
+{
+ struct vec *vec;
+
+ ASSERT(dsize != 0 && cap != 0);
+
+ vec = malloc(vec_data_offset + cap * dsize);
+ OOM_CHECK(vec);
+ vec->dsize = dsize;
+ vec->count = 0;
+ vec->cap = cap;
+
+ return vec;
+}
+
+void
+vec_free(struct vec *vec)
+{
+ ASSERT(vec != NULL);
+
+ free(vec);
+}
+
+void
+vec_clear(struct vec *vec)
+{
+ ASSERT(vec != NULL);
+
+ vec->count = 0;
+}
+
+void
+vec_resize(struct vec *vec, size_t cap)
+{
+ ASSERT(vec != NULL && cap != 0 && vec->count <= cap);
+
+ vec->cap = cap;
+ vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
+ OOM_CHECK(vec);
+}
+
+void
+vec_push(struct vec *vec, const void *data)
+{
+ ASSERT(vec != NULL && data != NULL);
+
+ if (vec->count == vec->cap) {
+ vec->cap *= 2;
+ vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
+ OOM_CHECK(vec);
+ }
+ vec->count++;
+ vec_set(vec, vec->count - 1, data);
+}
+
+void *
+vec_pop(struct vec *vec)
+{
+ ASSERT(vec != NULL);
+
+ vec->count--;
+ if (vec->count + 1 < vec->cap / 2) {
+ vec->cap /= 2;
+ vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
+ OOM_CHECK(vec);
+ }
+
+ return vec->data + vec->dsize * vec->count;
+}
+
+void *
+vec_at(struct vec *vec, size_t index)
+{
+ ASSERT(vec != NULL && index < vec->count);
+
+ return vec->data + vec->dsize * index;
+}
+
+bool
+vec_iter(struct vec *vec, void *_p)
+{
+ char **iter;
+
+ ASSERT(vec != NULL && vec != NULL);
+
+ iter = _p;
+ if (*iter == NULL) {
+ *iter = vec->data;
+ } else {
+ *iter += vec->dsize;
+ }
+
+ return *iter < vec->data + vec->dsize * vec->count;
+}
+
+void
+vec_set(struct vec *vec, size_t index, const void *data)
+{
+ ASSERT(vec != NULL && data != NULL && index < vec->count);
+
+ memcpy(vec->data + index * vec->dsize, data, vec->dsize);
+}
+
+void
+vec_rm(struct vec *vec, size_t index)
+{
+ void *start, *end;
+
+ ASSERT(vec != NULL && index < vec->count);
+
+ start = vec->data + index * vec->dsize;
+ end = vec->data + vec->count * vec->dsize;
+ if (start + vec->dsize < end) {
+ memcpy(start, start + vec->dsize, end - start - vec->dsize);
+ }
+
+ vec->count--;
+
+ if (vec->count < vec->cap / 4) {
+ vec->cap /= 2;
+ vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
+ OOM_CHECK(vec);
+ }
+}
+
+int
+vec_empty(struct vec *vec)
+{
+ ASSERT(vec != NULL);
+
+ return vec->count == 0;
+}
+
+int
+vec_len(struct vec *vec)
+{
+ ASSERT(vec != NULL);
+
+ return vec->count;
+}