Unified _set and _update functions
Also _remove now accepts an optional parameter if to retrieve or not the removed value. _update also has the same optional parameter that retrieves the old value. The multimap will allocate an array based on the amount of keys and add all the values to that array.
This commit is contained in:
1 parent
855e085996
commit
a1a940399a
3 files changed
+84
-134
No files matched your search
+10
-20
@@ -162,16 +162,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
|
||||
FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
|
||||
FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
|
||||
FMOD V PFX##_get(SNAME *_map_, K key); \
|
||||
FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
|
||||
FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_map_, K key); \
|
||||
FMOD bool PFX##_empty(SNAME *_map_); \
|
||||
@@ -378,20 +377,23 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
if (!entry) \
|
||||
return false; \
|
||||
\
|
||||
*old_value = entry->value; \
|
||||
if (old_value) \
|
||||
*old_value = entry->value; \
|
||||
\
|
||||
entry->value = new_value; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value) \
|
||||
{ \
|
||||
SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \
|
||||
\
|
||||
if (result == NULL) \
|
||||
return false; \
|
||||
\
|
||||
*value = result->value; \
|
||||
if (out_value) \
|
||||
*out_value = result->value; \
|
||||
\
|
||||
result->key = PFX##_impl_default_key(); \
|
||||
result->value = PFX##_impl_default_value(); \
|
||||
@@ -411,10 +413,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_remove(_map_, key, value); \
|
||||
return PFX##_remove(_map_, key, out_value); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
@@ -495,18 +497,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
return &(entry->value); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \
|
||||
{ \
|
||||
SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
||||
\
|
||||
if (!entry) \
|
||||
return false; \
|
||||
\
|
||||
entry->value = new_value; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_map_, K key) \
|
||||
{ \
|
||||
return PFX##_impl_get_entry(_map_, key) != NULL; \
|
||||
|
||||
+10
-20
@@ -115,16 +115,15 @@
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
|
||||
FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
|
||||
FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
|
||||
FMOD V PFX##_get(SNAME *_map_, K key); \
|
||||
FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
|
||||
FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_map_, K key); \
|
||||
FMOD bool PFX##_empty(SNAME *_map_); \
|
||||
@@ -337,20 +336,23 @@
|
||||
if (!node) \
|
||||
return false; \
|
||||
\
|
||||
*old_value = node->value; \
|
||||
if (old_value) \
|
||||
*old_value = node->value; \
|
||||
\
|
||||
node->value = new_value; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value) \
|
||||
{ \
|
||||
SNAME##_node *node = PFX##_impl_get_node(_map_, key); \
|
||||
\
|
||||
if (!node) \
|
||||
return false; \
|
||||
\
|
||||
*value = node->value; \
|
||||
if (out_value) \
|
||||
*out_value = node->value; \
|
||||
\
|
||||
SNAME##_node *temp = NULL, *unbalanced = NULL; \
|
||||
\
|
||||
@@ -476,10 +478,10 @@
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_remove(_map_, key, value); \
|
||||
return PFX##_remove(_map_, key, out_value); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
@@ -536,18 +538,6 @@
|
||||
return &(node->value); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \
|
||||
{ \
|
||||
SNAME##_node *node = PFX##_impl_get_node(_map_, key); \
|
||||
\
|
||||
if (!node) \
|
||||
return false; \
|
||||
\
|
||||
node->value = new_value; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_map_, K key) \
|
||||
{ \
|
||||
SNAME##_node *scan = _map_->root; \
|
||||
|
||||
+64
-94
@@ -170,6 +170,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
@@ -177,28 +178,25 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \
|
||||
FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \
|
||||
FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \
|
||||
/* Create */ \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
|
||||
FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \
|
||||
FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value); \
|
||||
FMOD size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
|
||||
/* Read */ \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
|
||||
FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
|
||||
FMOD V PFX##_get(SNAME *_map_, K key); \
|
||||
FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
|
||||
/* Update */ \
|
||||
FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \
|
||||
FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \
|
||||
FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \
|
||||
FMOD size_t PFX##_set_all(SNAME *_map_, K key, V new_value); \
|
||||
/* Delete */ \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
|
||||
FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_map_, K key); \
|
||||
FMOD bool PFX##_key_count(SNAME *_map_, K key); \
|
||||
FMOD bool PFX##_empty(SNAME *_map_); \
|
||||
FMOD size_t PFX##_count(SNAME *_map_); \
|
||||
FMOD bool PFX##_key_count(SNAME *_map_, K key); \
|
||||
FMOD size_t PFX##_capacity(SNAME *_map_); \
|
||||
/* Collection Utility */ \
|
||||
FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \
|
||||
@@ -244,6 +242,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \
|
||||
\
|
||||
@@ -409,7 +408,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
if (!entry) \
|
||||
return false; \
|
||||
\
|
||||
*old_value = entry->value; \
|
||||
if (old_value) \
|
||||
*old_value = entry->value; \
|
||||
\
|
||||
entry->value = new_value; \
|
||||
\
|
||||
return false; \
|
||||
@@ -417,37 +418,30 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
\
|
||||
FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values) \
|
||||
{ \
|
||||
size_t hash = _map_->hash(key); \
|
||||
\
|
||||
SNAME##_entry *bucket = _map_->buffer[hash % _map_->capacity][0]; \
|
||||
SNAME##_entry *entry = bucket; \
|
||||
\
|
||||
size_t total = 0; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
{ \
|
||||
if (_map_->cmp(entry->key, key) == 0) \
|
||||
total++; \
|
||||
\
|
||||
entry = entry->next; \
|
||||
} \
|
||||
size_t total = PFX##_key_count(_map_, key); \
|
||||
size_t index = 0; \
|
||||
\
|
||||
if (total == 0) \
|
||||
return total; \
|
||||
\
|
||||
*old_values = malloc(sizeof(V) * total); \
|
||||
if (old_values) \
|
||||
{ \
|
||||
*old_values = malloc(sizeof(V) * total); \
|
||||
\
|
||||
if (!(*old_values)) \
|
||||
return false; \
|
||||
if (!(*old_values)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
entry = bucket; \
|
||||
size_t index = 0; \
|
||||
size_t hash = _map_->hash(key); \
|
||||
\
|
||||
SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
{ \
|
||||
if (_map_->cmp(entry->key, key) == 0) \
|
||||
{ \
|
||||
(*old_values)[index++] = entry->value; \
|
||||
if (old_values) \
|
||||
(*old_values)[index++] = entry->value; \
|
||||
\
|
||||
entry->value = new_value; \
|
||||
} \
|
||||
@@ -455,10 +449,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
entry = entry->next; \
|
||||
} \
|
||||
\
|
||||
return total; \
|
||||
return index; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \
|
||||
FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value) \
|
||||
{ \
|
||||
size_t hash = _map_->hash(key); \
|
||||
\
|
||||
@@ -477,7 +471,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
*head = NULL; \
|
||||
*tail = NULL; \
|
||||
\
|
||||
*value = entry->value; \
|
||||
if (out_value) \
|
||||
*out_value = entry->value; \
|
||||
} \
|
||||
else \
|
||||
return false; \
|
||||
@@ -500,7 +495,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
if (entry->next != NULL) \
|
||||
entry->next->prev = entry->prev; \
|
||||
\
|
||||
*value = entry->value; \
|
||||
if (out_value) \
|
||||
*out_value = entry->value; \
|
||||
\
|
||||
found = true; \
|
||||
\
|
||||
break; \
|
||||
@@ -520,16 +517,21 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_remove_all(SNAME *_map_, K key) \
|
||||
FMOD size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values) \
|
||||
{ \
|
||||
size_t total = 0; \
|
||||
size_t hash = _map_->hash(key); \
|
||||
\
|
||||
SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \
|
||||
SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \
|
||||
\
|
||||
if (*head == NULL) \
|
||||
return total; \
|
||||
return 0; \
|
||||
\
|
||||
size_t total = PFX##_key_count(_map_, key); \
|
||||
size_t index = 0; \
|
||||
\
|
||||
if (out_values) \
|
||||
*out_values = malloc(sizeof(SNAME##_entry) * total); \
|
||||
\
|
||||
SNAME##_entry *entry = *head; \
|
||||
\
|
||||
@@ -538,9 +540,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
*head = NULL; \
|
||||
*tail = NULL; \
|
||||
\
|
||||
free(entry); \
|
||||
if (out_values) \
|
||||
(*out_values)[index++] = entry->value; \
|
||||
\
|
||||
total++; \
|
||||
free(entry); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
@@ -560,19 +563,21 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
if (entry->next != NULL) \
|
||||
entry->next->prev = entry->prev; \
|
||||
\
|
||||
free(entry); \
|
||||
entry = temp; \
|
||||
if (out_values) \
|
||||
(*out_values)[index++] = entry->value; \
|
||||
\
|
||||
total++; \
|
||||
free(entry); \
|
||||
\
|
||||
entry = temp; \
|
||||
} \
|
||||
else \
|
||||
entry = entry->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_map_->count -= total; \
|
||||
_map_->count -= index; \
|
||||
\
|
||||
return total; \
|
||||
return index; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \
|
||||
@@ -583,10 +588,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \
|
||||
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_remove(_map_, key, value); \
|
||||
return PFX##_remove(_map_, key, out_value); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
@@ -667,46 +672,21 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
return &(entry->value); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \
|
||||
{ \
|
||||
SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
|
||||
\
|
||||
if (!entry) \
|
||||
return false; \
|
||||
\
|
||||
entry->value = new_value; \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_set_all(SNAME *_map_, K key, V new_value) \
|
||||
{ \
|
||||
size_t hash = _map_->hash(key); \
|
||||
\
|
||||
SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \
|
||||
\
|
||||
size_t total = 0; \
|
||||
\
|
||||
while (entry != NULL) \
|
||||
{ \
|
||||
if (_map_->cmp(entry->key, key) == 0) \
|
||||
{ \
|
||||
entry->value = new_value; \
|
||||
\
|
||||
total++; \
|
||||
} \
|
||||
\
|
||||
entry = entry->next; \
|
||||
} \
|
||||
\
|
||||
return total; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_map_, K key) \
|
||||
{ \
|
||||
return PFX##_impl_get_entry(_map_, key) != NULL; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_map_) \
|
||||
{ \
|
||||
return _map_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_map_) \
|
||||
{ \
|
||||
return _map_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_key_count(SNAME *_map_, K key) \
|
||||
{ \
|
||||
size_t hash = _map_->hash(key); \
|
||||
@@ -729,16 +709,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
|
||||
return total_count; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_map_) \
|
||||
{ \
|
||||
return _map_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_map_) \
|
||||
{ \
|
||||
return _map_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(SNAME *_map_) \
|
||||
{ \
|
||||
return _map_->capacity; \
|
||||
|
||||
Reference in new issue
Block a user