libhmap-c

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

commit f5c5b102debbfa05ef7b00de7ee36a0df771b1af
parent d53b903d166cefb5b5bc03ae084f9e8adbac94d6
Author: Louis Burda <quent.burda@gmail.com>
Date:   Mon, 13 Mar 2023 22:02:56 +0100

Simplify by removing HANDLE_ERR and forwarding errno to caller

Diffstat:
MMakefile | 21+++++++--------------
Minclude/hashmap.h | 51+++++++--------------------------------------------
Mlibhashmap.lds | 2+-
Msrc/hashmap.c | 108++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/test.c | 16++++++++++------
5 files changed, 85 insertions(+), 113 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,19 +1,12 @@ PREFIX ?= /usr/local -INCLUDEDIR ?= /include +INCLDIR ?= /include LIBDIR ?= /lib -CFLAGS = -I include -Wno-prototype -Wunused-function -Wunused-variable +CFLAGS = -I include -Wno-prototype -Wunused-function +CFLAGS += -Wunused-variable -Wconversion -ifeq "$(LIBMAP_DEBUG)" "1" -CFLAGS += -g -endif - -ifeq "$(LIBMAP_ASSERT)" "1" -CFLAGS += -DLIBMAP_ASSERT_ENABLE=1 -endif - -ifeq "$(LIBMAP_HANDLE_ERR)" "1" -CFLAGS += -DLIBMAP_HANDLE_ERRS=1 +ifeq "$(DEBUG)" "1" +CFLAGS += -g -DLIBMAP_CHECK_ENABLE=1 endif all: build/libmap.so build/libmap.a build/test @@ -37,12 +30,12 @@ build/test: src/test.c build/libmap.a | build $(CC) -o $@ $^ -I include -g install: - install -m 644 include/hashmap.h -t "$(DESTDIR)$(PREFIX)$(INCLUDEDIR)" + install -m 644 include/hashmap.h -t "$(DESTDIR)$(PREFIX)$(INCLDIR)" install -m 755 build/libmap.a -t "$(DESTDIR)$(PREFIX)$(LIBDIR)" install -m 755 build/libmap.so -t "$(DESTDIR)$(PREFIX)$(LIBDIR)" uninstall: - rm -f "$(DESTDIR)$(PREFIX)$(INCLUDEDIR)/hashmap.h" + rm -f "$(DESTDIR)$(PREFIX)$(INCLDIR)/hashmap.h" rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/libmap.a" rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/libmap.so" diff --git a/include/hashmap.h b/include/hashmap.h @@ -4,45 +4,6 @@ #include <stdbool.h> #include <stdlib.h> -#ifdef LIBHASHMAP_ASSERT_ENABLE - -#include <stdio.h> - -#define LIBHASHMAP_ASSERT(x) libhashmap_assert((x), __FILE__, __LINE__, #x) - -static inline void libhashmap_assert(int cond, - const char *file, int line, const char *condstr) -{ - if (cond) return; - - fprintf(stderr, "libhashmap: Assertion failed at %s:%i (%s)\n", - file, line, condstr); - abort(); -} - -#else -#define LIBHASHMAP_ASSERT(x) -#endif - -#ifdef LIBHASHMAP_HANDLE_ERRS - -#include <errno.h> -#include <stdio.h> - -#define LIBHASHMAP_HANDLE_ERR(x) libhashmap_err(__FILE__, __LINE__, x) - -static inline void libhashmap_err(const char *file, int line, const char *info) -{ - fprintf(stderr, "libhashmap: %s at %s:%i: %s\n", - info, file, line, strerror(errno)); - exit(1); -} - -#else -#define LIBHASHMAP_HANDLE_ERR(x) -#endif - - #define HASHMAP_ITER(map, iter) \ hashmap_iter_init(iter); hashmap_iter_next(map, iter); @@ -67,20 +28,22 @@ struct hashmap { size_t size; }; -bool hashmap_init(struct hashmap *map, size_t size, map_hash_func hasher); +int hashmap_init(struct hashmap *map, size_t size, map_hash_func hasher); void hashmap_deinit(struct hashmap *map); -struct hashmap *hashmap_alloc(size_t size, map_hash_func hasher); +int hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher); void hashmap_free(struct hashmap *map); void hashmap_clear(struct hashmap *map); -struct hashmap_link *hashmap_get(struct hashmap *map, const void *key, size_t size); -struct hashmap_link *hashmap_pop(struct hashmap *map, const void *key, size_t size); +struct hashmap_link *hashmap_get(struct hashmap *map, + const void *key, size_t size); +struct hashmap_link *hashmap_pop(struct hashmap *map, + const void *key, size_t size); void hashmap_link_set(struct hashmap_link *link, void *key, size_t key_size, void *value, size_t value_size); -bool hashmap_set(struct hashmap *map, void *key, size_t key_size, +int hashmap_set(struct hashmap *map, void *key, size_t key_size, void *value, size_t value_size); void hashmap_iter_init(struct hashmap_iter *iter); diff --git a/libhashmap.lds b/libhashmap.lds @@ -1,4 +1,4 @@ -LIBHASHMAP_1.0 { +LIBHASHMAP_1.1 { hashmap_init; hashmap_deinit; diff --git a/src/hashmap.c b/src/hashmap.c @@ -1,13 +1,30 @@ #include "hashmap.h" +#include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +#ifdef LIBHASHMAP_CHECK_ENABLE +#define LIBHASHMAP_CHECK(x) libhashmap_assert((x), __FILE__, __LINE__, #x) +#else +#define LIBHASHMAP_CHECK(x) +#endif + static struct hashmap_link **hashmap_get_linkp(struct hashmap *map, const void *key, size_t size); -static struct hashmap_link *hashmap_link_alloc(void *key, size_t key_size, - void *value, size_t value_size); +static int hashmap_link_alloc(struct hashmap_link **link, + void *key, size_t key_size, void *value, size_t value_size); + +static inline void libhashmap_assert(int cond, + const char *file, int line, const char *condstr) +{ + if (cond) return; + + fprintf(stderr, "libhashmap: Assertion failed at %s:%i (%s)\n", + file, line, condstr); + abort(); +} static inline size_t hashmap_key_bucket(struct hashmap *map, const void *key, size_t size) @@ -26,7 +43,7 @@ hashmap_get_linkp(struct hashmap *map, const void *key, size_t size) { struct hashmap_link **iter, *link; - LIBHASHMAP_ASSERT(map != NULL && key != NULL && size != 0); + LIBHASHMAP_CHECK(map != NULL && key != NULL && size != 0); iter = &map->buckets[hashmap_key_bucket(map, key, size)]; while (*iter != NULL) { @@ -39,69 +56,63 @@ hashmap_get_linkp(struct hashmap *map, const void *key, size_t size) return NULL; } -struct hashmap_link * -hashmap_link_alloc(void *key, size_t key_size, void *value, size_t value_size) +int +hashmap_link_alloc(struct hashmap_link **out, void *key, size_t key_size, + void *value, size_t value_size) { struct hashmap_link *link; - LIBHASHMAP_ASSERT(key != NULL && value != NULL); + LIBHASHMAP_CHECK(key != NULL && value != NULL); link = malloc(sizeof(struct hashmap_link)); - if (!link) { - LIBHASHMAP_HANDLE_ERR("malloc"); - return NULL; - } + if (!link) return -errno; link->key = key; link->key_size = key_size; link->value = value; link->value_size = value_size; link->next = NULL; + *out = link; - return link; + return 0; } -bool +int hashmap_init(struct hashmap *map, size_t size, map_hash_func hasher) { - LIBHASHMAP_ASSERT(map != NULL && size != 0 && hasher != NULL); + LIBHASHMAP_CHECK(map != NULL && size != 0 && hasher != NULL); map->buckets = calloc(size, sizeof(struct hashmap_link *)); - if (!map->buckets) { - LIBHASHMAP_HANDLE_ERR("calloc"); - return false; - } + if (!map->buckets) return -errno; map->size = size; map->hash = hasher; - return true; + return 0; } void hashmap_deinit(struct hashmap *map) { - LIBHASHMAP_ASSERT(map != NULL); + LIBHASHMAP_CHECK(map != NULL); hashmap_clear(map); free(map->buckets); } -struct hashmap * -hashmap_alloc(size_t size, map_hash_func hasher) +int +hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher) { - struct hashmap *map; + int rc; - map = malloc(sizeof(struct hashmap)); - if (!map) { - LIBHASHMAP_HANDLE_ERR("malloc"); - return NULL; - } + *map = malloc(sizeof(struct hashmap)); + if (!*map) return -errno; - if (!hashmap_init(map, size, hasher)) { - free(map); - return NULL; + rc = hashmap_init(*map, size, hasher); + if (rc) { + free(*map); + return rc; } - return map; + return 0; } void @@ -116,9 +127,9 @@ hashmap_clear(struct hashmap *map) { struct hashmap_iter iter; struct hashmap_link *prev; - int i; + size_t i; - LIBHASHMAP_ASSERT(map != NULL); + LIBHASHMAP_CHECK(map != NULL); prev = NULL; for (HASHMAP_ITER(map, &iter)) { @@ -138,7 +149,7 @@ hashmap_get(struct hashmap *map, const void *key, size_t size) { struct hashmap_link **iter; - LIBHASHMAP_ASSERT(map != NULL); + LIBHASHMAP_CHECK(map != NULL); iter = hashmap_get_linkp(map, key, size); @@ -150,7 +161,7 @@ hashmap_pop(struct hashmap *map, const void *key, size_t size) { struct hashmap_link **iter; - LIBHASHMAP_ASSERT(map != NULL); + LIBHASHMAP_CHECK(map != NULL); iter = hashmap_get_linkp(map, key, size); if (iter) { @@ -165,7 +176,7 @@ void hashmap_link_set(struct hashmap_link *link, void *key, size_t key_size, void *value, size_t value_size) { - LIBHASHMAP_ASSERT(link != NULL); + LIBHASHMAP_CHECK(link != NULL); free(link->key); link->key = key; @@ -176,13 +187,14 @@ hashmap_link_set(struct hashmap_link *link, void *key, size_t key_size, link->value_size = value_size; } -bool +int hashmap_set(struct hashmap *map, void *key, size_t key_size, void *value, size_t value_size) { struct hashmap_link **iter; + int rc; - LIBHASHMAP_ASSERT(map != NULL); + LIBHASHMAP_CHECK(map != NULL); iter = hashmap_get_linkp(map, key, key_size); if (iter == NULL) { @@ -193,17 +205,17 @@ hashmap_set(struct hashmap *map, void *key, size_t key_size, if (*iter) { hashmap_link_set(*iter, key, key_size, value, value_size); } else { - *iter = hashmap_link_alloc(key, key_size, value, value_size); - if (!*iter) return false; + rc = hashmap_link_alloc(iter, key, key_size, value, value_size); + if (rc) return rc; } - return true; + return 0; } void hashmap_iter_init(struct hashmap_iter *iter) { - LIBHASHMAP_ASSERT(iter != NULL); + LIBHASHMAP_CHECK(iter != NULL); iter->bucket = 0; iter->link = NULL; @@ -212,9 +224,9 @@ hashmap_iter_init(struct hashmap_iter *iter) bool hashmap_iter_next(struct hashmap *map, struct hashmap_iter *iter) { - int i; + size_t i; - LIBHASHMAP_ASSERT(map != NULL && iter != NULL); + LIBHASHMAP_CHECK(map != NULL && iter != NULL); if (iter->link && iter->link->next) { iter->link = iter->link->next; @@ -239,13 +251,13 @@ uint32_t hashmap_str_hasher(const void *data, size_t size) { uint32_t hash; - int i; + size_t i; - LIBHASHMAP_ASSERT(data != NULL && size > 0); + LIBHASHMAP_CHECK(data != NULL && size > 0); - hash = 0; + hash = 5381; for (i = 0; i < size; i++) - hash = 31 * hash + ((uint8_t *) data)[i]; + hash = 33 * hash + ((uint8_t *) data)[i]; return hash; } diff --git a/src/test.c b/src/test.c @@ -1,8 +1,11 @@ #include "hashmap.h" -#include <stdlib.h> +#include <err.h> #include <stdio.h> #include <string.h> +#include <stdlib.h> + +#define LIBHASHMAP_ERR(rc) errx(1, "libhashmap: %s", rc < 0 ? strerror(-rc) : "???") int main(int argc, const char **argv) @@ -10,21 +13,22 @@ main(int argc, const char **argv) struct hashmap hashmap; struct hashmap_iter iter; void *key, *value; - int i; + int i, rc; - hashmap_init(&hashmap, 10, hashmap_str_hasher); + rc = hashmap_init(&hashmap, 10, hashmap_str_hasher); + if (rc) LIBHASHMAP_ERR(rc); for (i = 1; i < argc; i++) { key = strdup(argv[i]); value = malloc(sizeof(int)); memcpy(value, &i, sizeof(int)); - hashmap_set(&hashmap, key, strlen(key) + 1, + rc = hashmap_set(&hashmap, key, strlen(key) + 1, value, sizeof(int)); + if (rc) LIBHASHMAP_ERR(rc); } - for (HASHMAP_ITER(&hashmap, &iter)) { + for (HASHMAP_ITER(&hashmap, &iter)) printf("%s: %i\n", iter.link->key, *(int*)iter.link->value); - } hashmap_deinit(&hashmap); }