25 |
25 |
26 ```C |
26 ```C |
27 #include <cx/iterator.h> |
27 #include <cx/iterator.h> |
28 |
28 |
29 CxIterator cxIterator(const void *array, |
29 CxIterator cxIterator(const void *array, |
30 size_t elem_size, size_t elem_count); |
30 size_t elem_size, size_t elem_count, |
31 |
31 bool remove_keeps_order); |
32 CxIterator cxMutIterator(void *array, |
32 |
33 size_t elem_size, size_t elem_count, bool remove_keeps_order); |
33 CxIterator cxIteratorPtr(const void *array, |
34 |
34 size_t elem_count, |
35 CxIterator cxIteratorPtr(const void *array, size_t elem_count); |
|
36 |
|
37 CxIterator cxMutIteratorPtr(void *array, size_t elem_count, |
|
38 bool remove_keeps_order); |
35 bool remove_keeps_order); |
39 ``` |
36 ``` |
40 |
37 |
41 The `cxIterator()` function creates an iterator over the elements of `array` where |
38 The `cxIterator()` function creates an iterator over the elements of `array` where |
42 each element is `elem_size` bytes large and the array contains a total of `elem_count` elements. |
39 each element is `elem_size` bytes large and the array contains a total of `elem_count` elements. |
43 The `cxMutIterator()` function creates an equivalent [mutating iterator](#mutating-iterators). |
40 |
44 |
41 The `cxIteratorPtr()` function is equivalent to `cxIterator()`, except it assumes `sizeof(void*)` as the `elem_size`. |
45 The `cxIteratorPtr()` and `cxMutIteratorPtr()` functions are equivalent to |
|
46 the `cxIteratorPtr()` and `cxMutIteratorPtr()`, except they assume `sizeof(void*)` as the `elem_size`. |
|
47 |
42 |
48 The UCX collections also define functions for creating iterators over their items. |
43 The UCX collections also define functions for creating iterators over their items. |
49 You can read more about them in the respective Sections of the documentation. |
44 You can read more about them in the respective Sections of the documentation. |
50 |
45 |
51 ## Using an Iterator |
46 ## Using an Iterator |
84 > but they can also iterate over just the values or just the keys. |
79 > but they can also iterate over just the values or just the keys. |
85 > |
80 > |
86 > You should read the documentation of the function creating the iterator to learn |
81 > You should read the documentation of the function creating the iterator to learn |
87 > what exactly the iterator is iterating over. |
82 > what exactly the iterator is iterating over. |
88 |
83 |
89 ## Mutating Iterators |
84 ## Removing Elements via Iterators |
90 |
85 |
91 Usually an iterator is not mutating the collection it is iterating over. |
86 Usually an iterator is not mutating the collection it is iterating over. |
92 But sometimes it is desirable to remove an element from the collection while iterating over it. |
87 But sometimes it is desirable to remove an element from the collection while iterating over it. |
93 |
88 |
94 For this purpose, most collections allow the creation of a _mutating_ iterator. |
89 For this purpose, most collections allow to use `cxIteratorFlagRemoval()`, which instructs the iterator to remove |
95 On mutating iterators the `mutating` flag in the base structure is set to `true`, |
90 the current element from the collection on the next call to `cxIteratorNext()`. |
96 and it is allowed to call the `cxFlagForRemoval()` function, which instructs the iterator to remove |
|
97 the current element from the collection on the next call to `cxIteratorNext()` and clear the flag afterward. |
|
98 If you are implementing your own iterator, it is up to you to implement this behavior. |
91 If you are implementing your own iterator, it is up to you to implement this behavior. |
99 |
92 |
100 ## Passing Iterators to Functions |
93 ## Passing Iterators to Functions |
101 |
94 |
102 To eliminate the need of memory management for iterators, the structures are usually used by value. |
95 To eliminate the need of memory management for iterators, the structures are usually used by value. |
125 The base structure is defined as follows: |
118 The base structure is defined as follows: |
126 ```C |
119 ```C |
127 struct cx_iterator_base_s { |
120 struct cx_iterator_base_s { |
128 bool (*valid)(const void *); |
121 bool (*valid)(const void *); |
129 void *(*current)(const void *); |
122 void *(*current)(const void *); |
|
123 void (*next)(void *); |
130 void *(*current_impl)(const void *); |
124 void *(*current_impl)(const void *); |
131 void (*next)(void *); |
125 void (*next_impl)(void *); |
132 bool mutating; |
126 bool allow_remove; |
133 bool remove; |
127 bool remove; |
134 }; |
128 }; |
135 |
129 |
136 typedef struct cx_iterator_base_s CxIteratorBase; |
130 typedef struct cx_iterator_base_s CxIteratorBase; |
137 ``` |
131 ``` |
138 |
132 |
139 The `valid` function indicates whether the iterator is currently pointing to an element in the collection. |
133 The `valid` function indicates whether the iterator is currently pointing to an element in the collection. |
140 The `current` function is supposed to return that element, |
134 The `current` function is supposed to return that element, |
141 and the `next` function shall advance the iterator to the next element. |
135 and the `next` function shall advance the iterator to the next element. |
142 The booleans `mutating` and `remove` are used for [mutating iterators](#mutating-iterators) as explained above. |
136 |
143 |
137 The booleans `allow_remove` and `remove` are used for [removing elements](#removing-elements-via-iterators) as explained above. |
144 Iterators may be wrapped in which case the original implementation can be stored in `current_impl` and |
138 When an iterator is created, the `allow_remove` field is set to indicate if removal of elements is supported. |
145 called by a wrapper implementation pointed to by `current`. |
139 The `remove` field is set to indicate if the current element should be removed on the next call to `next()` (see `cxIteratorFlagRemoval()`). |
|
140 |
|
141 Iterators may be wrapped in which case the original implementation can be stored in `current_impl` and `next_impl`. |
|
142 They can then be called by a wrapper implementation pointed to by `current` and `next`, respectively. |
146 This can be useful when you want to support the `store_pointer` field of the [](collection.h.md) API. |
143 This can be useful when you want to support the `store_pointer` field of the [](collection.h.md) API. |
147 |
144 |
148 A specialized, simple, and fast iterator over an array of a certain type |
145 A specialized, simple, and fast iterator over an array of a certain type |
149 that does not support mutation can be implemented as follows: |
146 that does not support removing elements can be implemented as follows: |
150 ```C |
147 ```C |
151 #include <cx/iterator.h> |
148 #include <cx/iterator.h> |
152 |
149 |
153 typedef struct my_foo_s { |
150 typedef struct my_foo_s { |
154 // ... your data ... |
151 // ... your data ... |
182 // base fields |
179 // base fields |
183 iter.base.valid = my_foo_iter_valid; |
180 iter.base.valid = my_foo_iter_valid; |
184 iter.base.current = my_foo_iter_current; |
181 iter.base.current = my_foo_iter_current; |
185 iter.base.next = my_foo_iter_next; |
182 iter.base.next = my_foo_iter_next; |
186 iter.base.remove = false; |
183 iter.base.remove = false; |
187 iter.base.mutating = false; |
184 iter.base.allow_remove = false; |
188 |
185 |
189 // custom fields |
186 // custom fields |
190 iter.index = 0; |
187 iter.index = 0; |
191 iter.elem_count = elem_count; |
188 iter.elem_count = elem_count; |
192 |
189 |