/************************************************************************* * Copyright (c) 2020 Wirtos * * This library is free software; you can redistribute it and/or modify it * under the terms of the MIT license. See LICENSE for details. */ #ifndef CMAP_H #define CMAP_H #include <stddef.h> /* size_t, NULL */ #define MAP_VER_MAJOR 2 #define MAP_VER_MINOR 5 #define MAP_VER_PATCH 0 typedef size_t (*MapHashFunction)(const void *key, size_t memsize); typedef int (*MapCmpFunction)(const void *a, const void *b, size_t memsize); struct map_node_t; typedef struct { MapHashFunction hash_func; MapCmpFunction cmp_func; size_t nbuckets, nnodes; struct map_node_t **buckets; } map_base_t; typedef struct { size_t bucketidx; struct map_node_t *node; } map_iter_t; #define map_pair_t(KT, VT) \ struct { \ KT k; \ VT v; \ } #define map_t(KT, VT) \ struct { \ map_base_t base; \ KT tmpkey; \ VT tmpval; \ KT *keyref; \ VT *valref; \ } #define map_init(m, key_cmp_func, key_hash_func) \ (void)( \ (m)->base.nbuckets = 0, \ (m)->base.nnodes = 0, \ (m)->base.buckets = NULL, \ (m)->base.cmp_func = (key_cmp_func != NULL) ? key_cmp_func : map_generic_cmp, \ (m)->base.hash_func = (key_hash_func != NULL) ? key_hash_func : map_generic_hash\ ) #define map_stdinit(m) map_init(m, NULL, NULL) #define map_delete(m)\ (map_delete_(&(m)->base), map_init(m, (m)->base.cmp_func, (m)->base.hash_func)) #define map_get(m, key) \ ((m)->tmpkey = key, \ (m)->valref = map_get_(&(m)->base, &(m)->tmpkey, sizeof((m)->tmpkey))) #define map_set(m, key, value) \ ( \ (m)->tmpval = (value), (m)->tmpkey = (key), \ map_set_(&(m)->base, \ &(m)->tmpkey, sizeof((m)->tmpkey), \ map_boffset_(&(m)->tmpkey, &(m)->base.buckets), \ &(m)->tmpval, sizeof((m)->tmpval), \ map_boffset_(&(m)->tmpval, &(m)->base.buckets)) \ ) #define map_remove(m, key) \ ((m)->tmpkey = (key), \ map_remove_(&(m)->base, &(m)->tmpkey, sizeof((m)->tmpkey))) #define map_iter(m) \ map_iter_() #define map_next(m, iter, kptr) \ ((m)->keyref = map_next_(&(m)->base, iter), \ ((m)->keyref) \ ? ((*kptr = *(m)->keyref), 1) \ : 0 \ ) #define map_equal(m1, m2, val_cmp_func) \ ( \ map_sametype_(&(m1)->tmpkey, &(m2)->tmpkey), \ map_sametype_(&(m1)->tmpval, &(m2)->tmpval), \ map_equal_(&(m1)->base, &(m2)->base, \ sizeof((m2)->tmpkey), sizeof((m2)->tmpval), \ (val_cmp_func) ) \ ) #define map_from_pairs(m, count, pairs) \ ( \ ((count) > 0) \ ? ( \ map_sametype_(&(m)->tmpkey, &(pairs)->k), \ map_sametype_(&(m)->tmpval, &(pairs)->v), \ map_from_pairs_(&(m)->base, \ (count), \ sizeof(*pairs), \ &(pairs)->k, \ sizeof((m)->tmpkey), \ map_boffset_(&(m)->tmpkey, &(m)->base.buckets), \ &(pairs)->v, \ sizeof((m)->tmpval), \ map_boffset_(&(m)->tmpval, &(m)->base.buckets) ) \ ) \ : 1 \ ) /* copy from m2 into m1 */ #define map_copy(m1, m2) \ ( \ map_sametype_(&(m1)->tmpkey, &(m2)->tmpkey), \ map_sametype_(&(m1)->tmpval, &(m2)->tmpval), \ map_copy_(&(m1)->base, &(m2)->base, \ sizeof((m1)->tmpkey), \ map_boffset_(&(m1)->tmpkey, &(m1)->base.buckets), \ sizeof((m1)->tmpval), \ map_boffset_(&(m2)->tmpval, &(m2)->base.buckets)) \ ) size_t map_generic_hash(const void *mem, size_t memsize); size_t map_string_hash(const void *mem, size_t memsize); int map_generic_cmp(const void *a, const void *b, size_t memsize); int map_string_cmp(const void *a, const void *b, size_t memsize); /* "private" functions */ void map_delete_(map_base_t *); void *map_get_(map_base_t *, const void *, size_t); int map_set_(map_base_t *, const void *, size_t, size_t, const void *, size_t, size_t); void map_remove_(map_base_t *, const void *, size_t); map_iter_t map_iter_(void); void *map_next_(map_base_t *, map_iter_t *); int map_equal_(map_base_t *, map_base_t *, size_t, size_t, MapCmpFunction); int map_from_pairs_(map_base_t *, size_t, size_t, const void *, size_t, size_t, const void *, size_t, size_t); int map_copy_(map_base_t *, map_base_t *, size_t, size_t, size_t, size_t); #define map_boffset_(a, b) ((const char *)(a) - (const char *)(b)) #define map_sametype_(a, b) ((void)((1) ? (a) : (b))) /*typedef map_t(void *) map_void_t; typedef map_t(char *) map_str_t; typedef map_t(int) map_int_t; typedef map_t(char) map_char_t; typedef map_t(float) map_float_t; typedef map_t(double) map_double_t;*/ #endif /* CMAP_H */