From ae5241a6fbde63b17c413d5924efacfcd9029efa Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 May 2019 23:22:52 -0300 Subject: [PATCH] Fourth update on iterators - HASHSET --- examples/deque/even_odd.c | 5 +- examples/hashmap/iterator.c | 2 +- examples/hashset/iterator.c | 194 +++++++++++++++++++++++++ examples/hashset/set_ops.c | 8 +- examples/iterators/deque.c | 3 - examples/iterators/hashmap.c | 4 +- examples/iterators/hashset.c | 27 ++-- src/hashmap.h | 20 +-- src/hashset.h | 267 +++++++++++++++++++++-------------- 9 files changed, 387 insertions(+), 143 deletions(-) create mode 100644 examples/hashset/iterator.c diff --git a/examples/deque/even_odd.c b/examples/deque/even_odd.c index d3e29a6..b828fbf 100644 --- a/examples/deque/even_odd.c +++ b/examples/deque/even_odd.c @@ -33,9 +33,10 @@ int main(int argc, char const *argv[]) size_t result, index, sum = 0; - for (d_iter_toend(&iter); !d_iter_start(&iter);) + for (d_iter_to_end(&iter); !d_iter_start(&iter); d_iter_prev(&iter)) { - d_iter_prev(&iter, &result, &index); + result = d_iter_value(&iter); + index = d_iter_index(&iter); if ((double)index < (double)d_count(numbers) / 2.0) break; diff --git a/examples/hashmap/iterator.c b/examples/hashmap/iterator.c index 2520c6e..3714a40 100644 --- a/examples/hashmap/iterator.c +++ b/examples/hashmap/iterator.c @@ -36,7 +36,7 @@ HASHMAP_GENERATE(hm, hashmap, /* FMOD */, int, double) int main(int argc, char const *argv[]) { - // Create a new hashmap with an initial capacity of 100 + // Create a new hashmap with an initial capacity of 100 and load factor of 0.6 hashmap *my_map = hm_new(100, 0.6, intcmp, inthash); // Add pairs to the hashmap diff --git a/examples/hashset/iterator.c b/examples/hashset/iterator.c new file mode 100644 index 0000000..4cbdbcf --- /dev/null +++ b/examples/hashset/iterator.c @@ -0,0 +1,194 @@ +/** + * iterator.c + * + * Creation Date: 15/05/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + * Iterator Example + */ +#include "hashset.h" +#include +#include + +// Int hash function +size_t inthash(int t) +{ + size_t a = t; + a += ~(a << 15); + a ^= (a >> 10); + a += (a << 3); + a ^= (a >> 6); + a += ~(a << 11); + a ^= (a >> 16); + return a; +} + +// Int compare function +int intcmp(int a, int b) +{ + return a - b; +} + +// Creates a hashset of integers +HASHSET_GENERATE(hs, hashset, /* FMOD */, int) + +int main(int argc, char const *argv[]) +{ + // Create a new hashset with an initial capacity of 100 and load factor of 0.6 + hashset *my_hashset = hs_new(100, 0.6, intcmp, inthash); + + // Add elements to the hashset + for (int i = 0; i < 20; i++) + { + hs_insert(my_hashset, i); + } + + // Iterate from the start (index 0) to the end (index count - 1) of the hashset + for (hashset_iter it = my_hashset->it_start(my_hashset); // Initialize iterator 'it' to the start of the hashset + !hs_iter_end(&it); // Conditional stop (until it is not at the end) + hs_iter_next(&it)) // Iterator goes one position forward + { + // Access the current element + int e = hs_iter_value(&it); + + // Access the current index (index is relative to all the elements in the iteration) + size_t i = hs_iter_index(&it); + + // Print hashset + + // Index is useful in situations like this + // If it is the first element + if (i == 0) + printf("[ %d, ", e); + // If it is the last element + else if (i == hs_count(my_hashset) - 1) + printf("%d ]\n", e); + // For elements at the middle + else + printf("%d, ", e); + } + + // Index can also be used to iterate over a certain portion of a collection + size_t limit = hs_count(my_hashset) / 2; + for (hashset_iter it = my_hashset->it_start(my_hashset); !hs_iter_end(&it); hs_iter_next(&it)) + { + // Access the current element + int e = hs_iter_value(&it); + + // Access the current index (index is relative to all the elements in the iteration) + size_t i = hs_iter_index(&it); + + // Print hashset up until limit + + // If it is the first element + if (i == 0) + printf("[ %d, ", e); + // If it is the last element + else if (i == limit - 1) // -1 because index is 0 based and we want half of the hashset + { + printf("%d ]\n", e); + break; + } + // For elements at the middle + else + printf("%d, ", e); + } + + // Going backwards + for (hashset_iter it = my_hashset->it_end(my_hashset); // Initialize iterator 'it' to the end of the hashset + !hs_iter_start(&it); // Conditional stop (until it is not at the start) + hs_iter_prev(&it)) // Iterator goes one position backwards + { + // Access the current element + int e = hs_iter_value(&it); + + // Access the current index (index is relative to all the elements in the iteration) + size_t i = hs_iter_index(&it); + + // Print hashset + // Note how the conditions for the first and last elements are simply swapped + // Because iterating backwards make the first element be the index count - 1 + // and the last one be the index 0 + + // If it is the first element + if (i == hs_count(my_hashset) - 1) + printf("[ %d, ", e); + // If it is the last element + else if (i == 0) + printf("%d ]\n", e); + // For elements at the middle + else + printf("%d, ", e); + } + + // You can also use iterators in a while loop + // But to do so you must declare the iterator struct outside the loop first + hashset_iter it; + + // You have three options: + // - Initialize it using the functions provided by the hashset [ my_hashset->it_start() and my_hashset->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_hashset->it_start(my_hashset); + it = my_hashset->it_end(my_hashset); + + // This is equivalent to it_start() + hs_iter_init(&it, my_hashset); + + // For pointers + // Also equivalent to it_start() + hashset_iter *iter = hs_iter_new(my_hashset); + + // The actual while loop + while (!hs_iter_end(iter)) + { + // Accessing elements + int e = hs_iter_value(iter); + size_t i = hs_iter_index(iter); + + // Print index and element + printf("hashset[%2" PRIuMAX "] = %2d\n", i, e); + + // Move iterator forwards + hs_iter_next(iter); + } + + // Send the iterator to the start of the hashset + hs_iter_to_start(iter); + + // Send the iterator to the end of the hashset + hs_iter_to_end(iter); + + // Backwards loop + while (!hs_iter_start(iter)) + { + // Accessing elements + int e = hs_iter_value(iter); + size_t i = hs_iter_index(iter); + + // Print index and element + printf("hashset[%2" PRIuMAX "] = %2d\n", i, e); + + // Move iterator backwards + hs_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 element + // like tree-based collections and heap (collections that have some kind of ordering). + // You also can't change the keys of an associative collection + + // In the case of a hashset or any set, this is not possible because the + // values of a set are its keys. Changing the elements could cause the set + // to be in an invalid state. + + // Dispose the iterator called by hs_iter_new() + hs_iter_free(iter); + // Dispose the hashset created + hs_free(my_hashset); + + return 0; +} diff --git a/examples/hashset/set_ops.c b/examples/hashset/set_ops.c index 8a3378d..b3b8413 100644 --- a/examples/hashset/set_ops.c +++ b/examples/hashset/set_ops.c @@ -22,13 +22,13 @@ HASHSET_GENERATE(set, set, /* static */, int) void print_set(set *s) { - size_t index; - int result; set_iter iter; set_iter_init(&iter, s); - for (set_iter_tostart(&iter); !set_iter_end(&iter);) + for (set_iter_to_start(&iter); !set_iter_end(&iter); set_iter_next(&iter)) { - set_iter_next(&iter, &result, &index); + int result = set_iter_value(&iter); + size_t index = set_iter_index(&iter); + if (index == 0) printf("[ %2d, ", result); else if (index == s->count - 1) diff --git a/examples/iterators/deque.c b/examples/iterators/deque.c index e655fba..2b39196 100644 --- a/examples/iterators/deque.c +++ b/examples/iterators/deque.c @@ -15,9 +15,6 @@ DEQUE_GENERATE(d, deque, static, int) int main(int argc, char const *argv[]) { - size_t i; - int r; - // Initialize deque and add some elements deque *d = d_new(10); for (int i = 0; i < 10; i++) diff --git a/examples/iterators/hashmap.c b/examples/iterators/hashmap.c index 86f855e..66b5b48 100644 --- a/examples/iterators/hashmap.c +++ b/examples/iterators/hashmap.c @@ -32,9 +32,7 @@ int intcmp(int a, int b) int main(int argc, char const *argv[]) { - size_t i; - int k; - double v, varr[10] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}; + double varr[10] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}; // Initialize hashmap and add some element hmap *hm = hm_new(50, 0.9, intcmp, inthash); diff --git a/examples/iterators/hashset.c b/examples/iterators/hashset.c index bca21b8..1eff626 100644 --- a/examples/iterators/hashset.c +++ b/examples/iterators/hashset.c @@ -32,9 +32,6 @@ int intcmp(int a, int b) int main(int argc, char const *argv[]) { - size_t i; - int r; - // Initialize hash set and add some elements hset *hs = hs_new(10, 0.9, intcmp, inthash); for (int i = 0; i < 10; i++) @@ -47,26 +44,30 @@ int main(int argc, char const *argv[]) // Make the iterator go back and forward for (int j = 0; j < 4; j++) { - while (hs_iter_next(&iter, &r, &i)) - printf("C[%2d] = %2d\n", i, r); + while (!hs_iter_end(&iter)) + { + printf("C[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter)); + hs_iter_next(&iter); + } printf("\n"); - while (hs_iter_prev(&iter, &r, &i)) - printf("C[%2d] = %2d\n", i, r); + while (!hs_iter_start(&iter)) + { + printf("C[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter)); + hs_iter_prev(&iter); + } printf("\n\n"); } - for (hs_iter_tostart(&iter); !hs_iter_end(&iter); /**/) + for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter)) { - hs_iter_next(&iter, &r, &i); - printf("S[%2d] = %2d\n", i, r); + printf("S[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter)); } printf("\n"); - for (hs_iter_toend(&iter); !hs_iter_start(&iter); /**/) + for (hs_iter_to_end(&iter); !hs_iter_start(&iter); hs_iter_prev(&iter)) { - hs_iter_prev(&iter, &r, &i); - printf("S[%2d] = %2d\n", i, r); + printf("S[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter)); } hs_free(hs); diff --git a/src/hashmap.h b/src/hashmap.h index 375fcb4..1884936 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -89,7 +89,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Hashmap Structure */ \ typedef struct SNAME##_s \ { \ - /* Array of buckets */ \ + /* Array of Entries */ \ struct SNAME##_entry_s *buffer; \ \ /* Current array capacity */ \ @@ -118,10 +118,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Hashmap Entry */ \ typedef struct SNAME##_entry_s \ { \ - /* Key */ \ + /* Entry Key */ \ K key; \ \ - /* Value */ \ + /* Entry Value */ \ V value; \ \ /* The distance of this node to its original position, used by robin-hood hashing */ \ @@ -357,7 +357,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ \ SNAME##_iter iter; \ - K max_key; \ \ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ @@ -367,14 +366,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ if (index == 0) \ { \ - max_key = result_key; \ *key = result_key; \ *value = result_value; \ } \ - else if (_map_->cmp(result_key, max_key) > 0) \ + else if (_map_->cmp(result_key, *key) > 0) \ { \ - max_key = result_key; \ - *key = max_key; \ + *key = result_key; \ *value = result_value; \ } \ } \ @@ -388,7 +385,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ \ SNAME##_iter iter; \ - K min_key; \ \ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ @@ -398,14 +394,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ if (index == 0) \ { \ - min_key = result_key; \ *key = result_key; \ *value = result_value; \ } \ - else if (_map_->cmp(result_key, min_key) < 0) \ + else if (_map_->cmp(result_key, *key) < 0) \ { \ - min_key = result_key; \ - *key = min_key; \ + *key = result_key; \ *value = result_value; \ } \ } \ diff --git a/src/hashset.h b/src/hashset.h index 2761de4..01bbbc9 100644 --- a/src/hashset.h +++ b/src/hashset.h @@ -81,70 +81,121 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #define HASHSET_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \ HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* STRUCT ********************************************************************/ -#define HASHSET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \ - \ - struct SNAME##_s \ - { \ - struct SNAME##_entry_s *buffer; \ - size_t capacity; \ - size_t count; \ - double load; \ - int (*cmp)(V, V); \ - size_t (*hash)(V); \ - }; \ - \ - struct SNAME##_entry_s \ - { \ - V value; \ - size_t dist; \ - enum EntryState_e state; \ - }; \ - \ - struct SNAME##_iter_s \ - { \ - struct SNAME##_s *target; \ - size_t cursor; \ - size_t index; \ - size_t first; \ - size_t last; \ - bool start; \ - bool end; \ - }; \ - \ +#define HASHSET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) + /* HEADER ********************************************************************/ #define HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ \ - typedef struct SNAME##_s SNAME; \ - typedef struct SNAME##_entry_s SNAME##_entry; \ - typedef struct SNAME##_iter_s SNAME##_iter; \ + /* Hashset Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry_s *buffer; \ \ + /* Current Array Capcity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Element hash function */ \ + size_t (*hash)(V); \ + \ + /* Function that returns an iterator to the start of the hashset */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashset */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + typedef struct SNAME##_entry_s \ + { \ + /* Entry element */ \ + V value; \ + \ + /* The distance of this node to its original position, used by robin-hood hashing */ \ + size_t dist; \ + \ + /* The sate of this node (DELETED, EMPTY, FILLED) */ \ + enum EntryState_e state; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + /* Hashset Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target Hashset */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* 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(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)); \ FMOD void PFX##_clear(SNAME *_set_); \ FMOD void PFX##_free(SNAME *_set_); \ + /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_set_, V element); \ FMOD bool PFX##_remove(SNAME *_set_, V element); \ + /* Conditional Input and Output */ \ FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ - FMOD V PFX##_max(SNAME *_set_); \ - FMOD V PFX##_min(SNAME *_set_); \ + /* Element Access */ \ + FMOD bool PFX##_max(SNAME *_set_, V *value); \ + FMOD bool PFX##_min(SNAME *_set_, V *value); \ + /* Collection State */ \ FMOD bool PFX##_contains(SNAME *_set_, V element); \ FMOD bool PFX##_empty(SNAME *_set_); \ FMOD size_t PFX##_count(SNAME *_set_); \ \ + /* Set Operations */ \ FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ \ + /* 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); \ - FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ - FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *index); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *index); \ + /* 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 V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ \ /* SOURCE ********************************************************************/ #define HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ @@ -152,6 +203,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD bool PFX##_grow(SNAME *_set_); \ FMOD SNAME##_entry *PFX##_get_entry(SNAME *_set_, V element); \ FMOD size_t PFX##_calculate_size(size_t required); \ + SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ \ FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)) \ { \ @@ -181,6 +234,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, _set_->cmp = compare; \ _set_->hash = hash; \ \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ + \ return _set_; \ } \ \ @@ -286,50 +342,46 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ } \ \ - FMOD V PFX##_max(SNAME *_set_) \ + FMOD bool PFX##_max(SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ - return 0; \ + return false; \ \ - V result; \ - V max; \ - size_t index; \ SNAME##_iter iter; \ \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter);) \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ - PFX##_iter_next(&iter, &result, &index); \ + V result = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ \ if (index == 0) \ - max = result; \ - else if (_set_->cmp(result, max) > 0) \ - max = result; \ + *value = result; \ + else if (_set_->cmp(result, *value) > 0) \ + *value = result; \ } \ \ - return max; \ + return true; \ } \ \ - FMOD V PFX##_min(SNAME *_set_) \ + FMOD bool PFX##_min(SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ - return 0; \ + return false; \ \ - V result; \ - V min; \ - size_t index; \ SNAME##_iter iter; \ \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter);) \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ - PFX##_iter_next(&iter, &result, &index); \ + V result = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ \ if (index == 0) \ - min = result; \ - else if (_set_->cmp(result, min) < 0) \ - min = result; \ + *value = result; \ + else if (_set_->cmp(result, *value) < 0) \ + *value = result; \ } \ \ - return min; \ + return true; \ } \ \ FMOD bool PFX##_contains(SNAME *_set_, V element) \ @@ -349,28 +401,23 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ { \ - V value; \ - size_t index; \ - SNAME##_iter iter1, iter2; \ - \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ if (!_set_r_) \ return false; \ \ + SNAME##_iter iter1, iter2; \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ - for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ + for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ { \ - PFX##_iter_next(&iter1, &value, &index); \ - PFX##_insert(_set_r_, value); \ + PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \ } \ \ - for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ { \ - PFX##_iter_next(&iter2, &value, &index); \ - PFX##_insert(_set_r_, value); \ + PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ } \ \ return _set_r_; \ @@ -378,10 +425,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ { \ - V value; \ - size_t index; \ - SNAME##_iter iter; \ - \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ if (!_set_r_) \ @@ -390,11 +433,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ \ + SNAME##_iter iter; \ PFX##_iter_init(&iter, _set_A_); \ \ - for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ - PFX##_iter_next(&iter, &value, &index); \ + V value = PFX##_iter_value(&iter); \ \ if (PFX##_get_entry(_set_B_, value) != NULL) \ PFX##_insert(_set_r_, value); \ @@ -405,20 +449,17 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ { \ - V value; \ - size_t index; \ - SNAME##_iter iter; \ - \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ if (!_set_r_) \ return false; \ \ + SNAME##_iter iter; \ PFX##_iter_init(&iter, _set1_); \ \ - for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ - PFX##_iter_next(&iter, &value, &index); \ + V value = PFX##_iter_value(&iter); \ \ if (PFX##_get_entry(_set2_, value) == NULL) \ PFX##_insert(_set_r_, value); \ @@ -429,8 +470,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ { \ - V value; \ - size_t index; \ SNAME##_iter iter1, iter2; \ \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ @@ -441,17 +480,17 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ - for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ + for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ { \ - PFX##_iter_next(&iter1, &value, &index); \ + V value = PFX##_iter_value(&iter1); \ \ if (PFX##_get_entry(_set2_, value) == NULL) \ PFX##_insert(_set_r_, value); \ } \ \ - for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ { \ - PFX##_iter_next(&iter2, &value, &index); \ + V value = PFX##_iter_value(&iter2); \ \ if (PFX##_get_entry(_set1_, value) == NULL) \ PFX##_insert(_set_r_, value); \ @@ -519,7 +558,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ iter->cursor = iter->first; \ iter->index = 0; \ @@ -527,7 +566,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, iter->end = PFX##_empty(iter->target); \ } \ \ - FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ iter->cursor = iter->last; \ iter->index = iter->target->count - 1; \ @@ -535,16 +574,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, iter->end = true; \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *index) \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ \ SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ \ - *value = scan->value; \ - *index = iter->index; \ - \ if (iter->cursor == iter->last) \ iter->end = true; \ else \ @@ -566,16 +602,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *index) \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ \ SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ \ - *value = scan->value; \ - *index = iter->index; \ - \ if (iter->cursor == iter->first) \ iter->start = true; \ else \ @@ -597,6 +630,16 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ FMOD bool PFX##_grow(SNAME *_set_) \ { \ size_t new_size = PFX##_calculate_size(_set_->capacity + _set_->capacity / 2); \ @@ -606,14 +649,11 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (!_new_set_) \ return false; \ \ - V value; \ - size_t index; \ SNAME##_iter iter; \ \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter);) \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ - PFX##_iter_next(&iter, &value, &index); \ - PFX##_insert(_new_set_, value); \ + PFX##_insert(_new_set_, PFX##_iter_value(&iter)); \ } \ \ if (_set_->count != _new_set_->count) \ @@ -665,6 +705,25 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, i++; \ \ return cmc_hashtable_primes[i]; \ + } \ + \ + 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_HASHSET_H */