Added flags to multimap
This commit is contained in:
1 parent
dea981c154
commit
863a3a2d8d
2 files changed
+346
-92
No files matched your search
+231
-92
@@ -354,11 +354,11 @@ struct cmc_callbacks_multimap
|
|||||||
size_t PFX##_key_count(struct SNAME *_map_, K key); \
|
size_t PFX##_key_count(struct SNAME *_map_, K key); \
|
||||||
size_t PFX##_capacity(struct SNAME *_map_); \
|
size_t PFX##_capacity(struct SNAME *_map_); \
|
||||||
double PFX##_load(struct SNAME *_map_); \
|
double PFX##_load(struct SNAME *_map_); \
|
||||||
|
int PFX##_flag(struct SNAME *_map_); \
|
||||||
/* Collection Utility */ \
|
/* Collection Utility */ \
|
||||||
bool PFX##_resize(struct SNAME *_map_, size_t capacity); \
|
bool PFX##_resize(struct SNAME *_map_, size_t capacity); \
|
||||||
struct SNAME *PFX##_copy_of(struct SNAME *_map_); \
|
struct SNAME *PFX##_copy_of(struct SNAME *_map_); \
|
||||||
bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \
|
bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_); \
|
||||||
bool ignore_key_count); \
|
|
||||||
struct cmc_string PFX##_to_string(struct SNAME *_map_); \
|
struct cmc_string PFX##_to_string(struct SNAME *_map_); \
|
||||||
\
|
\
|
||||||
/* Iterator Functions */ \
|
/* Iterator Functions */ \
|
||||||
@@ -393,6 +393,7 @@ struct cmc_callbacks_multimap
|
|||||||
struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, \
|
struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, \
|
||||||
V value); \
|
V value); \
|
||||||
struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \
|
struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \
|
||||||
|
size_t PFX##_impl_key_count(struct SNAME *_map_, K key); \
|
||||||
size_t PFX##_impl_calculate_size(size_t required); \
|
size_t PFX##_impl_calculate_size(size_t required); \
|
||||||
static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \
|
static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \
|
||||||
static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \
|
static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \
|
||||||
@@ -535,6 +536,7 @@ struct cmc_callbacks_multimap
|
|||||||
sizeof(struct SNAME##_entry *[2]) * _map_->capacity); \
|
sizeof(struct SNAME##_entry *[2]) * _map_->capacity); \
|
||||||
\
|
\
|
||||||
_map_->count = 0; \
|
_map_->count = 0; \
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void PFX##_free(struct SNAME *_map_) \
|
void PFX##_free(struct SNAME *_map_) \
|
||||||
@@ -589,13 +591,15 @@ struct cmc_callbacks_multimap
|
|||||||
\
|
\
|
||||||
if (callbacks) \
|
if (callbacks) \
|
||||||
_map_->callbacks = callbacks; \
|
_map_->callbacks = callbacks; \
|
||||||
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
bool PFX##_insert(struct SNAME *_map_, K key, V value) \
|
bool PFX##_insert(struct SNAME *_map_, K key, V value) \
|
||||||
{ \
|
{ \
|
||||||
if (PFX##_full(_map_)) \
|
if (PFX##_full(_map_)) \
|
||||||
{ \
|
{ \
|
||||||
if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \
|
if (!PFX##_resize(_map_, _map_->capacity + 1)) \
|
||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -618,40 +622,44 @@ struct cmc_callbacks_multimap
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
_map_->count++; \
|
_map_->count++; \
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
\
|
\
|
||||||
return true; \
|
return true; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \
|
bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \
|
||||||
{ \
|
{ \
|
||||||
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
||||||
\
|
\
|
||||||
if (!entry) \
|
if (!entry) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
if (old_value) \
|
if (old_value) \
|
||||||
*old_value = entry->value; \
|
*old_value = entry->value; \
|
||||||
\
|
\
|
||||||
entry->value = new_value; \
|
entry->value = new_value; \
|
||||||
\
|
\
|
||||||
return false; \
|
_map_->flag = cmc_flags.OK; \
|
||||||
|
\
|
||||||
|
return true; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
size_t PFX##_update_all(struct SNAME *_map_, K key, V new_value, \
|
size_t PFX##_update_all(struct SNAME *_map_, K key, V new_value, \
|
||||||
V **old_values) \
|
V **old_values) \
|
||||||
{ \
|
{ \
|
||||||
size_t total = PFX##_key_count(_map_, key); \
|
if (PFX##_empty(_map_)) \
|
||||||
size_t index = 0; \
|
|
||||||
\
|
|
||||||
if (total == 0) \
|
|
||||||
return total; \
|
|
||||||
\
|
|
||||||
if (old_values) \
|
|
||||||
{ \
|
{ \
|
||||||
*old_values = _map_->alloc->malloc(sizeof(V) * total); \
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
\
|
return 0; \
|
||||||
if (!(*old_values)) \
|
|
||||||
return false; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
size_t hash = _map_->f_key->hash(key); \
|
size_t hash = _map_->f_key->hash(key); \
|
||||||
@@ -659,24 +667,60 @@ struct cmc_callbacks_multimap
|
|||||||
struct SNAME##_entry *entry = \
|
struct SNAME##_entry *entry = \
|
||||||
_map_->buffer[hash % _map_->capacity][0]; \
|
_map_->buffer[hash % _map_->capacity][0]; \
|
||||||
\
|
\
|
||||||
|
if (entry == NULL) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (old_values) \
|
||||||
|
{ \
|
||||||
|
size_t total = PFX##_impl_key_count(_map_, key); \
|
||||||
|
\
|
||||||
|
if (total == 0) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
*old_values = _map_->alloc->malloc(sizeof(V) * total); \
|
||||||
|
\
|
||||||
|
if (!(*old_values)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.ALLOC; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
size_t index = 0; \
|
||||||
|
\
|
||||||
while (entry != NULL) \
|
while (entry != NULL) \
|
||||||
{ \
|
{ \
|
||||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||||
{ \
|
{ \
|
||||||
if (old_values) \
|
if (old_values) \
|
||||||
(*old_values)[index++] = entry->value; \
|
(*old_values)[index] = entry->value; \
|
||||||
\
|
\
|
||||||
|
index++; \
|
||||||
entry->value = new_value; \
|
entry->value = new_value; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
entry = entry->next; \
|
entry = entry->next; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
|
\
|
||||||
return index; \
|
return index; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \
|
bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \
|
||||||
{ \
|
{ \
|
||||||
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
size_t hash = _map_->f_key->hash(key); \
|
size_t hash = _map_->f_key->hash(key); \
|
||||||
\
|
\
|
||||||
struct SNAME##_entry **head = \
|
struct SNAME##_entry **head = \
|
||||||
@@ -685,7 +729,10 @@ struct cmc_callbacks_multimap
|
|||||||
&(_map_->buffer[hash % _map_->capacity][1]); \
|
&(_map_->buffer[hash % _map_->capacity][1]); \
|
||||||
\
|
\
|
||||||
if (*head == NULL) \
|
if (*head == NULL) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
struct SNAME##_entry *entry = *head; \
|
struct SNAME##_entry *entry = *head; \
|
||||||
\
|
\
|
||||||
@@ -700,7 +747,10 @@ struct cmc_callbacks_multimap
|
|||||||
*out_value = entry->value; \
|
*out_value = entry->value; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
@@ -732,18 +782,28 @@ struct cmc_callbacks_multimap
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
if (!found) \
|
if (!found) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
_map_->alloc->free(entry); \
|
_map_->alloc->free(entry); \
|
||||||
\
|
\
|
||||||
_map_->count--; \
|
_map_->count--; \
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
\
|
\
|
||||||
return true; \
|
return true; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
size_t PFX##_remove_all(struct SNAME *_map_, K key, V **out_values) \
|
size_t PFX##_remove_all(struct SNAME *_map_, K key, V **out_values) \
|
||||||
{ \
|
{ \
|
||||||
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
size_t hash = _map_->f_key->hash(key); \
|
size_t hash = _map_->f_key->hash(key); \
|
||||||
\
|
\
|
||||||
struct SNAME##_entry **head = \
|
struct SNAME##_entry **head = \
|
||||||
@@ -752,15 +812,31 @@ struct cmc_callbacks_multimap
|
|||||||
&(_map_->buffer[hash % _map_->capacity][1]); \
|
&(_map_->buffer[hash % _map_->capacity][1]); \
|
||||||
\
|
\
|
||||||
if (*head == NULL) \
|
if (*head == NULL) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return 0; \
|
return 0; \
|
||||||
\
|
} \
|
||||||
size_t total = PFX##_key_count(_map_, key); \
|
|
||||||
size_t index = 0; \
|
|
||||||
\
|
\
|
||||||
if (out_values) \
|
if (out_values) \
|
||||||
*out_values = \
|
{ \
|
||||||
_map_->alloc->malloc(sizeof(struct SNAME##_entry) * total); \
|
size_t total = PFX##_impl_key_count(_map_, key); \
|
||||||
\
|
\
|
||||||
|
if (total == 0) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
*out_values = _map_->alloc->malloc(sizeof(V) * total); \
|
||||||
|
\
|
||||||
|
if (!(*out_values)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.ALLOC; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
size_t index = 0; \
|
||||||
struct SNAME##_entry *entry = *head; \
|
struct SNAME##_entry *entry = *head; \
|
||||||
\
|
\
|
||||||
if (entry->next == NULL) \
|
if (entry->next == NULL) \
|
||||||
@@ -769,8 +845,9 @@ struct cmc_callbacks_multimap
|
|||||||
*tail = NULL; \
|
*tail = NULL; \
|
||||||
\
|
\
|
||||||
if (out_values) \
|
if (out_values) \
|
||||||
(*out_values)[index++] = entry->value; \
|
(*out_values)[index] = entry->value; \
|
||||||
\
|
\
|
||||||
|
index++; \
|
||||||
_map_->alloc->free(entry); \
|
_map_->alloc->free(entry); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
@@ -784,7 +861,7 @@ struct cmc_callbacks_multimap
|
|||||||
if (*tail == entry) \
|
if (*tail == entry) \
|
||||||
*tail = entry->prev; \
|
*tail = entry->prev; \
|
||||||
\
|
\
|
||||||
struct SNAME##_entry *temp = entry->next; \
|
struct SNAME##_entry *next = entry->next; \
|
||||||
\
|
\
|
||||||
if (entry->prev != NULL) \
|
if (entry->prev != NULL) \
|
||||||
entry->prev->next = entry->next; \
|
entry->prev->next = entry->next; \
|
||||||
@@ -792,11 +869,12 @@ struct cmc_callbacks_multimap
|
|||||||
entry->next->prev = entry->prev; \
|
entry->next->prev = entry->prev; \
|
||||||
\
|
\
|
||||||
if (out_values) \
|
if (out_values) \
|
||||||
(*out_values)[index++] = entry->value; \
|
(*out_values)[index] = entry->value; \
|
||||||
\
|
\
|
||||||
|
index++; \
|
||||||
_map_->alloc->free(entry); \
|
_map_->alloc->free(entry); \
|
||||||
\
|
\
|
||||||
entry = temp; \
|
entry = next; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
entry = entry->next; \
|
entry = entry->next; \
|
||||||
@@ -804,6 +882,7 @@ struct cmc_callbacks_multimap
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
_map_->count -= index; \
|
_map_->count -= index; \
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
\
|
\
|
||||||
return index; \
|
return index; \
|
||||||
} \
|
} \
|
||||||
@@ -811,7 +890,13 @@ struct cmc_callbacks_multimap
|
|||||||
bool PFX##_max(struct SNAME *_map_, K *key, V *value) \
|
bool PFX##_max(struct SNAME *_map_, K *key, V *value) \
|
||||||
{ \
|
{ \
|
||||||
if (PFX##_empty(_map_)) \
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
K max_key; \
|
||||||
|
V max_val; \
|
||||||
\
|
\
|
||||||
struct SNAME##_iter iter; \
|
struct SNAME##_iter iter; \
|
||||||
\
|
\
|
||||||
@@ -824,23 +909,36 @@ struct cmc_callbacks_multimap
|
|||||||
\
|
\
|
||||||
if (index == 0) \
|
if (index == 0) \
|
||||||
{ \
|
{ \
|
||||||
*key = result_key; \
|
max_key = result_key; \
|
||||||
*value = result_value; \
|
max_val = result_value; \
|
||||||
} \
|
} \
|
||||||
else if (_map_->f_key->cmp(result_key, *key) > 0) \
|
else if (_map_->f_key->cmp(result_key, max_key) > 0) \
|
||||||
{ \
|
{ \
|
||||||
*key = result_key; \
|
max_key = result_key; \
|
||||||
*value = result_value; \
|
max_val = result_value; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
if (key) \
|
||||||
|
*key = max_key; \
|
||||||
|
if (value) \
|
||||||
|
*value = max_val; \
|
||||||
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
|
\
|
||||||
return true; \
|
return true; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
bool PFX##_min(struct SNAME *_map_, K *key, V *value) \
|
bool PFX##_min(struct SNAME *_map_, K *key, V *value) \
|
||||||
{ \
|
{ \
|
||||||
if (PFX##_empty(_map_)) \
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
K min_key; \
|
||||||
|
V min_val; \
|
||||||
\
|
\
|
||||||
struct SNAME##_iter iter; \
|
struct SNAME##_iter iter; \
|
||||||
\
|
\
|
||||||
@@ -853,35 +951,64 @@ struct cmc_callbacks_multimap
|
|||||||
\
|
\
|
||||||
if (index == 0) \
|
if (index == 0) \
|
||||||
{ \
|
{ \
|
||||||
*key = result_key; \
|
min_key = result_key; \
|
||||||
*value = result_value; \
|
min_val = result_value; \
|
||||||
} \
|
} \
|
||||||
else if (_map_->f_key->cmp(result_key, *key) < 0) \
|
else if (_map_->f_key->cmp(result_key, min_key) < 0) \
|
||||||
{ \
|
{ \
|
||||||
*key = result_key; \
|
min_key = result_key; \
|
||||||
*value = result_value; \
|
min_val = result_value; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
if (key) \
|
||||||
|
*key = min_key; \
|
||||||
|
if (value) \
|
||||||
|
*value = min_val; \
|
||||||
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
|
\
|
||||||
return true; \
|
return true; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
V PFX##_get(struct SNAME *_map_, K key) \
|
V PFX##_get(struct SNAME *_map_, K key) \
|
||||||
{ \
|
{ \
|
||||||
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
||||||
\
|
\
|
||||||
if (!entry) \
|
if (!entry) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return (V){ 0 }; \
|
return (V){ 0 }; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
\
|
\
|
||||||
return entry->value; \
|
return entry->value; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
V *PFX##_get_ref(struct SNAME *_map_, K key) \
|
V *PFX##_get_ref(struct SNAME *_map_, K key) \
|
||||||
{ \
|
{ \
|
||||||
|
if (PFX##_empty(_map_)) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.EMPTY; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
||||||
\
|
\
|
||||||
if (!entry) \
|
if (!entry) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.NOT_FOUND; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
\
|
\
|
||||||
return &(entry->value); \
|
return &(entry->value); \
|
||||||
} \
|
} \
|
||||||
@@ -908,25 +1035,7 @@ struct cmc_callbacks_multimap
|
|||||||
\
|
\
|
||||||
size_t PFX##_key_count(struct SNAME *_map_, K key) \
|
size_t PFX##_key_count(struct SNAME *_map_, K key) \
|
||||||
{ \
|
{ \
|
||||||
size_t hash = _map_->f_key->hash(key); \
|
return PFX##_impl_key_count(_map_, key); \
|
||||||
\
|
|
||||||
struct SNAME##_entry *entry = \
|
|
||||||
_map_->buffer[hash % _map_->capacity][0]; \
|
|
||||||
\
|
|
||||||
size_t total_count = 0; \
|
|
||||||
\
|
|
||||||
if (!entry) \
|
|
||||||
return total_count; \
|
|
||||||
\
|
|
||||||
while (entry != NULL) \
|
|
||||||
{ \
|
|
||||||
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
|
||||||
total_count++; \
|
|
||||||
\
|
|
||||||
entry = entry->next; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return total_count; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
size_t PFX##_capacity(struct SNAME *_map_) \
|
size_t PFX##_capacity(struct SNAME *_map_) \
|
||||||
@@ -939,31 +1048,47 @@ struct cmc_callbacks_multimap
|
|||||||
return _map_->load; \
|
return _map_->load; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
int PFX##_flag(struct SNAME *_map_) \
|
||||||
|
{ \
|
||||||
|
return _map_->flag; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
bool PFX##_resize(struct SNAME *_map_, size_t capacity) \
|
bool PFX##_resize(struct SNAME *_map_, size_t capacity) \
|
||||||
{ \
|
{ \
|
||||||
if (PFX##_capacity(_map_) == capacity) \
|
_map_->flag = cmc_flags.OK; \
|
||||||
|
\
|
||||||
|
if (_map_->capacity == capacity) \
|
||||||
return true; \
|
return true; \
|
||||||
\
|
\
|
||||||
if (PFX##_capacity(_map_) > capacity / _map_->load) \
|
if (_map_->capacity > capacity / _map_->load) \
|
||||||
return true; \
|
return true; \
|
||||||
\
|
\
|
||||||
/* Prevent integer overflow */ \
|
/* Prevent integer overflow */ \
|
||||||
if (capacity >= UINTMAX_MAX * _map_->load) \
|
if (capacity >= UINTMAX_MAX * _map_->load) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.ERROR; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
/* Calculate required capacity based on the prime numbers */ \
|
/* Calculate required capacity based on the prime numbers */ \
|
||||||
size_t theoretical_size = PFX##_impl_calculate_size(capacity); \
|
size_t theoretical_size = PFX##_impl_calculate_size(capacity); \
|
||||||
\
|
\
|
||||||
/* Not possible to shrink with current available prime numbers */ \
|
/* Not possible to shrink with current available prime numbers */ \
|
||||||
if (theoretical_size < PFX##_count(_map_) / _map_->load) \
|
if (theoretical_size < _map_->count / _map_->load) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.ERROR; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
struct SNAME *_new_map_ = \
|
struct SNAME *_new_map_ = \
|
||||||
PFX##_new_custom(capacity, _map_->load, _map_->f_key, \
|
PFX##_new_custom(capacity, _map_->load, _map_->f_key, \
|
||||||
_map_->f_val, _map_->alloc, _map_->callbacks); \
|
_map_->f_val, _map_->alloc, _map_->callbacks); \
|
||||||
\
|
\
|
||||||
if (!_new_map_) \
|
if (!_new_map_) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.ALLOC; \
|
||||||
return false; \
|
return false; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
struct SNAME##_iter iter; \
|
struct SNAME##_iter iter; \
|
||||||
\
|
\
|
||||||
@@ -976,9 +1101,11 @@ struct cmc_callbacks_multimap
|
|||||||
PFX##_insert(_new_map_, key, value); \
|
PFX##_insert(_new_map_, key, value); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
if (PFX##_count(_map_) != PFX##_count(_new_map_)) \
|
if (_map_->count != _new_map_->count) \
|
||||||
{ \
|
{ \
|
||||||
PFX##_free(_new_map_); \
|
PFX##_free(_new_map_); \
|
||||||
|
\
|
||||||
|
_map_->flag = cmc_flags.ERROR; \
|
||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -1002,7 +1129,10 @@ struct cmc_callbacks_multimap
|
|||||||
_map_->f_val, _map_->alloc, _map_->callbacks); \
|
_map_->f_val, _map_->alloc, _map_->callbacks); \
|
||||||
\
|
\
|
||||||
if (!result) \
|
if (!result) \
|
||||||
|
{ \
|
||||||
|
_map_->flag = cmc_flags.ERROR; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
struct SNAME##_iter iter; \
|
struct SNAME##_iter iter; \
|
||||||
PFX##_iter_init(&iter, _map_); \
|
PFX##_iter_init(&iter, _map_); \
|
||||||
@@ -1024,44 +1154,30 @@ struct cmc_callbacks_multimap
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
_map_->flag = cmc_flags.OK; \
|
||||||
|
\
|
||||||
return result; \
|
return result; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \
|
bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_) \
|
||||||
bool ignore_key_count) \
|
|
||||||
{ \
|
{ \
|
||||||
if (ignore_key_count) \
|
_map1_->flag = cmc_flags.OK; \
|
||||||
{ \
|
_map2_->flag = cmc_flags.OK; \
|
||||||
struct SNAME##_iter iter; \
|
|
||||||
PFX##_iter_init(&iter, _map1_); \
|
|
||||||
\
|
\
|
||||||
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \
|
if (_map1_->count != _map2_->count) \
|
||||||
PFX##_iter_next(&iter)) \
|
return false; \
|
||||||
{ \
|
\
|
||||||
if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == \
|
struct SNAME##_iter iter; \
|
||||||
NULL) \
|
PFX##_iter_init(&iter, _map1_); \
|
||||||
return false; \
|
\
|
||||||
} \
|
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \
|
||||||
} \
|
PFX##_iter_next(&iter)) \
|
||||||
else \
|
|
||||||
{ \
|
{ \
|
||||||
/* Since the key count matters this can be checked and an */ \
|
K key = PFX##_iter_key(&iter); \
|
||||||
/* early exit */ \
|
\
|
||||||
if (PFX##_count(_map1_) != PFX##_count(_map2_)) \
|
if (PFX##_impl_key_count(_map1_, key) != \
|
||||||
|
PFX##_impl_key_count(_map2_, key)) \
|
||||||
return false; \
|
return false; \
|
||||||
\
|
|
||||||
struct SNAME##_iter iter; \
|
|
||||||
PFX##_iter_init(&iter, _map1_); \
|
|
||||||
\
|
|
||||||
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \
|
|
||||||
PFX##_iter_next(&iter)) \
|
|
||||||
{ \
|
|
||||||
K key = PFX##_iter_key(&iter); \
|
|
||||||
\
|
|
||||||
if (PFX##_key_count(_map1_, key) != \
|
|
||||||
PFX##_key_count(_map2_, key)) \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
return true; \
|
return true; \
|
||||||
@@ -1237,13 +1353,13 @@ struct cmc_callbacks_multimap
|
|||||||
if (iter->end) \
|
if (iter->end) \
|
||||||
return false; \
|
return false; \
|
||||||
\
|
\
|
||||||
if (iter->index + 1 == PFX##_count(iter->target)) \
|
if (iter->index + 1 == iter->target->count) \
|
||||||
{ \
|
{ \
|
||||||
iter->end = true; \
|
iter->end = true; \
|
||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \
|
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||||
return false; \
|
return false; \
|
||||||
\
|
\
|
||||||
for (size_t i = 0; i < steps; i++) \
|
for (size_t i = 0; i < steps; i++) \
|
||||||
@@ -1277,7 +1393,7 @@ struct cmc_callbacks_multimap
|
|||||||
/* given index */ \
|
/* given index */ \
|
||||||
bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \
|
bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \
|
||||||
{ \
|
{ \
|
||||||
if (index >= PFX##_count(iter->target)) \
|
if (index >= iter->target->count) \
|
||||||
return false; \
|
return false; \
|
||||||
\
|
\
|
||||||
if (iter->index > index) \
|
if (iter->index > index) \
|
||||||
@@ -1352,6 +1468,29 @@ struct cmc_callbacks_multimap
|
|||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
size_t PFX##_impl_key_count(struct SNAME *_map_, K key) \
|
||||||
|
{ \
|
||||||
|
size_t hash = _map_->f_key->hash(key); \
|
||||||
|
\
|
||||||
|
struct SNAME##_entry *entry = \
|
||||||
|
_map_->buffer[hash % _map_->capacity][0]; \
|
||||||
|
\
|
||||||
|
size_t total_count = 0; \
|
||||||
|
\
|
||||||
|
if (!entry) \
|
||||||
|
return total_count; \
|
||||||
|
\
|
||||||
|
while (entry != NULL) \
|
||||||
|
{ \
|
||||||
|
if (_map_->f_key->cmp(entry->key, key) == 0) \
|
||||||
|
total_count++; \
|
||||||
|
\
|
||||||
|
entry = entry->next; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return total_count; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
size_t PFX##_impl_calculate_size(size_t required) \
|
size_t PFX##_impl_calculate_size(size_t required) \
|
||||||
{ \
|
{ \
|
||||||
const size_t count = \
|
const size_t count = \
|
||||||
|
|||||||
@@ -152,4 +152,119 @@ CMC_CREATE_UNIT(multimap_test, true, {
|
|||||||
|
|
||||||
mm_free(map);
|
mm_free(map);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
CMC_CREATE_TEST(flags, {
|
||||||
|
struct multimap *map = mm_new(100, 0.8, mm_ftab_key, mm_ftab_val);
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user