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,