diff --git a/examples/treemap/README.md b/examples/treemap/README.md index e9c8928..0bc53dd 100644 --- a/examples/treemap/README.md +++ b/examples/treemap/README.md @@ -1,3 +1,4 @@ # Treemap examples * pseudo_multiset.c - An example of how to make a multiset using a map. +* iterator.c - A complete example of the treemap iterator diff --git a/examples/treemap/iterator.c b/examples/treemap/iterator.c new file mode 100644 index 0000000..8574112 --- /dev/null +++ b/examples/treemap/iterator.c @@ -0,0 +1,217 @@ +/** + * iterator.c + * + * Creation Date: 16/05/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + * Iterator Example + */ +#include "treemap.h" +#include +#include + +// Int compare function +int intcmp(int a, int b) +{ + return a - b; +} + +// Creates a treemap of integers +TREEMAP_GENERATE(tm, treemap, /* FMOD */, int, double) + +int main(int argc, char const *argv[]) +{ + // Create a new treemap + treemap *my_map = tm_new(intcmp); + + // Add pairs to the treemap + for (int i = 0; i < 20; i++) + { + // Map integers to doubles + tm_insert(my_map, i, (double)i / 10.0); + } + + // Iterate from the start (left-most node) to the end (right-most node) of the treemap + for (treemap_iter it = my_map->it_start(my_map); // Initialize iterator 'it' to the start of the treemap + !tm_iter_end(&it); // Conditional stop (until it is not at the end) + tm_iter_next(&it)) // Iterator goes one position forward + { + // Access the current key + int k = tm_iter_key(&it); + + // Access the current value + double v = tm_iter_value(&it); + + // Access the current index (index is relative to all the pairs in the iteration) + size_t i = tm_iter_index(&it); + + // Print treemap + + // Index is useful in situations like this + // If it is the first pair + if (i == 0) + printf("[ {%d:%.2lf}, ", k, v); + // If it is the last pair + else if (i == tm_count(my_map) - 1) + printf("{%d:%.2lf} ]\n", k, v); + // For pairs at the middle + else + printf("{%d:%.2lf}, ", k, v); + } + + // Index can also be used to iterate over a certain portion of a collection + size_t limit = tm_count(my_map) / 2; + for (treemap_iter it = my_map->it_start(my_map); !tm_iter_end(&it); tm_iter_next(&it)) + { + // Access the current key + int k = tm_iter_key(&it); + + // Access the current value + double v = tm_iter_value(&it); + + // Access the current index (index is relative to all the pairs in the iteration) + size_t i = tm_iter_index(&it); + + // Print treemap up until limit + + // If it is the first pair + if (i == 0) + printf("[ {%d:%.2lf}, ", k, v); + // If it is the last pair + else if (i == limit - 1) // -1 because index is 0 based and we want half of the treemap + { + printf("{%d:%.2lf} ]\n", k, v); + break; + } + // For pairs at the middle + else + printf("{%d:%.2lf}, ", k, v); + } + + // Going backwards + for (treemap_iter it = my_map->it_end(my_map); // Initialize iterator 'it' to the end of the treemap + !tm_iter_start(&it); // Conditional stop (until it is not at the start) + tm_iter_prev(&it)) // Iterator goes one position backwards + { + // Access the current key + int k = tm_iter_key(&it); + + // Access the current value + double v = tm_iter_value(&it); + + // Access the current index (index is relative to all the pairs in the iteration) + size_t i = tm_iter_index(&it); + + // Print treemap + // Note how the conditions for the first and last pairs are simply swapped + // Because iterating backwards make the first pair be the index count - 1 + // and the last one be the index 0 + + // If it is the first pair + if (i == tm_count(my_map) - 1) + printf("[ {%d:%.2lf}, ", k, v); + // If it is the last pair + else if (i == 0) + printf("{%d:%.2lf} ]\n", k, v); + // For pairs at the middle + else + printf("{%d:%.2lf}, ", k, v); + } + + // You can also use iterators in a while loop + // But to do so you must declare the iterator struct outside the loop first + treemap_iter it; + + // You have three options: + // - Initialize it using the functions provided by the treemap [ my_map->it_start() and my_map->it_end() ] + // - Initialize it using the init() function (when the iterator is already allocated) + // - Initialize it using the new() function (allocates on the heap, pointers only) + + it = my_map->it_start(my_map); + it = my_map->it_end(my_map); + + // This is equivalent to it_start() + tm_iter_init(&it, my_map); + + // For pointers + // Also equivalent to it_start() + treemap_iter *iter = tm_iter_new(my_map); + + // The actual while loop + while (!tm_iter_end(iter)) + { + // Accessing pairs + int k = tm_iter_key(iter); + double v = tm_iter_value(iter); + size_t i = tm_iter_index(iter); + + // Print index and key value pair + printf("treemap[%2" PRIuMAX "] = { %2d : %.2lf }\n", i, k, v); + + // Move iterator forwards + tm_iter_next(iter); + } + + // Send the iterator to the start of the treemap + tm_iter_to_start(iter); + + // Send the iterator to the end of the treemap + tm_iter_to_end(iter); + + // Backwards loop + while (!tm_iter_start(iter)) + { + // Accessing pairs + int k = tm_iter_key(iter); + double v = tm_iter_value(iter); + size_t i = tm_iter_index(iter); + + // Print index and the key value pair + printf("treemap[%2" PRIuMAX "] = { %2d : %.2lf }\n", i, k, v); + + // Move iterator backwards + tm_iter_prev(iter); + } + + // Certain iterators also allow you to modify the contents it is iterating over + // Exceptions are collections that depend of the current state of the pair + // like tree-based collections and heap (collections that have some kind of ordering). + // You also can't change the keys of an associative collection + + // Change every value where its key is divisible by 3 to the number 7 + for (tm_iter_to_start(&it); !tm_iter_end(&it); tm_iter_next(&it)) + { + // Get current key + int k = tm_iter_key(&it); + + // Get a reference to the current value + double *v = tm_iter_rvalue(&it); + + if (k % 3 == 0) + *v = 7; + } + + // Now print it to see the difference + for (treemap_iter it = my_map->it_start(my_map); !tm_iter_end(&it); tm_iter_next(&it)) + { + int k = tm_iter_key(&it); + double v = tm_iter_value(&it); + size_t i = tm_iter_index(&it); + + if (i == 0) + printf("[ {%d:%.2lf}, ", k, v); + else if (i == tm_count(my_map) - 1) + printf("{%d:%.2lf} ]\n", k, v); + else + printf("{%d:%.2lf}, ", k, v); + } + + // Dispose the iterator called by tm_iter_new() + tm_iter_free(iter); + // Dispose the treemap created + tm_free(my_map); + + return 0; +} diff --git a/examples/treemap/pseudo_multiset.c b/examples/treemap/pseudo_multiset.c index 111906a..de6556a 100644 --- a/examples/treemap/pseudo_multiset.c +++ b/examples/treemap/pseudo_multiset.c @@ -12,6 +12,7 @@ #include "treemap.h" #include +#include // Mapping an integer by size_t which will represent the key's multiplicity // (key could be anything and multiplicity could be an integer, preferably @@ -36,7 +37,7 @@ void print_tree(tmap_node *root, int height) printf("|------- "); // Key:Multiplicity - printf("%d:%llu\n", root->key, root->value); + printf("%d:%" PRIuMAX "\n", root->key, root->value); print_tree(root->left, height + 1); } @@ -73,15 +74,10 @@ int main(int argc, char const *argv[]) printf("\n---------- SUMMARY ----------\n\n"); // Print using iterator - tmap_iter iter; - int key; - size_t mult, _; - - for (tm_iter_init(&iter, map); !tm_iter_end(&iter); /* empty */) + for (tmap_iter it = map->it_start(map); !tm_iter_end(&it); tm_iter_next(&it)) { // Map[key] = multiplicity - tm_iter_next(&iter, &key, &mult, &_); - printf("Map[%2d] = %llu\n", key, mult); + printf("Map[%2d] = %" PRIuMAX "\n", tm_iter_key(&it), tm_iter_value(&it)); } tm_free(map); diff --git a/src/treemap.h b/src/treemap.h index d4f92ae..942695b 100644 --- a/src/treemap.h +++ b/src/treemap.h @@ -36,738 +36,827 @@ #define TREEMAP_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \ TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) /* STRUCT ********************************************************************/ -#define TREEMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ - \ - struct SNAME##_s \ - { \ - struct SNAME##_node_s *root; \ - size_t count; \ - int (*cmp)(K, K); \ - }; \ - \ - struct SNAME##_node_s \ - { \ - K key; \ - V value; \ - unsigned char height; \ - struct SNAME##_node_s *right; \ - struct SNAME##_node_s *left; \ - struct SNAME##_node_s *parent; \ - }; \ - \ - struct SNAME##_iter_s \ - { \ - struct SNAME##_s *target; \ - struct SNAME##_node_s *cursor; \ - struct SNAME##_node_s *first; \ - struct SNAME##_node_s *last; \ - size_t index; \ - bool start; \ - bool end; \ - }; \ - \ +#define TREEMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) + /* HEADER ********************************************************************/ -#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - typedef struct SNAME##_s SNAME; \ - typedef struct SNAME##_node_s SNAME##_node; \ - typedef struct SNAME##_iter_s SNAME##_iter; \ - \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)); \ - FMOD void PFX##_clear(SNAME *_map_); \ - FMOD void PFX##_free(SNAME *_map_); \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ - FMOD V PFX##_get(SNAME *_map_, K key); \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ - FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index); \ - \ +#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + \ + /* Treemap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Root node */ \ + struct SNAME##_node_s *root; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Key comparison function */ \ + int (*cmp)(K, K); \ + \ + /* Function that returns an iterator to the start of the hashmap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashmap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Treemap Node */ \ + typedef struct SNAME##_node_s \ + { \ + /* Node Key */ \ + K key; \ + \ + /* Node Value */ \ + V value; \ + \ + /* Node height used by the AVL tree to keep it strictly balanced */ \ + unsigned char height; \ + \ + /* Right child node or subtree */ \ + struct SNAME##_node_s *right; \ + \ + /* Left child node or subtree */ \ + struct SNAME##_node_s *left; \ + \ + /* Parent node */ \ + struct SNAME##_node_s *parent; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Treemap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target treemap */ \ + struct SNAME##_s *target; \ + /* Cursor's current node */ \ + struct SNAME##_node_s *cursor; \ + \ + /* The first node in the iteration */ \ + struct SNAME##_node_s *first; \ + \ + /* The last node in the iteration */ \ + struct SNAME##_node_s *last; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(int (*compare)(K, K)); \ + FMOD void PFX##_clear(SNAME *_map_); \ + FMOD void PFX##_free(SNAME *_map_); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ + /* Element Access */ \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ + FMOD V PFX##_get(SNAME *_map_, K key); \ + FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_map_, K key); \ + FMOD bool PFX##_empty(SNAME *_map_); \ + FMOD size_t PFX##_count(SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD K PFX##_iter_key(SNAME##_iter *iter); \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ /* SOURCE ********************************************************************/ -#define TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ - \ - FMOD SNAME##_node *PFX##_new_node(K key, V value); \ - FMOD SNAME##_node *PFX##_get_node(SNAME *_map_, K key); \ - FMOD unsigned char PFX##_h(SNAME##_node *node); \ - FMOD unsigned char PFX##_hupdate(SNAME##_node *node); \ - FMOD void PFX##_rotate_right(SNAME##_node **Z); \ - FMOD void PFX##_rotate_left(SNAME##_node **Z); \ - FMOD void PFX##_rebalance(SNAME *_map_, SNAME##_node *node); \ - \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ - { \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - return _map_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_map_) \ - { \ - SNAME##_node *scan = _map_->root; \ - SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - 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; \ - } \ - \ - FMOD void PFX##_free(SNAME *_map_) \ - { \ - PFX##_clear(_map_); \ - \ - free(_map_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->root = PFX##_new_node(key, value); \ - \ - if (!_map_->root) \ - return false; \ - } \ - else \ - { \ - SNAME##_node *scan = _map_->root; \ - 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; \ - } \ - \ - SNAME##_node *node; \ - \ - if (_map_->cmp(parent->key, key) > 0) \ - { \ - parent->left = PFX##_new_node(key, value); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_new_node(key, value); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_rebalance(_map_, node); \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ - { \ - SNAME##_node *node = PFX##_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - *value = node->value; \ - \ - 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; \ - } \ - \ - 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; \ - } \ - \ - 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; \ - } \ - \ - 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; \ - } \ - \ - free(temp); \ - \ - node->key = temp_key; \ - node->value = temp_val; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_rebalance(_map_, unbalanced); \ - \ - _map_->count--; \ - \ - if (_map_->count == 0) \ - _map_->root = NULL; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_get_node(_map_, key); \ - \ - if (!node) \ - return 0; \ - \ - return node->value; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_get_node(_map_, key); \ - \ - if (!node) \ - return NULL; \ - \ - return &(node->value); \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ - { \ - 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; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - iter->cursor = target->root; \ - 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; \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ - { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ - } \ - \ - FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index) \ - { \ - if (iter->end) \ - return false; \ - \ - *key = iter->cursor->key; \ - *value = iter->cursor->value; \ - *index = iter->index; \ - \ - iter->start = false; \ - \ - 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 == iter->last) \ - { \ - iter->end = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index) \ - { \ - if (iter->start) \ - return false; \ - \ - *key = iter->cursor->key; \ - *value = iter->cursor->value; \ - *index = iter->index; \ - \ - iter->end = false; \ - \ - 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 == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD SNAME##_node *PFX##_new_node(K key, V value) \ - { \ - SNAME##_node *node = malloc(sizeof(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; \ - } \ - \ - FMOD SNAME##_node *PFX##_get_node(SNAME *_map_, K key) \ - { \ - if (PFX##_empty(_map_)) \ - return NULL; \ - \ - 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; \ - } \ - \ - FMOD unsigned char PFX##_h(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - FMOD unsigned char PFX##_hupdate(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_h(node->left); \ - unsigned char h_r = PFX##_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - FMOD void PFX##_rotate_right(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - 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##_hupdate(root); \ - new_root->height = PFX##_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - FMOD void PFX##_rotate_left(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - 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##_hupdate(root); \ - new_root->height = PFX##_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - FMOD void PFX##_rebalance(SNAME *_map_, SNAME##_node *node) \ - { \ - 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##_hupdate(scan); \ - balance = PFX##_h(scan->right) - PFX##_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_h(child->right) < PFX##_h(child->left)) \ - PFX##_rotate_right(&(scan->right)); \ - \ - PFX##_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_h(child->left) < PFX##_h(child->right)) \ - PFX##_rotate_left(&(scan->left)); \ - \ - PFX##_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _map_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ +#define TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ + \ + /* Implementation Detail Functions */ \ + FMOD SNAME##_node *PFX##_impl_new_node(K key, V value); \ + FMOD SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \ + FMOD unsigned char PFX##_impl_h(SNAME##_node *node); \ + FMOD unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ + FMOD void PFX##_impl_rotate_right(SNAME##_node **Z); \ + FMOD void PFX##_impl_rotate_left(SNAME##_node **Z); \ + FMOD void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \ + SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ + \ + FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ + { \ + SNAME *_map_ = malloc(sizeof(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; \ + \ + return _map_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_map_) \ + { \ + SNAME##_node *scan = _map_->root; \ + SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + 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; \ + } \ + \ + FMOD void PFX##_free(SNAME *_map_) \ + { \ + PFX##_clear(_map_); \ + \ + free(_map_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->root = PFX##_impl_new_node(key, value); \ + \ + if (!_map_->root) \ + return false; \ + } \ + else \ + { \ + SNAME##_node *scan = _map_->root; \ + 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; \ + } \ + \ + SNAME##_node *node; \ + \ + if (_map_->cmp(parent->key, key) > 0) \ + { \ + parent->left = PFX##_impl_new_node(key, value); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(key, value); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_map_, node); \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + *value = node->value; \ + \ + 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; \ + } \ + \ + 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; \ + } \ + \ + 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; \ + } \ + \ + 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; \ + } \ + \ + 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; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return 0; \ + \ + return node->value; \ + } \ + \ + FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return NULL; \ + \ + return &(node->value); \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_map_, K key) \ + { \ + 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; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + 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; \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->first; \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + \ + iter->cursor = iter->last; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = false; \ + \ + 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 == iter->last) \ + { \ + iter->end = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = false; \ + \ + 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 == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD K PFX##_iter_key(SNAME##_iter *iter) \ + { \ + return iter->cursor->key; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + return iter->cursor->value; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + return &(iter->cursor->value); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + FMOD SNAME##_node *PFX##_impl_new_node(K key, V value) \ + { \ + SNAME##_node *node = malloc(sizeof(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; \ + } \ + \ + FMOD SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \ + { \ + if (PFX##_empty(_map_)) \ + return NULL; \ + \ + 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; \ + } \ + \ + FMOD unsigned char PFX##_impl_h(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + FMOD unsigned char PFX##_impl_hupdate(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); \ + } \ + \ + FMOD void PFX##_impl_rotate_right(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + 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; \ + } \ + \ + FMOD void PFX##_impl_rotate_left(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + 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; \ + } \ + \ + FMOD void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \ + { \ + 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; \ + } \ + } \ + \ + SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_TREEMAP_H */