libdvec-c

C memory vector library
git clone https://git.sinitax.com/sinitax/libdvec-c
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

commit f7cdc492f86eee1740d7c40c00e31c9dafd51ff6
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sat, 12 Feb 2022 15:54:35 +0100

Core functionality

Diffstat:
A.gitignore | 5+++++
AMakefile | 42++++++++++++++++++++++++++++++++++++++++++
Ainclude/vec.h | 22++++++++++++++++++++++
Alibvec.abi | 17+++++++++++++++++
Asrc/test.c | 27+++++++++++++++++++++++++++
Asrc/vec.c | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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; +}