| 6 Creating an iterator is as simple as creating a `CxIterator` struct and setting the fields in a meaningful way. |
6 Creating an iterator is as simple as creating a `CxIterator` struct and setting the fields in a meaningful way. |
| 7 The UCX collections provide various functions to create such iterators. |
7 The UCX collections provide various functions to create such iterators. |
| 8 |
8 |
| 9 If the predefined fields are not enough (or introduce too much bloat) for your use case, |
9 If the predefined fields are not enough (or introduce too much bloat) for your use case, |
| 10 you can alternatively create your own iterator structure |
10 you can alternatively create your own iterator structure |
| 11 and place the `CX_ITERATOR_BASE` macro as first member of that structure. |
11 and place the `CX_ITERATOR_BASE` macro as the first member of that structure. |
| 12 |
12 |
| 13 ```C |
13 ```C |
| 14 #include <cx/iterator.h> |
14 #include <cx/iterator.h> |
| 15 |
15 |
| 16 struct my_fancy_iterator_s { |
16 struct my_fancy_iterator_s { |
| 34 ``` |
34 ``` |
| 35 |
35 |
| 36 The `cxIterator()` function creates an iterator over the elements of `array` where |
36 The `cxIterator()` function creates an iterator over the elements of `array` where |
| 37 each element is `elem_size` bytes large and the array contains a total of `elem_count` elements. |
37 each element is `elem_size` bytes large and the array contains a total of `elem_count` elements. |
| 38 |
38 |
| 39 The `cxIteratorPtr()` on the other hand assumes `sizeof(void*)` as the `elem_size` and automatically dereferences the pointers to the array elements. |
39 The `cxIteratorPtr()`, on the other hand, assumes `sizeof(void*)` as the `elem_size` and automatically dereferences the pointers to the array elements. |
| 40 That means, values returned by the iterator created with `cxIteratorPtr()` are the pointers stored in the array, |
40 That means, values returned by the iterator created with `cxIteratorPtr()` are the pointers stored in the array, |
| 41 while iterators created `cxIterator()` yield the pointers to the elements in the array. |
41 while iterators created `cxIterator()` yield the pointers to the elements in the array. |
| 42 |
42 |
| 43 Iterators created with the above functions are not allowed to remove elements because they are unable to update the size of the array they are iterating over. |
43 Iterators created with the above functions are not allowed to remove elements because they are unable to update the size of the array they are iterating over. |
| 44 |
44 |
| 86 ## Removing Elements via Iterators |
86 ## Removing Elements via Iterators |
| 87 |
87 |
| 88 Usually an iterator is not mutating the collection it is iterating over. |
88 Usually an iterator is not mutating the collection it is iterating over. |
| 89 But sometimes it is desirable to remove an element from the collection while iterating over it. |
89 But sometimes it is desirable to remove an element from the collection while iterating over it. |
| 90 |
90 |
| 91 For this purpose, most collections allow to use `cxIteratorFlagRemoval()`, which instructs the iterator to remove |
91 For this purpose, most collections allow using `cxIteratorFlagRemoval()`, which instructs the iterator to remove |
| 92 the current element from the collection on the next call to `cxIteratorNext()`. |
92 the current element from the collection on the next call to `cxIteratorNext()`. |
| 93 If you are implementing your own iterator, it is up to you to implement this behavior. |
93 If you are implementing your own iterator, it is up to you to implement this behavior. |
| 94 |
94 |
| 95 ## Passing Iterators to Functions |
95 ## Passing Iterators to Functions |
| 96 |
96 |
| 97 To eliminate the need of memory management for iterators, the structures are usually used by value. |
97 To eliminate the need of memory management for iterators, the structures are usually passed by value. |
| 98 This does not come with additional costs because iteration is implemented entirely by using macros. |
|
| 99 |
|
| 100 However, sometimes it is necessary to pass an iterator to another function. |
98 However, sometimes it is necessary to pass an iterator to another function. |
| |
99 |
| 101 To make that possible in a generalized way, such functions should accept a `CxIteratorBase*` pointer |
100 To make that possible in a generalized way, such functions should accept a `CxIteratorBase*` pointer |
| 102 which can be obtained with the `cxIteratorRef()` macro on the calling site. |
101 which can be obtained with the `cxIteratorRef()` macro on the calling site. |
| 103 |
102 |
| 104 In the following example, elements from a list are inserted into a tree: |
103 In the following example, elements from a list are inserted into a tree: |
| 105 |
104 |
| 109 |
108 |
| 110 CxIterator iter = cxListIterator(list); |
109 CxIterator iter = cxListIterator(list); |
| 111 cxTreeInsertIter(tree, cxIteratorRef(iter), cxListSize(list)); |
110 cxTreeInsertIter(tree, cxIteratorRef(iter), cxListSize(list)); |
| 112 ``` |
111 ``` |
| 113 |
112 |
| 114 > This is the reason, why `CX_ITERATOR_BASE` must be the first member of any iterator structure. |
113 > This is the reason why `CX_ITERATOR_BASE` must be the first member of any iterator structure. |
| 115 > Otherwise, the address taken by `cxIteratorRef()` would not equal the address of the iterator. |
114 > Otherwise, the address taken by `cxIteratorRef()` would not equal the address of the iterator. |
| 116 {style="note"} |
115 {style="note"} |
| 117 |
116 |
| 118 ## Custom Iterators |
117 ## Custom Iterators |
| 119 |
118 |
| 192 |
191 |
| 193 return iter; |
192 return iter; |
| 194 } |
193 } |
| 195 ``` |
194 ``` |
| 196 |
195 |
| 197 > Note, that the behavior of `current` is undefined when `valid` returns `false`. |
196 > Note that the behavior of `current` is undefined when `valid` returns `false`. |
| 198 > That means, on the one hand, `current` does not need to check for validity of the iterator, |
197 > That means, on the one hand, `current` does not need to check for validity of the iterator, |
| 199 > but on the other hand, it is forbidden to invoke `current` when `valid` would return `false`. |
198 > but on the other hand, it is forbidden to invoke `current` when `valid` would return `false`. |
| 200 {style="note"} |
199 {style="note"} |
| 201 |
200 |
| 202 > If performance matters in your application, it is recommended that you indeed create specialized iterators |
201 > If performance matters in your application, it is recommended that you indeed create specialized iterators |