Renamed multimap to hashmultimap
This commit is contained in:
1 parent
9962981047
commit
c41ce371d3
6 files changed
+794
-781
No files matched your search
+2
-2
@@ -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'},
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
});
|
||||
});
|
||||
@@ -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;
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user