From c41ce371d39834c563c932afe255960a99dc5e1d Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 5 May 2020 18:00:56 -0300 Subject: [PATCH] Renamed multimap to hashmultimap --- autogen.py | 4 +- src/cmc/{multimap.h => hashmultimap.h} | 81 +-- tests/main/main.c | 8 +- tests/main/src/{multimap.c => hashmultimap.c} | 510 +++++++++--------- tests/main/unt/hashmultimap.c | 486 +++++++++++++++++ tests/main/unt/multimap.c | 486 ----------------- 6 files changed, 794 insertions(+), 781 deletions(-) rename src/cmc/{multimap.h => hashmultimap.h} (97%) rename tests/main/src/{multimap.c => hashmultimap.c} (55%) create mode 100644 tests/main/unt/hashmultimap.c delete mode 100644 tests/main/unt/multimap.c diff --git a/autogen.py b/autogen.py index db4a10a..c2ce318 100644 --- a/autogen.py +++ b/autogen.py @@ -25,16 +25,16 @@ OUTPUT_DIR = './tests/main/src' collections = [ # type, header, pfx, sname, key, val - {'t': 'HASHBIDIMAP', 'h': '"cmc/hashbidimap.h"', 'pfx': 'hbm', 'sname': 'hashbidimap', 'key': 'size_t', 'val': 'size_t'}, {'t': 'BITSET', 'h': '"cmc/bitset.h"', 'pfx': 'bs', 'sname': 'bitset', 'key': '', 'val': '' }, {'t': 'DEQUE', 'h': '"cmc/deque.h"', 'pfx': 'd', 'sname': 'deque', 'key': '', 'val': 'size_t'}, + {'t': 'HASHBIDIMAP', 'h': '"cmc/hashbidimap.h"', 'pfx': 'hbm', 'sname': 'hashbidimap', 'key': 'size_t', 'val': 'size_t'}, {'t': 'HASHMAP', 'h': '"cmc/hashmap.h"', 'pfx': 'hm', 'sname': 'hashmap', 'key': 'size_t', 'val': 'size_t'}, + {'t': 'HASHMULTIMAP', 'h': '"cmc/hashmultimap.h"', 'pfx': 'hmm', 'sname': 'hashmultimap', 'key': 'size_t', 'val': 'size_t'}, {'t': 'HASHSET', 'h': '"cmc/hashset.h"', 'pfx': 'hs', 'sname': 'hashset', 'key': '', 'val': 'size_t'}, {'t': 'HEAP', 'h': '"cmc/heap.h"', 'pfx': 'h', 'sname': 'heap', 'key': '', 'val': 'size_t'}, {'t': 'INTERVALHEAP', 'h': '"cmc/intervalheap.h"', 'pfx': 'ih', 'sname': 'intervalheap', 'key': '', 'val': 'size_t'}, {'t': 'LINKEDLIST', 'h': '"cmc/linkedlist.h"', 'pfx': 'll', 'sname': 'linkedlist', 'key': '', 'val': 'size_t'}, {'t': 'LIST', 'h': '"cmc/list.h"', 'pfx': 'l', 'sname': 'list', 'key': '', 'val': 'size_t'}, - {'t': 'MULTIMAP', 'h': '"cmc/multimap.h"', 'pfx': 'mm', 'sname': 'multimap', 'key': 'size_t', 'val': 'size_t'}, {'t': 'MULTISET', 'h': '"cmc/multiset.h"', 'pfx': 'ms', 'sname': 'multiset', 'key': '', 'val': 'size_t'}, {'t': 'QUEUE', 'h': '"cmc/queue.h"', 'pfx': 'q', 'sname': 'queue', 'key': '', 'val': 'size_t'}, {'t': 'SORTEDLIST', 'h': '"cmc/sortedlist.h"', 'pfx': 'sl', 'sname': 'sortedlist', 'key': '', 'val': 'size_t'}, diff --git a/src/cmc/multimap.h b/src/cmc/hashmultimap.h similarity index 97% rename from src/cmc/multimap.h rename to src/cmc/hashmultimap.h index 9a73f93..e5adf9a 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/hashmultimap.h @@ -1,5 +1,5 @@ /** - * multimap.h + * hashmultimap.h * * Creation Date: 26/04/2019 * @@ -9,19 +9,20 @@ */ /** - * MultiMap + * HashMultiMap * - * The MultiMap is a Map that allows for multiple keys. This is a data structure - * that has a very narrow usage. A Map (either TreeMap or HashMap) can also work - * like a MultiMap if a certain key is mapped to another collection. + * The HashMultiMap is a Map that allows for multiple keys. This is a data + * structure that has a very narrow usage. A Map (either TreeMap or HashMap) can + * also work like a HashMultiMap if a certain key is mapped to another + * collection. * * Map> maps an integer to a list of integer. - * MultiMap maps many integer keys to integer values. + * HashMultiMap maps many integer keys to integer values. * - * The difference is that in a MultiMap you can store keys that are the same but - * might be different instances of the same value. This is also relevant if your - * data type is more complex like a struct where its ID is the same but some - * other members of this data type are different. + * The difference is that in a HashMultiMap you can store keys that are the same + * but might be different instances of the same value. This is also relevant if + * your data type is more complex like a struct where its ID is the same but + * some other members of this data type are different. * * Implementation * @@ -40,8 +41,8 @@ * the first key added will be the first to be removed. */ -#ifndef CMC_MULTIMAP_H -#define CMC_MULTIMAP_H +#ifndef CMC_HASHMULTIMAP_H +#define CMC_HASHMULTIMAP_H /* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library @@ -54,37 +55,37 @@ #include "../cor/hashtable.h" /* ------------------------------------------------------------------------- - * MultiMap specific + * HashMultiMap specific * ------------------------------------------------------------------------- */ /* to_string format */ -static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_key:%p, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }"; +static const char *cmc_string_fmt_hashmultimap = "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }"; -#define CMC_GENERATE_MULTIMAP(PFX, SNAME, K, V) \ - CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ - CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) +#define CMC_GENERATE_HASHMULTIMAP(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMULTIMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMULTIMAP_SOURCE(PFX, SNAME, K, V) -#define CMC_WRAPGEN_MULTIMAP_HEADER(PFX, SNAME, K, V) \ - CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) +#define CMC_WRAPGEN_HASHMULTIMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMULTIMAP_HEADER(PFX, SNAME, K, V) -#define CMC_WRAPGEN_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ - CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) +#define CMC_WRAPGEN_HASHMULTIMAP_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMULTIMAP_SOURCE(PFX, SNAME, K, V) /* ------------------------------------------------------------------------- * Header * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ +#define CMC_GENERATE_HASHMULTIMAP_HEADER(PFX, SNAME, K, V) \ \ - /* Multimap Structure */ \ + /* HashMultimap Structure */ \ struct SNAME \ { \ /* Array of linked list to entries */ \ @@ -114,14 +115,14 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " /* Custom callback functions */ \ struct cmc_callbacks *callbacks; \ \ - /* Function that returns an iterator to the start of the multimap */ \ + /* Returns an iterator to the start of the hashmultimap */ \ struct SNAME##_iter (*it_start)(struct SNAME *); \ \ - /* Function that returns an iterator to the end of the multimap */ \ + /* Returns an iterator to the end of the hashmultimap */ \ struct SNAME##_iter (*it_end)(struct SNAME *); \ }; \ \ - /* Multimap Entry */ \ + /* HashMultimap Entry */ \ struct SNAME##_entry \ { \ /* Entry Key */ \ @@ -183,7 +184,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ struct SNAME##_iter \ { \ - /* Target multimap */ \ + /* Target hashmultimap */ \ struct SNAME *target; \ \ /* Current entry */ \ @@ -276,7 +277,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " /* ------------------------------------------------------------------------- * Source * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ +#define CMC_GENERATE_HASHMULTIMAP_SOURCE(PFX, SNAME, K, V) \ \ /* Implementation Detail Functions */ \ struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, \ @@ -1112,7 +1113,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " struct cmc_string str; \ struct SNAME *m_ = _map_; \ \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmultimap, \ #SNAME, #K, #V, m_, m_->buffer, m_->capacity, \ m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, \ m_->alloc, m_->callbacks); \ @@ -1468,4 +1469,4 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " return iter; \ } -#endif /* CMC_MULTIMAP_H */ +#endif /* CMC_HASHMULTIMAP_H */ diff --git a/tests/main/main.c b/tests/main/main.c index ea60aa5..ad5422e 100644 --- a/tests/main/main.c +++ b/tests/main/main.c @@ -1,15 +1,15 @@ #include "utl/timer.h" -#include "unt/hashbidimap.c" #include "unt/bitset.c" #include "unt/deque.c" +#include "unt/hashbidimap.c" #include "unt/hashmap.c" +#include "unt/hashmultimap.c" #include "unt/hashset.c" #include "unt/heap.c" #include "unt/intervalheap.c" #include "unt/linkedlist.c" #include "unt/list.c" -#include "unt/multimap.c" #include "unt/multiset.c" #include "unt/queue.c" #include "unt/sortedlist.c" @@ -50,16 +50,16 @@ int main(void) cmc_run(BitSet, units, tests); cmc_run(BitSetIter, units, tests); cmc_run(Deque, units, tests); - cmc_run(HashBidiMap, units, tests); cmc_run(DequeIter, units, tests); + cmc_run(HashBidiMap, units, tests); cmc_run(HashMap, units, tests); cmc_run(HashMapIter, units, tests); + cmc_run(HashMultiMap, units, tests); cmc_run(HashSet, units, tests); cmc_run(Heap, units, tests); cmc_run(IntervalHeap, units, tests); cmc_run(LinkedList, units, tests); cmc_run(List, units, tests); - cmc_run(MultiMap, units, tests); cmc_run(MultiSet, units, tests); cmc_run(Queue, units, tests); cmc_run(SortedList, units, tests); diff --git a/tests/main/src/multimap.c b/tests/main/src/hashmultimap.c similarity index 55% rename from tests/main/src/multimap.c rename to tests/main/src/hashmultimap.c index 2238cf6..2257cab 100644 --- a/tests/main/src/multimap.c +++ b/tests/main/src/hashmultimap.c @@ -1,27 +1,27 @@ -#include "cmc/multimap.h" +#include "cmc/hashmultimap.h" -struct multimap +struct hashmultimap { - struct multimap_entry *(*buffer)[2]; + struct hashmultimap_entry *(*buffer)[2]; size_t capacity; size_t count; double load; int flag; - struct multimap_fkey *f_key; - struct multimap_fval *f_val; + struct hashmultimap_fkey *f_key; + struct hashmultimap_fval *f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; - struct multimap_iter (*it_start)(struct multimap *); - struct multimap_iter (*it_end)(struct multimap *); + struct hashmultimap_iter (*it_start)(struct hashmultimap *); + struct hashmultimap_iter (*it_end)(struct hashmultimap *); }; -struct multimap_entry +struct hashmultimap_entry { size_t key; size_t value; - struct multimap_entry *next; - struct multimap_entry *prev; + struct hashmultimap_entry *next; + struct hashmultimap_entry *prev; }; -struct multimap_fkey +struct hashmultimap_fkey { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); @@ -30,7 +30,7 @@ struct multimap_fkey size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; -struct multimap_fval +struct hashmultimap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); @@ -39,10 +39,10 @@ struct multimap_fval size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; -struct multimap_iter +struct hashmultimap_iter { - struct multimap *target; - struct multimap_entry *curr_entry; + struct hashmultimap *target; + struct hashmultimap_entry *curr_entry; size_t cursor; size_t index; size_t first; @@ -50,68 +50,70 @@ struct multimap_iter _Bool start; _Bool end; }; -struct multimap *mm_new(size_t capacity, double load, - struct multimap_fkey *f_key, - struct multimap_fval *f_val); -struct multimap *mm_new_custom(size_t capacity, double load, - struct multimap_fkey *f_key, - struct multimap_fval *f_val, - struct cmc_alloc_node *alloc, - struct cmc_callbacks *callbacks); -void mm_clear(struct multimap *_map_); -void mm_free(struct multimap *_map_); -void mm_customize(struct multimap *_map_, struct cmc_alloc_node *alloc, - struct cmc_callbacks *callbacks); -_Bool mm_insert(struct multimap *_map_, size_t key, size_t value); -_Bool mm_update(struct multimap *_map_, size_t key, size_t new_value, - size_t *old_value); -size_t mm_update_all(struct multimap *_map_, size_t key, size_t new_value, - size_t **old_values); -_Bool mm_remove(struct multimap *_map_, size_t key, size_t *out_value); -size_t mm_remove_all(struct multimap *_map_, size_t key, size_t **out_values); -_Bool mm_max(struct multimap *_map_, size_t *key, size_t *value); -_Bool mm_min(struct multimap *_map_, size_t *key, size_t *value); -size_t mm_get(struct multimap *_map_, size_t key); -size_t *mm_get_ref(struct multimap *_map_, size_t key); -_Bool mm_contains(struct multimap *_map_, size_t key); -_Bool mm_empty(struct multimap *_map_); -_Bool mm_full(struct multimap *_map_); -size_t mm_count(struct multimap *_map_); -size_t mm_key_count(struct multimap *_map_, size_t key); -size_t mm_capacity(struct multimap *_map_); -double mm_load(struct multimap *_map_); -int mm_flag(struct multimap *_map_); -_Bool mm_resize(struct multimap *_map_, size_t capacity); -struct multimap *mm_copy_of(struct multimap *_map_); -_Bool mm_equals(struct multimap *_map1_, struct multimap *_map2_); -struct cmc_string mm_to_string(struct multimap *_map_); -_Bool mm_print(struct multimap *_map_, FILE *fptr); -struct multimap_iter *mm_iter_new(struct multimap *target); -void mm_iter_free(struct multimap_iter *iter); -void mm_iter_init(struct multimap_iter *iter, struct multimap *target); -_Bool mm_iter_start(struct multimap_iter *iter); -_Bool mm_iter_end(struct multimap_iter *iter); -void mm_iter_to_start(struct multimap_iter *iter); -void mm_iter_to_end(struct multimap_iter *iter); -_Bool mm_iter_next(struct multimap_iter *iter); -_Bool mm_iter_prev(struct multimap_iter *iter); -_Bool mm_iter_advance(struct multimap_iter *iter, size_t steps); -_Bool mm_iter_rewind(struct multimap_iter *iter, size_t steps); -_Bool mm_iter_go_to(struct multimap_iter *iter, size_t index); -size_t mm_iter_key(struct multimap_iter *iter); -size_t mm_iter_value(struct multimap_iter *iter); -size_t *mm_iter_rvalue(struct multimap_iter *iter); -size_t mm_iter_index(struct multimap_iter *iter); -struct multimap_entry *mm_impl_new_entry(struct multimap *_map_, size_t key, - size_t value); -struct multimap_entry *mm_impl_get_entry(struct multimap *_map_, size_t key); -size_t mm_impl_key_count(struct multimap *_map_, size_t key); -size_t mm_impl_calculate_size(size_t required); -static struct multimap_iter mm_impl_it_start(struct multimap *_map_); -static struct multimap_iter mm_impl_it_end(struct multimap *_map_); -struct multimap *mm_new(size_t capacity, double load, - struct multimap_fkey *f_key, - struct multimap_fval *f_val) +struct hashmultimap *hmm_new(size_t capacity, double load, + struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val); +struct hashmultimap *hmm_new_custom(size_t capacity, double load, + struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val, + struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void hmm_clear(struct hashmultimap *_map_); +void hmm_free(struct hashmultimap *_map_); +void hmm_customize(struct hashmultimap *_map_, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +_Bool hmm_insert(struct hashmultimap *_map_, size_t key, size_t value); +_Bool hmm_update(struct hashmultimap *_map_, size_t key, size_t new_value, + size_t *old_value); +size_t hmm_update_all(struct hashmultimap *_map_, size_t key, size_t new_value, + size_t **old_values); +_Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value); +size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, + size_t **out_values); +_Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value); +_Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value); +size_t hmm_get(struct hashmultimap *_map_, size_t key); +size_t *hmm_get_ref(struct hashmultimap *_map_, size_t key); +_Bool hmm_contains(struct hashmultimap *_map_, size_t key); +_Bool hmm_empty(struct hashmultimap *_map_); +_Bool hmm_full(struct hashmultimap *_map_); +size_t hmm_count(struct hashmultimap *_map_); +size_t hmm_key_count(struct hashmultimap *_map_, size_t key); +size_t hmm_capacity(struct hashmultimap *_map_); +double hmm_load(struct hashmultimap *_map_); +int hmm_flag(struct hashmultimap *_map_); +_Bool hmm_resize(struct hashmultimap *_map_, size_t capacity); +struct hashmultimap *hmm_copy_of(struct hashmultimap *_map_); +_Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_); +struct cmc_string hmm_to_string(struct hashmultimap *_map_); +_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr); +struct hashmultimap_iter *hmm_iter_new(struct hashmultimap *target); +void hmm_iter_free(struct hashmultimap_iter *iter); +void hmm_iter_init(struct hashmultimap_iter *iter, struct hashmultimap *target); +_Bool hmm_iter_start(struct hashmultimap_iter *iter); +_Bool hmm_iter_end(struct hashmultimap_iter *iter); +void hmm_iter_to_start(struct hashmultimap_iter *iter); +void hmm_iter_to_end(struct hashmultimap_iter *iter); +_Bool hmm_iter_next(struct hashmultimap_iter *iter); +_Bool hmm_iter_prev(struct hashmultimap_iter *iter); +_Bool hmm_iter_advance(struct hashmultimap_iter *iter, size_t steps); +_Bool hmm_iter_rewind(struct hashmultimap_iter *iter, size_t steps); +_Bool hmm_iter_go_to(struct hashmultimap_iter *iter, size_t index); +size_t hmm_iter_key(struct hashmultimap_iter *iter); +size_t hmm_iter_value(struct hashmultimap_iter *iter); +size_t *hmm_iter_rvalue(struct hashmultimap_iter *iter); +size_t hmm_iter_index(struct hashmultimap_iter *iter); +struct hashmultimap_entry *hmm_impl_new_entry(struct hashmultimap *_map_, + size_t key, size_t value); +struct hashmultimap_entry *hmm_impl_get_entry(struct hashmultimap *_map_, + size_t key); +size_t hmm_impl_key_count(struct hashmultimap *_map_, size_t key); +size_t hmm_impl_calculate_size(size_t required); +static struct hashmultimap_iter hmm_impl_it_start(struct hashmultimap *_map_); +static struct hashmultimap_iter hmm_impl_it_end(struct hashmultimap *_map_); +struct hashmultimap *hmm_new(size_t capacity, double load, + struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val) { struct cmc_alloc_node *alloc = &cmc_alloc_node_default; if (capacity == 0 || load <= 0) @@ -120,12 +122,12 @@ struct multimap *mm_new(size_t capacity, double load, return ((void *)0); if (!f_key || !f_val) return ((void *)0); - size_t real_capacity = mm_impl_calculate_size(capacity / load); - struct multimap *_map_ = alloc->malloc(sizeof(struct multimap)); + size_t real_capacity = hmm_impl_calculate_size(capacity / load); + struct hashmultimap *_map_ = alloc->malloc(sizeof(struct hashmultimap)); if (!_map_) return ((void *)0); _map_->buffer = - alloc->calloc(real_capacity, sizeof(struct multimap_entry *[2])); + alloc->calloc(real_capacity, sizeof(struct hashmultimap_entry *[2])); if (!_map_->buffer) { alloc->free(_map_); @@ -139,15 +141,15 @@ struct multimap *mm_new(size_t capacity, double load, _map_->f_val = f_val; _map_->alloc = alloc; _map_->callbacks = ((void *)0); - _map_->it_end = mm_impl_it_end; - _map_->it_start = mm_impl_it_start; + _map_->it_end = hmm_impl_it_end; + _map_->it_start = hmm_impl_it_start; return _map_; } -struct multimap *mm_new_custom(size_t capacity, double load, - struct multimap_fkey *f_key, - struct multimap_fval *f_val, - struct cmc_alloc_node *alloc, - struct cmc_callbacks *callbacks) +struct hashmultimap *hmm_new_custom(size_t capacity, double load, + struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val, + struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) { if (capacity == 0 || load <= 0) return ((void *)0); @@ -157,12 +159,12 @@ struct multimap *mm_new_custom(size_t capacity, double load, return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; - size_t real_capacity = mm_impl_calculate_size(capacity / load); - struct multimap *_map_ = alloc->malloc(sizeof(struct multimap)); + size_t real_capacity = hmm_impl_calculate_size(capacity / load); + struct hashmultimap *_map_ = alloc->malloc(sizeof(struct hashmultimap)); if (!_map_) return ((void *)0); _map_->buffer = - alloc->calloc(real_capacity, sizeof(struct multimap_entry *[2])); + alloc->calloc(real_capacity, sizeof(struct hashmultimap_entry *[2])); if (!_map_->buffer) { alloc->free(_map_); @@ -176,18 +178,18 @@ struct multimap *mm_new_custom(size_t capacity, double load, _map_->f_val = f_val; _map_->alloc = alloc; _map_->callbacks = callbacks; - _map_->it_start = mm_impl_it_start; - _map_->it_end = mm_impl_it_end; + _map_->it_start = hmm_impl_it_start; + _map_->it_end = hmm_impl_it_end; return _map_; } -void mm_clear(struct multimap *_map_) +void hmm_clear(struct hashmultimap *_map_) { for (size_t i = 0; i < _map_->capacity; i++) { - struct multimap_entry *scan = _map_->buffer[i][0]; + struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan != ((void *)0)) { - struct multimap_entry *next = scan->next; + struct hashmultimap_entry *next = scan->next; if (_map_->f_key->free) _map_->f_key->free(scan->key); if (_map_->f_val->free) @@ -197,16 +199,16 @@ void mm_clear(struct multimap *_map_) } } memset(_map_->buffer, 0, - sizeof(struct multimap_entry *[2]) * _map_->capacity); + sizeof(struct hashmultimap_entry *[2]) * _map_->capacity); _map_->count = 0; _map_->flag = cmc_flags.OK; } -void mm_free(struct multimap *_map_) +void hmm_free(struct hashmultimap *_map_) { size_t index = 0; while (index < _map_->capacity) { - struct multimap_entry *scan = _map_->buffer[index][0]; + struct hashmultimap_entry *scan = _map_->buffer[index][0]; if (scan != ((void *)0)) { if (scan->next == ((void *)0) && scan->prev == ((void *)0)) @@ -221,7 +223,7 @@ void mm_free(struct multimap *_map_) { while (scan != ((void *)0)) { - struct multimap_entry *tmp = scan; + struct hashmultimap_entry *tmp = scan; scan = scan->next; if (_map_->f_key->free) _map_->f_key->free(tmp->key); @@ -236,8 +238,8 @@ void mm_free(struct multimap *_map_) _map_->alloc->free(_map_->buffer); _map_->alloc->free(_map_); } -void mm_customize(struct multimap *_map_, struct cmc_alloc_node *alloc, - struct cmc_callbacks *callbacks) +void hmm_customize(struct hashmultimap *_map_, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) { if (!alloc) _map_->alloc = &cmc_alloc_node_default; @@ -246,16 +248,16 @@ void mm_customize(struct multimap *_map_, struct cmc_alloc_node *alloc, _map_->callbacks = callbacks; _map_->flag = cmc_flags.OK; } -_Bool mm_insert(struct multimap *_map_, size_t key, size_t value) +_Bool hmm_insert(struct hashmultimap *_map_, size_t key, size_t value) { - if (mm_full(_map_)) + if (hmm_full(_map_)) { - if (!mm_resize(_map_, _map_->capacity + 1)) + if (!hmm_resize(_map_, _map_->capacity + 1)) return 0; } size_t hash = _map_->f_key->hash(key); size_t pos = hash % _map_->capacity; - struct multimap_entry *entry = mm_impl_new_entry(_map_, key, value); + struct hashmultimap_entry *entry = hmm_impl_new_entry(_map_, key, value); if (_map_->buffer[pos][0] == ((void *)0)) { _map_->buffer[pos][0] = entry; @@ -273,15 +275,15 @@ _Bool mm_insert(struct multimap *_map_, size_t key, size_t value) _map_->callbacks->create(); return 1; } -_Bool mm_update(struct multimap *_map_, size_t key, size_t new_value, - size_t *old_value) +_Bool hmm_update(struct hashmultimap *_map_, size_t key, size_t new_value, + size_t *old_value) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } - struct multimap_entry *entry = mm_impl_get_entry(_map_, key); + struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = cmc_flags.NOT_FOUND; @@ -295,16 +297,16 @@ _Bool mm_update(struct multimap *_map_, size_t key, size_t new_value, _map_->callbacks->update(); return 1; } -size_t mm_update_all(struct multimap *_map_, size_t key, size_t new_value, - size_t **old_values) +size_t hmm_update_all(struct hashmultimap *_map_, size_t key, size_t new_value, + size_t **old_values) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } size_t hash = _map_->f_key->hash(key); - struct multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; if (entry == ((void *)0)) { _map_->flag = cmc_flags.NOT_FOUND; @@ -312,7 +314,7 @@ size_t mm_update_all(struct multimap *_map_, size_t key, size_t new_value, } if (old_values) { - size_t total = mm_impl_key_count(_map_, key); + size_t total = hmm_impl_key_count(_map_, key); if (total == 0) { _map_->flag = cmc_flags.NOT_FOUND; @@ -342,22 +344,24 @@ size_t mm_update_all(struct multimap *_map_, size_t key, size_t new_value, _map_->callbacks->update(); return index; } -_Bool mm_remove(struct multimap *_map_, size_t key, size_t *out_value) +_Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } size_t hash = _map_->f_key->hash(key); - struct multimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); - struct multimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); + struct hashmultimap_entry **head = + &(_map_->buffer[hash % _map_->capacity][0]); + struct hashmultimap_entry **tail = + &(_map_->buffer[hash % _map_->capacity][1]); if (*head == ((void *)0)) { _map_->flag = cmc_flags.NOT_FOUND; return 0; } - struct multimap_entry *entry = *head; + struct hashmultimap_entry *entry = *head; if (entry->next == ((void *)0) && entry->prev == ((void *)0)) { if (_map_->f_key->cmp(entry->key, key) == 0) @@ -409,16 +413,19 @@ _Bool mm_remove(struct multimap *_map_, size_t key, size_t *out_value) _map_->callbacks->delete (); return 1; } -size_t mm_remove_all(struct multimap *_map_, size_t key, size_t **out_values) +size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, + size_t **out_values) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } size_t hash = _map_->f_key->hash(key); - struct multimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); - struct multimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); + struct hashmultimap_entry **head = + &(_map_->buffer[hash % _map_->capacity][0]); + struct hashmultimap_entry **tail = + &(_map_->buffer[hash % _map_->capacity][1]); if (*head == ((void *)0)) { _map_->flag = cmc_flags.NOT_FOUND; @@ -426,7 +433,7 @@ size_t mm_remove_all(struct multimap *_map_, size_t key, size_t **out_values) } if (out_values) { - size_t total = mm_impl_key_count(_map_, key); + size_t total = hmm_impl_key_count(_map_, key); if (total == 0) { _map_->flag = cmc_flags.NOT_FOUND; @@ -440,7 +447,7 @@ size_t mm_remove_all(struct multimap *_map_, size_t key, size_t **out_values) } } size_t index = 0; - struct multimap_entry *entry = *head; + struct hashmultimap_entry *entry = *head; if (entry->next == ((void *)0)) { *head = ((void *)0); @@ -460,7 +467,7 @@ size_t mm_remove_all(struct multimap *_map_, size_t key, size_t **out_values) *head = entry->next; if (*tail == entry) *tail = entry->prev; - struct multimap_entry *next = entry->next; + struct hashmultimap_entry *next = entry->next; if (entry->prev != ((void *)0)) entry->prev->next = entry->next; if (entry->next != ((void *)0)) @@ -481,21 +488,22 @@ size_t mm_remove_all(struct multimap *_map_, size_t key, size_t **out_values) _map_->callbacks->delete (); return index; } -_Bool mm_max(struct multimap *_map_, size_t *key, size_t *value) +_Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } size_t max_key; size_t max_val; - struct multimap_iter iter; - for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) + struct hashmultimap_iter iter; + for (hmm_iter_init(&iter, _map_); !hmm_iter_end(&iter); + hmm_iter_next(&iter)) { - size_t result_key = mm_iter_key(&iter); - size_t result_value = mm_iter_value(&iter); - size_t index = mm_iter_index(&iter); + size_t result_key = hmm_iter_key(&iter); + size_t result_value = hmm_iter_value(&iter); + size_t index = hmm_iter_index(&iter); if (index == 0) { max_key = result_key; @@ -516,21 +524,22 @@ _Bool mm_max(struct multimap *_map_, size_t *key, size_t *value) _map_->callbacks->read(); return 1; } -_Bool mm_min(struct multimap *_map_, size_t *key, size_t *value) +_Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } size_t min_key; size_t min_val; - struct multimap_iter iter; - for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) + struct hashmultimap_iter iter; + for (hmm_iter_init(&iter, _map_); !hmm_iter_end(&iter); + hmm_iter_next(&iter)) { - size_t result_key = mm_iter_key(&iter); - size_t result_value = mm_iter_value(&iter); - size_t index = mm_iter_index(&iter); + size_t result_key = hmm_iter_key(&iter); + size_t result_value = hmm_iter_value(&iter); + size_t index = hmm_iter_index(&iter); if (index == 0) { min_key = result_key; @@ -551,14 +560,14 @@ _Bool mm_min(struct multimap *_map_, size_t *key, size_t *value) _map_->callbacks->read(); return 1; } -size_t mm_get(struct multimap *_map_, size_t key) +size_t hmm_get(struct hashmultimap *_map_, size_t key) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } - struct multimap_entry *entry = mm_impl_get_entry(_map_, key); + struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = cmc_flags.NOT_FOUND; @@ -569,14 +578,14 @@ size_t mm_get(struct multimap *_map_, size_t key) _map_->callbacks->read(); return entry->value; } -size_t *mm_get_ref(struct multimap *_map_, size_t key) +size_t *hmm_get_ref(struct hashmultimap *_map_, size_t key) { - if (mm_empty(_map_)) + if (hmm_empty(_map_)) { _map_->flag = cmc_flags.EMPTY; return 0; } - struct multimap_entry *entry = mm_impl_get_entry(_map_, key); + struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = cmc_flags.NOT_FOUND; @@ -587,43 +596,43 @@ size_t *mm_get_ref(struct multimap *_map_, size_t key) _map_->callbacks->read(); return &(entry->value); } -_Bool mm_contains(struct multimap *_map_, size_t key) +_Bool hmm_contains(struct hashmultimap *_map_, size_t key) { _map_->flag = cmc_flags.OK; - _Bool result = mm_impl_get_entry(_map_, key) != ((void *)0); + _Bool result = hmm_impl_get_entry(_map_, key) != ((void *)0); if (_map_->callbacks && _map_->callbacks->read) _map_->callbacks->read(); return result; } -_Bool mm_empty(struct multimap *_map_) +_Bool hmm_empty(struct hashmultimap *_map_) { return _map_->count == 0; } -_Bool mm_full(struct multimap *_map_) +_Bool hmm_full(struct hashmultimap *_map_) { return (double)_map_->capacity * _map_->load <= (double)_map_->count; } -size_t mm_count(struct multimap *_map_) +size_t hmm_count(struct hashmultimap *_map_) { return _map_->count; } -size_t mm_key_count(struct multimap *_map_, size_t key) +size_t hmm_key_count(struct hashmultimap *_map_, size_t key) { - return mm_impl_key_count(_map_, key); + return hmm_impl_key_count(_map_, key); } -size_t mm_capacity(struct multimap *_map_) +size_t hmm_capacity(struct hashmultimap *_map_) { return _map_->capacity; } -double mm_load(struct multimap *_map_) +double hmm_load(struct hashmultimap *_map_) { return _map_->load; } -int mm_flag(struct multimap *_map_) +int hmm_flag(struct hashmultimap *_map_) { return _map_->flag; } -_Bool mm_resize(struct multimap *_map_, size_t capacity) +_Bool hmm_resize(struct hashmultimap *_map_, size_t capacity) { _map_->flag = cmc_flags.OK; if (_map_->capacity == capacity) @@ -635,107 +644,109 @@ _Bool mm_resize(struct multimap *_map_, size_t capacity) _map_->flag = cmc_flags.ERROR; return 0; } - size_t theoretical_size = mm_impl_calculate_size(capacity); + size_t theoretical_size = hmm_impl_calculate_size(capacity); if (theoretical_size < _map_->count / _map_->load) { _map_->flag = cmc_flags.INVALID; return 0; } - struct multimap *_new_map_ = - mm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, - _map_->alloc, ((void *)0)); + struct hashmultimap *_new_map_ = + hmm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, + _map_->alloc, ((void *)0)); if (!_new_map_) { _map_->flag = cmc_flags.ALLOC; return 0; } - struct multimap_iter iter; - for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) + struct hashmultimap_iter iter; + for (hmm_iter_init(&iter, _map_); !hmm_iter_end(&iter); + hmm_iter_next(&iter)) { - size_t key = mm_iter_key(&iter); - size_t value = mm_iter_value(&iter); - mm_insert(_new_map_, key, value); + size_t key = hmm_iter_key(&iter); + size_t value = hmm_iter_value(&iter); + hmm_insert(_new_map_, key, value); } if (_map_->count != _new_map_->count) { - mm_free(_new_map_); + hmm_free(_new_map_); _map_->flag = cmc_flags.ERROR; return 0; } - struct multimap_entry *(*tmp_b)[2] = _map_->buffer; + struct hashmultimap_entry *(*tmp_b)[2] = _map_->buffer; _map_->buffer = _new_map_->buffer; _new_map_->buffer = tmp_b; size_t tmp_c = _map_->capacity; _map_->capacity = _new_map_->capacity; _new_map_->capacity = tmp_c; - _new_map_->f_key = &(struct multimap_fkey){ ((void *)0) }; - _new_map_->f_val = &(struct multimap_fval){ ((void *)0) }; - mm_free(_new_map_); + _new_map_->f_key = &(struct hashmultimap_fkey){ ((void *)0) }; + _new_map_->f_val = &(struct hashmultimap_fval){ ((void *)0) }; + hmm_free(_new_map_); success: if (_map_->callbacks && _map_->callbacks->resize) _map_->callbacks->resize(); return 1; } -struct multimap *mm_copy_of(struct multimap *_map_) +struct hashmultimap *hmm_copy_of(struct hashmultimap *_map_) { - struct multimap *result = - mm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, - _map_->f_val, _map_->alloc, ((void *)0)); + struct hashmultimap *result = + hmm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, + _map_->f_val, _map_->alloc, ((void *)0)); if (!result) { _map_->flag = cmc_flags.ERROR; return ((void *)0); } - struct multimap_iter iter; - mm_iter_init(&iter, _map_); - if (!mm_empty(_map_)) + struct hashmultimap_iter iter; + hmm_iter_init(&iter, _map_); + if (!hmm_empty(_map_)) { - for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter)) + for (hmm_iter_to_start(&iter); !hmm_iter_end(&iter); + hmm_iter_next(&iter)) { - size_t key = mm_iter_key(&iter); - size_t value = mm_iter_value(&iter); + size_t key = hmm_iter_key(&iter); + size_t value = hmm_iter_value(&iter); if (_map_->f_key->cpy) key = _map_->f_key->cpy(key); if (_map_->f_val->cpy) value = _map_->f_val->cpy(value); - mm_insert(result, key, value); + hmm_insert(result, key, value); } } result->callbacks = _map_->callbacks; _map_->flag = cmc_flags.OK; return result; } -_Bool mm_equals(struct multimap *_map1_, struct multimap *_map2_) +_Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_) { _map1_->flag = cmc_flags.OK; _map2_->flag = cmc_flags.OK; if (_map1_->count != _map2_->count) return 0; - struct multimap_iter iter; - mm_iter_init(&iter, _map1_); - for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter)) + struct hashmultimap_iter iter; + hmm_iter_init(&iter, _map1_); + for (hmm_iter_to_start(&iter); !hmm_iter_end(&iter); hmm_iter_next(&iter)) { - size_t key = mm_iter_key(&iter); - if (mm_impl_key_count(_map1_, key) != mm_impl_key_count(_map2_, key)) + size_t key = hmm_iter_key(&iter); + if (hmm_impl_key_count(_map1_, key) != hmm_impl_key_count(_map2_, key)) return 0; } return 1; } -struct cmc_string mm_to_string(struct multimap *_map_) +struct cmc_string hmm_to_string(struct hashmultimap *_map_) { struct cmc_string str; - struct multimap *m_ = _map_; - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, "multimap", - "size_t", "size_t", m_, m_->buffer, m_->capacity, - m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, - m_->alloc, m_->callbacks); + struct hashmultimap *m_ = _map_; + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmultimap, + "hashmultimap", "size_t", "size_t", m_, m_->buffer, + m_->capacity, m_->count, m_->load, m_->flag, m_->f_key, + m_->f_val, m_->alloc, m_->callbacks); return n >= 0 ? str : (struct cmc_string){ 0 }; } -_Bool mm_print(struct multimap *_map_, FILE *fptr) +_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr) { for (size_t i = 0; i < _map_->capacity; i++) { - struct multimap_entry *scan = _map_->buffer[i][0]; + struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan != ((void *)0)) { if (!_map_->f_key->str(fptr, scan->key) || @@ -746,26 +757,26 @@ _Bool mm_print(struct multimap *_map_, FILE *fptr) } return 1; } -struct multimap_iter *mm_iter_new(struct multimap *target) +struct hashmultimap_iter *hmm_iter_new(struct hashmultimap *target) { - struct multimap_iter *iter = - target->alloc->malloc(sizeof(struct multimap_iter)); + struct hashmultimap_iter *iter = + target->alloc->malloc(sizeof(struct hashmultimap_iter)); if (!iter) return ((void *)0); - mm_iter_init(iter, target); + hmm_iter_init(iter, target); return iter; } -void mm_iter_free(struct multimap_iter *iter) +void hmm_iter_free(struct hashmultimap_iter *iter) { iter->target->alloc->free(iter); } -void mm_iter_init(struct multimap_iter *iter, struct multimap *target) +void hmm_iter_init(struct hashmultimap_iter *iter, struct hashmultimap *target) { - memset(iter, 0, sizeof(struct multimap_iter)); + memset(iter, 0, sizeof(struct hashmultimap_iter)); iter->target = target; iter->start = 1; - iter->end = mm_empty(target); - if (!mm_empty(target)) + iter->end = hmm_empty(target); + if (!hmm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { @@ -787,37 +798,37 @@ void mm_iter_init(struct multimap_iter *iter, struct multimap *target) } } } -_Bool mm_iter_start(struct multimap_iter *iter) +_Bool hmm_iter_start(struct hashmultimap_iter *iter) { - return mm_empty(iter->target) || iter->start; + return hmm_empty(iter->target) || iter->start; } -_Bool mm_iter_end(struct multimap_iter *iter) +_Bool hmm_iter_end(struct hashmultimap_iter *iter) { - return mm_empty(iter->target) || iter->end; + return hmm_empty(iter->target) || iter->end; } -void mm_iter_to_start(struct multimap_iter *iter) +void hmm_iter_to_start(struct hashmultimap_iter *iter) { - if (!mm_empty(iter->target)) + if (!hmm_empty(iter->target)) { iter->cursor = iter->first; iter->index = 0; iter->start = 1; - iter->end = mm_empty(iter->target); + iter->end = hmm_empty(iter->target); iter->curr_entry = iter->target->buffer[iter->first][0]; } } -void mm_iter_to_end(struct multimap_iter *iter) +void hmm_iter_to_end(struct hashmultimap_iter *iter) { - if (!mm_empty(iter->target)) + if (!hmm_empty(iter->target)) { iter->cursor = iter->last; iter->index = iter->target->count - 1; - iter->start = mm_empty(iter->target); + iter->start = hmm_empty(iter->target); iter->end = 1; iter->curr_entry = iter->target->buffer[iter->last][1]; } } -_Bool mm_iter_next(struct multimap_iter *iter) +_Bool hmm_iter_next(struct hashmultimap_iter *iter) { if (iter->end) return 0; @@ -839,10 +850,10 @@ _Bool mm_iter_next(struct multimap_iter *iter) iter->curr_entry = iter->target->buffer[iter->cursor][0]; iter->index++; } - iter->start = mm_empty(iter->target); + iter->start = hmm_empty(iter->target); return 1; } -_Bool mm_iter_prev(struct multimap_iter *iter) +_Bool hmm_iter_prev(struct hashmultimap_iter *iter) { if (iter->start) return 0; @@ -864,10 +875,10 @@ _Bool mm_iter_prev(struct multimap_iter *iter) iter->curr_entry = iter->target->buffer[iter->cursor][1]; iter->index--; } - iter->end = mm_empty(iter->target); + iter->end = hmm_empty(iter->target); return 1; } -_Bool mm_iter_advance(struct multimap_iter *iter, size_t steps) +_Bool hmm_iter_advance(struct hashmultimap_iter *iter, size_t steps) { if (iter->end) return 0; @@ -879,10 +890,10 @@ _Bool mm_iter_advance(struct multimap_iter *iter, size_t steps) if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) - mm_iter_next(iter); + hmm_iter_next(iter); return 1; } -_Bool mm_iter_rewind(struct multimap_iter *iter, size_t steps) +_Bool hmm_iter_rewind(struct hashmultimap_iter *iter, size_t steps) { if (iter->start) return 0; @@ -894,46 +905,46 @@ _Bool mm_iter_rewind(struct multimap_iter *iter, size_t steps) if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) - mm_iter_prev(iter); + hmm_iter_prev(iter); return 1; } -_Bool mm_iter_go_to(struct multimap_iter *iter, size_t index) +_Bool hmm_iter_go_to(struct hashmultimap_iter *iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) - return mm_iter_rewind(iter, iter->index - index); + return hmm_iter_rewind(iter, iter->index - index); else if (iter->index < index) - return mm_iter_advance(iter, index - iter->index); + return hmm_iter_advance(iter, index - iter->index); return 1; } -size_t mm_iter_key(struct multimap_iter *iter) +size_t hmm_iter_key(struct hashmultimap_iter *iter) { - if (mm_empty(iter->target)) + if (hmm_empty(iter->target)) return (size_t){ 0 }; return iter->curr_entry->key; } -size_t mm_iter_value(struct multimap_iter *iter) +size_t hmm_iter_value(struct hashmultimap_iter *iter) { - if (mm_empty(iter->target)) + if (hmm_empty(iter->target)) return (size_t){ 0 }; return iter->curr_entry->value; } -size_t *mm_iter_rvalue(struct multimap_iter *iter) +size_t *hmm_iter_rvalue(struct hashmultimap_iter *iter) { - if (mm_empty(iter->target)) + if (hmm_empty(iter->target)) return ((void *)0); return &(iter->curr_entry->value); } -size_t mm_iter_index(struct multimap_iter *iter) +size_t hmm_iter_index(struct hashmultimap_iter *iter) { return iter->index; } -struct multimap_entry *mm_impl_new_entry(struct multimap *_map_, size_t key, - size_t value) +struct hashmultimap_entry *hmm_impl_new_entry(struct hashmultimap *_map_, + size_t key, size_t value) { - struct multimap_entry *entry = - _map_->alloc->malloc(sizeof(struct multimap_entry)); + struct hashmultimap_entry *entry = + _map_->alloc->malloc(sizeof(struct hashmultimap_entry)); if (!entry) return ((void *)0); entry->key = key; @@ -942,10 +953,11 @@ struct multimap_entry *mm_impl_new_entry(struct multimap *_map_, size_t key, entry->prev = ((void *)0); return entry; } -struct multimap_entry *mm_impl_get_entry(struct multimap *_map_, size_t key) +struct hashmultimap_entry *hmm_impl_get_entry(struct hashmultimap *_map_, + size_t key) { size_t hash = _map_->f_key->hash(key); - struct multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; while (entry != ((void *)0)) { if (_map_->f_key->cmp(entry->key, key) == 0) @@ -954,10 +966,10 @@ struct multimap_entry *mm_impl_get_entry(struct multimap *_map_, size_t key) } return ((void *)0); } -size_t mm_impl_key_count(struct multimap *_map_, size_t key) +size_t hmm_impl_key_count(struct hashmultimap *_map_, size_t key) { size_t hash = _map_->f_key->hash(key); - struct multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; size_t total_count = 0; if (!entry) return total_count; @@ -969,7 +981,7 @@ size_t mm_impl_key_count(struct multimap *_map_, size_t key) } return total_count; } -size_t mm_impl_calculate_size(size_t required) +size_t hmm_impl_calculate_size(size_t required) { const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); @@ -980,16 +992,16 @@ size_t mm_impl_calculate_size(size_t required) i++; return cmc_hashtable_primes[i]; } -static struct multimap_iter mm_impl_it_start(struct multimap *_map_) +static struct hashmultimap_iter hmm_impl_it_start(struct hashmultimap *_map_) { - struct multimap_iter iter; - mm_iter_init(&iter, _map_); + struct hashmultimap_iter iter; + hmm_iter_init(&iter, _map_); return iter; } -static struct multimap_iter mm_impl_it_end(struct multimap *_map_) +static struct hashmultimap_iter hmm_impl_it_end(struct hashmultimap *_map_) { - struct multimap_iter iter; - mm_iter_init(&iter, _map_); - mm_iter_to_end(&iter); + struct hashmultimap_iter iter; + hmm_iter_init(&iter, _map_); + hmm_iter_to_end(&iter); return iter; } diff --git a/tests/main/unt/hashmultimap.c b/tests/main/unt/hashmultimap.c new file mode 100644 index 0000000..03b376c --- /dev/null +++ b/tests/main/unt/hashmultimap.c @@ -0,0 +1,486 @@ +#include "utl.c" +#include "utl/assert.h" +#include "utl/test.h" + +#include "../src/hashmultimap.c" + +struct hashmultimap_fkey *hmm_fkey = &(struct hashmultimap_fkey){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; + +struct hashmultimap_fval *hmm_fval = &(struct hashmultimap_fval){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; + +struct hashmultimap_fkey *hmm_fkey_counter = + &(struct hashmultimap_fkey){ .cmp = k_c_cmp, + .cpy = k_c_cpy, + .str = k_c_str, + .free = k_c_free, + .hash = k_c_hash, + .pri = k_c_pri }; + +struct hashmultimap_fval *hmm_fval_counter = + &(struct hashmultimap_fval){ .cmp = v_c_cmp, + .cpy = v_c_cpy, + .str = v_c_str, + .free = v_c_free, + .hash = v_c_hash, + .pri = v_c_pri }; + +struct cmc_alloc_node *hmm_alloc_node = &(struct cmc_alloc_node){ + .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free +}; + +CMC_CREATE_UNIT(HashMultiMap, true, { + CMC_CREATE_TEST(PFX##_new(), { + struct hashmultimap *map = hmm_new(943722, 0.6, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + cmc_assert_not_equals(ptr, NULL, map->buffer); + cmc_assert_equals(size_t, 0, map->count); + cmc_assert_equals(double, 0.6, map->load); + cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); + cmc_assert_equals(ptr, hmm_fkey, map->f_key); + cmc_assert_equals(ptr, hmm_fval, map->f_val); + cmc_assert_equals(ptr, &cmc_alloc_node_default, map->alloc); + cmc_assert_equals(ptr, NULL, map->callbacks); + + cmc_assert_greater_equals(size_t, (943722 / 0.6), hmm_capacity(map)); + + hmm_free(map); + + map = hmm_new(100, 0.6, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < map->capacity; i++) + { + cmc_assert_equals(ptr, NULL, map->buffer[i][0]); + cmc_assert_equals(ptr, NULL, map->buffer[i][1]); + } + + hmm_free(map); + + map = hmm_new(0, 0.6, hmm_fkey, hmm_fval); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new(UINT64_MAX, 0.99, hmm_fkey, hmm_fval); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new(1000, 0.6, hmm_fkey, NULL); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new(1000, 0.6, NULL, hmm_fval); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new(1000, 0.6, NULL, NULL); + cmc_assert_equals(ptr, NULL, map); + }); + + CMC_CREATE_TEST(PFX##_new_custom(), { + struct hashmultimap *map = hmm_new_custom(943722, 0.6, hmm_fkey, hmm_fval, + hmm_alloc_node, callbacks); + + cmc_assert_not_equals(ptr, NULL, map); + cmc_assert_not_equals(ptr, NULL, map->buffer); + cmc_assert_equals(size_t, 0, map->count); + cmc_assert_equals(double, 0.6, map->load); + cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); + cmc_assert_equals(ptr, hmm_fkey, map->f_key); + cmc_assert_equals(ptr, hmm_fval, map->f_val); + cmc_assert_equals(ptr, hmm_alloc_node, map->alloc); + cmc_assert_equals(ptr, callbacks, map->callbacks); + + cmc_assert_greater_equals(size_t, (943722 / 0.6), hmm_capacity(map)); + + hmm_free(map); + + map = hmm_new_custom(0, 0.6, hmm_fkey, hmm_fval, NULL, NULL); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new_custom(UINT64_MAX, 0.99, hmm_fkey, hmm_fval, NULL, NULL); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new_custom(1000, 0.6, hmm_fkey, NULL, NULL, NULL); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new_custom(1000, 0.6, NULL, hmm_fval, NULL, NULL); + cmc_assert_equals(ptr, NULL, map); + + map = hmm_new_custom(1000, 0.6, NULL, NULL, NULL, NULL); + cmc_assert_equals(ptr, NULL, map); + }); + + CMC_CREATE_TEST(PFX##_clear(), { + k_total_free = 0; + v_total_free = 0; + struct hashmultimap *map = + hmm_new(100, 0.6, hmm_fkey_counter, hmm_fval_counter); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 1000; i++) + hmm_insert(map, i, i); + + cmc_assert_equals(size_t, 1000, map->count); + + map->flag = cmc_flags.ERROR; + hmm_clear(map); + + cmc_assert_equals(size_t, 0, map->count); + cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); + cmc_assert_equals(int32_t, 1000, k_total_free); + cmc_assert_equals(int32_t, 1000, v_total_free); + + hmm_free(map); + k_total_free = 0; + v_total_free = 0; + }); + + CMC_CREATE_TEST(PFX##_free(), { + k_total_free = 0; + v_total_free = 0; + struct hashmultimap *map = + hmm_new(100, 0.6, hmm_fkey_counter, hmm_fval_counter); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 1000; i++) + hmm_insert(map, i, i); + + cmc_assert_equals(size_t, 1000, map->count); + + hmm_free(map); + + cmc_assert_equals(int32_t, 1000, k_total_free); + cmc_assert_equals(int32_t, 1000, v_total_free); + + map = hmm_new(1000, 0.6, hmm_fkey_counter, hmm_fval_counter); + + cmc_assert_not_equals(ptr, NULL, map); + cmc_assert_not_equals(ptr, NULL, map->buffer); + + hmm_free(map); + + cmc_assert_equals(int32_t, 1000, k_total_free); + cmc_assert_equals(int32_t, 1000, v_total_free); + k_total_free = 0; + v_total_free = 0; + }); + + CMC_CREATE_TEST(insert[count], { + struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hmm_insert(map, i % 20, i % 20)); + + cmc_assert_equals(size_t, 100, hmm_count(map)); + + hmm_free(map); + }); + + CMC_CREATE_TEST(remove[count], { + struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 200; i++) + cmc_assert(hmm_insert(map, i % 20, i % 20)); + + size_t r; + + for (size_t i = 0; i < 60; i++) + cmc_assert(hmm_remove(map, i % 20, &r)); + + cmc_assert_equals(size_t, 140, hmm_count(map)); + + hmm_free(map); + }); + + CMC_CREATE_TEST(remove[count = 0], { + struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + size_t r; + + cmc_assert(!hmm_remove(map, 10, &r)); + + hmm_free(map); + }); + + CMC_CREATE_TEST(remove[count = 1], { + struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + size_t r; + + cmc_assert(hmm_insert(map, 10, 11)); + cmc_assert(hmm_remove(map, 10, &r)); + + hmm_free(map); + }); + + CMC_CREATE_TEST(get[key ordering], { + struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + /* Assert that the value 100 is accessed before the value 101 for */ + /* the same key */ + cmc_assert(hmm_insert(map, 10, 100)); + cmc_assert(hmm_insert(map, 20, 102)); + cmc_assert(hmm_insert(map, 10, 101)); + + cmc_assert_equals(size_t, 100, hmm_get(map, 10)); + + hmm_free(map); + }); + + CMC_CREATE_TEST(key_count, { + struct hashmultimap *map = hmm_new(50, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 1000; i++) + cmc_assert(hmm_insert(map, i % 20, i % 20)); + + cmc_assert_equals(size_t, 1000, hmm_count(map)); + + for (size_t i = 0; i < 20; i++) + cmc_assert_equals(size_t, 50, hmm_key_count(map, i)); + + hmm_free(map); + }); + + CMC_CREATE_TEST(flags, { + struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval); + + cmc_assert_not_equals(ptr, NULL, map); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // clear + map->flag = cmc_flags.ERROR; + hmm_clear(map); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // customize + map->flag = cmc_flags.ERROR; + hmm_customize(map, NULL, NULL); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // insert + map->flag = cmc_flags.ERROR; + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // update + cmc_assert(!hmm_update(map, 9, 10, NULL)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hmm_flag(map)); + + cmc_assert(hmm_update(map, 1, 20, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // update_all + map->flag = cmc_flags.ERROR; + cmc_assert_equals(size_t, 1, hmm_update_all(map, 1, 2, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + map->flag = cmc_flags.ERROR; + cmc_assert_equals(size_t, 0, hmm_update_all(map, 2, 4, NULL)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hmm_flag(map)); + + hmm_clear(map); + cmc_assert_equals(size_t, 0, hmm_update_all(map, 1, 2, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + + // remove + map->flag = cmc_flags.ERROR; + cmc_assert(!hmm_remove(map, 1, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert(!hmm_remove(map, 2, NULL)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hmm_flag(map)); + + cmc_assert(hmm_remove(map, 1, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // remove_all + cmc_assert(!hmm_remove_all(map, 1, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + + cmc_assert(hmm_insert(map, 1, 1) && hmm_insert(map, 1, 1)); + cmc_assert_equals(size_t, 0, hmm_remove_all(map, 2, NULL)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hmm_flag(map)); + + cmc_assert_equals(size_t, 2, hmm_remove_all(map, 1, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // max min + cmc_assert(!hmm_max(map, NULL, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + map->flag = cmc_flags.ERROR; + cmc_assert(!hmm_min(map, NULL, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert(hmm_max(map, NULL, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + map->flag = cmc_flags.ERROR; + cmc_assert(hmm_min(map, NULL, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // get get_ref + hmm_get(map, 2); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hmm_flag(map)); + map->flag = cmc_flags.ERROR; + hmm_get_ref(map, 2); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hmm_flag(map)); + + hmm_get(map, 1); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + map->flag = cmc_flags.ERROR; + hmm_get_ref(map, 1); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + hmm_clear(map); + hmm_get(map, 1); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + map->flag = cmc_flags.ERROR; + hmm_get_ref(map, 1); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hmm_flag(map)); + + // contains + map->flag = cmc_flags.ERROR; + cmc_assert(!hmm_contains(map, 1000)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + + // copy_of + map->flag = cmc_flags.ERROR; + struct hashmultimap *map2 = hmm_copy_of(map); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map2)); + + // equals + map->flag = cmc_flags.ERROR; + map2->flag = cmc_flags.ERROR; + cmc_assert(hmm_equals(map, map2)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map)); + cmc_assert_equals(int32_t, cmc_flags.OK, hmm_flag(map2)); + + hmm_free(map); + hmm_free(map2); + }); + + CMC_CREATE_TEST(callbacks, { + struct hashmultimap *map = + hmm_new_custom(100, 0.8, hmm_fkey, hmm_fval, NULL, callbacks); + + cmc_assert_not_equals(ptr, NULL, map); + + total_create = 0; + total_read = 0; + total_update = 0; + total_delete = 0; + total_resize = 0; + + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert_equals(int32_t, 1, total_create); + + cmc_assert(hmm_update(map, 1, 2, NULL)); + cmc_assert_equals(int32_t, 1, total_update); + + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert_equals(int32_t, 2, total_create); + + cmc_assert_equals(size_t, 2, hmm_update_all(map, 1, 3, NULL)); + cmc_assert_equals(int32_t, 2, total_update); + + cmc_assert(hmm_remove(map, 1, NULL)); + cmc_assert_equals(int32_t, 1, total_delete); + + cmc_assert(hmm_insert(map, 1, 2)); + cmc_assert_equals(int32_t, 3, total_create); + + cmc_assert_equals(size_t, 2, hmm_remove_all(map, 1, NULL)); + cmc_assert_equals(int32_t, 2, total_delete); + + cmc_assert(hmm_insert(map, 1, 2)); + cmc_assert_equals(int32_t, 4, total_create); + + cmc_assert(hmm_max(map, NULL, NULL)); + cmc_assert_equals(int32_t, 1, total_read); + + cmc_assert(hmm_min(map, NULL, NULL)); + cmc_assert_equals(int32_t, 2, total_read); + + cmc_assert_equals(size_t, 2, hmm_get(map, 1)); + cmc_assert_equals(int32_t, 3, total_read); + + cmc_assert_not_equals(ptr, NULL, hmm_get_ref(map, 1)); + cmc_assert_equals(int32_t, 4, total_read); + + cmc_assert(hmm_contains(map, 1)); + cmc_assert_equals(int32_t, 5, total_read); + + cmc_assert(hmm_resize(map, 1000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(hmm_resize(map, 100)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 2, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + hmm_customize(map, NULL, NULL); + + cmc_assert_equals(ptr, NULL, map->callbacks); + + hmm_clear(map); + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert(hmm_update(map, 1, 2, NULL)); + cmc_assert(hmm_insert(map, 1, 1)); + cmc_assert_equals(size_t, 2, hmm_update_all(map, 1, 3, NULL)); + cmc_assert(hmm_remove(map, 1, NULL)); + cmc_assert(hmm_insert(map, 1, 2)); + cmc_assert_equals(size_t, 2, hmm_remove_all(map, 1, NULL)); + cmc_assert(hmm_insert(map, 1, 2)); + cmc_assert(hmm_max(map, NULL, NULL)); + cmc_assert(hmm_min(map, NULL, NULL)); + cmc_assert_equals(size_t, 2, hmm_get(map, 1)); + cmc_assert_not_equals(ptr, NULL, hmm_get_ref(map, 1)); + cmc_assert(hmm_contains(map, 1)); + cmc_assert(hmm_resize(map, 1000)); + cmc_assert(hmm_resize(map, 100)); + + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 2, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, map->callbacks); + + hmm_free(map); + + total_create = 0; + total_read = 0; + total_update = 0; + total_delete = 0; + total_resize = 0; + }); +}); diff --git a/tests/main/unt/multimap.c b/tests/main/unt/multimap.c deleted file mode 100644 index 05be216..0000000 --- a/tests/main/unt/multimap.c +++ /dev/null @@ -1,486 +0,0 @@ -#include "utl.c" -#include "utl/assert.h" -#include "utl/test.h" - -#include "../src/multimap.c" - -struct multimap_fkey *mm_fkey = &(struct multimap_fkey){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; - -struct multimap_fval *mm_fval = &(struct multimap_fval){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; - -struct multimap_fkey *mm_fkey_counter = - &(struct multimap_fkey){ .cmp = k_c_cmp, - .cpy = k_c_cpy, - .str = k_c_str, - .free = k_c_free, - .hash = k_c_hash, - .pri = k_c_pri }; - -struct multimap_fval *mm_fval_counter = - &(struct multimap_fval){ .cmp = v_c_cmp, - .cpy = v_c_cpy, - .str = v_c_str, - .free = v_c_free, - .hash = v_c_hash, - .pri = v_c_pri }; - -struct cmc_alloc_node *mm_alloc_node = &(struct cmc_alloc_node){ - .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free -}; - -CMC_CREATE_UNIT(MultiMap, true, { - CMC_CREATE_TEST(PFX##_new(), { - struct multimap *map = mm_new(943722, 0.6, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - cmc_assert_not_equals(ptr, NULL, map->buffer); - cmc_assert_equals(size_t, 0, map->count); - cmc_assert_equals(double, 0.6, map->load); - cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); - cmc_assert_equals(ptr, mm_fkey, map->f_key); - cmc_assert_equals(ptr, mm_fval, map->f_val); - cmc_assert_equals(ptr, &cmc_alloc_node_default, map->alloc); - cmc_assert_equals(ptr, NULL, map->callbacks); - - cmc_assert_greater_equals(size_t, (943722 / 0.6), mm_capacity(map)); - - mm_free(map); - - map = mm_new(100, 0.6, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 0; i < map->capacity; i++) - { - cmc_assert_equals(ptr, NULL, map->buffer[i][0]); - cmc_assert_equals(ptr, NULL, map->buffer[i][1]); - } - - mm_free(map); - - map = mm_new(0, 0.6, mm_fkey, mm_fval); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new(UINT64_MAX, 0.99, mm_fkey, mm_fval); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new(1000, 0.6, mm_fkey, NULL); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new(1000, 0.6, NULL, mm_fval); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new(1000, 0.6, NULL, NULL); - cmc_assert_equals(ptr, NULL, map); - }); - - CMC_CREATE_TEST(PFX##_new_custom(), { - struct multimap *map = mm_new_custom(943722, 0.6, mm_fkey, mm_fval, - mm_alloc_node, callbacks); - - cmc_assert_not_equals(ptr, NULL, map); - cmc_assert_not_equals(ptr, NULL, map->buffer); - cmc_assert_equals(size_t, 0, map->count); - cmc_assert_equals(double, 0.6, map->load); - cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); - cmc_assert_equals(ptr, mm_fkey, map->f_key); - cmc_assert_equals(ptr, mm_fval, map->f_val); - cmc_assert_equals(ptr, mm_alloc_node, map->alloc); - cmc_assert_equals(ptr, callbacks, map->callbacks); - - cmc_assert_greater_equals(size_t, (943722 / 0.6), mm_capacity(map)); - - mm_free(map); - - map = mm_new_custom(0, 0.6, mm_fkey, mm_fval, NULL, NULL); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new_custom(UINT64_MAX, 0.99, mm_fkey, mm_fval, NULL, NULL); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new_custom(1000, 0.6, mm_fkey, NULL, NULL, NULL); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new_custom(1000, 0.6, NULL, mm_fval, NULL, NULL); - cmc_assert_equals(ptr, NULL, map); - - map = mm_new_custom(1000, 0.6, NULL, NULL, NULL, NULL); - cmc_assert_equals(ptr, NULL, map); - }); - - CMC_CREATE_TEST(PFX##_clear(), { - k_total_free = 0; - v_total_free = 0; - struct multimap *map = - mm_new(100, 0.6, mm_fkey_counter, mm_fval_counter); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 1; i <= 1000; i++) - mm_insert(map, i, i); - - cmc_assert_equals(size_t, 1000, map->count); - - map->flag = cmc_flags.ERROR; - mm_clear(map); - - cmc_assert_equals(size_t, 0, map->count); - cmc_assert_equals(int32_t, cmc_flags.OK, map->flag); - cmc_assert_equals(int32_t, 1000, k_total_free); - cmc_assert_equals(int32_t, 1000, v_total_free); - - mm_free(map); - k_total_free = 0; - v_total_free = 0; - }); - - CMC_CREATE_TEST(PFX##_free(), { - k_total_free = 0; - v_total_free = 0; - struct multimap *map = - mm_new(100, 0.6, mm_fkey_counter, mm_fval_counter); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 1; i <= 1000; i++) - mm_insert(map, i, i); - - cmc_assert_equals(size_t, 1000, map->count); - - mm_free(map); - - cmc_assert_equals(int32_t, 1000, k_total_free); - cmc_assert_equals(int32_t, 1000, v_total_free); - - map = mm_new(1000, 0.6, mm_fkey_counter, mm_fval_counter); - - cmc_assert_not_equals(ptr, NULL, map); - cmc_assert_not_equals(ptr, NULL, map->buffer); - - mm_free(map); - - cmc_assert_equals(int32_t, 1000, k_total_free); - cmc_assert_equals(int32_t, 1000, v_total_free); - k_total_free = 0; - v_total_free = 0; - }); - - CMC_CREATE_TEST(insert[count], { - struct multimap *map = mm_new(100, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 0; i < 100; i++) - cmc_assert(mm_insert(map, i % 20, i % 20)); - - cmc_assert_equals(size_t, 100, mm_count(map)); - - mm_free(map); - }); - - CMC_CREATE_TEST(remove[count], { - struct multimap *map = mm_new(100, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 0; i < 200; i++) - cmc_assert(mm_insert(map, i % 20, i % 20)); - - size_t r; - - for (size_t i = 0; i < 60; i++) - cmc_assert(mm_remove(map, i % 20, &r)); - - cmc_assert_equals(size_t, 140, mm_count(map)); - - mm_free(map); - }); - - CMC_CREATE_TEST(remove[count = 0], { - struct multimap *map = mm_new(100, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - size_t r; - - cmc_assert(!mm_remove(map, 10, &r)); - - mm_free(map); - }); - - CMC_CREATE_TEST(remove[count = 1], { - struct multimap *map = mm_new(100, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - size_t r; - - cmc_assert(mm_insert(map, 10, 11)); - cmc_assert(mm_remove(map, 10, &r)); - - mm_free(map); - }); - - CMC_CREATE_TEST(get[key ordering], { - struct multimap *map = mm_new(100, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - /* Assert that the value 100 is accessed before the value 101 for */ - /* the same key */ - cmc_assert(mm_insert(map, 10, 100)); - cmc_assert(mm_insert(map, 20, 102)); - cmc_assert(mm_insert(map, 10, 101)); - - cmc_assert_equals(size_t, 100, mm_get(map, 10)); - - mm_free(map); - }); - - CMC_CREATE_TEST(key_count, { - struct multimap *map = mm_new(50, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 0; i < 1000; i++) - cmc_assert(mm_insert(map, i % 20, i % 20)); - - cmc_assert_equals(size_t, 1000, mm_count(map)); - - for (size_t i = 0; i < 20; i++) - cmc_assert_equals(size_t, 50, mm_key_count(map, i)); - - mm_free(map); - }); - - CMC_CREATE_TEST(flags, { - struct multimap *map = mm_new(100, 0.8, mm_fkey, mm_fval); - - cmc_assert_not_equals(ptr, NULL, map); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // clear - map->flag = cmc_flags.ERROR; - mm_clear(map); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // customize - map->flag = cmc_flags.ERROR; - mm_customize(map, NULL, NULL); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // insert - map->flag = cmc_flags.ERROR; - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // update - cmc_assert(!mm_update(map, 9, 10, NULL)); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, mm_flag(map)); - - cmc_assert(mm_update(map, 1, 20, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // update_all - map->flag = cmc_flags.ERROR; - cmc_assert_equals(size_t, 1, mm_update_all(map, 1, 2, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - map->flag = cmc_flags.ERROR; - cmc_assert_equals(size_t, 0, mm_update_all(map, 2, 4, NULL)); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, mm_flag(map)); - - mm_clear(map); - cmc_assert_equals(size_t, 0, mm_update_all(map, 1, 2, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - - // remove - map->flag = cmc_flags.ERROR; - cmc_assert(!mm_remove(map, 1, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert(!mm_remove(map, 2, NULL)); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, mm_flag(map)); - - cmc_assert(mm_remove(map, 1, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // remove_all - cmc_assert(!mm_remove_all(map, 1, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - - cmc_assert(mm_insert(map, 1, 1) && mm_insert(map, 1, 1)); - cmc_assert_equals(size_t, 0, mm_remove_all(map, 2, NULL)); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, mm_flag(map)); - - cmc_assert_equals(size_t, 2, mm_remove_all(map, 1, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // max min - cmc_assert(!mm_max(map, NULL, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - map->flag = cmc_flags.ERROR; - cmc_assert(!mm_min(map, NULL, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert(mm_max(map, NULL, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - map->flag = cmc_flags.ERROR; - cmc_assert(mm_min(map, NULL, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // get get_ref - mm_get(map, 2); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, mm_flag(map)); - map->flag = cmc_flags.ERROR; - mm_get_ref(map, 2); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, mm_flag(map)); - - mm_get(map, 1); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - map->flag = cmc_flags.ERROR; - mm_get_ref(map, 1); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - mm_clear(map); - mm_get(map, 1); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - map->flag = cmc_flags.ERROR; - mm_get_ref(map, 1); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, mm_flag(map)); - - // contains - map->flag = cmc_flags.ERROR; - cmc_assert(!mm_contains(map, 1000)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - - // copy_of - map->flag = cmc_flags.ERROR; - struct multimap *map2 = mm_copy_of(map); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map2)); - - // equals - map->flag = cmc_flags.ERROR; - map2->flag = cmc_flags.ERROR; - cmc_assert(mm_equals(map, map2)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map)); - cmc_assert_equals(int32_t, cmc_flags.OK, mm_flag(map2)); - - mm_free(map); - mm_free(map2); - }); - - CMC_CREATE_TEST(callbacks, { - struct multimap *map = - mm_new_custom(100, 0.8, mm_fkey, mm_fval, NULL, callbacks); - - cmc_assert_not_equals(ptr, NULL, map); - - total_create = 0; - total_read = 0; - total_update = 0; - total_delete = 0; - total_resize = 0; - - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert_equals(int32_t, 1, total_create); - - cmc_assert(mm_update(map, 1, 2, NULL)); - cmc_assert_equals(int32_t, 1, total_update); - - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert_equals(int32_t, 2, total_create); - - cmc_assert_equals(size_t, 2, mm_update_all(map, 1, 3, NULL)); - cmc_assert_equals(int32_t, 2, total_update); - - cmc_assert(mm_remove(map, 1, NULL)); - cmc_assert_equals(int32_t, 1, total_delete); - - cmc_assert(mm_insert(map, 1, 2)); - cmc_assert_equals(int32_t, 3, total_create); - - cmc_assert_equals(size_t, 2, mm_remove_all(map, 1, NULL)); - cmc_assert_equals(int32_t, 2, total_delete); - - cmc_assert(mm_insert(map, 1, 2)); - cmc_assert_equals(int32_t, 4, total_create); - - cmc_assert(mm_max(map, NULL, NULL)); - cmc_assert_equals(int32_t, 1, total_read); - - cmc_assert(mm_min(map, NULL, NULL)); - cmc_assert_equals(int32_t, 2, total_read); - - cmc_assert_equals(size_t, 2, mm_get(map, 1)); - cmc_assert_equals(int32_t, 3, total_read); - - cmc_assert_not_equals(ptr, NULL, mm_get_ref(map, 1)); - cmc_assert_equals(int32_t, 4, total_read); - - cmc_assert(mm_contains(map, 1)); - cmc_assert_equals(int32_t, 5, total_read); - - cmc_assert(mm_resize(map, 1000)); - cmc_assert_equals(int32_t, 1, total_resize); - - cmc_assert(mm_resize(map, 100)); - cmc_assert_equals(int32_t, 2, total_resize); - - cmc_assert_equals(int32_t, 4, total_create); - cmc_assert_equals(int32_t, 5, total_read); - cmc_assert_equals(int32_t, 2, total_update); - cmc_assert_equals(int32_t, 2, total_delete); - cmc_assert_equals(int32_t, 2, total_resize); - - mm_customize(map, NULL, NULL); - - cmc_assert_equals(ptr, NULL, map->callbacks); - - mm_clear(map); - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert(mm_update(map, 1, 2, NULL)); - cmc_assert(mm_insert(map, 1, 1)); - cmc_assert_equals(size_t, 2, mm_update_all(map, 1, 3, NULL)); - cmc_assert(mm_remove(map, 1, NULL)); - cmc_assert(mm_insert(map, 1, 2)); - cmc_assert_equals(size_t, 2, mm_remove_all(map, 1, NULL)); - cmc_assert(mm_insert(map, 1, 2)); - cmc_assert(mm_max(map, NULL, NULL)); - cmc_assert(mm_min(map, NULL, NULL)); - cmc_assert_equals(size_t, 2, mm_get(map, 1)); - cmc_assert_not_equals(ptr, NULL, mm_get_ref(map, 1)); - cmc_assert(mm_contains(map, 1)); - cmc_assert(mm_resize(map, 1000)); - cmc_assert(mm_resize(map, 100)); - - cmc_assert_equals(int32_t, 4, total_create); - cmc_assert_equals(int32_t, 5, total_read); - cmc_assert_equals(int32_t, 2, total_update); - cmc_assert_equals(int32_t, 2, total_delete); - cmc_assert_equals(int32_t, 2, total_resize); - - cmc_assert_equals(ptr, NULL, map->callbacks); - - mm_free(map); - - total_create = 0; - total_read = 0; - total_update = 0; - total_delete = 0; - total_resize = 0; - }); -});