diff --git a/examples/hashset/README.md b/examples/hashset/README.md index 8fe249f..1d544e7 100644 --- a/examples/hashset/README.md +++ b/examples/hashset/README.md @@ -1,3 +1,4 @@ # Hashset examples +* iterator.c - A complete example of the hashset iterator * set_ops.c - Demonstrates common set operations like *union*, *intersection*, *difference* and *symmetric difference*. diff --git a/examples/heap/README.md b/examples/heap/README.md index 0bba70f..5b402b4 100644 --- a/examples/heap/README.md +++ b/examples/heap/README.md @@ -1,3 +1,4 @@ # Heap examples * heapsort.c - Uses the heap to sort the elements in a given array. +* iterator.c - A complete example of the heap iterator diff --git a/examples/iterators/deque.c b/examples/iterators/deque.c index 2b39196..c360908 100644 --- a/examples/iterators/deque.c +++ b/examples/iterators/deque.c @@ -7,9 +7,9 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "deque.h" #include #include -#include "deque.h" DEQUE_GENERATE(d, deque, static, int) diff --git a/examples/iterators/hashmap.c b/examples/iterators/hashmap.c index 66b5b48..ec47695 100644 --- a/examples/iterators/hashmap.c +++ b/examples/iterators/hashmap.c @@ -7,9 +7,9 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "hashmap.h" #include #include -#include "hashmap.h" HASHMAP_GENERATE(hm, hmap, static, int, double) diff --git a/examples/iterators/hashset.c b/examples/iterators/hashset.c index 1eff626..c0736ec 100644 --- a/examples/iterators/hashset.c +++ b/examples/iterators/hashset.c @@ -7,9 +7,9 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "hashset.h" #include #include -#include "hashset.h" HASHSET_GENERATE(hs, hset, static, int) diff --git a/examples/iterators/heap.c b/examples/iterators/heap.c index 8c79fe0..213b4be 100644 --- a/examples/iterators/heap.c +++ b/examples/iterators/heap.c @@ -7,9 +7,9 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "heap.h" #include #include -#include "heap.h" int intcmp(int a, int b) { diff --git a/examples/iterators/linkedlist.c b/examples/iterators/linkedlist.c index 87c6795..8608c01 100644 --- a/examples/iterators/linkedlist.c +++ b/examples/iterators/linkedlist.c @@ -7,52 +7,53 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "linkedlist.h" #include #include -#include "linkedlist.h" -LINKEDLIST_GENERATE(ll, linked, static, int) +LINKEDLIST_GENERATE(ll, linkedlist, static, int) int main(int argc, char const *argv[]) { - size_t i; - int r; - - // Initialize linked list and add some elements - linked *ll = ll_new(); + // Initialize list and add some elements + linkedlist *l = ll_new(); for (int i = 0; i < 10; i++) - ll_push_back(ll, i); + ll_push_back(l, i); // Initialize iterator - linked_iter iter; - ll_iter_init(&iter, ll); + linkedlist_iter iter; + ll_iter_init(&iter, l); // Make the iterator go back and forward for (int j = 0; j < 4; j++) { - while (ll_iter_next(&iter, &r, &i)) - printf("C[%2d] = %2d\n", i, r); + while (!ll_iter_end(&iter)) + { + printf("C[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter)); + ll_iter_next(&iter); + } printf("\n"); - while (ll_iter_prev(&iter, &r, &i)) - printf("C[%2d] = %2d\n", i, r); + while (!ll_iter_start(&iter)) + { + printf("C[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter)); + ll_iter_prev(&iter); + } printf("\n\n"); } - for (ll_iter_tostart(&iter); !ll_iter_end(&iter); /**/) + for (ll_iter_to_start(&iter); !ll_iter_end(&iter); ll_iter_next(&iter)) { - ll_iter_next(&iter, &r, &i); - printf("LL[%2d] = %2d\n", i, r); + printf("LL[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter)); } printf("\n"); - for (ll_iter_toend(&iter); !ll_iter_start(&iter); /**/) + for (ll_iter_to_end(&iter); !ll_iter_start(&iter); ll_iter_prev(&iter)) { - ll_iter_prev(&iter, &r, &i); - printf("LL[%2d] = %2d\n", i, r); + printf("LL[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter)); } - ll_free(ll); + ll_free(l); return 0; } diff --git a/examples/iterators/list.c b/examples/iterators/list.c index 5527b71..d04205c 100644 --- a/examples/iterators/list.c +++ b/examples/iterators/list.c @@ -7,17 +7,14 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "list.h" #include #include -#include "list.h" LIST_GENERATE(l, list, static, int) int main(int argc, char const *argv[]) { - size_t i; - int r; - // Initialize list and add some elements list *l = l_new(10); for (int i = 0; i < 10; i++) diff --git a/examples/linkedlist/README.md b/examples/linkedlist/README.md index 693d154..816a805 100644 --- a/examples/linkedlist/README.md +++ b/examples/linkedlist/README.md @@ -1,4 +1,4 @@ # Linkedlist examples -* iterator.c - Example of using a linked list iterator. +* iterator.c - A complete example of the linked list iterator * linked_list_node.c - Example of using functions that add or remove elements relative to a node. diff --git a/examples/linkedlist/iterator.c b/examples/linkedlist/iterator.c index ba21ad6..116f815 100644 --- a/examples/linkedlist/iterator.c +++ b/examples/linkedlist/iterator.c @@ -1,46 +1,195 @@ /** * iterator.c * - * Creation Date: 22/03/2019 + * Creation Date: 10/05/2019 * * Authors: * Leonardo Vencovsky (https://github.com/LeoVen) * + * Iterator Example */ -#include #include "linkedlist.h" +#include +#include -LINKEDLIST_GENERATE(ll, linked, static, int) +// Creates a linkedlist of integers +LINKEDLIST_GENERATE(ll, linkedlist, /* FMOD */, int) int main(int argc, char const *argv[]) { - size_t i; - int r; + // Create a new linkedlist + linkedlist *my_linkedlist = ll_new(); - // Initliazie linked list and add some elements - linked *ll = ll_new(); + // Add elements to the linkedlist for (int i = 0; i < 20; i++) - ll_push_back(ll, i); + { + ll_push_back(my_linkedlist, i); + } - // Initialize iterator - linked_iter iter; - ll_iter_init(&iter, ll); + // Iterate from the start (index 0) to the end (index count - 1) of the linkedlist + for (linkedlist_iter it = my_linkedlist->it_start(my_linkedlist); // Initialize iterator 'it' to the start of the linkedlist + !ll_iter_end(&it); // Conditional stop (until it is not at the end) + ll_iter_next(&it)) // Iterator goes one position forward + { + // Access the current element + int e = ll_iter_value(&it); - // Move cursor to the end of the list - ll_iter_toend(&iter); - // While there is a previous element on the list - while (ll_iter_prev(&iter, &r, &i)) - printf("list[%2d] = %2d\n", i, r); + // Access the current index (index is relative to all the elements in the iteration) + size_t i = ll_iter_index(&it); - printf("\n"); + // Print linkedlist - // Move cursor to the start of the list - ll_iter_tostart(&iter); - // While there is a next element on the list - while (ll_iter_next(&iter, &r, &i)) - printf("list[%2d] = %2d\n", i, r); + // 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 == ll_count(my_linkedlist) - 1) + printf("%d ]\n", e); + // For elements at the middle + else + printf("%d, ", e); + } - ll_free(ll); + // Index can also be used to iterate over a certain portion of a collection + size_t limit = ll_count(my_linkedlist) / 2; + for (linkedlist_iter it = my_linkedlist->it_start(my_linkedlist); !ll_iter_end(&it); ll_iter_next(&it)) + { + // Access the current element + int e = ll_iter_value(&it); + + // Access the current index (index is relative to all the elements in the iteration) + size_t i = ll_iter_index(&it); + + // Print linkedlist 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 linkedlist + { + printf("%d ]\n", e); + break; + } + // For elements at the middle + else + printf("%d, ", e); + } + + // Going backwards + for (linkedlist_iter it = my_linkedlist->it_end(my_linkedlist); // Initialize iterator 'it' to the end of the linkedlist + !ll_iter_start(&it); // Conditional stop (until it is not at the start) + ll_iter_prev(&it)) // Iterator goes one position backwards + { + // Access the current element + int e = ll_iter_value(&it); + + // Access the current index (index is relative to all the elements in the iteration) + size_t i = ll_iter_index(&it); + + // Print linkedlist + // 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 == ll_count(my_linkedlist) - 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 + linkedlist_iter it; + + // You have three options: + // - Initialize it using the functions provided by the linkedlist [ my_linkedlist->it_start() and my_linkedlist->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_linkedlist->it_start(my_linkedlist); + it = my_linkedlist->it_end(my_linkedlist); + + // This is equivalent to it_start() + ll_iter_init(&it, my_linkedlist); + + // For pointers + // Also equivalent to it_start() + linkedlist_iter *iter = ll_iter_new(my_linkedlist); + + // The actual while loop + while (!ll_iter_end(iter)) + { + // Accessing elements + int e = ll_iter_value(iter); + size_t i = ll_iter_index(iter); + + // Print index and element + printf("linkedlist[%2" PRIuMAX "] = %2d\n", i, e); + + // Move iterator forwards + ll_iter_next(iter); + } + + // Send the iterator to the start of the linkedlist + ll_iter_to_start(iter); + + // Send the iterator to the end of the linkedlist + ll_iter_to_end(iter); + + // Backwards loop + while (!ll_iter_start(iter)) + { + // Accessing elements + int e = ll_iter_value(iter); + size_t i = ll_iter_index(iter); + + // Print index and element + printf("linkedlist[%2" PRIuMAX "] = %2d\n", i, e); + + // Move iterator backwards + ll_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 + + // Change every element that is divisible by 2 to the number 7 + for (ll_iter_to_start(&it); !ll_iter_end(&it); ll_iter_next(&it)) + { + // Get a reference to the current value + int *r = ll_iter_rvalue(&it); + + if (r != NULL && *r % 2 == 0) + *r = 7; + } + + // Now print it to see the difference + for (linkedlist_iter it = my_linkedlist->it_start(my_linkedlist); !ll_iter_end(&it); ll_iter_next(&it)) + { + int e = ll_iter_value(&it); + size_t i = ll_iter_index(&it); + + if (i == 0) + printf("[ %d, ", e); + else if (i == ll_count(my_linkedlist) - 1) + printf("%d ]\n", e); + else + printf("%d, ", e); + } + + // Dispose the iterator called by ll_iter_new() + ll_iter_free(iter); + // Dispose the linkedlist created + ll_free(my_linkedlist); return 0; } diff --git a/src/linkedlist.h b/src/linkedlist.h index 2586388..88b7b8e 100644 --- a/src/linkedlist.h +++ b/src/linkedlist.h @@ -36,82 +36,135 @@ #define LINKEDLIST_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \ LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* STRUCT ********************************************************************/ -#define LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \ - \ - struct SNAME##_s \ - { \ - struct SNAME##_node_s *head; \ - struct SNAME##_node_s *tail; \ - size_t count; \ - }; \ - \ - struct SNAME##_node_s \ - { \ - V data; \ - struct SNAME##_node_s *next; \ - struct SNAME##_node_s *prev; \ - }; \ - \ - struct SNAME##_iter_s \ - { \ - struct SNAME##_s *target; \ - struct SNAME##_node_s *cursor; \ - size_t index; \ - bool start; \ - bool end; \ - }; \ - \ +#define LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) + /* HEADER ********************************************************************/ #define LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ \ - typedef struct SNAME##_s SNAME; \ - typedef struct SNAME##_node_s SNAME##_node; \ - typedef struct SNAME##_iter_s SNAME##_iter; \ + /* Linked List Structure */ \ + typedef struct SNAME##_s \ + { \ + /* First node in the list */ \ + struct SNAME##_node_s *head; \ \ + /* Last node in the list */ \ + struct SNAME##_node_s *tail; \ + \ + /* Current amount of elements in the list */ \ + size_t count; \ + \ + /* Function that returns an iterator to the start of the list */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the list */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME_ptr; \ + \ + /* Doubly-linked list node */ \ + typedef struct SNAME##_node_s \ + { \ + /* Node's data */ \ + V data; \ + \ + /* Pointer to the next node on the linked list */ \ + struct SNAME##_node_s *next; \ + \ + /* Pointer to the previous node on the linked list */ \ + struct SNAME##_node_s *prev; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Linked List Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target Linked List */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node_s *cursor; \ + \ + /* 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(void); \ FMOD void PFX##_clear(SNAME *_list_); \ FMOD void PFX##_free(SNAME *_list_); \ + /* Collection Input and Output */ \ FMOD bool PFX##_push_front(SNAME *_list_, V element); \ FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \ FMOD bool PFX##_push_back(SNAME *_list_, V element); \ FMOD bool PFX##_pop_front(SNAME *_list_); \ FMOD bool PFX##_pop(SNAME *_list_, size_t index); \ FMOD bool PFX##_pop_back(SNAME *_list_); \ + /* Conditional Input and Output */ \ FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \ FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \ + /* Element Access */ \ FMOD V PFX##_front(SNAME *_list_); \ FMOD V PFX##_get(SNAME *_list_, size_t index); \ FMOD V *PFX##_get_ref(SNAME *_list_, size_t index); \ FMOD V PFX##_back(SNAME *_list_); \ + /* Collection State */ \ FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \ FMOD bool PFX##_empty(SNAME *_list_); \ FMOD size_t PFX##_count(SNAME *_list_); \ \ + /* Node Related Functions */ \ + /* Node Allocation and Deallocation */ \ FMOD SNAME##_node *PFX##_new_node(V element); \ + FMOD void PFX##_free_node(SNAME##_node *_node_); \ + /* Node Access Relative to a Linked List */ \ FMOD SNAME##_node *PFX##_head(SNAME *_list_); \ FMOD SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index); \ FMOD SNAME##_node *PFX##_tail(SNAME *_list_); \ + /* Input and Output Relative to a Node */ \ FMOD bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element); \ FMOD bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element); \ FMOD bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_); \ FMOD bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_); \ FMOD bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_); \ + /* Node Access Relative to a Linked List Node */ \ FMOD SNAME##_node *PFX##_next_node(SNAME##_node *_node_); \ FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *_node_); \ \ + /* 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 *result, size_t *index); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, 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 V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + FMOD SNAME##_node *PFX##_iter_node(SNAME##_iter *iter); \ \ /* SOURCE ********************************************************************/ #define LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ \ + /* Implementation Detail Functions */ \ + SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ + SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ + \ FMOD SNAME *PFX##_new(void) \ { \ SNAME *_list_ = malloc(sizeof(SNAME)); \ @@ -123,6 +176,9 @@ _list_->head = NULL; \ _list_->tail = NULL; \ \ + _list_->it_start = PFX##_impl_it_start; \ + _list_->it_end = PFX##_impl_it_end; \ + \ return _list_; \ } \ \ @@ -151,21 +207,21 @@ \ FMOD bool PFX##_push_front(SNAME *_list_, V element) \ { \ - SNAME##_node *node = PFX##_new_node(element); \ + SNAME##_node *_node_ = PFX##_new_node(element); \ \ - if (!node) \ + if (!_node_) \ return false; \ \ if (PFX##_empty(_list_)) \ { \ - _list_->head = node; \ - _list_->tail = node; \ + _list_->head = _node_; \ + _list_->tail = _node_; \ } \ else \ { \ - node->next = _list_->head; \ - _list_->head->prev = node; \ - _list_->head = node; \ + _node_->next = _list_->head; \ + _list_->head->prev = _node_; \ + _list_->head = _node_; \ } \ \ _list_->count++; \ @@ -187,17 +243,17 @@ return PFX##_push_back(_list_, element); \ } \ \ - SNAME##_node *node = PFX##_new_node(element); \ + SNAME##_node *_node_ = PFX##_new_node(element); \ \ - if (!node) \ + if (!_node_) \ return false; \ \ SNAME##_node *scan = PFX##_get_node(_list_, index - 1); \ \ - node->next = scan->next; \ - node->prev = scan; \ - node->next->prev = node; \ - node->prev->next = node; \ + _node_->next = scan->next; \ + _node_->prev = scan; \ + _node_->next->prev = _node_; \ + _node_->prev->next = _node_; \ \ _list_->count++; \ \ @@ -206,21 +262,21 @@ \ FMOD bool PFX##_push_back(SNAME *_list_, V element) \ { \ - SNAME##_node *node = PFX##_new_node(element); \ + SNAME##_node *_node_ = PFX##_new_node(element); \ \ - if (!node) \ + if (!_node_) \ return false; \ \ if (PFX##_empty(_list_)) \ { \ - _list_->head = node; \ - _list_->tail = node; \ + _list_->head = _node_; \ + _list_->tail = _node_; \ } \ else \ { \ - node->prev = _list_->tail; \ - _list_->tail->next = node; \ - _list_->tail = node; \ + _node_->prev = _list_->tail; \ + _list_->tail->next = _node_; \ + _list_->tail = _node_; \ } \ \ _list_->count++; \ @@ -233,10 +289,10 @@ if (PFX##_empty(_list_)) \ return false; \ \ - SNAME##_node *node = _list_->head; \ + SNAME##_node *_node_ = _list_->head; \ _list_->head = _list_->head->next; \ \ - free(node); \ + free(_node_); \ \ if (_list_->head == NULL) \ _list_->tail = NULL; \ @@ -265,15 +321,15 @@ return PFX##_pop_back(_list_); \ } \ \ - SNAME##_node *node = PFX##_get_node(_list_, index); \ + SNAME##_node *_node_ = PFX##_get_node(_list_, index); \ \ - if (!node) \ + if (!_node_) \ return false; \ \ - node->next->prev = node->prev; \ - node->prev->next = node->next; \ + _node_->next->prev = _node_->prev; \ + _node_->prev->next = _node_->next; \ \ - free(node); \ + free(_node_); \ \ _list_->count--; \ \ @@ -285,10 +341,10 @@ if (PFX##_empty(_list_)) \ return false; \ \ - SNAME##_node *node = _list_->tail; \ + SNAME##_node *_node_ = _list_->tail; \ _list_->tail = _list_->tail->prev; \ \ - free(node); \ + free(_node_); \ \ if (_list_->tail == NULL) \ _list_->head = NULL; \ @@ -391,16 +447,21 @@ \ FMOD SNAME##_node *PFX##_new_node(V element) \ { \ - SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \ \ - if (!node) \ + if (!_node_) \ return NULL; \ \ - node->data = element; \ - node->next = NULL; \ - node->prev = NULL; \ + _node_->data = element; \ + _node_->next = NULL; \ + _node_->prev = NULL; \ \ - return node; \ + return _node_; \ + } \ + \ + FMOD void PFX##_free_node(SNAME##_node *_node_) \ + { \ + free(_node_); \ } \ \ FMOD SNAME##_node *PFX##_head(SNAME *_list_) \ @@ -416,26 +477,26 @@ if (PFX##_empty(_list_)) \ return NULL; \ \ - SNAME##_node *scan = NULL; \ + SNAME##_node *_node_ = NULL; \ \ if (index <= _list_->count / 2) \ { \ - scan = _list_->head; \ + _node_ = _list_->head; \ for (size_t i = 0; i < index; i++) \ { \ - scan = scan->next; \ + _node_ = _node_->next; \ } \ } \ else \ { \ - scan = _list_->tail; \ + _node_ = _list_->tail; \ for (size_t i = _list_->count - 1; i > index; i--) \ { \ - scan = scan->prev; \ + _node_ = _node_->prev; \ } \ } \ \ - return scan; \ + return _node_; \ } \ \ FMOD SNAME##_node *PFX##_tail(SNAME *_list_) \ @@ -596,7 +657,7 @@ 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->target->head; \ iter->index = 0; \ @@ -604,7 +665,7 @@ 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->target->tail; \ iter->index = iter->target->count - 1; \ @@ -612,14 +673,12 @@ iter->end = true; \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index) \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ \ - *index = iter->index; \ - *result = iter->cursor->data; \ - iter->start = false; \ + iter->start = PFX##_empty(iter->target); \ \ if (iter->cursor->next == NULL) \ iter->end = true; \ @@ -632,14 +691,12 @@ return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ \ - *index = iter->index; \ - *result = iter->cursor->data; \ - iter->end = false; \ + iter->end = PFX##_empty(iter->target); \ \ if (iter->cursor->prev == NULL) \ iter->start = true; \ @@ -650,6 +707,46 @@ } \ \ return true; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + return iter->cursor->data; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + return &(iter->cursor->data); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + FMOD SNAME##_node *PFX##_iter_node(SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_LINKEDLIST_H */