Renamed multimap to hashmultimap

This commit is contained in:
Leonardo committed 2020-05-05 18:00:56 -03:00
1 parent 9962981047
commit c41ce371d3
6 files changed
+794 -781

No files matched your search

+2 -2
View File
@@ -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'},
+41 -40
View File
@@ -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<K = int, V = List<int>> maps an integer to a list of integer.
* MultiMap<K = int, V = int> maps many integer keys to integer values.
* HashMultiMap<K = int, V = int> 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 */
+4 -4
View File
@@ -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);
@@ -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;
}
+486
View File
@@ -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;
});
});
-486
View File
@@ -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;
});
});