HashMultiMap no longer depends on ITER
This commit is contained in:
1 parent
b51efa5c45
commit
6308936e65
9 files changed
+278
-139
No files matched your search
@@ -8,7 +8,8 @@
|
||||
|
||||
#include "../../util/twister.c"
|
||||
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMULTIMAP, (hmm, hashmultimap, , uint64_t, uint64_t))
|
||||
CMC_CMC_HASHMULTIMAP_CORE(PUBLIC, HEADER, (hmm, hashmultimap, , uint64_t, uint64_t))
|
||||
CMC_CMC_HASHMULTIMAP_CORE(PUBLIC, SOURCE, (hmm, hashmultimap, , uint64_t, uint64_t))
|
||||
|
||||
int cmp(uint64_t a, uint64_t b)
|
||||
{
|
||||
|
||||
+5
-5
@@ -86,10 +86,10 @@
|
||||
/* Current array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Currently used bits */\
|
||||
/* This should always be true: */\
|
||||
/* capacity - count < sizeof(cmc_bitset_word) * CHAR_BIT */\
|
||||
size_t count;\
|
||||
/* Currently used bits */ \
|
||||
/* This should always be true: */ \
|
||||
/* capacity - count < sizeof(cmc_bitset_word) * CHAR_BIT */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
@@ -156,7 +156,7 @@
|
||||
/* Iterator Initialization */ \
|
||||
/* Iterator State */ \
|
||||
/* Iterator Movement */ \
|
||||
/* Iterator Access */ \
|
||||
/* Iterator Access */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
|
||||
+4
-4
@@ -461,8 +461,8 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
K max_key = (K) { 0 }; \
|
||||
V max_val = (V) { 0 }; \
|
||||
K max_key = (K){ 0 }; \
|
||||
V max_val = (V){ 0 }; \
|
||||
size_t first = 0; \
|
||||
\
|
||||
for (; first < _map_->capacity; first++) \
|
||||
@@ -505,8 +505,8 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
K min_key = (K) { 0 }; \
|
||||
V min_val = (V) { 0 }; \
|
||||
K min_key = (K){ 0 }; \
|
||||
V min_val = (V){ 0 }; \
|
||||
size_t first = 0; \
|
||||
\
|
||||
for (; first < _map_->capacity; first++) \
|
||||
|
||||
+91
-69
@@ -300,7 +300,7 @@
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
while (scan) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *next = scan->next; \
|
||||
\
|
||||
@@ -329,7 +329,7 @@
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[index][0]; \
|
||||
\
|
||||
if (scan != NULL) \
|
||||
if (scan) \
|
||||
{ \
|
||||
if (scan->next == NULL && scan->prev == NULL) \
|
||||
{ \
|
||||
@@ -342,7 +342,7 @@
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
while (scan != NULL) \
|
||||
while (scan) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *tmp = scan; \
|
||||
\
|
||||
@@ -481,7 +481,7 @@
|
||||
\
|
||||
size_t index = 0; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
while (entry) \
|
||||
{ \
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||
{ \
|
||||
@@ -543,7 +543,7 @@
|
||||
{ \
|
||||
bool found = false; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
while (entry) \
|
||||
{ \
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||
{ \
|
||||
@@ -552,9 +552,9 @@
|
||||
if (*tail == entry) \
|
||||
*tail = entry->prev; \
|
||||
\
|
||||
if (entry->prev != NULL) \
|
||||
if (entry->prev) \
|
||||
entry->prev->next = entry->next; \
|
||||
if (entry->next != NULL) \
|
||||
if (entry->next) \
|
||||
entry->next->prev = entry->prev; \
|
||||
\
|
||||
if (out_value) \
|
||||
@@ -639,7 +639,7 @@
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
while (entry != NULL) \
|
||||
while (entry) \
|
||||
{ \
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||
{ \
|
||||
@@ -650,9 +650,9 @@
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *next = entry->next; \
|
||||
\
|
||||
if (entry->prev != NULL) \
|
||||
if (entry->prev) \
|
||||
entry->prev->next = entry->next; \
|
||||
if (entry->next != NULL) \
|
||||
if (entry->next) \
|
||||
entry->next->prev = entry->prev; \
|
||||
\
|
||||
if (out_values) \
|
||||
@@ -684,27 +684,30 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
K max_key = (K) { 0 }; \
|
||||
V max_val = (V) { 0 }; \
|
||||
bool first = true; \
|
||||
K max_key = (K){ 0 }; \
|
||||
V max_val = (V){ 0 }; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \
|
||||
\
|
||||
/* TODO Turn this into a normal loop */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
K result_key = CMC_(PFX, _iter_key)(&iter); \
|
||||
V result_value = CMC_(PFX, _iter_value)(&iter); \
|
||||
size_t index = CMC_(PFX, _iter_index)(&iter); \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
if (index == 0) \
|
||||
while (scan) \
|
||||
{ \
|
||||
max_key = result_key; \
|
||||
max_val = result_value; \
|
||||
} \
|
||||
else if (_map_->f_key->cmp(result_key, max_key) > 0) \
|
||||
{ \
|
||||
max_key = result_key; \
|
||||
max_val = result_value; \
|
||||
if (first) \
|
||||
{ \
|
||||
max_key = scan->key; \
|
||||
max_val = scan->value; \
|
||||
\
|
||||
first = false; \
|
||||
} \
|
||||
else if (_map_->f_key->cmp(scan->key, max_key) > 0) \
|
||||
{ \
|
||||
max_key = scan->key; \
|
||||
max_val = scan->value; \
|
||||
} \
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -728,27 +731,30 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
K min_key = (K) { 0 }; \
|
||||
V min_val = (V) { 0 }; \
|
||||
bool first = true; \
|
||||
K min_key = (K){ 0 }; \
|
||||
V min_val = (V){ 0 }; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \
|
||||
\
|
||||
/* TODO Turn this into a normal loop */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
K result_key = CMC_(PFX, _iter_key)(&iter); \
|
||||
V result_value = CMC_(PFX, _iter_value)(&iter); \
|
||||
size_t index = CMC_(PFX, _iter_index)(&iter); \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
if (index == 0) \
|
||||
while (scan) \
|
||||
{ \
|
||||
min_key = result_key; \
|
||||
min_val = result_value; \
|
||||
} \
|
||||
else if (_map_->f_key->cmp(result_key, min_key) < 0) \
|
||||
{ \
|
||||
min_key = result_key; \
|
||||
min_val = result_value; \
|
||||
if (first) \
|
||||
{ \
|
||||
min_key = scan->key; \
|
||||
min_val = scan->value; \
|
||||
\
|
||||
first = false; \
|
||||
} \
|
||||
else if (_map_->f_key->cmp(scan->key, min_key) < 0) \
|
||||
{ \
|
||||
min_key = scan->key; \
|
||||
min_val = scan->value; \
|
||||
} \
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -893,16 +899,17 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \
|
||||
\
|
||||
/* TODO Turn this into a normal loop */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
K key = CMC_(PFX, _iter_key)(&iter); \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
/* TODO check for errors */ \
|
||||
CMC_(PFX, _insert)(_new_map_, key, value); \
|
||||
while (scan) \
|
||||
{ \
|
||||
/* TODO check for errors */ \
|
||||
CMC_(PFX, _insert)(_new_map_, scan->key, scan->value); \
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (_map_->count != _new_map_->count) \
|
||||
@@ -946,23 +953,28 @@
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(_map_)) \
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
/* TODO Turn this into a normal loop */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
while (scan) \
|
||||
{ \
|
||||
K key = CMC_(PFX, _iter_key)(&iter); \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
K key;\
|
||||
V value;\
|
||||
\
|
||||
if (_map_->f_key->cpy) \
|
||||
key = _map_->f_key->cpy(key); \
|
||||
key = _map_->f_key->cpy(scan->key); \
|
||||
else\
|
||||
key = scan->key;\
|
||||
if (_map_->f_val->cpy) \
|
||||
value = _map_->f_val->cpy(value); \
|
||||
value = _map_->f_val->cpy(scan->value); \
|
||||
else\
|
||||
value = scan->value;\
|
||||
\
|
||||
/* TODO check for errors */ \
|
||||
CMC_(PFX, _insert)(result, key, value); \
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -980,15 +992,25 @@
|
||||
if (_map1_->count != _map2_->count) \
|
||||
return false; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map1_); \
|
||||
/* Optimize loop using the smallest hashtable */ \
|
||||
struct SNAME *_map_a_; \
|
||||
struct SNAME *_map_b_; \
|
||||
\
|
||||
/* TODO Turn this into a normal loop */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
_map_a_ = _map1_->capacity < _map2_->capacity ? _map1_ : _map2_; \
|
||||
_map_b_ = _map_a_ == _map1_ ? _map2_ : _map1_; \
|
||||
\
|
||||
for (size_t i = 0; i < _map_a_->capacity; i++) \
|
||||
{ \
|
||||
K key = CMC_(PFX, _iter_key)(&iter); \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_a_->buffer[i][0]; \
|
||||
\
|
||||
if (CMC_(PFX, _impl_key_count)(_map1_, key) != CMC_(PFX, _impl_key_count)(_map2_, key)) \
|
||||
return false; \
|
||||
while (scan) \
|
||||
{ \
|
||||
/* OPTIMIZE - This is calling key_count for repeating keys */\
|
||||
if (CMC_(PFX, _impl_key_count)(_map_a_, scan->key) != CMC_(PFX, _impl_key_count)(_map_b_, scan->key))\
|
||||
return false;\
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
@@ -1015,7 +1037,7 @@
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[hash % _map_->capacity][0]; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
while (entry) \
|
||||
{ \
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||
return entry; \
|
||||
@@ -1037,7 +1059,7 @@
|
||||
if (!entry) \
|
||||
return total_count; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
while (entry) \
|
||||
{ \
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||
total_count++; \
|
||||
|
||||
@@ -477,7 +477,7 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
V max_val = (V) { 0 }; \
|
||||
V max_val = (V){ 0 }; \
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
|
||||
\
|
||||
/* TODO transform this into a normal loop */ \
|
||||
@@ -510,7 +510,7 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
V min_val = (V) { 0 }; \
|
||||
V min_val = (V){ 0 }; \
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
|
||||
\
|
||||
/* TODO transform this into a normal loop */ \
|
||||
|
||||
+2
-2
@@ -378,7 +378,7 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
V max_val = (V) { 0 }; \
|
||||
V max_val = (V){ 0 }; \
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
|
||||
\
|
||||
/* TODO turn this into a normal loop */ \
|
||||
@@ -411,7 +411,7 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
V min_val = (V) { 0 }; \
|
||||
V min_val = (V){ 0 }; \
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
|
||||
\
|
||||
/* TODO turn this into a normal loop */ \
|
||||
|
||||
@@ -557,7 +557,6 @@
|
||||
return true; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ void hmm_clear(struct hashmultimap *_map_)
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
struct hashmultimap_entry *scan = _map_->buffer[i][0];
|
||||
while (scan != ((void *)0))
|
||||
while (scan)
|
||||
{
|
||||
struct hashmultimap_entry *next = scan->next;
|
||||
if (_map_->f_key->free)
|
||||
@@ -69,7 +69,7 @@ void hmm_free(struct hashmultimap *_map_)
|
||||
while (index < _map_->capacity)
|
||||
{
|
||||
struct hashmultimap_entry *scan = _map_->buffer[index][0];
|
||||
if (scan != ((void *)0))
|
||||
if (scan)
|
||||
{
|
||||
if (scan->next == ((void *)0) && scan->prev == ((void *)0))
|
||||
{
|
||||
@@ -81,7 +81,7 @@ void hmm_free(struct hashmultimap *_map_)
|
||||
}
|
||||
else
|
||||
{
|
||||
while (scan != ((void *)0))
|
||||
while (scan)
|
||||
{
|
||||
struct hashmultimap_entry *tmp = scan;
|
||||
scan = scan->next;
|
||||
@@ -188,7 +188,7 @@ size_t hmm_update_all(struct hashmultimap *_map_, size_t key, size_t new_value,
|
||||
}
|
||||
}
|
||||
size_t index = 0;
|
||||
while (entry != ((void *)0))
|
||||
while (entry)
|
||||
{
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0)
|
||||
{
|
||||
@@ -239,7 +239,7 @@ _Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value)
|
||||
else
|
||||
{
|
||||
_Bool found = 0;
|
||||
while (entry != ((void *)0))
|
||||
while (entry)
|
||||
{
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0)
|
||||
{
|
||||
@@ -247,9 +247,9 @@ _Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value)
|
||||
*head = entry->next;
|
||||
if (*tail == entry)
|
||||
*tail = entry->prev;
|
||||
if (entry->prev != ((void *)0))
|
||||
if (entry->prev)
|
||||
entry->prev->next = entry->next;
|
||||
if (entry->next != ((void *)0))
|
||||
if (entry->next)
|
||||
entry->next->prev = entry->prev;
|
||||
if (out_value)
|
||||
*out_value = entry->value;
|
||||
@@ -316,7 +316,7 @@ size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, size_t **out_value
|
||||
}
|
||||
else
|
||||
{
|
||||
while (entry != ((void *)0))
|
||||
while (entry)
|
||||
{
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0)
|
||||
{
|
||||
@@ -325,9 +325,9 @@ size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, size_t **out_value
|
||||
if (*tail == entry)
|
||||
*tail = entry->prev;
|
||||
struct hashmultimap_entry *next = entry->next;
|
||||
if (entry->prev != ((void *)0))
|
||||
if (entry->prev)
|
||||
entry->prev->next = entry->next;
|
||||
if (entry->next != ((void *)0))
|
||||
if (entry->next)
|
||||
entry->next->prev = entry->prev;
|
||||
if (out_values)
|
||||
(*out_values)[index] = entry->value;
|
||||
@@ -353,23 +353,26 @@ _Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value)
|
||||
_map_->flag = CMC_FLAG_EMPTY;
|
||||
return 0;
|
||||
}
|
||||
_Bool first = 1;
|
||||
size_t max_key = (size_t){ 0 };
|
||||
size_t max_val = (size_t){ 0 };
|
||||
struct hashmultimap_iter iter = hmm_iter_start(_map_);
|
||||
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
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)
|
||||
struct hashmultimap_entry *scan = _map_->buffer[i][0];
|
||||
while (scan)
|
||||
{
|
||||
max_key = result_key;
|
||||
max_val = result_value;
|
||||
}
|
||||
else if (_map_->f_key->cmp(result_key, max_key) > 0)
|
||||
{
|
||||
max_key = result_key;
|
||||
max_val = result_value;
|
||||
if (first)
|
||||
{
|
||||
max_key = scan->key;
|
||||
max_val = scan->value;
|
||||
first = 0;
|
||||
}
|
||||
else if (_map_->f_key->cmp(scan->key, max_key) > 0)
|
||||
{
|
||||
max_key = scan->key;
|
||||
max_val = scan->value;
|
||||
}
|
||||
scan = scan->next;
|
||||
}
|
||||
}
|
||||
if (key)
|
||||
@@ -389,23 +392,26 @@ _Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value)
|
||||
_map_->flag = CMC_FLAG_EMPTY;
|
||||
return 0;
|
||||
}
|
||||
_Bool first = 1;
|
||||
size_t min_key = (size_t){ 0 };
|
||||
size_t min_val = (size_t){ 0 };
|
||||
struct hashmultimap_iter iter = hmm_iter_start(_map_);
|
||||
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
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)
|
||||
struct hashmultimap_entry *scan = _map_->buffer[i][0];
|
||||
while (scan)
|
||||
{
|
||||
min_key = result_key;
|
||||
min_val = result_value;
|
||||
}
|
||||
else if (_map_->f_key->cmp(result_key, min_key) < 0)
|
||||
{
|
||||
min_key = result_key;
|
||||
min_val = result_value;
|
||||
if (first)
|
||||
{
|
||||
min_key = scan->key;
|
||||
min_val = scan->value;
|
||||
first = 0;
|
||||
}
|
||||
else if (_map_->f_key->cmp(scan->key, min_key) < 0)
|
||||
{
|
||||
min_key = scan->key;
|
||||
min_val = scan->value;
|
||||
}
|
||||
scan = scan->next;
|
||||
}
|
||||
}
|
||||
if (key)
|
||||
@@ -518,12 +524,14 @@ _Bool hmm_resize(struct hashmultimap *_map_, size_t capacity)
|
||||
_map_->flag = CMC_FLAG_ALLOC;
|
||||
return 0;
|
||||
}
|
||||
struct hashmultimap_iter iter = hmm_iter_start(_map_);
|
||||
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
size_t key = hmm_iter_key(&iter);
|
||||
size_t value = hmm_iter_value(&iter);
|
||||
hmm_insert(_new_map_, key, value);
|
||||
struct hashmultimap_entry *scan = _map_->buffer[i][0];
|
||||
while (scan)
|
||||
{
|
||||
hmm_insert(_new_map_, scan->key, scan->value);
|
||||
scan = scan->next;
|
||||
}
|
||||
}
|
||||
if (_map_->count != _new_map_->count)
|
||||
{
|
||||
@@ -555,18 +563,23 @@ struct hashmultimap *hmm_copy_of(struct hashmultimap *_map_)
|
||||
_map_->flag = CMC_FLAG_ERROR;
|
||||
return ((void *)0);
|
||||
}
|
||||
struct hashmultimap_iter iter = hmm_iter_start(_map_);
|
||||
if (!hmm_empty(_map_))
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
|
||||
struct hashmultimap_entry *scan = _map_->buffer[i][0];
|
||||
while (scan)
|
||||
{
|
||||
size_t key = hmm_iter_key(&iter);
|
||||
size_t value = hmm_iter_value(&iter);
|
||||
size_t key;
|
||||
size_t value;
|
||||
if (_map_->f_key->cpy)
|
||||
key = _map_->f_key->cpy(key);
|
||||
key = _map_->f_key->cpy(scan->key);
|
||||
else
|
||||
key = scan->key;
|
||||
if (_map_->f_val->cpy)
|
||||
value = _map_->f_val->cpy(value);
|
||||
value = _map_->f_val->cpy(scan->value);
|
||||
else
|
||||
value = scan->value;
|
||||
hmm_insert(result, key, value);
|
||||
scan = scan->next;
|
||||
}
|
||||
}
|
||||
(result)->callbacks = _map_->callbacks;
|
||||
@@ -579,12 +592,19 @@ _Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_)
|
||||
_map2_->flag = CMC_FLAG_OK;
|
||||
if (_map1_->count != _map2_->count)
|
||||
return 0;
|
||||
struct hashmultimap_iter iter = hmm_iter_start(_map1_);
|
||||
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
|
||||
struct hashmultimap *_map_a_;
|
||||
struct hashmultimap *_map_b_;
|
||||
_map_a_ = _map1_->capacity < _map2_->capacity ? _map1_ : _map2_;
|
||||
_map_b_ = _map_a_ == _map1_ ? _map2_ : _map1_;
|
||||
for (size_t i = 0; i < _map_a_->capacity; i++)
|
||||
{
|
||||
size_t key = hmm_iter_key(&iter);
|
||||
if (hmm_impl_key_count(_map1_, key) != hmm_impl_key_count(_map2_, key))
|
||||
return 0;
|
||||
struct hashmultimap_entry *scan = _map_a_->buffer[i][0];
|
||||
while (scan)
|
||||
{
|
||||
if (hmm_impl_key_count(_map_a_, scan->key) != hmm_impl_key_count(_map_b_, scan->key))
|
||||
return 0;
|
||||
scan = scan->next;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -603,7 +623,7 @@ struct hashmultimap_entry *hmm_impl_get_entry(struct hashmultimap *_map_, size_t
|
||||
{
|
||||
size_t hash = _map_->f_key->hash(key);
|
||||
struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0];
|
||||
while (entry != ((void *)0))
|
||||
while (entry)
|
||||
{
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0)
|
||||
return entry;
|
||||
@@ -618,7 +638,7 @@ size_t hmm_impl_key_count(struct hashmultimap *_map_, size_t key)
|
||||
size_t total_count = 0;
|
||||
if (!entry)
|
||||
return total_count;
|
||||
while (entry != ((void *)0))
|
||||
while (entry)
|
||||
{
|
||||
if (_map_->f_key->cmp(entry->key, key) == 0)
|
||||
total_count++;
|
||||
|
||||
@@ -227,6 +227,103 @@ CMC_CREATE_UNIT(CMCHashMultiMap, true, {
|
||||
hmm_free(map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_max(), {
|
||||
struct hashmultimap *map = hmm_new(50, 0.8, hmm_fkey, hmm_fval);
|
||||
|
||||
size_t max_key;
|
||||
size_t max_val;
|
||||
cmc_assert(!hmm_max(map, &max_key, &max_val));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, map->flag);
|
||||
|
||||
cmc_assert(hmm_insert(map, 1, 2));
|
||||
cmc_assert(hmm_max(map, &max_key, &max_val));
|
||||
cmc_assert_equals(size_t, 1, max_key);
|
||||
cmc_assert_equals(size_t, 2, max_val);
|
||||
|
||||
cmc_assert(hmm_insert(map, 2, 3));
|
||||
cmc_assert(hmm_insert(map, 0, 1));
|
||||
cmc_assert(hmm_max(map, &max_key, &max_val));
|
||||
cmc_assert_equals(size_t, 2, max_key);
|
||||
cmc_assert_equals(size_t, 3, max_val);
|
||||
|
||||
for (size_t i = 3; i <= 100; i++)
|
||||
{
|
||||
cmc_assert(hmm_insert(map, i, i));
|
||||
}
|
||||
|
||||
cmc_assert(hmm_max(map, &max_key, &max_val));
|
||||
cmc_assert_equals(size_t, 100, max_key);
|
||||
cmc_assert_equals(size_t, 100, max_val);
|
||||
|
||||
hmm_free(map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_min(), {
|
||||
struct hashmultimap *map = hmm_new(50, 0.8, hmm_fkey, hmm_fval);
|
||||
|
||||
size_t min_key;
|
||||
size_t min_val;
|
||||
cmc_assert(!hmm_min(map, &min_key, &min_val));
|
||||
cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, map->flag);
|
||||
|
||||
cmc_assert(hmm_insert(map, 1, 2));
|
||||
cmc_assert(hmm_min(map, &min_key, &min_val));
|
||||
cmc_assert_equals(size_t, 1, min_key);
|
||||
cmc_assert_equals(size_t, 2, min_val);
|
||||
|
||||
cmc_assert(hmm_insert(map, 2, 3));
|
||||
cmc_assert(hmm_insert(map, 0, 1));
|
||||
cmc_assert(hmm_min(map, &min_key, &min_val));
|
||||
cmc_assert_equals(size_t, 0, min_key);
|
||||
cmc_assert_equals(size_t, 1, min_val);
|
||||
|
||||
for (size_t i = 3; i <= 100; i++)
|
||||
{
|
||||
cmc_assert(hmm_insert(map, i, i));
|
||||
}
|
||||
|
||||
cmc_assert(hmm_min(map, &min_key, &min_val));
|
||||
cmc_assert_equals(size_t, 0, min_key);
|
||||
cmc_assert_equals(size_t, 1, min_val);
|
||||
|
||||
hmm_free(map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_copy_of(), {
|
||||
struct hashmultimap *map = hmm_new(100, 0.8, hmm_fkey, hmm_fval);
|
||||
|
||||
for (size_t i = 0; i < 1000; i++)
|
||||
hmm_insert(map, i, i);
|
||||
|
||||
struct hashmultimap *map2 = hmm_copy_of(map);
|
||||
|
||||
cmc_assert_equals(size_t, map->count, map2->count);
|
||||
cmc_assert(hmm_equals(map, map2));
|
||||
|
||||
hmm_free(map);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(PFX##_equals(), {
|
||||
struct hashmultimap *map1 = hmm_new(100, 0.8, hmm_fkey, hmm_fval);
|
||||
struct hashmultimap *map2 = hmm_new(100, 0.8, hmm_fkey, hmm_fval);
|
||||
|
||||
cmc_assert(hmm_equals(map1, map2));
|
||||
|
||||
cmc_assert(hmm_insert(map1, 1, 1));
|
||||
cmc_assert(hmm_insert(map2, 1, 1));
|
||||
cmc_assert(hmm_equals(map1, map2));
|
||||
|
||||
for (size_t i = 2; i < 200; i++)
|
||||
{
|
||||
cmc_assert(hmm_insert(map1, i, i) && hmm_insert(map2, i, i));
|
||||
}
|
||||
|
||||
cmc_assert(hmm_equals(map1, map2));
|
||||
|
||||
hmm_free(map1);
|
||||
hmm_free(map2);
|
||||
});
|
||||
|
||||
CMC_CREATE_TEST(key_count, {
|
||||
struct hashmultimap *map = hmm_new(50, 0.8, hmm_fkey, hmm_fval);
|
||||
|
||||
|
||||
Reference in new issue
Block a user