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:
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);
}