From 209d45be5d7c256307a41a8ae50fa1690d55f0d8 Mon Sep 17 00:00:00 2001 From: Leonardo Vencovsky Date: Wed, 8 Jul 2020 23:00:24 -0300 Subject: [PATCH] TreeMap no longer depends on ITER --- src/cmc/hashmultiset.h | 10 ++--- src/cmc/hashset.h | 6 +-- src/cmc/treemap.h | 86 ++++++++++++++++++++++++++++++++++------- tests/src/cmc/treemap.c | 70 +++++++++++++++++++++++++++------ tests/unt/cmc/treemap.h | 3 ++ 5 files changed, 143 insertions(+), 32 deletions(-) diff --git a/src/cmc/hashmultiset.h b/src/cmc/hashmultiset.h index 8cfff7d..367de32 100644 --- a/src/cmc/hashmultiset.h +++ b/src/cmc/hashmultiset.h @@ -648,9 +648,9 @@ \ /* TODO check this for possible errors where entry == NULL */ \ struct CMC_DEF_ENTRY(SNAME) *entry = CMC_(PFX, _impl_insert_and_return)(_new_set_, value, NULL); \ - \ - entry->multiplicity = multiplicity;\ - /* Setting cardinality not required, _new_set_ is temporary */\ +\ + entry->multiplicity = multiplicity; \ + /* Setting cardinality not required, _new_set_ is temporary */ \ } \ } \ \ @@ -785,7 +785,7 @@ /* something with it. This function only guarantees that there is */ \ /* a valid entry for a given value */ \ \ - if (new_node)\ + if (new_node) \ *new_node = false; \ \ struct CMC_DEF_ENTRY(SNAME) *entry = CMC_(PFX, _impl_get_entry)(_set_, value); \ @@ -793,7 +793,7 @@ if (entry != NULL) \ return entry; \ \ - if (new_node)\ + if (new_node) \ *new_node = true; \ \ if (CMC_(PFX, _full)(_set_)) \ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 5e22961..cc707a2 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -625,9 +625,9 @@ { \ if (_set_a_->buffer[i].state == CMC_ES_FILLED) \ { \ - \ - if (!CMC_(PFX, _impl_get_entry)(_set_b_, _set_a_->buffer[i].value))\ - return false;\ +\ + if (!CMC_(PFX, _impl_get_entry)(_set_b_, _set_a_->buffer[i].value)) \ + return false; \ } \ } \ \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index 9f93cfb..bdc0fa6 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -688,25 +688,57 @@ return NULL; \ } \ \ - /* TODO turn this into a normal loop */ \ - struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \ + struct CMC_DEF_NODE(SNAME) *root = _map_->root; \ \ - for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \ + bool left_done = false; \ +\ + while (root) \ { \ - K key = CMC_(PFX, _iter_key)(&iter); \ - V value = CMC_(PFX, _iter_value)(&iter); \ + if (!left_done) \ + { \ + while (root->left) \ + root = root->left; \ + } \ +\ + K key; \ + V value; \ \ if (_map_->f_key->cpy) \ - key = _map_->f_key->cpy(key); \ + key = _map_->f_key->cpy(root->key); \ + else \ + key = root->key; \ if (_map_->f_val->cpy) \ - value = _map_->f_val->cpy(value); \ + value = _map_->f_val->cpy(root->value); \ + else \ + value = root->value; \ \ /* TODO check this for errors */ \ CMC_(PFX, _insert)(result, key, value); \ +\ + left_done = true; \ +\ + if (root->right) \ + { \ + left_done = false; \ + root = root->right; \ + } \ + else if (root->parent) \ + { \ + while (root->parent && root == root->parent->right) \ + root = root->parent; \ +\ + if (!root->parent) \ + break; \ +\ + root = root->parent; \ + } \ + else \ + break; \ } \ \ - CMC_CALLBACKS_ASSIGN(result, _map_->callbacks); \ _map_->flag = CMC_FLAG_OK; \ +\ + CMC_CALLBACKS_ASSIGN(result, _map_->callbacks); \ \ return result; \ } \ @@ -719,18 +751,46 @@ if (_map1_->count != _map2_->count) \ return false; \ \ - /* TODO turn this into a normal loop */ \ - struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map1_); \ + struct CMC_DEF_NODE(SNAME) *root = _map1_->root; \ \ - for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \ + bool left_done = false; \ +\ + while (root) \ { \ - struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map2_, CMC_(PFX, _iter_key)(&iter)); \ + if (!left_done) \ + { \ + while (root->left) \ + root = root->left; \ + } \ +\ + /* TODO this can be optimized by doing two in-order traversals */\ + struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map2_, root->key); \ \ if (node == NULL) \ return false; \ \ - if (_map1_->f_val->cmp(node->value, CMC_(PFX, _iter_value)(&iter)) != 0) \ + if (_map1_->f_val->cmp(node->value, root->value) != 0) \ return false; \ +\ + left_done = true; \ +\ + if (root->right) \ + { \ + left_done = false; \ + root = root->right; \ + } \ + else if (root->parent) \ + { \ + while (root->parent && root == root->parent->right) \ + root = root->parent; \ +\ + if (!root->parent) \ + break; \ +\ + root = root->parent; \ + } \ + else \ + break; \ } \ \ return true; \ diff --git a/tests/src/cmc/treemap.c b/tests/src/cmc/treemap.c index 6c495e7..a019f9b 100644 --- a/tests/src/cmc/treemap.c +++ b/tests/src/cmc/treemap.c @@ -400,19 +400,45 @@ struct treemap *tm_copy_of(struct treemap *_map_) _map_->flag = CMC_FLAG_ERROR; return ((void *)0); } - struct treemap_iter iter = tm_iter_start(_map_); - for (; !tm_iter_at_end(&iter); tm_iter_next(&iter)) + struct treemap_node *root = _map_->root; + _Bool left_done = 0; + while (root) { - size_t key = tm_iter_key(&iter); - size_t value = tm_iter_value(&iter); + if (!left_done) + { + while (root->left) + root = root->left; + } + size_t key; + size_t value; if (_map_->f_key->cpy) - key = _map_->f_key->cpy(key); + key = _map_->f_key->cpy(root->key); + else + key = root->key; if (_map_->f_val->cpy) - value = _map_->f_val->cpy(value); + value = _map_->f_val->cpy(root->value); + else + value = root->value; tm_insert(result, key, value); + left_done = 1; + if (root->right) + { + left_done = 0; + root = root->right; + } + else if (root->parent) + { + while (root->parent && root == root->parent->right) + root = root->parent; + if (!root->parent) + break; + root = root->parent; + } + else + break; } - (result)->callbacks = _map_->callbacks; _map_->flag = CMC_FLAG_OK; + (result)->callbacks = _map_->callbacks; return result; } _Bool tm_equals(struct treemap *_map1_, struct treemap *_map2_) @@ -421,14 +447,36 @@ _Bool tm_equals(struct treemap *_map1_, struct treemap *_map2_) _map2_->flag = CMC_FLAG_OK; if (_map1_->count != _map2_->count) return 0; - struct treemap_iter iter = tm_iter_start(_map1_); - for (; !tm_iter_at_end(&iter); tm_iter_next(&iter)) + struct treemap_node *root = _map1_->root; + _Bool left_done = 0; + while (root) { - struct treemap_node *node = tm_impl_get_node(_map2_, tm_iter_key(&iter)); + if (!left_done) + { + while (root->left) + root = root->left; + } + struct treemap_node *node = tm_impl_get_node(_map2_, root->key); if (node == ((void *)0)) return 0; - if (_map1_->f_val->cmp(node->value, tm_iter_value(&iter)) != 0) + if (_map1_->f_val->cmp(node->value, root->value) != 0) return 0; + left_done = 1; + if (root->right) + { + left_done = 0; + root = root->right; + } + else if (root->parent) + { + while (root->parent && root == root->parent->right) + root = root->parent; + if (!root->parent) + break; + root = root->parent; + } + else + break; } return 1; } diff --git a/tests/unt/cmc/treemap.h b/tests/unt/cmc/treemap.h index 014ac02..90e2483 100644 --- a/tests/unt/cmc/treemap.h +++ b/tests/unt/cmc/treemap.h @@ -116,6 +116,9 @@ CMC_CREATE_UNIT(CMCTreeMap, true, { tm_get_ref(map, 1); cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, tm_flag(map)); + for (size_t i = 0; i < 100; i++) + cmc_assert(tm_insert(map, i, i)); + // copy_of map->flag = CMC_FLAG_ERROR; struct treemap *map2 = tm_copy_of(map);