diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index d15c412..54803ae 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -490,6 +490,7 @@ struct cmc_callbacks_bidimap _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_->flag = cmc_flags.OK; \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 7cb9a88..14f732e 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -492,7 +492,7 @@ struct cmc_callbacks_stack \ int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, #SNAME, \ #V, s_, s_->buffer, s_->capacity, s_->count, \ - s_->f_val, s_->alloc, s_->callbacks); \ + s_->flag, s_->f_val, s_->alloc, s_->callbacks); \ \ return n >= 0 ? str : (struct cmc_string){ 0 }; \ } \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index abbaeb0..8bd288d 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -85,7 +85,9 @@ static const char *cmc_string_fmt_treemap = "struct %s<%s, %s> " "at %p { " "root:%p, " "count:%" PRIuMAX ", " - "cmp:%p, " + "flag:%d, " + "f_val:%p, " + "f_key:%p, " "alloc:%p, " "callbacks:%p }"; @@ -128,20 +130,26 @@ struct cmc_callbacks_treemap /* Current amount of keys */ \ size_t count; \ \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ + /* Flags indicating errors or success */ \ + int flag; \ \ - /* Function that returns an iterator to the start of the treemap */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ + /* Key function table */ \ + struct SNAME##_ftab_key *f_key; \ \ - /* Function that returns an iterator to the end of the treemap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ + /* Value function table */ \ + struct SNAME##_ftab_val *f_val; \ \ /* Custom allocation functions */ \ struct cmc_alloc_node *alloc; \ \ /* Custom callback functions */ \ struct cmc_callbacks_treemap *callbacks; \ + \ + /* Function that returns an iterator to the start of the treemap */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the treemap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ }; \ \ /* Treemap Node */ \ @@ -166,6 +174,50 @@ struct cmc_callbacks_treemap struct SNAME##_node *parent; \ }; \ \ + /* Key struct function table */ \ + struct SNAME##_ftab_key \ + { \ + /* Comparator function */ \ + int (*cmp)(K, K); \ + \ + /* Copy function */ \ + K (*cpy)(K); \ + \ + /* To string function */ \ + bool (*str)(FILE *, K); \ + \ + /* Free from memory function */ \ + void (*free)(K); \ + \ + /* Hash function */ \ + size_t (*hash)(K); \ + \ + /* Priority function */ \ + int (*pri)(K, K); \ + }; \ + \ + /* Value struct function table */ \ + struct SNAME##_ftab_val \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + V (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ + }; \ + \ /* Treemap Iterator */ \ struct SNAME##_iter \ { \ @@ -193,12 +245,14 @@ struct cmc_callbacks_treemap \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(int (*compare)(K, K)); \ - struct SNAME *PFX##_new_custom(int (*compare)(K, K), \ + struct SNAME *PFX##_new(struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val); \ + struct SNAME *PFX##_new_custom(struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val, \ struct cmc_alloc_node *alloc, \ struct cmc_callbacks_treemap *callbacks); \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_clear(struct SNAME *_map_); \ + void PFX##_free(struct SNAME *_map_); \ /* Customization of Allocation and Callbacks */ \ void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks_treemap *callbacks); \ @@ -216,10 +270,8 @@ struct cmc_callbacks_treemap bool PFX##_empty(struct SNAME *_map_); \ size_t PFX##_count(struct SNAME *_map_); \ /* Collection Utility */ \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ - int (*value_comparator)(V, V)); \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_); \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_); \ struct cmc_string PFX##_to_string(struct SNAME *_map_); \ \ /* Iterator Functions */ \ @@ -248,914 +300,914 @@ struct cmc_callbacks_treemap /* ------------------------------------------------------------------------- * Source * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - 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); \ - static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node); \ - static void PFX##_impl_rotate_right(struct SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(struct SNAME##_node **Z); \ - static void PFX##_impl_rebalance(struct SNAME *_map_, \ - struct SNAME##_node *node); \ - 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(int (*compare)(K, K)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - _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(int (*compare)(K, K), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treemap *callbacks) \ - { \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - _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)) \ - { \ - struct SNAME##_node *scan = _map_->root; \ - struct SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - struct SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - struct SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - _map_->alloc->free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - _map_->alloc->free(scan); \ - \ - if (up->right != NULL) \ - { \ - scan = up->right; \ - up->right = NULL; \ - break; \ - } \ - else \ - { \ - scan = up; \ - up = up->left; \ - } \ - } \ - } \ - } \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - } \ - \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - PFX##_clear(_map_, deallocator); \ - \ - _map_->alloc->free(_map_); \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->root = PFX##_impl_new_node(_map_, key, value); \ - \ - if (!_map_->root) \ - return false; \ - } \ - else \ - { \ - struct SNAME##_node *scan = _map_->root; \ - struct SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - struct SNAME##_node *node; \ - \ - if (_map_->cmp(parent->key, key) > 0) \ - { \ - parent->left = PFX##_impl_new_node(_map_, key, value); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_impl_new_node(_map_, key, value); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_impl_rebalance(_map_, node); \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - if (old_value) \ - *old_value = node->value; \ - \ - node->value = new_value; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - if (out_value) \ - *out_value = node->value; \ - \ - struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ - \ - bool is_root = node->parent == NULL; \ - \ - if (node->left == NULL && node->right == NULL) \ - { \ - if (is_root) \ - _map_->root = NULL; \ - else \ - { \ - unbalanced = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = NULL; \ - else \ - node->parent->left = NULL; \ - } \ - \ - _map_->alloc->free(node); \ - } \ - else if (node->left == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->right; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->right->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->right; \ - else \ - node->parent->left = node->right; \ - } \ - \ - _map_->alloc->free(node); \ - } \ - else if (node->right == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->left; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->left->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->left; \ - else \ - node->parent->left = node->left; \ - } \ - \ - _map_->alloc->free(node); \ - } \ - else \ - { \ - temp = node->right; \ - while (temp->left != NULL) \ - temp = temp->left; \ - \ - K temp_key = temp->key; \ - V temp_val = temp->value; \ - \ - unbalanced = temp->parent; \ - \ - if (temp->left == NULL && temp->right == NULL) \ - { \ - if (temp->parent->right == temp) \ - temp->parent->right = NULL; \ - else \ - temp->parent->left = NULL; \ - } \ - else if (temp->left == NULL) \ - { \ - temp->right->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->right; \ - else \ - temp->parent->left = temp->right; \ - } \ - else if (temp->right == NULL) \ - { \ - temp->left->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->left; \ - else \ - temp->parent->left = temp->left; \ - } \ - \ - _map_->alloc->free(temp); \ - \ - node->key = temp_key; \ - node->value = temp_val; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_impl_rebalance(_map_, unbalanced); \ - \ - _map_->count--; \ - \ - if (_map_->count == 0) \ - _map_->root = NULL; \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - V PFX##_get(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return (V){ 0 }; \ - \ - return node->value; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return NULL; \ - \ - return &(node->value); \ - } \ - \ - bool PFX##_contains(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ - { \ - struct SNAME *result = \ - PFX##_new_custom(_map_->cmp, _map_->alloc, _map_->callbacks); \ - \ - 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_, \ - int (*value_comparator)(V, V)) \ - { \ - 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)) \ - { \ - struct SNAME##_node *node = \ - PFX##_impl_get_node(_map2_, PFX##_iter_key(&iter)); \ - \ - if (node == NULL) \ - return false; \ - \ - if (value_comparator) \ - { \ - if (value_comparator(node->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_treemap, \ - #SNAME, #K, #V, m_, m_->root, m_->count, m_->cmp, \ - 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) \ - { \ - 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); \ - \ - iter->cursor = target->root; \ - \ - if (!PFX##_empty(target)) \ - { \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->first = iter->cursor; \ - \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ - } \ - } \ - \ - 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->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->cursor = iter->first; \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - iter->cursor = iter->last; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->cursor->right != NULL) \ - { \ - iter->cursor = iter->cursor->right; \ - \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->cursor->left != NULL) \ - { \ - iter->cursor = iter->cursor->left; \ - \ - while (iter->cursor->right != NULL) \ - iter->cursor = iter->cursor->right; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - /* 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->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->index += steps; \ - \ - 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->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - iter->index -= steps; \ - \ - 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->cursor->key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){ 0 }; \ - \ - return iter->cursor->value; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->value); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_node *PFX##_impl_new_node(struct SNAME *_map_, \ - K key, V value) \ - { \ - struct SNAME##_node *node = \ - _map_->alloc->malloc(sizeof(struct SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->key = key; \ - node->value = value; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, \ - K key) \ - { \ - if (PFX##_empty(_map_)) \ - return NULL; \ - \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_impl_h(node->left); \ - unsigned char h_r = PFX##_impl_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ - { \ - struct SNAME##_node *root = *Z; \ - struct SNAME##_node *new_root = root->left; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->left == root) \ - root->parent->left = new_root; \ - else \ - root->parent->right = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->left = new_root->right; \ - \ - if (root->left) \ - root->left->parent = root; \ - \ - new_root->right = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ - { \ - struct SNAME##_node *root = *Z; \ - struct SNAME##_node *new_root = root->right; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->right == root) \ - root->parent->right = new_root; \ - else \ - root->parent->left = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->right = new_root->left; \ - \ - if (root->right) \ - root->right->parent = root; \ - \ - new_root->left = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rebalance(struct SNAME *_map_, \ - struct SNAME##_node *node) \ - { \ - struct SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_impl_hupdate(scan); \ - balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ - PFX##_impl_rotate_right(&(scan->right)); \ - \ - PFX##_impl_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ - PFX##_impl_rotate_left(&(scan->left)); \ - \ - PFX##_impl_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _map_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - 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_TREEMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + 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); \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node); \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z); \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z); \ + static void PFX##_impl_rebalance(struct SNAME *_map_, \ + struct SNAME##_node *node); \ + 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(struct SNAME##_ftab_key *f_key, \ + struct SNAME##_ftab_val *f_val) \ + { \ + if (!f_key || !f_val) \ + return NULL; \ + \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + _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( \ + struct SNAME##_ftab_key *f_key, struct SNAME##_ftab_val *f_val, \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_treemap *callbacks) \ + { \ + if (!f_key || !f_val) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + _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_) \ + { \ + struct SNAME##_node *scan = _map_->root; \ + struct SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + struct SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + struct SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + if (_map_->f_key->free) \ + _map_->f_key->free(scan->key); \ + if (_map_->f_val->free) \ + _map_->f_val->free(scan->value); \ + \ + _map_->alloc->free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + if (_map_->f_key->free) \ + _map_->f_key->free(scan->key); \ + if (_map_->f_val->free) \ + _map_->f_val->free(scan->value); \ + \ + _map_->alloc->free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + } \ + \ + void PFX##_free(struct SNAME *_map_) \ + { \ + PFX##_clear(_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(_map_, key, value); \ + \ + if (!_map_->root) \ + return false; \ + } \ + else \ + { \ + struct SNAME##_node *scan = _map_->root; \ + struct SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_map_->f_key->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->f_key->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + struct SNAME##_node *node; \ + \ + if (_map_->f_key->cmp(parent->key, key) > 0) \ + { \ + parent->left = PFX##_impl_new_node(_map_, key, value); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(_map_, key, value); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_map_, node); \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + if (old_value) \ + *old_value = node->value; \ + \ + node->value = new_value; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + if (out_value) \ + *out_value = node->value; \ + \ + struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _map_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + _map_->alloc->free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->right; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + _map_->alloc->free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->left; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + _map_->alloc->free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + K temp_key = temp->key; \ + V temp_val = temp->value; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + _map_->alloc->free(temp); \ + \ + node->key = temp_key; \ + node->value = temp_val; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_impl_rebalance(_map_, unbalanced); \ + \ + _map_->count--; \ + \ + if (_map_->count == 0) \ + _map_->root = NULL; \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + V PFX##_get(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return (V){ 0 }; \ + \ + return node->value; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return NULL; \ + \ + return &(node->value); \ + } \ + \ + bool PFX##_contains(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->f_key->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->f_key->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_) \ + { \ + struct SNAME *result = PFX##_new_custom( \ + _map_->f_key, _map_->f_val, _map_->alloc, _map_->callbacks); \ + \ + 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 (_map_->f_key->cpy) \ + key = _map_->f_key->cpy(key); \ + if (_map_->f_val->cpy) \ + value = _map_->f_val->cpy(value); \ + \ + PFX##_insert(result, key, value); \ + } \ + } \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_) \ + { \ + if (_map1_->count != _map2_->count) \ + 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)) \ + { \ + struct SNAME##_node *node = \ + PFX##_impl_get_node(_map2_, PFX##_iter_key(&iter)); \ + \ + if (node == NULL) \ + return false; \ + \ + if (_map1_->f_val->cmp(node->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_treemap, \ + #SNAME, #K, #V, m_, m_->root, m_->count, m_->flag, \ + m_->f_key, m_->f_val, m_->alloc, m_->callbacks); \ + \ + return n >= 0 ? str : (struct cmc_string){ 0 }; \ + } \ + \ + 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); \ + \ + iter->cursor = target->root; \ + \ + if (!PFX##_empty(target)) \ + { \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + } \ + \ + 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->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->cursor = iter->first; \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->cursor = iter->last; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + /* 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->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->index += steps; \ + \ + 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->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->index -= steps; \ + \ + 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->cursor->key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->cursor->value; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->cursor->value); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_node *PFX##_impl_new_node(struct SNAME *_map_, \ + K key, V value) \ + { \ + struct SNAME##_node *node = \ + _map_->alloc->malloc(sizeof(struct SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->key = key; \ + node->value = value; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, \ + K key) \ + { \ + if (PFX##_empty(_map_)) \ + return NULL; \ + \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->f_key->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->f_key->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_impl_h(node->left); \ + unsigned char h_r = PFX##_impl_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ + { \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ + { \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rebalance(struct SNAME *_map_, \ + struct SNAME##_node *node) \ + { \ + struct SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_impl_hupdate(scan); \ + balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ + PFX##_impl_rotate_right(&(scan->right)); \ + \ + PFX##_impl_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ + PFX##_impl_rotate_left(&(scan->left)); \ + \ + PFX##_impl_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _map_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + 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_TREEMAP_H */ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 9136789..737113c 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -85,7 +85,8 @@ static const char *cmc_string_fmt_treeset = "struct %s<%s> " "at %p { " "root:%p, " "count:%" PRIuMAX ", " - "cmp:%p, " + "flag:%d, " + "f_val:%p, " "alloc:%p, " "callbacks:%p }"; @@ -128,20 +129,23 @@ struct cmc_callbacks_treeset /* Current amount of elements */ \ size_t count; \ \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ + /* Flags indicating errors or success */ \ + int flag; \ \ - /* Function that returns an iterator to the start of the treeset */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the treeset */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ + /* Value function table */ \ + struct SNAME##_ftab_val *f_val; \ \ /* Custom allocation functions */ \ struct cmc_alloc_node *alloc; \ \ /* Custom callback functions */ \ struct cmc_callbacks_treeset *callbacks; \ + \ + /* Function that returns an iterator to the start of the treeset */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the treeset */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ }; \ \ /* Treeset Node */ \ @@ -163,6 +167,28 @@ struct cmc_callbacks_treeset struct SNAME##_node *parent; \ }; \ \ + /* Value struct function table */ \ + struct SNAME##_ftab_val \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + V (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ + }; \ + \ /* Treeset Iterator */ \ struct SNAME##_iter \ { \ @@ -190,12 +216,12 @@ struct cmc_callbacks_treeset \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom(int (*compare)(V, V), \ + struct SNAME *PFX##_new(struct SNAME##_ftab_val *f_val); \ + struct SNAME *PFX##_new_custom(struct SNAME##_ftab_val *f_val, \ struct cmc_alloc_node *alloc, \ struct cmc_callbacks_treeset *callbacks); \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_clear(struct SNAME *_set_); \ + void PFX##_free(struct SNAME *_set_); \ /* Customization of Allocation and Callbacks */ \ void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks_treeset *callbacks); \ @@ -210,7 +236,7 @@ struct cmc_callbacks_treeset bool PFX##_empty(struct SNAME *_set_); \ size_t PFX##_count(struct SNAME *_set_); \ /* Collection Utility */ \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_); \ bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_); \ struct cmc_string PFX##_to_string(struct SNAME *_set_); \ \ @@ -278,8 +304,11 @@ struct cmc_callbacks_treeset static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ \ - struct SNAME *PFX##_new(int (*compare)(V, V)) \ + struct SNAME *PFX##_new(struct SNAME##_ftab_val *f_val) \ { \ + if (!f_val) \ + return NULL; \ + \ struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ \ struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ @@ -289,21 +318,23 @@ struct cmc_callbacks_treeset \ _set_->count = 0; \ _set_->root = NULL; \ - _set_->cmp = compare; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ + _set_->flag = cmc_flags.OK; \ + _set_->f_val = f_val; \ _set_->alloc = alloc; \ _set_->callbacks = NULL; \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ \ return _set_; \ } \ \ - struct SNAME *PFX##_new_custom(int (*compare)(V, V), \ + struct SNAME *PFX##_new_custom(struct SNAME##_ftab_val *f_val, \ struct cmc_alloc_node *alloc, \ struct cmc_callbacks_treeset *callbacks) \ { \ + if (!f_val) \ + return NULL; \ + \ if (!alloc) \ alloc = &cmc_alloc_node_default; \ \ @@ -314,18 +345,17 @@ struct cmc_callbacks_treeset \ _set_->count = 0; \ _set_->root = NULL; \ - _set_->cmp = compare; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ + _set_->flag = cmc_flags.OK; \ + _set_->f_val = f_val; \ _set_->alloc = alloc; \ _set_->callbacks = callbacks; \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ \ return _set_; \ } \ \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_set_) \ { \ struct SNAME##_node *scan = _set_->root; \ struct SNAME##_node *up = NULL; \ @@ -353,8 +383,8 @@ struct cmc_callbacks_treeset { \ if (up == NULL) \ { \ - if (deallocator) \ - deallocator(scan->value); \ + if (_set_->f_val->free) \ + _set_->f_val->free(scan->value); \ \ _set_->alloc->free(scan); \ scan = NULL; \ @@ -362,8 +392,8 @@ struct cmc_callbacks_treeset \ while (up != NULL) \ { \ - if (deallocator) \ - deallocator(scan->value); \ + if (_set_->f_val->free) \ + _set_->f_val->free(scan->value); \ \ _set_->alloc->free(scan); \ \ @@ -386,9 +416,9 @@ struct cmc_callbacks_treeset _set_->root = NULL; \ } \ \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_set_) \ { \ - PFX##_clear(_set_, deallocator); \ + PFX##_clear(_set_); \ \ _set_->alloc->free(_set_); \ } \ @@ -411,9 +441,9 @@ struct cmc_callbacks_treeset { \ parent = scan; \ \ - if (_set_->cmp(scan->value, element) > 0) \ + if (_set_->f_val->cmp(scan->value, element) > 0) \ scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ + else if (_set_->f_val->cmp(scan->value, element) < 0) \ scan = scan->right; \ else \ return false; \ @@ -421,7 +451,7 @@ struct cmc_callbacks_treeset \ struct SNAME##_node *node; \ \ - if (_set_->cmp(parent->value, element) > 0) \ + if (_set_->f_val->cmp(parent->value, element) > 0) \ { \ parent->left = PFX##_impl_new_node(_set_, element); \ \ @@ -607,9 +637,9 @@ struct cmc_callbacks_treeset \ while (scan != NULL) \ { \ - if (_set_->cmp(scan->value, element) > 0) \ + if (_set_->f_val->cmp(scan->value, element) > 0) \ scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ + else if (_set_->f_val->cmp(scan->value, element) < 0) \ scan = scan->right; \ else \ return true; \ @@ -628,10 +658,10 @@ struct cmc_callbacks_treeset return _set_->count; \ } \ \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_) \ { \ struct SNAME *result = \ - PFX##_new_custom(_set_->cmp, _set_->alloc, _set_->callbacks); \ + PFX##_new_custom(_set_->f_val, _set_->alloc, _set_->callbacks); \ \ if (!result) \ return NULL; \ @@ -644,8 +674,9 @@ struct cmc_callbacks_treeset for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ PFX##_iter_next(&iter)) \ { \ - if (copy_func) \ - PFX##_insert(result, copy_func(PFX##_iter_value(&iter))); \ + if (_set_->f_val->cpy) \ + PFX##_insert(result, \ + _set_->f_val->cpy(PFX##_iter_value(&iter))); \ else \ PFX##_insert(result, PFX##_iter_value(&iter)); \ } \ @@ -656,7 +687,7 @@ struct cmc_callbacks_treeset \ bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + if (_set1_->count != _set2_->count) \ return false; \ \ struct SNAME##_iter iter; \ @@ -678,21 +709,16 @@ struct cmc_callbacks_treeset struct SNAME *s_ = _set_; \ \ int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \ - #SNAME, #V, s_, s_->root, s_->count, s_->cmp, \ - s_->alloc, s_->callbacks); \ + #SNAME, #V, s_, s_->root, s_->count, s_->flag, \ + s_->f_val, s_->alloc, s_->callbacks); \ \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){ 0 }; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ + return n >= 0 ? str : (struct cmc_string){ 0 }; \ } \ \ struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->f_val, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -720,7 +746,7 @@ struct cmc_callbacks_treeset struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->f_val, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -747,7 +773,7 @@ struct cmc_callbacks_treeset struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->f_val, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -771,7 +797,7 @@ struct cmc_callbacks_treeset struct SNAME *_set2_) \ { \ struct SNAME *_set_r_ = \ - PFX##_new_custom(_set1_->cmp, _set1_->alloc, _set1_->callbacks); \ + PFX##_new_custom(_set1_->f_val, _set1_->alloc, _set1_->callbacks); \ \ if (!_set_r_) \ return NULL; \ @@ -1167,9 +1193,9 @@ struct cmc_callbacks_treeset \ while (scan != NULL) \ { \ - if (_set_->cmp(scan->value, element) > 0) \ + if (_set_->f_val->cmp(scan->value, element) > 0) \ scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ + else if (_set_->f_val->cmp(scan->value, element) < 0) \ scan = scan->right; \ else \ return scan; \ diff --git a/tests/main/unt/treemap.c b/tests/main/unt/treemap.c index 3f72f27..d13c508 100644 --- a/tests/main/unt/treemap.c +++ b/tests/main/unt/treemap.c @@ -7,17 +7,33 @@ CMC_GENERATE_TREEMAP(tm, treemap, size_t, size_t) +struct treemap_ftab_key *tm_ftab_key = + &(struct treemap_ftab_key){ .cmp = cmp, + .cpy = copy, + .str = str, + .free = custom_free, + .hash = hash, + .pri = pri }; + +struct treemap_ftab_val *tm_ftab_val = + &(struct treemap_ftab_val){ .cmp = cmp, + .cpy = copy, + .str = str, + .free = custom_free, + .hash = hash, + .pri = pri }; + CMC_CREATE_UNIT(treemap_test, true, { CMC_CREATE_TEST(new, { - struct treemap *map = tm_new(cmp); + struct treemap *map = tm_new(tm_ftab_key, tm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); - tm_free(map, NULL); + tm_free(map); }); CMC_CREATE_TEST(clear[count], { - struct treemap *map = tm_new(cmp); + struct treemap *map = tm_new(tm_ftab_key, tm_ftab_val); cmc_assert_not_equals(ptr, NULL, map); @@ -26,11 +42,11 @@ CMC_CREATE_UNIT(treemap_test, true, { cmc_assert_equals(size_t, 50, tm_count(map)); - tm_clear(map, NULL); + tm_clear(map); cmc_assert_equals(size_t, 0, tm_count(map)); cmc_assert_equals(ptr, NULL, map->root); - tm_free(map, NULL); + tm_free(map); }); }); diff --git a/tests/main/unt/treeset.c b/tests/main/unt/treeset.c index 3492aae..9f1e40c 100644 --- a/tests/main/unt/treeset.c +++ b/tests/main/unt/treeset.c @@ -7,17 +7,25 @@ CMC_GENERATE_TREESET(ts, treeset, size_t) +struct treeset_ftab_val *ts_ftab_val = + &(struct treeset_ftab_val){ .cmp = cmp, + .cpy = copy, + .str = str, + .free = custom_free, + .hash = hash, + .pri = pri }; + CMC_CREATE_UNIT(treeset_test, true, { CMC_CREATE_TEST(new, { - struct treeset *set = ts_new(cmp); + struct treeset *set = ts_new(ts_ftab_val); cmc_assert_not_equals(ptr, NULL, set); - ts_free(set, NULL); + ts_free(set); }); CMC_CREATE_TEST(clear[count], { - struct treeset *set = ts_new(cmp); + struct treeset *set = ts_new(ts_ftab_val); cmc_assert_not_equals(ptr, NULL, set); @@ -26,11 +34,11 @@ CMC_CREATE_UNIT(treeset_test, true, { cmc_assert_equals(size_t, 50, ts_count(set)); - ts_clear(set, NULL); + ts_clear(set); cmc_assert_equals(size_t, 0, ts_count(set)); cmc_assert_equals(ptr, NULL, set->root); - ts_free(set, NULL); + ts_free(set); }); }); diff --git a/tests/to_string.c b/tests/to_string.c index 92bfb65..42aae05 100644 --- a/tests/to_string.c +++ b/tests/to_string.c @@ -28,17 +28,27 @@ int main(void) &(struct hmap_ftab_val){ 0 }, NULL, NULL); struct hset *hs = hs_new_custom(100, 0.6, &(struct hset_ftab_val){ 0 }, NULL, NULL); - struct heap *h = h_new_custom(100, cmc_max_heap, NULL, NULL, NULL); - struct iheap *ih = ih_new_custom(100, NULL, NULL, NULL); - struct linked *ll = ll_new_custom(NULL, NULL); - struct list *l = l_new_custom(100, NULL, NULL); - struct mmap *mm = mm_new_custom(100, 0.8, NULL, NULL, NULL, NULL); - struct mset *ms = ms_new_custom(100, 0.6, NULL, NULL, NULL, NULL); - struct queue *q = q_new_custom(100, NULL, NULL); - struct slist *sl = sl_new_custom(100, NULL, NULL, NULL); - struct stack *s = s_new_custom(100, NULL, NULL); - struct tmap *tm = tm_new_custom(NULL, NULL, NULL); - struct tset *ts = ts_new_custom(NULL, NULL, NULL); + struct heap *h = h_new_custom(100, cmc_max_heap, + &(struct heap_ftab_val){ 0 }, NULL, NULL); + struct iheap *ih = + ih_new_custom(100, &(struct iheap_ftab_val){ 0 }, NULL, NULL); + struct linked *ll = + ll_new_custom(&(struct linked_ftab_val){ 0 }, NULL, NULL); + struct list *l = + l_new_custom(100, &(struct list_ftab_val){ 0 }, NULL, NULL); + struct mmap *mm = mm_new_custom(100, 0.8, &(struct mmap_ftab_key){ 0 }, + &(struct mmap_ftab_val){ 0 }, NULL, NULL); + struct mset *ms = + ms_new_custom(100, 0.6, &(struct mset_ftab_val){ 0 }, NULL, NULL); + struct queue *q = + q_new_custom(100, &(struct queue_ftab_val){ 0 }, NULL, NULL); + struct slist *sl = + sl_new_custom(100, &(struct slist_ftab_val){ 0 }, NULL, NULL); + struct stack *s = + s_new_custom(100, &(struct stack_ftab_val){ 0 }, NULL, NULL); + struct tmap *tm = tm_new_custom(&(struct tmap_ftab_key){ 0 }, + &(struct tmap_ftab_val){ 0 }, NULL, NULL); + struct tset *ts = ts_new_custom(&(struct tset_ftab_val){ 0 }, NULL, NULL); printf("%s\n", bm_to_string(bm).s); printf("%s\n", d_to_string(d).s); @@ -60,15 +70,15 @@ int main(void) d_free(d); hm_free(hm); hs_free(hs); - h_free(h, NULL); - ih_free(ih, NULL); - ll_free(ll, NULL); - l_free(l, NULL); - mm_free(mm, NULL); - ms_free(ms, NULL); - q_free(q, NULL); - sl_free(sl, NULL); - s_free(s, NULL); - tm_free(tm, NULL); - ts_free(ts, NULL); + h_free(h); + ih_free(ih); + ll_free(ll); + l_free(l); + mm_free(mm); + ms_free(ms); + q_free(q); + sl_free(sl); + s_free(s); + tm_free(tm); + ts_free(ts); }