libbitvec-c

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

commit 1db0e289b5bc04b0dda98abbfce10be0b9c59058
parent 78cdbdf01dfca7700db07caec49067eb44b09721
Author: Louis Burda <quent.burda@gmail.com>
Date:   Mon, 13 Mar 2023 20:23:07 +0100

Simplify by removing HANDLE_ERR and forwarding errno to caller

Diffstat:
MMakefile | 12++----------
Minclude/bitvec.h | 52++++++++--------------------------------------------
Mlibbitvec.abi | 2++
Mlibbitvec.lds | 4+++-
Msrc/bitvec.c | 72+++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/test.c | 14++++++++++----
6 files changed, 72 insertions(+), 84 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,16 +4,8 @@ LIBDIR ?= /lib CFLAGS = -I include -Wno-prototype -Wunused-function -Wunused-variable -ifeq "$(LIBBITVEC_DEBUG)" "1" -CFLAGS += -g -endif - -ifeq "$(LIBBITVEC_ASSERT)" "1" -CFLAGS += -DLIBBITVEC_ASSERT_ENABLE=1 -endif - -ifeq "$(LIBBITVEC_HANDLE_ERR)" "1" -CFLAGS += -DLIBBITVEC_HANDLE_ERRS=1 +ifeq "$(DEBUG)" "1" +CFLAGS += -g -DLIBBITVEC_CHECK_ENABLE=1 endif all: build/libbitvec.so build/libbitvec.a build/test diff --git a/include/bitvec.h b/include/bitvec.h @@ -4,63 +4,27 @@ #include <stdbool.h> #include <stdlib.h> -#ifdef LIBBITVEC_ASSERT_ENABLE - -#include <stdio.h> - -#define LIBBITVEC_ASSERT(x) libbitvec_assert((x), __FILE__, __LINE__, #x) - -static inline void libbitvec_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 LIBBITVEC_ASSERT(x) -#endif - -#ifdef LIBBITVEC_HANDLE_ERRS - -#include <errno.h> -#include <stdio.h> - -#define LIBBITVEC_HANDLE_ERR(x) libbitvec_err(__FILE__, __LINE__, x) - -static inline void libbitvec_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 LIBBITVEC_HANDLE_ERR(x) -#endif - #ifdef UINT64_MAX -typedef uint64_t libbitvec_slot_t; +typedef uint64_t bitvec_slot_t; #else -typedef uint32_t libbitvec_slot_t; +typedef uint32_t bitvec_slot_t; #endif struct bitvec { size_t cap; - libbitvec_slot_t *data; + bitvec_slot_t *data; }; -bool bitvec_init(struct bitvec *vec, size_t cap); +extern int libbitvec_errno; + +int 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); +int bitvec_reserve(struct bitvec *vec, size_t cnt); +int 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); diff --git a/libbitvec.abi b/libbitvec.abi @@ -1,3 +1,5 @@ +libbitvec_errno + bitvec_init bitvec_deinit diff --git a/libbitvec.lds b/libbitvec.lds @@ -1,5 +1,7 @@ -LIBBITVEC_1.0 { +LIBBITVEC_1.1 { global: + libbitvec_errno; + bitvec_init; bitvec_deinit; diff --git a/src/bitvec.c b/src/bitvec.c @@ -1,30 +1,51 @@ #include "bitvec.h" +#include <errno.h> +#include <stdio.h> #include <string.h> +#include <stdlib.h> -#define SLOT_BYTES sizeof(libbitvec_slot_t) +#define SLOT_BYTES sizeof(bitvec_slot_t) #define SLOT_BITS (SLOT_BYTES * 8) -#define SLOT_MAX (~(libbitvec_slot_t)0) +#define SLOT_MAX (~(bitvec_slot_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) (((libbitvec_slot_t)1) << n) +#define SLOT_BIT(n) (((bitvec_slot_t)1) << n) #define APPLY_MASK(x,s,m) ((s) ? ((x) | (m)) : ((x) & ~(m))) -bool +#ifdef LIBBITVEC_CHECK_ENABLE +#define LIBBITVEC_CHECK(x) libbitvec_assert((x), __FILE__, __LINE__, #x) +#else +#define LIBBITVEC_CHECK(x) +#endif + +int libbitvec_errno = 0; + +static inline void +libbitvec_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(); +} + +int bitvec_init(struct bitvec *vec, size_t cap) { - LIBBITVEC_ASSERT(vec != NULL); + LIBBITVEC_CHECK(vec != NULL); if (cap) { vec->data = calloc(SLOTCNT(cap), SLOT_BYTES); if (!vec->data) { - LIBBITVEC_HANDLE_ERR("calloc"); - return false; + libbitvec_errno = errno; + return libbitvec_errno; } } else { vec->data = NULL; @@ -32,13 +53,13 @@ bitvec_init(struct bitvec *vec, size_t cap) vec->cap = BITCEIL(cap); - return true; + return 0; } void bitvec_deinit(struct bitvec *vec) { - LIBBITVEC_ASSERT(vec != NULL); + LIBBITVEC_CHECK(vec != NULL); vec->cap = 0; free(vec->data); @@ -51,7 +72,7 @@ bitvec_alloc(size_t cap) bitvec = malloc(sizeof(struct bitvec)); if (!bitvec) { - LIBBITVEC_HANDLE_ERR("malloc"); + libbitvec_errno = errno; return NULL; } @@ -70,52 +91,53 @@ bitvec_free(struct bitvec *vec) free(vec); } -bool +int bitvec_reserve(struct bitvec *vec, size_t cnt) { void *alloc; - LIBBITVEC_ASSERT(vec != NULL); + LIBBITVEC_CHECK(vec != NULL); cnt = BITCEIL(cnt); if (vec->cap >= cnt) return true; alloc = realloc(vec->data, SLOTCNT(cnt) * SLOT_BYTES); if (!alloc) { - LIBBITVEC_HANDLE_ERR("realloc"); - return false; + libbitvec_errno = errno; + return libbitvec_errno; } alloc = vec->data; memset(vec->data + SLOT(vec->cap), 0, SLOT(cnt) - SLOT(vec->cap)); vec->cap = cnt; - return true; + return 0; } -bool +int bitvec_shrink(struct bitvec *vec, size_t cnt) { void *alloc; - LIBBITVEC_ASSERT(vec != NULL); + + LIBBITVEC_CHECK(vec != NULL); cnt = BITCEIL(cnt); if (vec->cap <= cnt) return true; alloc = realloc(vec->data, SLOTCNT(cnt)); if (!alloc) { - LIBBITVEC_HANDLE_ERR("realloc"); - return false; + libbitvec_errno = errno; + return libbitvec_errno; } vec->data = alloc; vec->cap = cnt; - return true; + return 0; } bool bitvec_get(struct bitvec *vec, size_t pos) { - LIBBITVEC_ASSERT(vec != NULL); + LIBBITVEC_CHECK(vec != NULL); if (pos >= vec->cap) return false; return !!(vec->data[pos / SLOT_BITS] & SLOT_BIT(pos % SLOT_BITS)); @@ -124,7 +146,7 @@ bitvec_get(struct bitvec *vec, size_t pos) void bitvec_set(struct bitvec *vec, size_t pos) { - LIBBITVEC_ASSERT(vec != NULL && pos < vec->cap); + LIBBITVEC_CHECK(vec != NULL && pos < vec->cap); vec->data[pos / SLOT_BITS] |= SLOT_BIT(pos % SLOT_BITS); } @@ -132,7 +154,7 @@ bitvec_set(struct bitvec *vec, size_t pos) void bitvec_clear(struct bitvec *vec, size_t pos) { - LIBBITVEC_ASSERT(vec != NULL && pos < vec->cap); + LIBBITVEC_CHECK(vec != NULL && pos < vec->cap); vec->data[pos / SLOT_BITS] &= ~SLOT_BIT(pos % SLOT_BITS); } @@ -140,10 +162,10 @@ bitvec_clear(struct bitvec *vec, size_t pos) void bitvec_setn(struct bitvec *vec, size_t start, size_t end, bool set) { - libbitvec_slot_t mask; + bitvec_slot_t mask; size_t starti, endi, i; - LIBBITVEC_ASSERT(vec != NULL && end >= start && end <= vec->cap); + LIBBITVEC_CHECK(vec != NULL && end >= start && end <= vec->cap); if (start == end) return; diff --git a/src/test.c b/src/test.c @@ -1,22 +1,28 @@ #include "bitvec.h" +#include <err.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +#define LIBBITVEC_ERR() errx(1, "test: libbitvec: %s", strerror(libbitvec_errno)) + int main(int argc, const char **argv) { struct bitvec bitvec; - int i, *val; + int i, ret; + int *val; - bitvec_init(&bitvec, 10); + ret = bitvec_init(&bitvec, 10); + if (ret) LIBBITVEC_ERR(); for (i = 1; i < argc; i++) { *val = atoi(argv[i]); if (bitvec_get(&bitvec, *val)) printf("%i -> dup!\n", *val); - bitvec_reserve(&bitvec, *val); + ret = bitvec_reserve(&bitvec, *val); + if (ret) LIBBITVEC_ERR(); bitvec_set(&bitvec, *val); } @@ -24,7 +30,7 @@ main(int argc, const char **argv) printf("%i", bitvec_get(&bitvec, i)); printf("\n"); - printf("bitvec len: %lu\n", bitvec.cap / (8 * sizeof(libbitvec_slot_t))); + printf("bitvec len: %lu\n", bitvec.cap / (8 * sizeof(bitvec_slot_t))); bitvec_deinit(&bitvec); }