libhmap-c

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

commit 2cc02a318e3c42e536715e1af1213f25a2440da2
parent e4746507ef06d7380d113c3fea7303c7bc891049
Author: Louis Burda <quent.burda@gmail.com>
Date:   Fri, 17 Mar 2023 19:27:20 +0100

Use liballoc for allocations

Diffstat:
A.gitmodules | 3+++
MMakefile | 9++++++---
Minclude/hashmap.h | 14++++++++++----
Alib/liballoc | 1+
Msrc/hashmap.c | 78++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/test.c | 8+++++---
6 files changed, 67 insertions(+), 46 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/liballoc"] + path = lib/liballoc + url = git@sinitax.com:snx/liballoc diff --git a/Makefile b/Makefile @@ -2,7 +2,7 @@ PREFIX ?= /usr/local INCLDIR ?= /include LIBDIR ?= /lib -CFLAGS = -I include -Wno-prototype -Wunused-function +CFLAGS = -I include -I lib/liballoc/include -Wno-prototype -Wunused-function CFLAGS += -Wunused-variable -Wconversion ifeq "$(DEBUG)" "1" @@ -17,6 +17,9 @@ clean: build: mkdir build +lib/liballoc/build/liballoc.a: + make -C lib/liballoc build/liballoc.a + build/libhashmap.a: src/hashmap.c include/hashmap.h | build $(CC) -o build/tmp.o src/hashmap.c $(CFLAGS) -r objcopy --keep-global-symbols=libhashmap.api build/tmp.o build/fixed.o @@ -26,8 +29,8 @@ build/libhashmap.so: src/hashmap.c include/hashmap.h | build $(CC) -o $@ src/hashmap.c -fPIC $(CFLAGS) -shared \ -Wl,-version-script libhashmap.lds -build/test: src/test.c build/libhashmap.a | build - $(CC) -o $@ $^ -I include -g +build/test: src/test.c build/libhashmap.a lib/liballoc/build/liballoc.a | build + $(CC) -o $@ $^ -I include -I lib/liballoc/include -g install: install -m 644 include/hashmap.h -t "$(DESTDIR)$(PREFIX)$(INCLDIR)" diff --git a/include/hashmap.h b/include/hashmap.h @@ -1,8 +1,10 @@ #pragma once +#include "allocator.h" + #include <stdint.h> #include <stdbool.h> -#include <stdlib.h> +#include <stddef.h> #define HASHMAP_ITER(map, iter) \ hashmap_iter_init(iter); hashmap_iter_next(map, iter); @@ -26,12 +28,15 @@ struct hashmap { map_hash_func hash; struct hashmap_link **buckets; size_t size; + const struct allocator *allocator; }; -int 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, + const struct allocator *allocator); void hashmap_deinit(struct hashmap *map); -int hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher); +int hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher, + const struct allocator *allocator); void hashmap_free(struct hashmap *map); void hashmap_clear(struct hashmap *map); @@ -41,7 +46,8 @@ struct hashmap_link *hashmap_get(struct hashmap *map, 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 hashmap_link_set(struct hashmap *map, + struct hashmap_link *link, void *key, size_t key_size, void *value, size_t value_size); int hashmap_set(struct hashmap *map, void *key, size_t key_size, void *value, size_t value_size); diff --git a/lib/liballoc b/lib/liballoc @@ -0,0 +1 @@ +Subproject commit 322bdbc251ccb21e967c75ee1b88ce152fc99982 diff --git a/src/hashmap.c b/src/hashmap.c @@ -1,25 +1,13 @@ #include "hashmap.h" #include <errno.h> -#include <stdlib.h> -#include <stdio.h> #include <string.h> static struct hashmap_link **hashmap_get_linkp(struct hashmap *map, const void *key, size_t size); -static int hashmap_link_alloc(struct hashmap_link **link, +static int hashmap_link_alloc(struct hashmap *map, 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) { @@ -49,13 +37,14 @@ hashmap_get_linkp(struct hashmap *map, const void *key, size_t size) } int -hashmap_link_alloc(struct hashmap_link **out, void *key, size_t key_size, - void *value, size_t value_size) +hashmap_link_alloc(struct hashmap *map, struct hashmap_link **out, + void *key, size_t key_size, void *value, size_t value_size) { struct hashmap_link *link; + int rc; - link = malloc(sizeof(struct hashmap_link)); - if (!link) return -errno; + rc = map->allocator->alloc((void **)&link, sizeof(struct hashmap_link)); + if (rc) return -rc; link->key = key; link->key_size = key_size; link->value = value; @@ -67,13 +56,20 @@ hashmap_link_alloc(struct hashmap_link **out, void *key, size_t key_size, } int -hashmap_init(struct hashmap *map, size_t size, map_hash_func hasher) +hashmap_init(struct hashmap *map, size_t size, map_hash_func hasher, + const struct allocator *allocator) { - map->buckets = calloc(size, sizeof(struct hashmap_link *)); - if (!map->buckets) return -errno; + int rc; + + map->allocator = allocator; map->size = size; map->hash = hasher; + rc = map->allocator->alloc((void **)&map->buckets, + sizeof(void *) * size); + if (rc) return -rc; + memset(map->buckets, 0, size * sizeof(void *)); + return 0; } @@ -81,20 +77,21 @@ void hashmap_deinit(struct hashmap *map) { hashmap_clear(map); - free(map->buckets); + map->allocator->free(map->buckets); } int -hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher) +hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher, + const struct allocator *allocator) { int rc; - *map = malloc(sizeof(struct hashmap)); - if (!*map) return -errno; + rc = allocator->alloc((void **)map, sizeof(struct hashmap)); + if (rc) return -rc; - rc = hashmap_init(*map, size, hasher); + rc = hashmap_init(*map, size, hasher, allocator); if (rc) { - free(*map); + allocator->free(*map); return rc; } @@ -104,21 +101,28 @@ hashmap_alloc(struct hashmap **map, size_t size, map_hash_func hasher) void hashmap_free(struct hashmap *map) { + const struct allocator *allocator; + + allocator = map->allocator; hashmap_deinit(map); - free(map); + allocator->free(map); } void hashmap_clear(struct hashmap *map) { struct hashmap_iter iter; + struct hashmap_link *prev; size_t i; + prev = NULL; for (HASHMAP_ITER(map, &iter)) { - free(iter.link->key); - free(iter.link->value); - free(iter.link); + free(prev); + map->allocator->free(iter.link->key); + map->allocator->free(iter.link->value); + prev = iter.link; } + free(prev); for (i = 0; i < map->size; i++) map->buckets[i] = NULL; @@ -149,14 +153,14 @@ 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) +hashmap_link_set(struct hashmap *map, struct hashmap_link *link, + void *key, size_t key_size, void *value, size_t value_size) { - free(link->key); + map->allocator->free(link->key); link->key = key; link->key_size = key_size; - free(link->value); + map->allocator->free(link->value); link->value = value; link->value_size = value_size; } @@ -175,9 +179,11 @@ hashmap_set(struct hashmap *map, void *key, size_t key_size, } if (*iter) { - hashmap_link_set(*iter, key, key_size, value, value_size); + hashmap_link_set(map, *iter, + key, key_size, value, value_size); } else { - rc = hashmap_link_alloc(iter, key, key_size, value, value_size); + rc = hashmap_link_alloc(map, iter, + key, key_size, value, value_size); if (rc) return rc; } diff --git a/src/test.c b/src/test.c @@ -15,7 +15,7 @@ main(int argc, const char **argv) void *key, *value; int i, rc; - rc = hashmap_init(&hashmap, 10, hashmap_str_hasher); + rc = hashmap_init(&hashmap, 10, hashmap_str_hasher, &stdlib_heap_allocator); if (rc) LIBHASHMAP_ERR(rc); for (i = 1; i < argc; i++) { @@ -27,8 +27,10 @@ main(int argc, const char **argv) if (rc) LIBHASHMAP_ERR(rc); } - for (HASHMAP_ITER(&hashmap, &iter)) - printf("%s: %i\n", iter.link->key, *(int*)iter.link->value); + for (HASHMAP_ITER(&hashmap, &iter)) { + printf("%s: %i\n", (char *)iter.link->key, + *(int*)iter.link->value); + } hashmap_deinit(&hashmap); }