libdvec-c

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

commit 8892e68e27576b4601da16173e2b82665a7fcdeb
parent 53ccd2847a9b0cac412b18bf778dffb42d395b97
Author: Louis Burda <quent.burda@gmail.com>
Date:   Fri, 17 Feb 2023 19:47:53 +0100

Migrate out bitvec into separate library

Diffstat:
MMakefile | 31+++++++++++++++++++++++--------
Dinclude/assert.h | 43-------------------------------------------
Dinclude/bitvec.h | 32--------------------------------
Minclude/vec.h | 41+++++++++++++++++++++++++++++++++++++++--
Mlibvec.abi | 14--------------
Mlibvec.lds | 14--------------
Dsrc/bitvec.c | 166-------------------------------------------------------------------------------
Msrc/test.c | 12------------
8 files changed, 62 insertions(+), 291 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,12 @@ -CFLAGS = -g -I include -Wno-prototype -Wunused-function -Wunused-variable +PREFIX ?= /usr/local +LIBDIR ?= /lib +INCLUDEDIR ?= /include -SRC = src/vec.c src/bitvec.c -HDR = include/vec.h include/bitvec.h +CFLAGS = -I include -Wno-prototype -Wunused-function -Wunused-variable + +ifeq "$(LIBVEC_DEBUG)" "1" +CFLAGS += -g +endif ifeq "$(LIBVEC_ASSERT)" "1" CFLAGS += -DLIBVEC_ASSERT_ENABLE=1 @@ -19,15 +24,25 @@ clean: build: mkdir build -build/libvec.a: $(SRC) $(HDR) | build - $(CC) -o build/tmp.o $(SRC) $(CFLAGS) -r +build/libvec.a: src/vec.c include/vec.h | build + $(CC) -o build/tmp.o src/vec.c $(CFLAGS) -r objcopy --keep-global-symbols=libvec.abi build/tmp.o build/fixed.o ar rcs $@ build/fixed.o -build/libvec.so: $(SRC) $(HDR) | build - $(CC) -o $@ $(SRC) -fPIC $(CFLAGS) -shared -Wl,-version-script libvec.lds +build/libvec.so: src/vec.c include/vec.h | build + $(CC) -o $@ src/vec.c -fPIC $(CFLAGS) -shared -Wl,-version-script libvec.lds build/test: src/test.c build/libvec.a $(CC) -o $@ $^ $(CFLAGS) -.PHONY: all clean +install: + install -m644 include/vec.h -t "$(DESTDIR)$(PREFIX)$(INCLUDEDIR)" + install -m755 build/libvec.so -t "$(DESTDIR)$(PREFIX)$(LIBDIR)" + install -m755 build/libvec.a -t "$(DESTDIR)$(PREFIX)$(LIBDIR)" + +uninstall: + rm -f "$(DESTDIR)$(PREFIX)$(INCLUDEDIR)/vec.h" + rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/libvec.so" + rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/libvec.a" + +.PHONY: all clean install uninstall diff --git a/include/assert.h b/include/assert.h @@ -1,43 +0,0 @@ -#pragma once - -#ifdef LIBVEC_ASSERT_ENABLE - -#include <stdio.h> -#include <stdlib.h> - -#define LIBVEC_ASSERT(x) libvec_assert((x), __FILE__, __LINE__, #x) - -static inline void libvec_assert(int cond, - const char *file, int line, const char *condstr) -{ - if (cond) return; - - fprintf(stderr, "libvec: Assertion failed at %s:%i (%s)\n", - file, line, condstr); - abort(); -} - -#else -#define LIBVEC_ASSERT(x) -#endif - - -#ifdef LIBVEC_HANDLE_ERRS - -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#define LIBVEC_HANDLE_ERR(x) libvec_err(__FILE__, __LINE__, x) - -static inline void libvec_err(const char *file, int line, const char *info) -{ - fprintf(stderr, "libvec: %s at %s:%i: %s\n", - info, file, line, strerror(errno)); - exit(1); -} - -#else -#define LIBVEC_HANDLE_ERR(x) -#endif diff --git a/include/bitvec.h b/include/bitvec.h @@ -1,32 +0,0 @@ -#pragma once - -#include "assert.h" - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> - -#ifdef UINT64_MAX -typedef uint64_t libvec_bitslot_t; -#else -typedef uint32_t libvec_bitslot_t; -#endif - -struct bitvec { - size_t cap; - libvec_bitslot_t *data; -}; - -bool bitvec_init(struct bitvec *vec, size_t cap); -void bitvec_deinit(struct bitvec *vec); - -struct bitvec *bitvec_alloc(size_t cap); -void bitvec_free(struct bitvec *vec); - -bool bitvec_reserve(struct bitvec *vec, size_t cnt); -bool bitvec_shrink(struct bitvec *vec, size_t cnt); - -bool bitvec_get(struct bitvec *vec, size_t pos); -void bitvec_set(struct bitvec *vec, size_t pos); -void bitvec_clear(struct bitvec *vec, size_t pos); -void bitvec_setn(struct bitvec *vec, size_t start, size_t end, bool set); diff --git a/include/vec.h b/include/vec.h @@ -1,11 +1,47 @@ #pragma once -#include "assert.h" - #include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#ifdef LIBVEC_ASSERT_ENABLE + +#include <stdio.h> + +#define LIBVEC_ASSERT(x) libvec_assert((x), __FILE__, __LINE__, #x) + +static inline void libvec_assert(int cond, + const char *file, int line, const char *condstr) +{ + if (cond) return; + + fprintf(stderr, "libvec: Assertion failed at %s:%i (%s)\n", + file, line, condstr); + abort(); +} + +#else +#define LIBVEC_ASSERT(x) +#endif + +#ifdef LIBVEC_HANDLE_ERRS + +#include <errno.h> +#include <stdio.h> + +#define LIBVEC_HANDLE_ERR(x) libvec_err(__FILE__, __LINE__, x) + +static inline void libvec_err(const char *file, int line, const char *info) +{ + fprintf(stderr, "libvec: %s at %s:%i: %s\n", + info, file, line, strerror(errno)); + exit(1); +} + +#else +#define LIBVEC_HANDLE_ERR(x) +#endif + struct vec { size_t dsize; size_t len, cap; @@ -62,6 +98,7 @@ static inline void * vec_alloc_slots(struct vec *vec, size_t count) { vec_reserve(vec, vec->len, count); + return vec->data + (vec->len - count) * vec->dsize; } diff --git a/libvec.abi b/libvec.abi @@ -14,17 +14,3 @@ vec_replace vec_iter_fwd vec_iter_bwd - -bitvec_init -bitvec_deinit - -bitvec_alloc -bitvec_free - -bitvec_reserve -bitvec_shrink - -bitvec_get -bitvec_set -bitvec_clear -bitvec_setn diff --git a/libvec.lds b/libvec.lds @@ -16,19 +16,5 @@ LIBVEC_1.1 { vec_iter_fwd; vec_iter_bwd; - - bitvec_init; - bitvec_deinit; - - bitvec_alloc; - bitvec_free; - - bitvec_reserve; - bitvec_shrink; - - bitvec_get; - bitvec_set; - bitvec_clear; - bitvec_setn; local: *; }; diff --git a/src/bitvec.c b/src/bitvec.c @@ -1,166 +0,0 @@ -#include "bitvec.h" - -#include <string.h> - -#define SLOT_BYTES sizeof(libvec_bitslot_t) -#define SLOT_BITS (SLOT_BYTES * 8) -#define SLOT_MAX (~(libvec_bitslot_t)0) - -#define CEILDIV(n, d) ((n) / (d) + ((n) % (d) == 0 ? 0 : 1)) -#define BITCEIL(n) ((n) + SLOT_BITS - 1 - (SLOT_BITS - 1 + n) % SLOT_BITS) - -#define SLOT(n) ((n) / SLOT_BITS) -#define SLOTCNT(n) CEILDIV(n, SLOT_BITS) -#define SLOT_BIT(n) (((libvec_bitslot_t)1) << n) - -#define APPLY_MASK(x,s,m) ((s) ? ((x) | (m)) : ((x) & ~(m))) - -bool -bitvec_init(struct bitvec *vec, size_t cap) -{ - LIBVEC_ASSERT(vec != NULL); - - if (cap) { - vec->data = calloc(SLOTCNT(cap), SLOT_BYTES); - if (!vec->data) { - LIBVEC_HANDLE_ERR("calloc"); - return false; - } - } else { - vec->data = NULL; - } - - vec->cap = BITCEIL(cap); - - return true; -} - -void -bitvec_deinit(struct bitvec *vec) -{ - LIBVEC_ASSERT(vec != NULL); - - vec->cap = 0; - free(vec->data); -} - -struct bitvec * -bitvec_alloc(size_t cap) -{ - struct bitvec *bitvec; - - bitvec = malloc(sizeof(struct bitvec)); - if (!bitvec) { - LIBVEC_HANDLE_ERR("malloc"); - return NULL; - } - - if (!bitvec_init(bitvec, cap)) { - free(bitvec); - return NULL; - } - - return bitvec; -} - -void -bitvec_free(struct bitvec *vec) -{ - bitvec_deinit(vec); - free(vec); -} - -bool -bitvec_reserve(struct bitvec *vec, size_t cnt) -{ - LIBVEC_ASSERT(vec != NULL); - - cnt = BITCEIL(cnt); - if (vec->cap >= cnt) return true; - - vec->data = realloc(vec->data, SLOTCNT(cnt) * SLOT_BYTES); - if (!vec->data) { - LIBVEC_HANDLE_ERR("realloc"); - return false; - } - - memset(vec->data + SLOT(vec->cap), 0, SLOT(cnt) - SLOT(vec->cap)); - vec->cap = cnt; - - return true; -} - -bool -bitvec_shrink(struct bitvec *vec, size_t cnt) -{ - LIBVEC_ASSERT(vec != NULL); - - cnt = BITCEIL(cnt); - if (vec->cap <= cnt) return true; - - vec->data = realloc(vec->data, SLOTCNT(cnt)); - if (!vec->data) { - LIBVEC_HANDLE_ERR("realloc"); - return false; - } - - vec->cap = cnt; - - return true; -} - -bool -bitvec_get(struct bitvec *vec, size_t pos) -{ - LIBVEC_ASSERT(vec != NULL); - - if (pos >= vec->cap) return false; - return !!(vec->data[pos / SLOT_BITS] & SLOT_BIT(pos % SLOT_BITS)); -} - -void -bitvec_set(struct bitvec *vec, size_t pos) -{ - LIBVEC_ASSERT(vec != NULL && pos < vec->cap); - - vec->data[pos / SLOT_BITS] |= SLOT_BIT(pos % SLOT_BITS); -} - -void -bitvec_clear(struct bitvec *vec, size_t pos) -{ - LIBVEC_ASSERT(vec != NULL && pos < vec->cap); - - vec->data[pos / SLOT_BITS] &= ~SLOT_BIT(pos % SLOT_BITS); -} - -void -bitvec_setn(struct bitvec *vec, size_t start, size_t end, bool set) -{ - libvec_bitslot_t mask; - size_t starti, endi, i; - - LIBVEC_ASSERT(vec != NULL && end >= start && end <= vec->cap); - - if (start == end) return; - - starti = SLOT(start); - end = SLOT(end - 1); - - if (starti == endi) { - if (end % SLOT_BITS == 0) - mask = SLOT_MAX - SLOT_BIT(start % SLOT_BITS); - else - mask = SLOT_BIT(end % SLOT_BITS) - SLOT_BIT(start % SLOT_BITS); - vec->data[starti] = APPLY_MASK(vec->data[starti], set, mask); - } else { - mask = SLOT_MAX - SLOT_BIT(start % SLOT_BITS); - vec->data[starti] = APPLY_MASK(vec->data[starti], set, mask); - - for (i = starti + 1; i <= endi - 1; i++) - vec->data[i] = APPLY_MASK(vec->data[i], set, SLOT_MAX); - - mask = SLOT_BIT(end % SLOT_BITS) - SLOT_BIT(0); - vec->data[endi] = APPLY_MASK(vec->data[endi], set, mask); - } -} diff --git a/src/test.c b/src/test.c @@ -1,5 +1,4 @@ #include "vec.h" -#include "bitvec.h" #include <stdlib.h> #include <stdio.h> @@ -8,31 +7,20 @@ int main(int argc, const char **argv) { - struct bitvec bitvec; struct vec vec; int i, *val; vec_init(&vec, sizeof(int), 10); - bitvec_init(&bitvec, 10); for (i = 1; i < argc; i++) { val = vec_alloc_slot(&vec); *val = atoi(argv[i]); - if (bitvec_get(&bitvec, *val)) - printf("%i -> dup!\n", *val); - bitvec_reserve(&bitvec, *val); - bitvec_set(&bitvec, *val); } - for (i = 0; i < 10; i++) - printf("%i", bitvec_get(&bitvec, i)); - printf("\n"); - for (i = 0; i < vec.len; i++) printf("%i\n", *(int *)vec_at(&vec, i)); printf("vec len: %lu\n", vec.len); - printf("bitvec len: %lu\n", bitvec.cap / (8 * sizeof(libvec_bitslot_t))); vec_deinit(&vec); }