diff --git a/src/cmc/multimap.h b/src/cmc/multimap.h index 3e46726..6e8a224 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/multimap.h @@ -324,987 +324,992 @@ struct cmc_callbacks_multimap /* ------------------------------------------------------------------------- * Source * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - struct SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ - struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \ - 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, \ - int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity == 0 || load <= 0) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - 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 *[2])); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->cmp = compare; \ - _map_->hash = hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = NULL; \ - \ - return _map_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, \ - int (*compare)(K, K), size_t (*hash)(K), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multimap *callbacks) \ - { \ - if (capacity == 0 || load <= 0) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - 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 *[2])); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->cmp = compare; \ - _map_->hash = hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = callbacks; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - struct SNAME##_entry *scan; \ - \ - while (index < _map_->capacity) \ - { \ - scan = _map_->buffer[index][0]; \ - \ - if (scan != NULL) \ - { \ - if (scan->next == NULL && scan->prev == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - } \ - else \ - { \ - while (scan != NULL) \ - { \ - struct SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - memset(_map_->buffer, 0, \ - sizeof(struct SNAME##_entry *[2]) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - struct SNAME##_entry *scan; \ - \ - while (index < _map_->capacity) \ - { \ - scan = _map_->buffer[index][0]; \ - \ - if (scan != NULL) \ - { \ - if (scan->next == NULL && scan->prev == NULL) \ - free(scan); \ - else \ - { \ - while (scan != NULL) \ - { \ - struct SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - free(_map_->buffer); \ - free(_map_); \ - } \ - \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multimap *callbacks) \ - { \ - if (alloc) \ - _map_->alloc = alloc; \ - \ - if (callbacks) \ - _map_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_full(_map_)) \ - { \ - if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - struct SNAME##_entry *entry = PFX##_impl_new_entry(key, value); \ - \ - if (_map_->buffer[pos][0] == NULL) \ - { \ - _map_->buffer[pos][0] = entry; \ - _map_->buffer[pos][1] = entry; \ - } \ - else \ - { \ - entry->prev = _map_->buffer[pos][1]; \ - \ - _map_->buffer[pos][1]->next = entry; \ - _map_->buffer[pos][1] = entry; \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (old_value) \ - *old_value = entry->value; \ - \ - entry->value = new_value; \ - \ - return false; \ - } \ - \ - size_t PFX##_update_all(struct SNAME *_map_, K key, V new_value, \ - V **old_values) \ - { \ - size_t total = PFX##_key_count(_map_, key); \ - size_t index = 0; \ - \ - if (total == 0) \ - return total; \ - \ - if (old_values) \ - { \ - *old_values = malloc(sizeof(V) * total); \ - \ - if (!(*old_values)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry *entry = \ - _map_->buffer[hash % _map_->capacity][0]; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (old_values) \ - (*old_values)[index++] = entry->value; \ - \ - entry->value = new_value; \ - } \ - \ - entry = entry->next; \ - } \ - \ - return index; \ - } \ - \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry **head = \ - &(_map_->buffer[hash % _map_->capacity][0]); \ - struct SNAME##_entry **tail = \ - &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return false; \ - \ - struct SNAME##_entry *entry = *head; \ - \ - if (entry->next == NULL && entry->prev == NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - *head = NULL; \ - *tail = NULL; \ - \ - if (out_value) \ - *out_value = entry->value; \ - } \ - else \ - return false; \ - } \ - else \ - { \ - bool found = false; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (*head == entry) \ - *head = entry->next; \ - if (*tail == entry) \ - *tail = entry->prev; \ - \ - if (entry->prev != NULL) \ - entry->prev->next = entry->next; \ - if (entry->next != NULL) \ - entry->next->prev = entry->prev; \ - \ - if (out_value) \ - *out_value = entry->value; \ - \ - found = true; \ - \ - break; \ - } \ - else \ - entry = entry->next; \ - } \ - \ - if (!found) \ - return false; \ - } \ - \ - free(entry); \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - size_t PFX##_remove_all(struct SNAME *_map_, K key, V **out_values) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry **head = \ - &(_map_->buffer[hash % _map_->capacity][0]); \ - struct SNAME##_entry **tail = \ - &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return 0; \ - \ - size_t total = PFX##_key_count(_map_, key); \ - size_t index = 0; \ - \ - if (out_values) \ - *out_values = malloc(sizeof(struct SNAME##_entry) * total); \ - \ - struct SNAME##_entry *entry = *head; \ - \ - if (entry->next == NULL) \ - { \ - *head = NULL; \ - *tail = NULL; \ - \ - if (out_values) \ - (*out_values)[index++] = entry->value; \ - \ - free(entry); \ - } \ - else \ - { \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (*head == entry) \ - *head = entry->next; \ - if (*tail == entry) \ - *tail = entry->prev; \ - \ - struct SNAME##_entry *temp = entry->next; \ - \ - if (entry->prev != NULL) \ - entry->prev->next = entry->next; \ - if (entry->next != NULL) \ - entry->next->prev = entry->prev; \ - \ - if (out_values) \ - (*out_values)[index++] = entry->value; \ - \ - free(entry); \ - \ - entry = temp; \ - } \ - else \ - entry = entry->next; \ - } \ - } \ - \ - _map_->count -= index; \ - \ - return index; \ - } \ - \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) > 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) < 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - V PFX##_get(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return (V){ 0 }; \ - \ - return entry->value; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - bool PFX##_contains(struct SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= \ - (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_key_count(struct SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry *entry = \ - _map_->buffer[hash % _map_->capacity][0]; \ - \ - size_t total_count = 0; \ - \ - if (!entry) \ - return total_count; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - total_count++; \ - \ - entry = entry->next; \ - } \ - \ - return total_count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ - { \ - if (PFX##_capacity(_map_) == capacity) \ - return true; \ - \ - if (PFX##_capacity(_map_) > capacity / PFX##_load(_map_)) \ - return true; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ - 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 < PFX##_count(_map_) / PFX##_load(_map_)) \ - return false; \ - \ - struct SNAME *_new_map_ = \ - PFX##_new(capacity, PFX##_load(_map_), _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - struct SNAME##_iter iter; \ - \ - 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); \ - } \ - \ - if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - PFX##_free(_new_map_, NULL); \ - return false; \ - } \ - \ - struct SNAME##_entry *(*tmp_b)[2] = _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_, NULL); \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ - { \ - struct SNAME *result = \ - PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - if (!PFX##_empty(_map_)) \ - { \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - if (key_copy_func) \ - key = key_copy_func(key); \ - if (value_copy_func) \ - value = value_copy_func(value); \ - \ - PFX##_insert(result, key, value); \ - } \ - } \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ - bool ignore_key_count) \ - { \ - if (ignore_key_count) \ - { \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == \ - NULL) \ - return false; \ - } \ - } \ - else \ - { \ - /* Since the key count matters this can be checked and an */ \ - /* early exit */ \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ - PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - \ - if (PFX##_key_count(_map1_, key) != \ - PFX##_key_count(_map2_, key)) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - 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_multimap, #SNAME, \ - #K, #V, m_, m_->buffer, m_->capacity, m_->count, \ - m_->load, m_->cmp, m_->hash, m_->alloc, m_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){ 0 }; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - 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][0] != NULL) \ - { \ - iter->curr_entry = target->buffer[i][0]; \ - iter->first = i; \ - break; \ - } \ - } \ - \ - iter->cursor = iter->first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1][0] != NULL) \ - { \ - 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); \ - iter->curr_entry = iter->target->buffer[iter->first][0]; \ - } \ - } \ - \ - 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; \ - iter->curr_entry = iter->target->buffer[iter->last][1]; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->curr_entry->next != NULL) \ - { \ - iter->curr_entry = iter->curr_entry->next; \ - iter->index++; \ - } \ - else \ - { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->cursor++; \ - \ - while (iter->target->buffer[iter->cursor][0] == NULL) \ - iter->cursor++; \ - \ - iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ - \ - iter->index++; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->curr_entry->prev != NULL) \ - { \ - iter->curr_entry = iter->curr_entry->prev; \ - iter->index--; \ - } \ - else \ - { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->cursor--; \ - \ - while (iter->target->buffer[iter->cursor][1] == NULL) \ - iter->cursor--; \ - \ - iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ - \ - iter->index--; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - 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 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - 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 >= PFX##_count(iter->target)) \ - 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->curr_entry->key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){ 0 }; \ - \ - return iter->curr_entry->value; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->curr_entry->value); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - struct SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ - { \ - struct SNAME##_entry *entry = malloc(sizeof(struct SNAME##_entry)); \ - \ - if (!entry) \ - return NULL; \ - \ - entry->key = key; \ - entry->value = value; \ - entry->next = NULL; \ - entry->prev = NULL; \ - \ - return entry; \ - } \ - \ - struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry *entry = \ - _map_->buffer[hash % _map_->capacity][0]; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - return entry; \ - \ - entry = entry->next; \ - } \ - \ - return NULL; \ - } \ - \ - 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_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, \ + V value); \ + struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \ + 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, \ + int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity == 0 || load <= 0) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + 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 *[2])); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = NULL; \ + \ + return _map_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multimap *callbacks) \ + { \ + if (capacity == 0 || load <= 0) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + 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 *[2])); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = callbacks; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + size_t index = 0; \ + struct SNAME##_entry *scan; \ + \ + while (index < _map_->capacity) \ + { \ + scan = _map_->buffer[index][0]; \ + \ + if (scan != NULL) \ + { \ + if (scan->next == NULL && scan->prev == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + } \ + else \ + { \ + while (scan != NULL) \ + { \ + struct SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + memset(_map_->buffer, 0, \ + sizeof(struct SNAME##_entry *[2]) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + size_t index = 0; \ + struct SNAME##_entry *scan; \ + \ + while (index < _map_->capacity) \ + { \ + scan = _map_->buffer[index][0]; \ + \ + if (scan != NULL) \ + { \ + if (scan->next == NULL && scan->prev == NULL) \ + free(scan); \ + else \ + { \ + while (scan != NULL) \ + { \ + struct SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multimap *callbacks) \ + { \ + if (alloc) \ + _map_->alloc = alloc; \ + \ + if (callbacks) \ + _map_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_map_, K key, V value) \ + { \ + if (PFX##_full(_map_)) \ + { \ + if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + struct SNAME##_entry *entry = PFX##_impl_new_entry(_map_, key, value); \ + \ + if (_map_->buffer[pos][0] == NULL) \ + { \ + _map_->buffer[pos][0] = entry; \ + _map_->buffer[pos][1] = entry; \ + } \ + else \ + { \ + entry->prev = _map_->buffer[pos][1]; \ + \ + _map_->buffer[pos][1]->next = entry; \ + _map_->buffer[pos][1] = entry; \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return false; \ + \ + if (old_value) \ + *old_value = entry->value; \ + \ + entry->value = new_value; \ + \ + return false; \ + } \ + \ + size_t PFX##_update_all(struct SNAME *_map_, K key, V new_value, \ + V **old_values) \ + { \ + size_t total = PFX##_key_count(_map_, key); \ + size_t index = 0; \ + \ + if (total == 0) \ + return total; \ + \ + if (old_values) \ + { \ + *old_values = _map_->alloc->malloc(sizeof(V) * total); \ + \ + if (!(*old_values)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry *entry = \ + _map_->buffer[hash % _map_->capacity][0]; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (old_values) \ + (*old_values)[index++] = entry->value; \ + \ + entry->value = new_value; \ + } \ + \ + entry = entry->next; \ + } \ + \ + return index; \ + } \ + \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry **head = \ + &(_map_->buffer[hash % _map_->capacity][0]); \ + struct SNAME##_entry **tail = \ + &(_map_->buffer[hash % _map_->capacity][1]); \ + \ + if (*head == NULL) \ + return false; \ + \ + struct SNAME##_entry *entry = *head; \ + \ + if (entry->next == NULL && entry->prev == NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + *head = NULL; \ + *tail = NULL; \ + \ + if (out_value) \ + *out_value = entry->value; \ + } \ + else \ + return false; \ + } \ + else \ + { \ + bool found = false; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (*head == entry) \ + *head = entry->next; \ + if (*tail == entry) \ + *tail = entry->prev; \ + \ + if (entry->prev != NULL) \ + entry->prev->next = entry->next; \ + if (entry->next != NULL) \ + entry->next->prev = entry->prev; \ + \ + if (out_value) \ + *out_value = entry->value; \ + \ + found = true; \ + \ + break; \ + } \ + else \ + entry = entry->next; \ + } \ + \ + if (!found) \ + return false; \ + } \ + \ + free(entry); \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + size_t PFX##_remove_all(struct SNAME *_map_, K key, V **out_values) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry **head = \ + &(_map_->buffer[hash % _map_->capacity][0]); \ + struct SNAME##_entry **tail = \ + &(_map_->buffer[hash % _map_->capacity][1]); \ + \ + if (*head == NULL) \ + return 0; \ + \ + size_t total = PFX##_key_count(_map_, key); \ + size_t index = 0; \ + \ + if (out_values) \ + *out_values = \ + _map_->alloc->malloc(sizeof(struct SNAME##_entry) * total); \ + \ + struct SNAME##_entry *entry = *head; \ + \ + if (entry->next == NULL) \ + { \ + *head = NULL; \ + *tail = NULL; \ + \ + if (out_values) \ + (*out_values)[index++] = entry->value; \ + \ + free(entry); \ + } \ + else \ + { \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (*head == entry) \ + *head = entry->next; \ + if (*tail == entry) \ + *tail = entry->prev; \ + \ + struct SNAME##_entry *temp = entry->next; \ + \ + if (entry->prev != NULL) \ + entry->prev->next = entry->next; \ + if (entry->next != NULL) \ + entry->next->prev = entry->prev; \ + \ + if (out_values) \ + (*out_values)[index++] = entry->value; \ + \ + free(entry); \ + \ + entry = temp; \ + } \ + else \ + entry = entry->next; \ + } \ + } \ + \ + _map_->count -= index; \ + \ + return index; \ + } \ + \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) > 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) < 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + V PFX##_get(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return (V){ 0 }; \ + \ + return entry->value; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return NULL; \ + \ + return &(entry->value); \ + } \ + \ + bool PFX##_contains(struct SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry(_map_, key) != NULL; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_map_) \ + { \ + return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= \ + (double)PFX##_count(_map_); \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + size_t PFX##_key_count(struct SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry *entry = \ + _map_->buffer[hash % _map_->capacity][0]; \ + \ + size_t total_count = 0; \ + \ + if (!entry) \ + return total_count; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + total_count++; \ + \ + entry = entry->next; \ + } \ + \ + return total_count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_map_) \ + { \ + return _map_->load; \ + } \ + \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ + { \ + if (PFX##_capacity(_map_) == capacity) \ + return true; \ + \ + if (PFX##_capacity(_map_) > capacity / PFX##_load(_map_)) \ + return true; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ + 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 < PFX##_count(_map_) / PFX##_load(_map_)) \ + return false; \ + \ + struct SNAME *_new_map_ = \ + PFX##_new(capacity, PFX##_load(_map_), _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + struct SNAME##_iter iter; \ + \ + 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); \ + } \ + \ + if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ + { \ + PFX##_free(_new_map_, NULL); \ + return false; \ + } \ + \ + struct SNAME##_entry *(*tmp_b)[2] = _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_, NULL); \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)) \ + { \ + struct SNAME *result = \ + PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + if (!PFX##_empty(_map_)) \ + { \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + if (key_copy_func) \ + key = key_copy_func(key); \ + if (value_copy_func) \ + value = value_copy_func(value); \ + \ + PFX##_insert(result, key, value); \ + } \ + } \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ + bool ignore_key_count) \ + { \ + if (ignore_key_count) \ + { \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == \ + NULL) \ + return false; \ + } \ + } \ + else \ + { \ + /* Since the key count matters this can be checked and an */ \ + /* early exit */ \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + \ + if (PFX##_key_count(_map1_, key) != \ + PFX##_key_count(_map2_, key)) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + 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_multimap, #SNAME, \ + #K, #V, m_, m_->buffer, m_->capacity, m_->count, \ + m_->load, m_->cmp, m_->hash, m_->alloc, m_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + 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) \ + { \ + 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][0] != NULL) \ + { \ + iter->curr_entry = target->buffer[i][0]; \ + iter->first = i; \ + break; \ + } \ + } \ + \ + iter->cursor = iter->first; \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + if (target->buffer[i - 1][0] != NULL) \ + { \ + 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); \ + iter->curr_entry = iter->target->buffer[iter->first][0]; \ + } \ + } \ + \ + 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; \ + iter->curr_entry = iter->target->buffer[iter->last][1]; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->curr_entry->next != NULL) \ + { \ + iter->curr_entry = iter->curr_entry->next; \ + iter->index++; \ + } \ + else \ + { \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->cursor++; \ + \ + while (iter->target->buffer[iter->cursor][0] == NULL) \ + iter->cursor++; \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ + \ + iter->index++; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->curr_entry->prev != NULL) \ + { \ + iter->curr_entry = iter->curr_entry->prev; \ + iter->index--; \ + } \ + else \ + { \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->cursor--; \ + \ + while (iter->target->buffer[iter->cursor][1] == NULL) \ + iter->cursor--; \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ + \ + iter->index--; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + 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 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + 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 >= PFX##_count(iter->target)) \ + 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->curr_entry->key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->curr_entry->value; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->curr_entry->value); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, \ + V value) \ + { \ + struct SNAME##_entry *entry = \ + _map_->alloc->malloc(sizeof(struct SNAME##_entry)); \ + \ + if (!entry) \ + return NULL; \ + \ + entry->key = key; \ + entry->value = value; \ + entry->next = NULL; \ + entry->prev = NULL; \ + \ + return entry; \ + } \ + \ + struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry *entry = \ + _map_->buffer[hash % _map_->capacity][0]; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + return entry; \ + \ + entry = entry->next; \ + } \ + \ + return NULL; \ + } \ + \ + 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_MULTIMAP_H */ diff --git a/src/cmc/multiset.h b/src/cmc/multiset.h index 4ef4fd9..d40e680 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -1091,7 +1091,7 @@ struct cmc_callbacks_multiset \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index cab366b..86023e8 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -297,14 +297,13 @@ struct cmc_callbacks_stack \ void PFX##_free(struct SNAME *_stack_, void (*deallocator)(V)) \ { \ - _stack_->alloc->free(_stack_->buffer); \ - \ if (deallocator) \ { \ for (size_t i = 0; i < _stack_->count; i++) \ deallocator(_stack_->buffer[i]); \ } \ - \ + \ + _stack_->alloc->free(_stack_->buffer); \ _stack_->alloc->free(_stack_); \ } \ \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index 316cb74..7139e51 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -236,7 +236,7 @@ struct cmc_callbacks_treemap #define CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) \ \ /* Implementation Detail Functions */ \ - static struct SNAME##_node *PFX##_impl_new_node(K key, V value); \ + static struct SNAME##_node *PFX##_impl_new_node(struct SNAME *_map_, K key, V value); \ static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, \ K key); \ static unsigned char PFX##_impl_h(struct SNAME##_node *node); \ @@ -326,7 +326,7 @@ struct cmc_callbacks_treemap if (deallocator) \ deallocator(scan->key, scan->value); \ \ - free(scan); \ + _map_->alloc->free(scan); \ scan = NULL; \ } \ \ @@ -335,7 +335,7 @@ struct cmc_callbacks_treemap if (deallocator) \ deallocator(scan->key, scan->value); \ \ - free(scan); \ + _map_->alloc->free(scan); \ \ if (up->right != NULL) \ { \ @@ -360,14 +360,14 @@ struct cmc_callbacks_treemap { \ PFX##_clear(_map_, deallocator); \ \ - free(_map_); \ + _map_->alloc->free(_map_); \ } \ \ bool PFX##_insert(struct SNAME *_map_, K key, V value) \ { \ if (PFX##_empty(_map_)) \ { \ - _map_->root = PFX##_impl_new_node(key, value); \ + _map_->root = PFX##_impl_new_node(_map_, key, value); \ \ if (!_map_->root) \ return false; \ @@ -393,7 +393,7 @@ struct cmc_callbacks_treemap \ if (_map_->cmp(parent->key, key) > 0) \ { \ - parent->left = PFX##_impl_new_node(key, value); \ + parent->left = PFX##_impl_new_node(_map_, key, value); \ \ if (!parent->left) \ return false; \ @@ -403,7 +403,7 @@ struct cmc_callbacks_treemap } \ else \ { \ - parent->right = PFX##_impl_new_node(key, value); \ + parent->right = PFX##_impl_new_node(_map_, key, value); \ \ if (!parent->right) \ return false; \ @@ -463,7 +463,7 @@ struct cmc_callbacks_treemap node->parent->left = NULL; \ } \ \ - free(node); \ + _map_->alloc->free(node); \ } \ else if (node->left == NULL) \ { \ @@ -484,7 +484,7 @@ struct cmc_callbacks_treemap node->parent->left = node->right; \ } \ \ - free(node); \ + _map_->alloc->free(node); \ } \ else if (node->right == NULL) \ { \ @@ -505,7 +505,7 @@ struct cmc_callbacks_treemap node->parent->left = node->left; \ } \ \ - free(node); \ + _map_->alloc->free(node); \ } \ else \ { \ @@ -544,7 +544,7 @@ struct cmc_callbacks_treemap temp->parent->left = temp->left; \ } \ \ - free(temp); \ + _map_->alloc->free(temp); \ \ node->key = temp_key; \ node->value = temp_val; \ @@ -719,7 +719,7 @@ struct cmc_callbacks_treemap \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -731,7 +731,7 @@ struct cmc_callbacks_treemap \ void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ - free(iter); \ + iter->target->alloc->free(iter); \ } \ \ void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ @@ -959,9 +959,9 @@ struct cmc_callbacks_treemap return iter->index; \ } \ \ - static struct SNAME##_node *PFX##_impl_new_node(K key, V value) \ + static struct SNAME##_node *PFX##_impl_new_node(struct SNAME *_map_, K key, V value) \ { \ - struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ + struct SNAME##_node *node = _map_->alloc->malloc(sizeof(struct SNAME##_node)); \ \ if (!node) \ return NULL; \ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 20ac037..c7f2cee 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -250,7 +250,7 @@ struct cmc_callbacks_treeset #define CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ - static struct SNAME##_node *PFX##_impl_new_node(V element); \ + static struct SNAME##_node *PFX##_impl_new_node(struct SNAME *_set_, V element); \ static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_set_, \ V element); \ static unsigned char PFX##_impl_h(struct SNAME##_node *node); \ @@ -340,7 +340,7 @@ struct cmc_callbacks_treeset if (deallocator) \ deallocator(scan->value); \ \ - free(scan); \ + _set_->alloc->free(scan); \ scan = NULL; \ } \ \ @@ -349,7 +349,7 @@ struct cmc_callbacks_treeset if (deallocator) \ deallocator(scan->value); \ \ - free(scan); \ + _set_->alloc->free(scan); \ \ if (up->right != NULL) \ { \ @@ -374,14 +374,14 @@ struct cmc_callbacks_treeset { \ PFX##_clear(_set_, deallocator); \ \ - free(_set_); \ + _set_->alloc->free(_set_); \ } \ \ bool PFX##_insert(struct SNAME *_set_, V element) \ { \ if (PFX##_empty(_set_)) \ { \ - _set_->root = PFX##_impl_new_node(element); \ + _set_->root = PFX##_impl_new_node(_set_, element); \ \ if (!_set_->root) \ return false; \ @@ -417,7 +417,7 @@ struct cmc_callbacks_treeset } \ else \ { \ - parent->right = PFX##_impl_new_node(element); \ + parent->right = PFX##_impl_new_node(_set_, element); \ \ if (!parent->right) \ return false; \ @@ -459,7 +459,7 @@ struct cmc_callbacks_treeset node->parent->left = NULL; \ } \ \ - free(node); \ + _set_->alloc->free(node); \ } \ else if (node->left == NULL) \ { \ @@ -480,7 +480,7 @@ struct cmc_callbacks_treeset node->parent->left = node->right; \ } \ \ - free(node); \ + _set_->alloc->free(node); \ } \ else if (node->right == NULL) \ { \ @@ -501,7 +501,7 @@ struct cmc_callbacks_treeset node->parent->left = node->left; \ } \ \ - free(node); \ + _set_->alloc->free(node); \ } \ else \ { \ @@ -539,7 +539,7 @@ struct cmc_callbacks_treeset temp->parent->left = temp->left; \ } \ \ - free(temp); \ + _set_->alloc->free(temp); \ \ node->value = temp_value; \ } \ @@ -892,7 +892,7 @@ struct cmc_callbacks_treeset \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -904,7 +904,7 @@ struct cmc_callbacks_treeset \ void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ - free(iter); \ + iter->target->alloc->free(iter); \ } \ \ void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ @@ -1117,9 +1117,9 @@ struct cmc_callbacks_treeset return iter->index; \ } \ \ - static struct SNAME##_node *PFX##_impl_new_node(V element) \ + static struct SNAME##_node *PFX##_impl_new_node(struct SNAME *_set_, V element) \ { \ - struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ + struct SNAME##_node *node = _set_->alloc->malloc(sizeof(struct SNAME##_node)); \ \ if (!node) \ return NULL; \