From 2c732dbadfa63ce74bc9d3bf448ecb8e82df8657 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sat, 28 Mar 2020 17:54:31 -0300 Subject: [PATCH] Added callbacks to multimap and multiset, removed enabled flag and more The enabled flag from the previous commit was removed because it seemed pointless PFX##_customize functions were changed, now callbacks can be NULL but not allloc_node Added more code to callback test Added some missing functions and changed some others Added more TODO comments of missing code checks or possible improvements Added more callback guards for set functions --- src/cmc/bidimap.h | 40 +- src/cmc/deque.h | 31 +- src/cmc/hashmap.h | 1890 ++++++++++++++++----------------- src/cmc/hashset.h | 80 +- src/cmc/heap.h | 22 +- src/cmc/intervalheap.h | 34 +- src/cmc/linkedlist.h | 40 +- src/cmc/list.h | 61 +- src/cmc/multimap.h | 68 +- src/cmc/multiset.h | 132 ++- src/cmc/queue.h | 7 +- src/cmc/sortedlist.h | 7 +- src/cmc/stack.h | 7 +- src/cmc/treemap.h | 12 + src/cmc/treeset.h | 13 + src/cor/core.h | 3 - tests/main/unt/bidimap.c | 35 + tests/main/unt/deque.c | 38 + tests/main/unt/hashmap.c | 37 + tests/main/unt/hashset.c | 34 + tests/main/unt/heap.c | 27 + tests/main/unt/intervalheap.c | 33 + tests/main/unt/linkedlist.c | 32 + tests/main/unt/list.c | 52 +- tests/main/unt/multimap.c | 93 ++ tests/main/unt/multiset.c | 81 ++ tests/main/unt/utl.c | 3 +- 27 files changed, 1703 insertions(+), 1209 deletions(-) diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index 2ee2f19..0e5d4fa 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -411,11 +411,12 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _map_->alloc = &cmc_alloc_node_default; \ + else \ _map_->alloc = alloc; \ \ - if (callbacks) \ - _map_->callbacks = callbacks; \ + _map_->callbacks = callbacks; \ \ _map_->flag = cmc_flags.OK; \ } \ @@ -459,8 +460,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " _map_->count++; \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->create) \ + if (_map_->callbacks && _map_->callbacks->create) \ _map_->callbacks->create(); \ \ return true; \ @@ -518,8 +518,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->update) \ + if (_map_->callbacks && _map_->callbacks->update) \ _map_->callbacks->update(); \ \ return true; \ @@ -578,8 +577,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->update) \ + if (_map_->callbacks && _map_->callbacks->update) \ _map_->callbacks->update(); \ \ return true; \ @@ -626,8 +624,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " _map_->count--; \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->delete) \ + if (_map_->callbacks && _map_->callbacks->delete) \ _map_->callbacks->delete (); \ \ return true; \ @@ -674,8 +671,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " _map_->count--; \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->delete) \ + if (_map_->callbacks && _map_->callbacks->delete) \ _map_->callbacks->delete (); \ \ return true; \ @@ -694,8 +690,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ + if (_map_->callbacks && _map_->callbacks->read) \ _map_->callbacks->read(); \ \ return (*entry)->key; \ @@ -714,8 +709,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ + if (_map_->callbacks && _map_->callbacks->read) \ _map_->callbacks->read(); \ \ return (*entry)->value; \ @@ -727,8 +721,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ bool result = PFX##_impl_get_entry_by_key(_map_, key) != NULL; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ + if (_map_->callbacks && _map_->callbacks->read) \ _map_->callbacks->read(); \ \ return result; \ @@ -740,8 +733,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ bool result = PFX##_impl_get_entry_by_val(_map_, val) != NULL; \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ + if (_map_->callbacks && _map_->callbacks->read) \ _map_->callbacks->read(); \ \ return result; \ @@ -804,9 +796,10 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " return false; \ } \ \ + /* No callbacks since _new_map_ is just a temporary hashtable */ \ struct SNAME *_new_map_ = \ PFX##_new_custom(capacity, _map_->load, _map_->f_key, \ - _map_->f_val, _map_->alloc, _map_->callbacks); \ + _map_->f_val, _map_->alloc, NULL); \ \ if (!_new_map_) \ { \ @@ -859,8 +852,7 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " \ success: \ \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->resize) \ + if (_map_->callbacks && _map_->callbacks->resize) \ _map_->callbacks->resize(); \ \ return true; \ diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 5b7d36a..84ecc09 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -324,11 +324,12 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _deque_->alloc = &cmc_alloc_node_default; \ + else \ _deque_->alloc = alloc; \ \ - if (callbacks) \ - _deque_->callbacks = callbacks; \ + _deque_->callbacks = callbacks; \ \ _deque_->flag = cmc_flags.OK; \ } \ @@ -349,8 +350,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " _deque_->count++; \ _deque_->flag = cmc_flags.OK; \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->create) \ + if (_deque_->callbacks && _deque_->callbacks->create) \ _deque_->callbacks->create(); \ \ return true; \ @@ -372,8 +372,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " _deque_->count++; \ _deque_->flag = cmc_flags.OK; \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->create) \ + if (_deque_->callbacks && _deque_->callbacks->create) \ _deque_->callbacks->create(); \ \ return true; \ @@ -396,8 +395,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " _deque_->count--; \ _deque_->flag = cmc_flags.OK; \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->delete) \ + if (_deque_->callbacks && _deque_->callbacks->delete) \ _deque_->callbacks->delete (); \ \ return true; \ @@ -419,8 +417,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " _deque_->count--; \ _deque_->flag = cmc_flags.OK; \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->delete) \ + if (_deque_->callbacks && _deque_->callbacks->delete) \ _deque_->callbacks->delete (); \ \ return true; \ @@ -436,8 +433,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " \ _deque_->flag = cmc_flags.OK; \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->read) \ + if (_deque_->callbacks && _deque_->callbacks->read) \ _deque_->callbacks->read(); \ \ return _deque_->buffer[_deque_->front]; \ @@ -453,8 +449,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " \ _deque_->flag = cmc_flags.OK; \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->read) \ + if (_deque_->callbacks && _deque_->callbacks->read) \ _deque_->callbacks->read(); \ \ return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 \ @@ -478,8 +473,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " i = (i + 1) % _deque_->capacity; \ } \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->read) \ + if (_deque_->callbacks && _deque_->callbacks->read) \ _deque_->callbacks->read(); \ \ return result; \ @@ -547,8 +541,7 @@ static const char *cmc_string_fmt_deque = "struct %s<%s> " \ success: \ \ - if (_deque_->callbacks && _deque_->callbacks->enabled && \ - _deque_->callbacks->resize) \ + if (_deque_->callbacks && _deque_->callbacks->resize) \ _deque_->callbacks->resize(); \ \ return true; \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 3cb501b..f58c417 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -247,963 +247,939 @@ static const char *cmc_string_fmt_hashmap = "struct %s<%s, %s> " /* ------------------------------------------------------------------------- * Source * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_entry *PFX##_impl_insert(struct SNAME *_map_, K key, \ - V value); \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, \ - K key); \ - static 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_end(struct SNAME *_map_); \ - \ - struct SNAME *PFX##_new(size_t capacity, double load, \ - struct SNAME##_ftab_key *f_key, \ - struct SNAME##_ftab_val *f_val) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - if (!f_key || !f_val) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = \ - alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->flag = cmc_flags.OK; \ - _map_->f_key = f_key; \ - _map_->f_val = f_val; \ - _map_->alloc = alloc; \ - _map_->callbacks = NULL; \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - struct SNAME *PFX##_new_custom( \ - size_t capacity, double load, struct SNAME##_ftab_key *f_key, \ - struct SNAME##_ftab_val *f_val, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks *callbacks) \ - { \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - if (!f_key || !f_val) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = \ - alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->flag = cmc_flags.OK; \ - _map_->f_key = f_key; \ - _map_->f_val = f_val; \ - _map_->alloc = alloc; \ - _map_->callbacks = callbacks; \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(struct SNAME *_map_) \ - { \ - if (_map_->f_key->free || _map_->f_val->free) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - if (_map_->f_key->free) \ - _map_->f_key->free(entry->key); \ - if (_map_->f_val->free) \ - _map_->f_val->free(entry->value); \ - } \ - } \ - } \ - \ - memset(_map_->buffer, 0, \ - sizeof(struct SNAME##_entry) * _map_->capacity); \ - \ - _map_->count = 0; \ - _map_->flag = cmc_flags.OK; \ - } \ - \ - void PFX##_free(struct SNAME *_map_) \ - { \ - if (_map_->f_key->free || _map_->f_val->free) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - if (_map_->f_key->free) \ - _map_->f_key->free(entry->key); \ - if (_map_->f_val->free) \ - _map_->f_val->free(entry->value); \ - } \ - } \ - } \ - \ - _map_->alloc->free(_map_->buffer); \ - _map_->alloc->free(_map_); \ - } \ - \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks *callbacks) \ - { \ - if (alloc) \ - _map_->alloc = alloc; \ - \ - if (callbacks) \ - _map_->callbacks = callbacks; \ - \ - _map_->flag = cmc_flags.OK; \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_full(_map_)) \ - { \ - if (!PFX##_resize(_map_, _map_->capacity + 1)) \ - return false; \ - } \ - \ - if (PFX##_impl_get_entry(_map_, key) != NULL) \ - { \ - _map_->flag = cmc_flags.DUPLICATE; \ - return false; \ - } \ - \ - if (PFX##_impl_insert(_map_, key, value) == NULL) \ - { \ - _map_->flag = cmc_flags.ERROR; \ - return false; \ - } \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->create) \ - _map_->callbacks->create(); \ - \ - _map_->count++; \ - _map_->flag = cmc_flags.OK; \ - \ - return true; \ - } \ - \ - 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); \ - \ - if (!entry) \ - { \ - _map_->flag = cmc_flags.NOT_FOUND; \ - return false; \ - } \ - \ - if (old_value) \ - *old_value = entry->value; \ - \ - entry->value = new_value; \ - \ - _map_->flag = cmc_flags.OK; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->update) \ - _map_->callbacks->update(); \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->flag = cmc_flags.EMPTY; \ - return false; \ - } \ - \ - struct SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ - \ - if (result == NULL) \ - { \ - _map_->flag = cmc_flags.NOT_FOUND; \ - return false; \ - } \ - \ - if (out_value) \ - *out_value = result->value; \ - \ - result->key = (K){ 0 }; \ - result->value = (V){ 0 }; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _map_->count--; \ - _map_->flag = cmc_flags.OK; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->delete) \ - _map_->callbacks->delete (); \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->flag = cmc_flags.EMPTY; \ - return false; \ - } \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - K max_key = PFX##_iter_key(&iter); \ - V max_val = PFX##_iter_value(&iter); \ - \ - PFX##_iter_next(&iter); \ - \ - /* TODO Turn this into a normal loop */ \ - for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K iter_key = PFX##_iter_key(&iter); \ - V iter_val = PFX##_iter_value(&iter); \ - \ - if (_map_->f_key->cmp(iter_key, max_key) > 0) \ - { \ - max_key = iter_key; \ - max_val = iter_val; \ - } \ - } \ - \ - if (key) \ - *key = max_key; \ - if (value) \ - *value = max_val; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ - _map_->callbacks->read(); \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->flag = cmc_flags.EMPTY; \ - return false; \ - } \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - K min_key = PFX##_iter_key(&iter); \ - V min_val = PFX##_iter_value(&iter); \ - \ - PFX##_iter_next(&iter); \ - \ - /* TODO Turn this into a normal loop */ \ - for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K iter_key = PFX##_iter_key(&iter); \ - V iter_val = PFX##_iter_value(&iter); \ - \ - if (_map_->f_key->cmp(iter_key, min_key) < 0) \ - { \ - min_key = iter_key; \ - min_val = iter_val; \ - } \ - } \ - \ - if (key) \ - *key = min_key; \ - if (value) \ - *value = min_val; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ - _map_->callbacks->read(); \ - \ - return true; \ - } \ - \ - 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); \ - \ - if (!entry) \ - { \ - _map_->flag = cmc_flags.NOT_FOUND; \ - return (V){ 0 }; \ - } \ - \ - _map_->flag = cmc_flags.OK; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ - _map_->callbacks->read(); \ - \ - return entry->value; \ - } \ - \ - 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); \ - \ - if (!entry) \ - { \ - _map_->flag = cmc_flags.NOT_FOUND; \ - return NULL; \ - } \ - \ - _map_->flag = cmc_flags.OK; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ - _map_->callbacks->read(); \ - \ - return &(entry->value); \ - } \ - \ - bool PFX##_contains(struct SNAME *_map_, K key) \ - { \ - _map_->flag = cmc_flags.OK; \ - \ - bool result = PFX##_impl_get_entry(_map_, key) != NULL; \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->read) \ - _map_->callbacks->read(); \ - \ - return result; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_map_) \ - { \ - return (double)_map_->capacity * _map_->load <= (double)_map_->count; \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - int PFX##_flag(struct SNAME *_map_) \ - { \ - return _map_->flag; \ - } \ - \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ - { \ - _map_->flag = cmc_flags.OK; \ - \ - if (_map_->capacity == capacity) \ - goto success; \ - \ - if (_map_->capacity > capacity / _map_->load) \ - goto success; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * _map_->load) \ - { \ - _map_->flag = cmc_flags.ERROR; \ - return false; \ - } \ - \ - /* Calculate required capacity based on the prime numbers */ \ - size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ - \ - /* Not possible to shrink with current available prime numbers */ \ - if (theoretical_size < _map_->count / _map_->load) \ - { \ - _map_->flag = cmc_flags.INVALID; \ - return false; \ - } \ - \ - struct SNAME *_new_map_ = \ - PFX##_new_custom(capacity, _map_->load, _map_->f_key, \ - _map_->f_val, _map_->alloc, _map_->callbacks); \ - \ - if (!_new_map_) \ - { \ - _map_->flag = cmc_flags.ALLOC; \ - return false; \ - } \ - \ - struct SNAME##_iter iter; \ - \ - /* TODO turn this into a normal loop */ \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_impl_insert(_new_map_, key, value); \ - \ - _new_map_->count++; \ - } \ - \ - if (_map_->count != _new_map_->count) \ - { \ - PFX##_free(_new_map_); \ - \ - _map_->flag = cmc_flags.ERROR; \ - return false; \ - } \ - \ - struct SNAME##_entry *tmp_b = _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; \ - \ - PFX##_free(_new_map_); \ - \ - success: \ - \ - if (_map_->callbacks && _map_->callbacks->enabled && \ - _map_->callbacks->resize) \ - _map_->callbacks->resize(); \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_) \ - { \ - struct SNAME *result = PFX##_new_custom( \ - _map_->capacity * _map_->load, _map_->load, _map_->f_key, \ - _map_->f_val, _map_->alloc, _map_->callbacks); \ - \ - if (!result) \ - { \ - _map_->flag = cmc_flags.ERROR; \ - return NULL; \ - } \ - \ - if (_map_->f_key->cpy || _map_->f_val->cpy) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *scan = &(_map_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - struct SNAME##_entry *target = &(result->buffer[i]); \ - \ - if (scan->state == CMC_ES_DELETED) \ - target->state = CMC_ES_DELETED; \ - else \ - { \ - target->state = scan->state; \ - target->dist = scan->dist; \ - \ - if (_map_->f_key->cpy) \ - target->key = _map_->f_key->cpy(scan->key); \ - else \ - target->key = scan->key; \ - \ - if (_map_->f_val->cpy) \ - target->value = _map_->f_val->cpy(scan->value); \ - else \ - target->value = scan->value; \ - } \ - } \ - } \ - } \ - else \ - memcpy(result->buffer, _map_->buffer, \ - sizeof(struct SNAME##_entry) * _map_->capacity); \ - \ - result->count = _map_->count; \ - \ - _map_->flag = cmc_flags.OK; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_) \ - { \ - _map1_->flag = cmc_flags.OK; \ - _map2_->flag = cmc_flags.OK; \ - \ - if (_map1_->count != _map2_->count) \ - return false; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - /* TODO optimize this loop */ \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - struct SNAME##_entry *entry = \ - PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)); \ - \ - if (entry == NULL) \ - return false; \ - \ - if (_map1_->f_val->cmp(entry->value, PFX##_iter_value(&iter)) != \ - 0) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_map_) \ - { \ - struct cmc_string str; \ - struct SNAME *m_ = _map_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ - #SNAME, #K, #V, 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 PFX##_print(struct SNAME *_map_, FILE *fptr) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - if (!_map_->f_key->str(fptr, entry->key) || \ - !_map_->f_val->str(fptr, entry->value)) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = \ - target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!PFX##_empty(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i].state == CMC_ES_FILLED) \ - { \ - iter->first = i; \ - break; \ - } \ - } \ - \ - iter->cursor = iter->first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1].state == CMC_ES_FILLED) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - struct SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - struct SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= iter->target->count) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the */ \ - /* given index */ \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ - { \ - if (index >= iter->target->count) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K PFX##_iter_key(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){ 0 }; \ - \ - return iter->target->buffer[iter->cursor].key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){ 0 }; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor].value); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_insert(struct SNAME *_map_, K key, \ - V value) \ - { \ - size_t hash = _map_->f_key->hash(key); \ - size_t original_pos = hash % _map_->capacity; \ - size_t pos = original_pos; \ - \ - struct SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->key = key; \ - target->value = value; \ - target->dist = 0; \ - target->state = CMC_ES_FILLED; \ - \ - return target; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - \ - if (target->state == CMC_ES_EMPTY || \ - target->state == CMC_ES_DELETED) \ - { \ - target->key = key; \ - target->value = value; \ - target->dist = pos - original_pos; \ - target->state = CMC_ES_FILLED; \ - \ - return target; \ - } \ - else if (target->dist < pos - original_pos) \ - { \ - K tmp_k = target->key; \ - V tmp_v = target->value; \ - size_t tmp_dist = target->dist; \ - \ - target->key = key; \ - target->value = value; \ - target->dist = pos - original_pos; \ - \ - key = tmp_k; \ - value = tmp_v; \ - original_pos = pos - tmp_dist; \ - } \ - } \ - } \ - \ - return NULL; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, \ - K key) \ - { \ - size_t hash = _map_->f_key->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - struct SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - while (target->state == CMC_ES_FILLED || \ - target->state == CMC_ES_DELETED) \ - { \ - if (_map_->f_key->cmp(target->key, key) == 0) \ - return target; \ - \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_impl_calculate_size(size_t required) \ - { \ - const size_t count = \ - sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \ - \ - if (cmc_hashtable_primes[count - 1] < required) \ - return required; \ - \ - size_t i = 0; \ - while (cmc_hashtable_primes[i] < required) \ - i++; \ - \ - return cmc_hashtable_primes[i]; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, \ + K key); \ + static 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_end(struct SNAME *_map_); \ + \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + if (!f_key || !f_val) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->flag = cmc_flags.OK; \ + _map_->f_key = f_key; \ + _map_->f_val = f_val; \ + _map_->alloc = alloc; \ + _map_->callbacks = NULL; \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, double load, struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks *callbacks) \ + { \ + if (capacity == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + if (!f_key || !f_val) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->flag = cmc_flags.OK; \ + _map_->f_key = f_key; \ + _map_->f_val = f_val; \ + _map_->alloc = alloc; \ + _map_->callbacks = callbacks; \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(struct SNAME *_map_) \ + { \ + if (_map_->f_key->free || _map_->f_val->free) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + if (_map_->f_key->free) \ + _map_->f_key->free(entry->key); \ + if (_map_->f_val->free) \ + _map_->f_val->free(entry->value); \ + } \ + } \ + } \ + \ + memset(_map_->buffer, 0, \ + sizeof(struct SNAME##_entry) * _map_->capacity); \ + \ + _map_->count = 0; \ + _map_->flag = cmc_flags.OK; \ + } \ + \ + void PFX##_free(struct SNAME *_map_) \ + { \ + if (_map_->f_key->free || _map_->f_val->free) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + if (_map_->f_key->free) \ + _map_->f_key->free(entry->key); \ + if (_map_->f_val->free) \ + _map_->f_val->free(entry->value); \ + } \ + } \ + } \ + \ + _map_->alloc->free(_map_->buffer); \ + _map_->alloc->free(_map_); \ + } \ + \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks *callbacks) \ + { \ + if (!alloc) \ + _map_->alloc = &cmc_alloc_node_default; \ + else \ + _map_->alloc = alloc; \ + \ + _map_->callbacks = callbacks; \ + \ + _map_->flag = cmc_flags.OK; \ + } \ + \ + bool PFX##_insert(struct SNAME *_map_, K key, V value) \ + { \ + if (PFX##_full(_map_)) \ + { \ + if (!PFX##_resize(_map_, _map_->capacity + 1)) \ + return false; \ + } \ + \ + if (PFX##_impl_get_entry(_map_, key) != NULL) \ + { \ + _map_->flag = cmc_flags.DUPLICATE; \ + return false; \ + } \ + \ + size_t hash = _map_->f_key->hash(key); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + struct SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = 0; \ + target->state = CMC_ES_FILLED; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + \ + if (target->state == CMC_ES_EMPTY || \ + target->state == CMC_ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + target->state = CMC_ES_FILLED; \ + \ + break; \ + } \ + else if (target->dist < pos - original_pos) \ + { \ + K tmp_k = target->key; \ + V tmp_v = target->value; \ + size_t tmp_dist = target->dist; \ + \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + \ + key = tmp_k; \ + value = tmp_v; \ + original_pos = pos - tmp_dist; \ + } \ + } \ + } \ + \ + _map_->count++; \ + _map_->flag = cmc_flags.OK; \ + \ + if (_map_->callbacks && _map_->callbacks->create) \ + _map_->callbacks->create(); \ + \ + return true; \ + } \ + \ + 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); \ + \ + if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ + return false; \ + } \ + \ + if (old_value) \ + *old_value = entry->value; \ + \ + entry->value = new_value; \ + \ + _map_->flag = cmc_flags.OK; \ + \ + if (_map_->callbacks && _map_->callbacks->update) \ + _map_->callbacks->update(); \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ + return false; \ + } \ + \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ + \ + if (result == NULL) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ + return false; \ + } \ + \ + if (out_value) \ + *out_value = result->value; \ + \ + result->key = (K){ 0 }; \ + result->value = (V){ 0 }; \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _map_->count--; \ + _map_->flag = cmc_flags.OK; \ + \ + if (_map_->callbacks && _map_->callbacks->delete) \ + _map_->callbacks->delete (); \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ + return false; \ + } \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + K max_key = PFX##_iter_key(&iter); \ + V max_val = PFX##_iter_value(&iter); \ + \ + PFX##_iter_next(&iter); \ + \ + /* TODO Turn this into a normal loop */ \ + for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K iter_key = PFX##_iter_key(&iter); \ + V iter_val = PFX##_iter_value(&iter); \ + \ + if (_map_->f_key->cmp(iter_key, max_key) > 0) \ + { \ + max_key = iter_key; \ + max_val = iter_val; \ + } \ + } \ + \ + if (key) \ + *key = max_key; \ + if (value) \ + *value = max_val; \ + \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->flag = cmc_flags.EMPTY; \ + return false; \ + } \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + K min_key = PFX##_iter_key(&iter); \ + V min_val = PFX##_iter_value(&iter); \ + \ + PFX##_iter_next(&iter); \ + \ + /* TODO Turn this into a normal loop */ \ + for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K iter_key = PFX##_iter_key(&iter); \ + V iter_val = PFX##_iter_value(&iter); \ + \ + if (_map_->f_key->cmp(iter_key, min_key) < 0) \ + { \ + min_key = iter_key; \ + min_val = iter_val; \ + } \ + } \ + \ + if (key) \ + *key = min_key; \ + if (value) \ + *value = min_val; \ + \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ + return true; \ + } \ + \ + 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); \ + \ + if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ + return (V){ 0 }; \ + } \ + \ + _map_->flag = cmc_flags.OK; \ + \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ + return entry->value; \ + } \ + \ + 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); \ + \ + if (!entry) \ + { \ + _map_->flag = cmc_flags.NOT_FOUND; \ + return NULL; \ + } \ + \ + _map_->flag = cmc_flags.OK; \ + \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ + return &(entry->value); \ + } \ + \ + bool PFX##_contains(struct SNAME *_map_, K key) \ + { \ + _map_->flag = cmc_flags.OK; \ + \ + bool result = PFX##_impl_get_entry(_map_, key) != NULL; \ + \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ + return result; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_map_) \ + { \ + return (double)_map_->capacity * _map_->load <= (double)_map_->count; \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_map_) \ + { \ + return _map_->load; \ + } \ + \ + int PFX##_flag(struct SNAME *_map_) \ + { \ + return _map_->flag; \ + } \ + \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ + { \ + _map_->flag = cmc_flags.OK; \ + \ + if (_map_->capacity == capacity) \ + goto success; \ + \ + if (_map_->capacity > capacity / _map_->load) \ + goto success; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * _map_->load) \ + { \ + _map_->flag = cmc_flags.ERROR; \ + return false; \ + } \ + \ + /* Calculate required capacity based on the prime numbers */ \ + size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ + \ + /* Not possible to shrink with current available prime numbers */ \ + if (theoretical_size < _map_->count / _map_->load) \ + { \ + _map_->flag = cmc_flags.INVALID; \ + return false; \ + } \ + \ + /* No callbacks since _new_map_ is just a temporary hashtable */ \ + struct SNAME *_new_map_ = \ + PFX##_new_custom(capacity, _map_->load, _map_->f_key, \ + _map_->f_val, _map_->alloc, NULL); \ + \ + if (!_new_map_) \ + { \ + _map_->flag = cmc_flags.ALLOC; \ + return false; \ + } \ + \ + struct SNAME##_iter iter; \ + \ + /* TODO turn this into a normal loop */ \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + PFX##_insert(_new_map_, key, value); \ + } \ + \ + /* Unlikely */ \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_); \ + \ + _map_->flag = cmc_flags.ERROR; \ + return false; \ + } \ + \ + struct SNAME##_entry *tmp_b = _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; \ + \ + PFX##_free(_new_map_); \ + \ + success: \ + \ + if (_map_->callbacks && _map_->callbacks->resize) \ + _map_->callbacks->resize(); \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_) \ + { \ + struct SNAME *result = PFX##_new_custom( \ + _map_->capacity * _map_->load, _map_->load, _map_->f_key, \ + _map_->f_val, _map_->alloc, _map_->callbacks); \ + \ + if (!result) \ + { \ + _map_->flag = cmc_flags.ERROR; \ + return NULL; \ + } \ + \ + if (_map_->f_key->cpy || _map_->f_val->cpy) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *scan = &(_map_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + struct SNAME##_entry *target = &(result->buffer[i]); \ + \ + if (scan->state == CMC_ES_DELETED) \ + target->state = CMC_ES_DELETED; \ + else \ + { \ + target->state = scan->state; \ + target->dist = scan->dist; \ + \ + if (_map_->f_key->cpy) \ + target->key = _map_->f_key->cpy(scan->key); \ + else \ + target->key = scan->key; \ + \ + if (_map_->f_val->cpy) \ + target->value = _map_->f_val->cpy(scan->value); \ + else \ + target->value = scan->value; \ + } \ + } \ + } \ + } \ + else \ + memcpy(result->buffer, _map_->buffer, \ + sizeof(struct SNAME##_entry) * _map_->capacity); \ + \ + result->count = _map_->count; \ + \ + _map_->flag = cmc_flags.OK; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_) \ + { \ + _map1_->flag = cmc_flags.OK; \ + _map2_->flag = cmc_flags.OK; \ + \ + if (_map1_->count != _map2_->count) \ + return false; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + /* TODO optimize this loop */ \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + struct SNAME##_entry *entry = \ + PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)); \ + \ + if (entry == NULL) \ + return false; \ + \ + if (_map1_->f_val->cmp(entry->value, PFX##_iter_value(&iter)) != \ + 0) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_map_) \ + { \ + struct cmc_string str; \ + struct SNAME *m_ = _map_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ + #SNAME, #K, #V, 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 PFX##_print(struct SNAME *_map_, FILE *fptr) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + if (!_map_->f_key->str(fptr, entry->key) || \ + !_map_->f_val->str(fptr, entry->value)) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct SNAME##_iter)); \ + \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + if (!PFX##_empty(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + if (target->buffer[i].state == CMC_ES_FILLED) \ + { \ + iter->first = i; \ + break; \ + } \ + } \ + \ + iter->cursor = iter->first; \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + if (target->buffer[i - 1].state == CMC_ES_FILLED) \ + { \ + iter->last = i - 1; \ + break; \ + } \ + } \ + } \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + struct SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + iter->index++; \ + \ + while (1) \ + { \ + iter->cursor++; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == CMC_ES_FILLED) \ + break; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + struct SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + iter->index--; \ + \ + while (1) \ + { \ + iter->cursor--; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == CMC_ES_FILLED) \ + break; \ + } \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= iter->target->count) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the */ \ + /* given index */ \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ + { \ + if (index >= iter->target->count) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + K PFX##_iter_key(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor].value); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, \ + K key) \ + { \ + size_t hash = _map_->f_key->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + struct SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + while (target->state == CMC_ES_FILLED || \ + target->state == CMC_ES_DELETED) \ + { \ + if (_map_->f_key->cmp(target->key, key) == 0) \ + return target; \ + \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + } \ + \ + return NULL; \ + } \ + \ + static size_t PFX##_impl_calculate_size(size_t required) \ + { \ + const size_t count = \ + sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \ + \ + if (cmc_hashtable_primes[count - 1] < required) \ + return required; \ + \ + size_t i = 0; \ + while (cmc_hashtable_primes[i] < required) \ + i++; \ + \ + return cmc_hashtable_primes[i]; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_HASHMAP_H */ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index c94b469..780251b 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -367,11 +367,12 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _set_->alloc = &cmc_alloc_node_default; \ + else \ _set_->alloc = alloc; \ \ - if (callbacks) \ - _set_->callbacks = callbacks; \ + _set_->callbacks = callbacks; \ \ _set_->flag = cmc_flags.OK; \ } \ @@ -435,8 +436,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " _set_->count++; \ _set_->flag = cmc_flags.OK; \ \ - if (_set_->callbacks && _set_->callbacks->enabled && \ - _set_->callbacks->create) \ + if (_set_->callbacks && _set_->callbacks->create) \ _set_->callbacks->create(); \ \ return true; \ @@ -465,8 +465,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " _set_->count--; \ _set_->flag = cmc_flags.OK; \ \ - if (_set_->callbacks && _set_->callbacks->enabled && \ - _set_->callbacks->delete) \ + if (_set_->callbacks && _set_->callbacks->delete) \ _set_->callbacks->delete (); \ \ return true; \ @@ -501,8 +500,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " \ _set_->flag = cmc_flags.OK; \ \ - if (_set_->callbacks && _set_->callbacks->enabled && \ - _set_->callbacks->read) \ + if (_set_->callbacks && _set_->callbacks->read) \ _set_->callbacks->read(); \ \ return true; \ @@ -537,8 +535,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " \ _set_->flag = cmc_flags.OK; \ \ - if (_set_->callbacks && _set_->callbacks->enabled && \ - _set_->callbacks->read) \ + if (_set_->callbacks && _set_->callbacks->read) \ _set_->callbacks->read(); \ \ return true; \ @@ -550,8 +547,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " \ bool result = PFX##_impl_get_entry(_set_, element) != NULL; \ \ - if (_set_->callbacks && _set_->callbacks->enabled && \ - _set_->callbacks->read) \ + if (_set_->callbacks && _set_->callbacks->read) \ _set_->callbacks->read(); \ \ return result; \ @@ -614,9 +610,9 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " return false; \ } \ \ - struct SNAME *_new_set_ = \ - PFX##_new_custom(capacity, _set_->load, _set_->f_val, \ - _set_->alloc, _set_->callbacks); \ + /* No callbacks since _new_set_ is just a temporary hashtable */ \ + struct SNAME *_new_set_ = PFX##_new_custom( \ + capacity, _set_->load, _set_->f_val, _set_->alloc, NULL); \ \ if (!_new_set_) \ { \ @@ -626,9 +622,6 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " \ struct SNAME##_iter iter; \ \ - if (_set_->callbacks) \ - _set_->callbacks->enabled = false; \ - \ /* TODO turn this into a normal loop */ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ @@ -639,12 +632,12 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " PFX##_insert(_new_set_, value); \ } \ \ - if (_set_->callbacks) \ - _set_->callbacks->enabled = true; \ - \ + /* Unlikely */ \ if (_set_->count != _new_set_->count) \ { \ PFX##_free(_new_set_); \ + \ + _set_->flag = cmc_flags.ERROR; \ return false; \ } \ \ @@ -660,8 +653,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " \ success: \ \ - if (_set_->callbacks && _set_->callbacks->enabled && \ - _set_->callbacks->resize) \ + if (_set_->callbacks && _set_->callbacks->resize) \ _set_->callbacks->resize(); \ \ return true; \ @@ -768,9 +760,10 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " \ struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ { \ @@ -783,9 +776,6 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = false; \ - \ /* TODO turn this into a normal loop and check for errors */ \ for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); \ PFX##_iter_next(&iter1)) \ @@ -799,8 +789,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ } \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = true; \ + _set_r_->callbacks = _set1_->callbacks; \ \ return _set_r_; \ } \ @@ -808,9 +797,10 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ { \ @@ -826,9 +816,6 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set_A_); \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = false; \ - \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -838,17 +825,17 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " PFX##_insert(_set_r_, value); \ } \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = true; \ + _set_r_->callbacks = _set1_->callbacks; \ \ return _set_r_; \ } \ \ struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ { \ @@ -860,9 +847,6 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set1_); \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = false; \ - \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -872,8 +856,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " PFX##_insert(_set_r_, value); \ } \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = true; \ + _set_r_->callbacks = _set1_->callbacks; \ \ return _set_r_; \ } \ @@ -881,11 +864,10 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ struct SNAME *_set2_) \ { \ - struct SNAME##_iter iter1, iter2; \ - \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ { \ @@ -894,12 +876,11 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " return NULL; \ } \ \ + struct SNAME##_iter iter1, iter2; \ + \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = false; \ - \ for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); \ PFX##_iter_next(&iter1)) \ { \ @@ -918,8 +899,7 @@ static const char *cmc_string_fmt_hashset = "struct %s<%s> " PFX##_insert(_set_r_, value); \ } \ \ - if (_set_r_->callbacks) \ - _set_r_->callbacks->enabled = true; \ + _set_r_->callbacks = _set1_->callbacks; \ \ return _set_r_; \ } \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index f781468..31f1830 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -333,11 +333,12 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _heap_->alloc = &cmc_alloc_node_default; \ + else \ _heap_->alloc = alloc; \ \ - if (callbacks) \ - _heap_->callbacks = callbacks; \ + _heap_->callbacks = callbacks; \ \ _heap_->flag = cmc_flags.OK; \ } \ @@ -359,8 +360,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->create) \ + if (_heap_->callbacks && _heap_->callbacks->create) \ _heap_->callbacks->create(); \ \ return true; \ @@ -383,8 +383,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->delete) \ + if (_heap_->callbacks && _heap_->callbacks->delete) \ _heap_->callbacks->delete (); \ \ return true; \ @@ -400,8 +399,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->read) \ + if (_heap_->callbacks && _heap_->callbacks->read) \ _heap_->callbacks->read(); \ \ return _heap_->buffer[0]; \ @@ -422,8 +420,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " } \ } \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->read) \ + if (_heap_->callbacks && _heap_->callbacks->read) \ _heap_->callbacks->read(); \ \ return result; \ @@ -483,8 +480,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " \ success: \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->resize) \ + if (_heap_->callbacks && _heap_->callbacks->resize) \ _heap_->callbacks->resize(); \ \ return true; \ diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 5dde4bb..5c20103 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -325,11 +325,12 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _heap_->alloc = &cmc_alloc_node_default; \ + else \ _heap_->alloc = alloc; \ \ - if (callbacks) \ - _heap_->callbacks = callbacks; \ + _heap_->callbacks = callbacks; \ \ _heap_->flag = cmc_flags.OK; \ } \ @@ -385,8 +386,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " /* else no float up required */ \ } \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->create) \ + if (_heap_->callbacks && _heap_->callbacks->create) \ _heap_->callbacks->create(); \ \ return true; \ @@ -439,8 +439,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->delete) \ + if (_heap_->callbacks && _heap_->callbacks->delete) \ _heap_->callbacks->delete (); \ \ return true; \ @@ -493,8 +492,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->delete) \ + if (_heap_->callbacks && _heap_->callbacks->delete) \ _heap_->callbacks->delete (); \ \ return true; \ @@ -531,8 +529,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->update) \ + if (_heap_->callbacks && _heap_->callbacks->update) \ _heap_->callbacks->update(); \ \ return true; \ @@ -569,8 +566,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->update) \ + if (_heap_->callbacks && _heap_->callbacks->update) \ _heap_->callbacks->update(); \ \ return true; \ @@ -586,8 +582,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->read) \ + if (_heap_->callbacks && _heap_->callbacks->read) \ _heap_->callbacks->read(); \ \ /* If there is only one element, then the maximum element is the */ \ @@ -608,8 +603,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->read) \ + if (_heap_->callbacks && _heap_->callbacks->read) \ _heap_->callbacks->read(); \ \ return _heap_->buffer[0].data[0]; \ @@ -631,8 +625,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " } \ } \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->read) \ + if (_heap_->callbacks && _heap_->callbacks->read) \ _heap_->callbacks->read(); \ \ return result; \ @@ -707,8 +700,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " \ _heap_->flag = cmc_flags.OK; \ \ - if (_heap_->callbacks && _heap_->callbacks->enabled && \ - _heap_->callbacks->resize) \ + if (_heap_->callbacks && _heap_->callbacks->resize) \ _heap_->callbacks->resize(); \ \ return true; \ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index a3b9119..29e5c5f 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -320,11 +320,12 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _list_->alloc = &cmc_alloc_node_default; \ + else \ _list_->alloc = alloc; \ \ - if (callbacks) \ - _list_->callbacks = callbacks; \ + _list_->callbacks = callbacks; \ \ _list_->flag = cmc_flags.OK; \ } \ @@ -351,8 +352,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " _list_->count++; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -390,8 +390,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " _list_->count++; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -419,8 +418,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " _list_->count++; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -447,8 +445,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " _list_->count--; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -490,8 +487,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " _list_->count--; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -518,8 +514,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " _list_->count--; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -535,8 +530,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return _list_->head->value; \ @@ -561,8 +555,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " if (scan == NULL) \ return (V){ 0 }; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return scan->value; \ @@ -587,8 +580,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " if (scan == NULL) \ return NULL; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return &(scan->value); \ @@ -604,8 +596,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return _list_->tail->value; \ @@ -630,8 +621,7 @@ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " scan = scan->next; \ } \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return result; \ diff --git a/src/cmc/list.h b/src/cmc/list.h index 58e1735..7b85998 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -323,11 +323,12 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _list_->alloc = &cmc_alloc_node_default; \ + else \ _list_->alloc = alloc; \ \ - if (callbacks) \ - _list_->callbacks = callbacks; \ + _list_->callbacks = callbacks; \ \ _list_->flag = cmc_flags.OK; \ } \ @@ -351,8 +352,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->count++; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -379,8 +379,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->count++; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -397,8 +396,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->buffer[_list_->count++] = element; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -418,8 +416,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->buffer[--_list_->count] = (V){ 0 }; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -445,8 +442,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->buffer[--_list_->count] = (V){ 0 }; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -460,8 +456,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->buffer[--_list_->count] = (V){ 0 }; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -489,8 +484,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->count += size; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -530,8 +524,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->count += size; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -556,8 +549,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->count += size; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->create) \ + if (_list_->callbacks && _list_->callbacks->create) \ _list_->callbacks->create(); \ \ return true; \ @@ -588,8 +580,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->count -= to - from + 1; \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return true; \ @@ -634,8 +625,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->enabled && _list_->callbacks->delete) \ + if (_list_->callbacks && _list_->callbacks->delete) \ _list_->callbacks->delete (); \ \ return result; \ @@ -651,8 +641,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return _list_->buffer[0]; \ @@ -674,8 +663,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return _list_->buffer[index]; \ @@ -697,8 +685,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return &(_list_->buffer[index]); \ @@ -714,8 +701,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " \ _list_->flag = cmc_flags.OK; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return _list_->buffer[_list_->count - 1]; \ @@ -750,8 +736,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " } \ } \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return result; \ @@ -772,8 +757,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " } \ } \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->read) \ + if (_list_->callbacks && _list_->callbacks->read) \ _list_->callbacks->read(); \ \ return result; \ @@ -836,8 +820,7 @@ static const char *cmc_string_fmt_list = "struct %s<%s> " _list_->buffer = new_buffer; \ _list_->capacity = capacity; \ \ - if (_list_->callbacks && _list_->callbacks->enabled && \ - _list_->callbacks->resize) \ + if (_list_->callbacks && _list_->callbacks->resize) \ _list_->callbacks->resize(); \ \ return true; \ diff --git a/src/cmc/multimap.h b/src/cmc/multimap.h index af37ca7..e8c1db0 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/multimap.h @@ -456,11 +456,12 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _map_->alloc = &cmc_alloc_node_default; \ + else \ _map_->alloc = alloc; \ \ - if (callbacks) \ - _map_->callbacks = callbacks; \ + _map_->callbacks = callbacks; \ \ _map_->flag = cmc_flags.OK; \ } \ @@ -494,6 +495,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " _map_->count++; \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->create) \ + _map_->callbacks->create(); \ + \ return true; \ } \ \ @@ -520,6 +524,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->update) \ + _map_->callbacks->update(); \ + \ return true; \ } \ \ @@ -580,6 +587,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->update) \ + _map_->callbacks->update(); \ + \ return index; \ } \ \ @@ -663,6 +673,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " _map_->count--; \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->delete) \ + _map_->callbacks->delete (); \ + \ return true; \ } \ \ @@ -754,6 +767,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " _map_->count -= index; \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->delete) \ + _map_->callbacks->delete (); \ + \ return index; \ } \ \ @@ -770,6 +786,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ struct SNAME##_iter iter; \ \ + /* TODO Turn this into a normal loop */ \ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -796,6 +813,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ return true; \ } \ \ @@ -812,6 +832,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ struct SNAME##_iter iter; \ \ + /* TODO Turn this into a normal loop */ \ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -838,6 +859,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ return true; \ } \ \ @@ -859,6 +883,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ return entry->value; \ } \ \ @@ -880,6 +907,9 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ _map_->flag = cmc_flags.OK; \ \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ return &(entry->value); \ } \ \ @@ -887,7 +917,12 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " { \ _map_->flag = cmc_flags.OK; \ \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ + bool result = PFX##_impl_get_entry(_map_, key) != NULL; \ + \ + if (_map_->callbacks && _map_->callbacks->read) \ + _map_->callbacks->read(); \ + \ + return result; \ } \ \ bool PFX##_empty(struct SNAME *_map_) \ @@ -930,10 +965,10 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " _map_->flag = cmc_flags.OK; \ \ if (_map_->capacity == capacity) \ - return true; \ + goto success; \ \ if (_map_->capacity > capacity / _map_->load) \ - return true; \ + goto success; \ \ /* Prevent integer overflow */ \ if (capacity >= UINTMAX_MAX * _map_->load) \ @@ -952,9 +987,10 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " return false; \ } \ \ + /* No callbacks since _new_map_ is just a temporary hashtable */ \ struct SNAME *_new_map_ = \ PFX##_new_custom(capacity, _map_->load, _map_->f_key, \ - _map_->f_val, _map_->alloc, _map_->callbacks); \ + _map_->f_val, _map_->alloc, NULL); \ \ if (!_new_map_) \ { \ @@ -964,12 +1000,14 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ struct SNAME##_iter iter; \ \ + /* TODO Turn this into a normal loop */ \ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ K key = PFX##_iter_key(&iter); \ V value = PFX##_iter_value(&iter); \ \ + /* TODO check for errors */ \ PFX##_insert(_new_map_, key, value); \ } \ \ @@ -991,14 +1029,20 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ PFX##_free(_new_map_); \ \ + success: \ + \ + if (_map_->callbacks && _map_->callbacks->resize) \ + _map_->callbacks->resize(); \ + \ return true; \ } \ \ struct SNAME *PFX##_copy_of(struct SNAME *_map_) \ { \ - struct SNAME *result = PFX##_new_custom( \ - _map_->capacity * _map_->load, _map_->load, _map_->f_key, \ - _map_->f_val, _map_->alloc, _map_->callbacks); \ + /* Callback will be added later */ \ + struct SNAME *result = \ + PFX##_new_custom(_map_->capacity * _map_->load, _map_->load, \ + _map_->f_key, _map_->f_val, _map_->alloc, NULL); \ \ if (!result) \ { \ @@ -1011,6 +1055,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " \ if (!PFX##_empty(_map_)) \ { \ + /* TODO Turn this into a normal loop */ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -1022,10 +1067,12 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " if (_map_->f_val->cpy) \ value = _map_->f_val->cpy(value); \ \ + /* TODO check for errors */ \ PFX##_insert(result, key, value); \ } \ } \ \ + result->callbacks = _map_->callbacks; \ _map_->flag = cmc_flags.OK; \ \ return result; \ @@ -1042,6 +1089,7 @@ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _map1_); \ \ + /* TODO Turn this into a normal loop */ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ diff --git a/src/cmc/multiset.h b/src/cmc/multiset.h index 5564689..7f35685 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -243,6 +243,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " #define CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ + static size_t PFX##_impl_multiplicity_of(struct SNAME *_set_, V element); \ static struct SNAME##_entry *PFX##_impl_insert_and_return( \ struct SNAME *_set_, V element, bool *new_node); \ static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, \ @@ -387,11 +388,12 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _set_->alloc = &cmc_alloc_node_default; \ + else \ _set_->alloc = alloc; \ \ - if (callbacks) \ - _set_->callbacks = callbacks; \ + _set_->callbacks = callbacks; \ \ _set_->flag = cmc_flags.OK; \ } \ @@ -415,16 +417,16 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " _set_->cardinality++; \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->create) \ + _set_->callbacks->create(); \ + \ return true; \ } \ \ bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count) \ { \ if (count == 0) \ - { \ - _set_->flag = cmc_flags.OK; \ - return true; \ - } \ + goto success; \ \ bool new_node; \ \ @@ -443,8 +445,14 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " entry->multiplicity += count; \ \ _set_->cardinality += count; \ + \ + success: \ + \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->create) \ + _set_->callbacks->create(); \ + \ return true; \ } \ \ @@ -456,11 +464,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " struct SNAME##_entry *result = \ PFX##_impl_get_entry(_set_, element); \ \ - _set_->flag = cmc_flags.OK; \ - \ if (!result) \ /* If no entry was found then its multiplicity is already 0 */ \ - return true; \ + goto success; \ \ _set_->count--; \ _set_->cardinality -= result->multiplicity; \ @@ -470,7 +476,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " result->dist = 0; \ result->state = CMC_ES_DELETED; \ \ - return true; \ + goto success; \ } \ \ bool new_node; \ @@ -489,8 +495,13 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ entry->multiplicity = multiplicity; \ \ + success: \ + \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->update) \ + _set_->callbacks->update(); \ + \ return true; \ } \ \ @@ -525,6 +536,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " _set_->cardinality--; \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->delete) \ + _set_->callbacks->delete (); \ + \ return true; \ } \ \ @@ -555,6 +569,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " _set_->cardinality -= removed; \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->delete) \ + _set_->callbacks->delete (); \ + \ return removed; \ } \ \ @@ -587,6 +604,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->read) \ + _set_->callbacks->read(); \ + \ return true; \ } \ \ @@ -619,6 +639,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->read) \ + _set_->callbacks->read(); \ + \ return true; \ } \ \ @@ -628,6 +651,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ _set_->flag = cmc_flags.OK; \ \ + if (_set_->callbacks && _set_->callbacks->read) \ + _set_->callbacks->read(); \ + \ if (!entry) \ return 0; \ \ @@ -638,7 +664,12 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " { \ _set_->flag = cmc_flags.OK; \ \ - return PFX##_impl_get_entry(_set_, element) != NULL; \ + bool result = PFX##_impl_get_entry(_set_, element) != NULL; \ + \ + if (_set_->callbacks && _set_->callbacks->read) \ + _set_->callbacks->read(); \ + \ + return result; \ } \ \ bool PFX##_empty(struct SNAME *_set_) \ @@ -681,10 +712,10 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " _set_->flag = cmc_flags.OK; \ \ if (_set_->capacity == capacity) \ - return true; \ + goto success; \ \ if (_set_->capacity > capacity / _set_->load) \ - return true; \ + goto success; \ \ /* Prevent integer overflow */ \ if (capacity >= UINTMAX_MAX * _set_->load) \ @@ -703,9 +734,9 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " return false; \ } \ \ - struct SNAME *_new_set_ = \ - PFX##_new_custom(capacity, _set_->load, _set_->f_val, \ - _set_->alloc, _set_->callbacks); \ + /* No callbacks since _new_set_ is just a temporary hashtable */ \ + struct SNAME *_new_set_ = PFX##_new_custom( \ + capacity, _set_->load, _set_->f_val, _set_->alloc, NULL); \ \ if (!_new_set_) \ { \ @@ -715,6 +746,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ struct SNAME##_iter iter; \ \ + /* TODO transform this into a normal loop */ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ @@ -725,6 +757,8 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " if (_set_->count != _new_set_->count) \ { \ PFX##_free(_new_set_); \ + \ + _set_->flag = cmc_flags.ERROR; \ return false; \ } \ \ @@ -738,6 +772,11 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ PFX##_free(_new_set_); \ \ + success: \ + \ + if (_set_->callbacks && _set_->callbacks->resize) \ + _set_->callbacks->resize(); \ + \ return true; \ } \ \ @@ -811,7 +850,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " struct SNAME##_entry *entry = \ PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)); \ \ - if (entry == NULL) \ + if (!entry) \ return false; \ \ if (entry->multiplicity != PFX##_iter_multiplicity(&iter)) \ @@ -852,9 +891,10 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " \ struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ return NULL; \ @@ -869,7 +909,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " V value = PFX##_iter_value(&iter1); \ \ size_t m1 = PFX##_iter_multiplicity(&iter1); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + size_t m2 = PFX##_impl_multiplicity_of(_set2_, value); \ size_t max_ = m1 > m2 ? m1 : m2; \ \ PFX##_update(_set_r_, value, max_); \ @@ -880,22 +920,25 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " { \ V value = PFX##_iter_value(&iter2); \ \ - size_t m1 = PFX##_multiplicity_of(_set1_, value); \ + size_t m1 = PFX##_impl_multiplicity_of(_set1_, value); \ size_t m2 = PFX##_iter_multiplicity(&iter2); \ size_t max_ = m1 > m2 ? m1 : m2; \ \ PFX##_update(_set_r_, value, max_); \ } \ \ + _set_r_->callbacks = _set1_->callbacks; \ + \ return _set_r_; \ } \ \ struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ return NULL; \ @@ -913,20 +956,23 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " V value = PFX##_iter_value(&iter); \ \ size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set_B_, value); \ + size_t m2 = PFX##_impl_multiplicity_of(_set_B_, value); \ size_t max_ = m1 < m2 ? m1 : m2; \ \ PFX##_update(_set_r_, value, max_); \ } \ \ + _set_r_->callbacks = _set1_->callbacks; \ + \ return _set_r_; \ } \ \ struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ return NULL; \ @@ -940,20 +986,23 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " V value = PFX##_iter_value(&iter); \ \ size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + size_t m2 = PFX##_impl_multiplicity_of(_set2_, value); \ \ if (m1 > m2) \ PFX##_update(_set_r_, value, m1 - m2); \ } \ \ + _set_r_->callbacks = _set1_->callbacks; \ + \ return _set_r_; \ } \ \ struct SNAME *PFX##_summation(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ return NULL; \ @@ -976,21 +1025,24 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " PFX##_iter_multiplicity(&iter2)); \ } \ \ + _set_r_->callbacks = _set1_->callbacks; \ + \ return _set_r_; \ } \ \ struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ struct SNAME *_set2_) \ { \ - struct SNAME##_iter iter1, iter2; \ - \ + /* Callbacks are added later */ \ struct SNAME *_set_r_ = \ PFX##_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, \ - _set1_->alloc, _set1_->callbacks); \ + _set1_->alloc, NULL); \ \ if (!_set_r_) \ return NULL; \ \ + struct SNAME##_iter iter1, iter2; \ + \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ @@ -1000,7 +1052,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " V value = PFX##_iter_value(&iter1); \ \ size_t m1 = PFX##_iter_multiplicity(&iter1); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + size_t m2 = PFX##_impl_multiplicity_of(_set2_, value); \ \ if (m1 != m2) \ { \ @@ -1016,7 +1068,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " { \ V value = PFX##_iter_value(&iter2); \ \ - size_t m1 = PFX##_multiplicity_of(_set1_, value); \ + size_t m1 = PFX##_impl_multiplicity_of(_set1_, value); \ size_t m2 = PFX##_iter_multiplicity(&iter2); \ \ if (m1 != m2) \ @@ -1028,6 +1080,8 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " } \ } \ \ + _set_r_->callbacks = _set1_->callbacks; \ + \ return _set_r_; \ } \ \ @@ -1049,7 +1103,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " V value = PFX##_iter_value(&iter); \ \ size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + size_t m2 = PFX##_impl_multiplicity_of(_set2_, value); \ \ if (m1 > m2) \ return false; \ @@ -1086,7 +1140,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " V value = PFX##_iter_value(&iter); \ \ size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + size_t m2 = PFX##_impl_multiplicity_of(_set2_, value); \ \ if (m1 >= m2) \ return false; \ @@ -1114,7 +1168,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " { \ V value = PFX##_iter_value(&iter); \ \ - if (PFX##_contains(_set2_, value)) \ + if (PFX##_impl_get_entry(_set2_, value) != NULL) \ return false; \ } \ \ @@ -1339,6 +1393,16 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " return iter->index; \ } \ \ + static size_t PFX##_impl_multiplicity_of(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ + \ + if (!entry) \ + return 0; \ + \ + return entry->multiplicity; \ + } \ + \ static struct SNAME##_entry *PFX##_impl_insert_and_return( \ struct SNAME *_set_, V element, bool *new_node) \ { \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 14449a9..861ef9c 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -334,11 +334,12 @@ static const char *cmc_string_fmt_queue = "struct %s<%s> " void PFX##_customize(struct SNAME *_queue_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _queue_->alloc = &cmc_alloc_node_default; \ + else \ _queue_->alloc = alloc; \ \ - if (callbacks) \ - _queue_->callbacks = callbacks; \ + _queue_->callbacks = callbacks; \ \ _queue_->flag = cmc_flags.OK; \ } \ diff --git a/src/cmc/sortedlist.h b/src/cmc/sortedlist.h index fa293d2..7307fdb 100644 --- a/src/cmc/sortedlist.h +++ b/src/cmc/sortedlist.h @@ -302,11 +302,12 @@ static const char *cmc_string_fmt_sortedlist = "struct %s<%s> " void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _list_->alloc = &cmc_alloc_node_default; \ + else \ _list_->alloc = alloc; \ \ - if (callbacks) \ - _list_->callbacks = callbacks; \ + _list_->callbacks = callbacks; \ \ _list_->flag = cmc_flags.OK; \ } \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 4554f9f..d2c0794 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -293,11 +293,12 @@ static const char *cmc_string_fmt_stack = "struct %s<%s> " void PFX##_customize(struct SNAME *_stack_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks *callbacks) \ { \ - if (alloc) \ + if (!alloc) \ + _stack_->alloc = &cmc_alloc_node_default; \ + else \ _stack_->alloc = alloc; \ \ - if (callbacks) \ - _stack_->callbacks = callbacks; \ + _stack_->callbacks = callbacks; \ \ _stack_->flag = cmc_flags.OK; \ } \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index 7ddea6b..ce9b94c 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -374,6 +374,18 @@ static const char *cmc_string_fmt_treemap = "struct %s<%s, %s> " PFX##_clear(_map_); \ \ _map_->alloc->free(_map_); \ + } \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks *callbacks) \ + { \ + if (!alloc) \ + _map_->alloc = &cmc_alloc_node_default; \ + else \ + _map_->alloc = alloc; \ + \ + _map_->callbacks = callbacks; \ + \ + _map_->flag = cmc_flags.OK; \ } \ \ bool PFX##_insert(struct SNAME *_map_, K key, V value) \ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index e2b0052..8e4c42f 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -358,6 +358,19 @@ static const char *cmc_string_fmt_treeset = "struct %s<%s> " _set_->alloc->free(_set_); \ } \ \ + void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks *callbacks) \ + { \ + if (!alloc) \ + _set_->alloc = &cmc_alloc_node_default; \ + else \ + _set_->alloc = alloc; \ + \ + _set_->callbacks = callbacks; \ + \ + _set_->flag = cmc_flags.OK; \ + } \ + \ bool PFX##_insert(struct SNAME *_set_, V element) \ { \ if (PFX##_empty(_set_)) \ diff --git a/src/cor/core.h b/src/cor/core.h index fe9092f..f70d675 100644 --- a/src/cor/core.h +++ b/src/cor/core.h @@ -62,12 +62,9 @@ static struct cmc_alloc_node * - update : an element in the collection was successfully updated * - delete : an element was successfully removed from the collection * - resize : the collection was full and successfully resized - * - * enabled : if true, callbacks will be called. */ struct cmc_callbacks { - bool enabled; void (*create)(void); void (*read)(void); void (*update)(void); diff --git a/tests/main/unt/bidimap.c b/tests/main/unt/bidimap.c index 7208c29..7b4f22f 100644 --- a/tests/main/unt/bidimap.c +++ b/tests/main/unt/bidimap.c @@ -543,6 +543,8 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert_equals(int32_t, 2, total_delete); cmc_assert(bm_insert(map, 1, 2)); + cmc_assert_equals(int32_t, 3, total_create); + cmc_assert_equals(size_t, 1, bm_get_key(map, 2)); cmc_assert_equals(int32_t, 1, total_read); @@ -561,6 +563,39 @@ CMC_CREATE_UNIT(bidimap_test, true, { cmc_assert(bm_contains_val(map, 2)); cmc_assert_equals(int32_t, 4, total_read); + cmc_assert_equals(int32_t, 3, total_create); + cmc_assert_equals(int32_t, 4, 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); + + bm_customize(map, NULL, NULL); + + cmc_assert_equals(ptr, NULL, map->callbacks); + + bm_clear(map); + cmc_assert(bm_insert(map, 10, 10)); + cmc_assert(bm_update_key(map, 10, 5)); + cmc_assert(bm_update_val(map, 5, 5)); + cmc_assert(bm_insert(map, 10, 10)); + cmc_assert(bm_remove_by_key(map, 5, NULL, NULL)); + cmc_assert(bm_remove_by_val(map, 10, NULL, NULL)); + cmc_assert(bm_insert(map, 1, 2)); + cmc_assert_equals(size_t, 1, bm_get_key(map, 2)); + cmc_assert_equals(size_t, 2, bm_get_val(map, 1)); + cmc_assert(bm_resize(map, 1000)); + cmc_assert(bm_resize(map, 200)); + cmc_assert(bm_contains_key(map, 1)); + cmc_assert(bm_contains_val(map, 2)); + + cmc_assert_equals(int32_t, 3, total_create); + cmc_assert_equals(int32_t, 4, 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); + bm_free(map); }); }); diff --git a/tests/main/unt/deque.c b/tests/main/unt/deque.c index 02ae64d..8c06ae0 100644 --- a/tests/main/unt/deque.c +++ b/tests/main/unt/deque.c @@ -772,6 +772,44 @@ CMC_CREATE_UNIT(deque_test, true, { cmc_assert(!d_contains(d, 1)); cmc_assert_equals(int32_t, 4, total_read); + cmc_assert(d_resize(d, 1000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(d_resize(d, 10)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 4, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + d_customize(d, NULL, NULL); + + cmc_assert_equals(ptr, NULL, d->callbacks); + + d_clear(d); + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_front(d)); + cmc_assert(d_pop_back(d)); + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_push_front(d, 5)); + cmc_assert_equals(size_t, 5, d_front(d)); + cmc_assert_equals(size_t, 10, d_back(d)); + cmc_assert(d_contains(d, 10)); + cmc_assert(!d_contains(d, 1)); + cmc_assert(d_resize(d, 1000)); + cmc_assert(d_resize(d, 10)); + + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 4, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, d->callbacks); + d_free(d); }); }); diff --git a/tests/main/unt/hashmap.c b/tests/main/unt/hashmap.c index 7d15efd..5afbb47 100644 --- a/tests/main/unt/hashmap.c +++ b/tests/main/unt/hashmap.c @@ -640,6 +640,43 @@ CMC_CREATE_UNIT(hashmap_test, true, { cmc_assert(hm_contains(map, 1)); cmc_assert_equals(int32_t, 5, total_read); + cmc_assert(hm_resize(map, 10000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(hm_resize(map, 500)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 1, total_update); + cmc_assert_equals(int32_t, 1, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + hm_customize(map, NULL, NULL); + + cmc_assert_equals(ptr, NULL, map->callbacks); + + hm_clear(map); + cmc_assert(hm_insert(map, 1, 2)); + cmc_assert(hm_update(map, 1, 10, NULL)); + cmc_assert(hm_remove(map, 1, NULL)); + cmc_assert(hm_insert(map, 1, 2)); + cmc_assert(hm_max(map, NULL, NULL)); + cmc_assert(hm_min(map, NULL, NULL)); + cmc_assert_equals(size_t, 2, hm_get(map, 1)); + cmc_assert_not_equals(ptr, NULL, hm_get_ref(map, 1)); + cmc_assert(hm_contains(map, 1)); + cmc_assert(hm_resize(map, 10000)); + cmc_assert(hm_resize(map, 500)); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 1, total_update); + cmc_assert_equals(int32_t, 1, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, map->callbacks); + hm_free(map); }); }); diff --git a/tests/main/unt/hashset.c b/tests/main/unt/hashset.c index 67c88c2..7f5d3b0 100644 --- a/tests/main/unt/hashset.c +++ b/tests/main/unt/hashset.c @@ -510,6 +510,40 @@ CMC_CREATE_UNIT(hashset_test, true, { cmc_assert(hs_contains(set, 1)); cmc_assert_equals(int32_t, 3, total_read); + cmc_assert(hs_resize(set, 10000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(hs_resize(set, 500)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 3, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 1, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + hs_customize(set, NULL, NULL); + + cmc_assert_equals(ptr, NULL, set->callbacks); + + hs_clear(set); + cmc_assert(hs_resize(set, 10000)); + cmc_assert(hs_resize(set, 500)); + cmc_assert(hs_insert(set, 1)); + cmc_assert(hs_remove(set, 1)); + cmc_assert(hs_insert(set, 1)); + cmc_assert(hs_max(set, NULL)); + cmc_assert(hs_min(set, NULL)); + cmc_assert(hs_contains(set, 1)); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 3, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 1, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, set->callbacks); + hs_free(set); }); }); diff --git a/tests/main/unt/heap.c b/tests/main/unt/heap.c index 97a5f19..c9a24a9 100644 --- a/tests/main/unt/heap.c +++ b/tests/main/unt/heap.c @@ -255,6 +255,33 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert(h_resize(h, 100)); cmc_assert_equals(int32_t, 2, total_resize); + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 2, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 1, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + h_customize(h, NULL, NULL); + + cmc_assert_equals(ptr, NULL, h->callbacks); + + h_clear(h); + cmc_assert(h_insert(h, 10)); + cmc_assert(h_remove(h)); + cmc_assert(h_insert(h, 10)); + cmc_assert_equals(size_t, 10, h_peek(h)); + cmc_assert(h_contains(h, 10)); + cmc_assert(h_resize(h, 1000)); + cmc_assert(h_resize(h, 100)); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 2, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 1, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, h->callbacks); + h_free(h); }); }); diff --git a/tests/main/unt/intervalheap.c b/tests/main/unt/intervalheap.c index 41f02f2..8cb262f 100644 --- a/tests/main/unt/intervalheap.c +++ b/tests/main/unt/intervalheap.c @@ -308,6 +308,39 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert(ih_resize(ih, 50)); cmc_assert_equals(int32_t, 2, total_resize); + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 3, 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); + + ih_customize(ih, NULL, NULL); + + cmc_assert_equals(ptr, NULL, ih->callbacks); + + ih_clear(ih); + cmc_assert(ih_insert(ih, 10)); + cmc_assert(ih_remove_max(ih)); + cmc_assert(ih_insert(ih, 10)); + cmc_assert(ih_remove_min(ih)); + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 2)); + cmc_assert(ih_update_max(ih, 1)); + cmc_assert(ih_update_min(ih, 2)); + cmc_assert_equals(size_t, 2, ih_max(ih)); + cmc_assert_equals(size_t, 1, ih_min(ih)); + cmc_assert(ih_contains(ih, 1)); + cmc_assert(ih_resize(ih, 1000)); + cmc_assert(ih_resize(ih, 50)); + + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 3, 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, ih->callbacks); + ih_free(ih); }); }); diff --git a/tests/main/unt/linkedlist.c b/tests/main/unt/linkedlist.c index 83be48a..cd04e84 100644 --- a/tests/main/unt/linkedlist.c +++ b/tests/main/unt/linkedlist.c @@ -302,6 +302,38 @@ CMC_CREATE_UNIT(linkedlist_test, true, { cmc_assert(ll_contains(ll, 10)); cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 3, total_delete); + cmc_assert_equals(int32_t, 0, total_resize); + + ll_customize(ll, NULL, NULL); + + cmc_assert_equals(ptr, NULL, ll->callbacks); + + ll_clear(ll); + cmc_assert(ll_push_front(ll, 10)); + cmc_assert(ll_push_back(ll, 10)); + cmc_assert(ll_push_at(ll, 10, 1)); + cmc_assert(ll_pop_at(ll, 1)); + cmc_assert(ll_pop_front(ll)); + cmc_assert(ll_pop_back(ll)); + cmc_assert(ll_push_back(ll, 10)); + cmc_assert_equals(size_t, 10, ll_front(ll)); + cmc_assert_equals(size_t, 10, ll_back(ll)); + cmc_assert_equals(size_t, 10, ll_get(ll, 0)); + cmc_assert_not_equals(ptr, NULL, ll_get_ref(ll, 0)); + cmc_assert(ll_contains(ll, 10)); + + cmc_assert_equals(int32_t, 4, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 3, total_delete); + cmc_assert_equals(int32_t, 0, total_resize); + + cmc_assert_equals(ptr, NULL, ll->callbacks); + ll_free(ll); }); }); diff --git a/tests/main/unt/list.c b/tests/main/unt/list.c index 8a93212..c8906f9 100644 --- a/tests/main/unt/list.c +++ b/tests/main/unt/list.c @@ -542,13 +542,13 @@ CMC_CREATE_UNIT(list_test, true, { cmc_assert(l_contains(l, 10)); cmc_assert_equals(int32_t, 5, total_read); - cmc_assert(l_seq_push_front(l, (size_t[]) {7, 8, 9}, 3)); + cmc_assert(l_seq_push_front(l, (size_t[]){ 7, 8, 9 }, 3)); cmc_assert_equals(int32_t, 5, total_create); - cmc_assert(l_seq_push_back(l, (size_t[]) {14, 15, 16}, 3)); + cmc_assert(l_seq_push_back(l, (size_t[]){ 14, 15, 16 }, 3)); cmc_assert_equals(int32_t, 6, total_create); - cmc_assert(l_seq_push_at(l, (size_t[]) {11, 12, 13}, 3, 4)); + cmc_assert(l_seq_push_at(l, (size_t[]){ 11, 12, 13 }, 3, 4)); cmc_assert_equals(int32_t, 7, total_create); cmc_assert(l_seq_pop_at(l, 1, 4)); @@ -557,7 +557,53 @@ CMC_CREATE_UNIT(list_test, true, { struct list *l2 = l_seq_sublist(l, 0, 4); cmc_assert_equals(int32_t, 5, total_delete); + cmc_assert(l_resize(l, 1000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(l_resize(l2, 1000)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 7, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 5, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + l_customize(l, NULL, NULL); + + cmc_assert_equals(ptr, NULL, l->callbacks); + + l_clear(l); + cmc_assert(l_push_front(l, 10)); + cmc_assert(l_push_back(l, 10)); + cmc_assert(l_push_at(l, 10, 1)); + cmc_assert(l_pop_at(l, 1)); + cmc_assert(l_pop_front(l)); + cmc_assert(l_pop_back(l)); + cmc_assert(l_push_back(l, 10)); + cmc_assert_equals(size_t, 10, l_front(l)); + cmc_assert_equals(size_t, 10, l_back(l)); + cmc_assert_equals(size_t, 10, l_get(l, 0)); + cmc_assert_not_equals(ptr, NULL, l_get_ref(l, 0)); + cmc_assert(l_contains(l, 10)); + cmc_assert(l_seq_push_front(l, (size_t[]){ 7, 8, 9 }, 3)); + cmc_assert(l_seq_push_back(l, (size_t[]){ 14, 15, 16 }, 3)); + cmc_assert(l_seq_push_at(l, (size_t[]){ 11, 12, 13 }, 3, 4)); + cmc_assert(l_seq_pop_at(l, 1, 4)); + struct list *l3 = l_seq_sublist(l, 0, 4); + cmc_assert(l_resize(l, 1000)); + cmc_assert(l_resize(l3, 1000)); + + cmc_assert_equals(int32_t, 7, total_create); + cmc_assert_equals(int32_t, 5, total_read); + cmc_assert_equals(int32_t, 0, total_update); + cmc_assert_equals(int32_t, 5, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, l->callbacks); + l_free(l); l_free(l2); + l_free(l3); }); }) diff --git a/tests/main/unt/multimap.c b/tests/main/unt/multimap.c index e3c9461..79c2d63 100644 --- a/tests/main/unt/multimap.c +++ b/tests/main/unt/multimap.c @@ -272,4 +272,97 @@ CMC_CREATE_UNIT(multimap_test, true, { mm_free(map); mm_free(map2); }); + + CMC_CREATE_TEST(callbacks, { + struct multimap *map = + mm_new_custom(100, 0.8, mm_ftab_key, mm_ftab_val, NULL, callbacks); + + 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); + }); }); diff --git a/tests/main/unt/multiset.c b/tests/main/unt/multiset.c index bba7da1..c057ad4 100644 --- a/tests/main/unt/multiset.c +++ b/tests/main/unt/multiset.c @@ -262,4 +262,85 @@ CMC_CREATE_UNIT(multiset_test, true, { ms_free(set); ms_free(set2); }); + + CMC_CREATE_TEST(callbacks, { + struct multiset *set = + ms_new_custom(100, 0.8, ms_ftab_val, NULL, callbacks); + + total_create = 0; + total_read = 0; + total_update = 0; + total_delete = 0; + total_resize = 0; + + cmc_assert(ms_insert(set, 1)); + cmc_assert_equals(int32_t, 1, total_create); + + cmc_assert(ms_insert_many(set, 1, 3)); + cmc_assert_equals(int32_t, 2, total_create); + + cmc_assert(ms_update(set, 1, 0)); + cmc_assert_equals(int32_t, 1, total_update); + + cmc_assert(ms_update(set, 1, 10)); + cmc_assert_equals(int32_t, 2, total_update); + + cmc_assert(ms_remove(set, 1)); + cmc_assert_equals(int32_t, 1, total_delete); + + cmc_assert(ms_remove_all(set, 1)); + cmc_assert_equals(int32_t, 2, total_delete); + + cmc_assert(ms_update(set, 1, 10)); + cmc_assert_equals(int32_t, 3, total_update); + + cmc_assert(ms_max(set, NULL)); + cmc_assert_equals(int32_t, 1, total_read); + + cmc_assert(ms_min(set, NULL)); + cmc_assert_equals(int32_t, 2, total_read); + + cmc_assert(ms_contains(set, 1)); + cmc_assert_equals(int32_t, 3, total_read); + + cmc_assert(ms_resize(set, 1000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(ms_resize(set, 100)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 3, total_read); + cmc_assert_equals(int32_t, 3, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + ms_customize(set, NULL, NULL); + + cmc_assert_equals(ptr, NULL, set->callbacks); + + ms_clear(set); + cmc_assert(ms_insert(set, 1)); + cmc_assert(ms_insert_many(set, 1, 3)); + cmc_assert(ms_update(set, 1, 0)); + cmc_assert(ms_update(set, 1, 10)); + cmc_assert(ms_remove(set, 1)); + cmc_assert(ms_remove_all(set, 1)); + cmc_assert(ms_update(set, 1, 10)); + cmc_assert(ms_max(set, NULL)); + cmc_assert(ms_min(set, NULL)); + cmc_assert(ms_contains(set, 1)); + cmc_assert(ms_resize(set, 1000)); + cmc_assert(ms_resize(set, 100)); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 3, total_read); + cmc_assert_equals(int32_t, 3, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, set->callbacks); + + ms_free(set); + }); }); diff --git a/tests/main/unt/utl.c b/tests/main/unt/utl.c index 770c1ca..3d2a8f7 100644 --- a/tests/main/unt/utl.c +++ b/tests/main/unt/utl.c @@ -99,8 +99,7 @@ void callback_resize(void) } struct cmc_callbacks *callbacks = - &(struct cmc_callbacks){ .enabled = true, - .create = callback_create, + &(struct cmc_callbacks){ .create = callback_create, .read = callback_read, .update = callback_update, .delete = callback_delete,