| 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
| 27 */ |
27 */ |
| 28 /** |
28 /** |
| 29 * \file iterator.h |
29 * @file iterator.h |
| 30 * \brief Interface for iterator implementations. |
30 * @brief Interface for iterator implementations. |
| 31 * \author Mike Becker |
31 * @author Mike Becker |
| 32 * \author Olaf Wintermann |
32 * @author Olaf Wintermann |
| 33 * \copyright 2-Clause BSD License |
33 * @copyright 2-Clause BSD License |
| 34 */ |
34 */ |
| 35 |
35 |
| 36 #ifndef UCX_ITERATOR_H |
36 #ifndef UCX_ITERATOR_H |
| 37 #define UCX_ITERATOR_H |
37 #define UCX_ITERATOR_H |
| 38 |
38 |
| 45 /** |
45 /** |
| 46 * Common data for all iterators. |
46 * Common data for all iterators. |
| 47 */ |
47 */ |
| 48 struct cx_iterator_base_s { |
48 struct cx_iterator_base_s { |
| 49 /** |
49 /** |
| 50 * True iff the iterator points to valid data. |
50 * True if the iterator points to valid data. |
| 51 */ |
51 */ |
| 52 cx_attr_nonnull |
|
| 53 bool (*valid)(const void *); |
52 bool (*valid)(const void *); |
| 54 |
53 |
| 55 /** |
54 /** |
| 56 * Returns a pointer to the current element. |
55 * Returns a pointer to the current element. |
| 57 * |
56 * |
| 58 * When valid returns false, the behavior of this function is undefined. |
57 * When valid returns false, the behavior of this function is undefined. |
| 59 */ |
58 */ |
| 60 cx_attr_nonnull |
|
| 61 cx_attr_nodiscard |
|
| 62 void *(*current)(const void *); |
59 void *(*current)(const void *); |
| 63 |
60 |
| 64 /** |
61 /** |
| 65 * Original implementation in case the function needs to be wrapped. |
62 * Original implementation in case the function needs to be wrapped. |
| 66 */ |
63 */ |
| 67 cx_attr_nonnull |
|
| 68 cx_attr_nodiscard |
|
| 69 void *(*current_impl)(const void *); |
64 void *(*current_impl)(const void *); |
| 70 |
65 |
| 71 /** |
66 /** |
| 72 * Advances the iterator. |
67 * Advances the iterator. |
| 73 * |
68 * |
| 74 * When valid returns false, the behavior of this function is undefined. |
69 * When valid returns false, the behavior of this function is undefined. |
| 75 */ |
70 */ |
| 76 cx_attr_nonnull |
|
| 77 void (*next)(void *); |
71 void (*next)(void *); |
| 78 /** |
72 /** |
| 79 * Indicates whether this iterator may remove elements. |
73 * Indicates whether this iterator may remove elements. |
| 80 */ |
74 */ |
| 81 bool mutating; |
75 bool mutating; |
| 82 /** |
76 /** |
| 83 * Internal flag for removing the current element when advancing. |
77 * Internal flag for removing the current element when advancing. |
| 84 */ |
78 */ |
| 85 bool remove; |
79 bool remove; |
| 86 }; |
80 }; |
| |
81 |
| |
82 /** |
| |
83 * Convenience type definition for the base structure of an iterator. |
| |
84 * @see #CX_ITERATOR_BASE |
| |
85 */ |
| |
86 typedef struct cx_iterator_base_s CxIteratorBase; |
| 87 |
87 |
| 88 /** |
88 /** |
| 89 * Declares base attributes for an iterator. |
89 * Declares base attributes for an iterator. |
| 90 * Must be the first member of an iterator structure. |
90 * Must be the first member of an iterator structure. |
| 91 */ |
91 */ |
| 118 */ |
118 */ |
| 119 const void *c; |
119 const void *c; |
| 120 } src_handle; |
120 } src_handle; |
| 121 |
121 |
| 122 /** |
122 /** |
| 123 * Field for storing a key-value pair. |
|
| 124 * May be used by iterators that iterate over k/v-collections. |
|
| 125 */ |
|
| 126 struct { |
|
| 127 /** |
|
| 128 * A pointer to the key. |
|
| 129 */ |
|
| 130 const void *key; |
|
| 131 /** |
|
| 132 * A pointer to the value. |
|
| 133 */ |
|
| 134 void *value; |
|
| 135 } kv_data; |
|
| 136 |
|
| 137 /** |
|
| 138 * Field for storing a slot number. |
|
| 139 * May be used by iterators that iterate over multi-bucket collections. |
|
| 140 */ |
|
| 141 size_t slot; |
|
| 142 |
|
| 143 /** |
|
| 144 * If the iterator is position-aware, contains the index of the element in the underlying collection. |
123 * If the iterator is position-aware, contains the index of the element in the underlying collection. |
| 145 * Otherwise, this field is usually uninitialized. |
124 * Otherwise, this field is usually uninitialized. |
| 146 */ |
125 */ |
| 147 size_t index; |
126 size_t index; |
| 148 |
127 |
| 164 * An iterator points to a certain element in a (possibly unbounded) chain of elements. |
143 * An iterator points to a certain element in a (possibly unbounded) chain of elements. |
| 165 * Iterators that are based on collections (which have a defined "first" element), are supposed |
144 * Iterators that are based on collections (which have a defined "first" element), are supposed |
| 166 * to be "position-aware", which means that they keep track of the current index within the collection. |
145 * to be "position-aware", which means that they keep track of the current index within the collection. |
| 167 * |
146 * |
| 168 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, |
147 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, |
| 169 * any concurrent mutation of the collection other than by this iterator makes this iterator invalid |
148 * any concurrent mutation of the collection other than by this iterator makes this iterator invalid, |
| 170 * and it must not be used anymore. |
149 * and it must not be used anymore. |
| 171 */ |
150 */ |
| 172 typedef struct cx_iterator_s CxIterator; |
151 typedef struct cx_iterator_s CxIterator; |
| 173 |
152 |
| 174 /** |
153 /** |
| 175 * Checks if the iterator points to valid data. |
154 * Checks if the iterator points to valid data. |
| 176 * |
155 * |
| 177 * This is especially false for past-the-end iterators. |
156 * @param iter the iterator |
| 178 * |
157 * @retval true if the iterator points to valid data |
| 179 * @param iter the iterator |
158 * @retval false if the iterator already moved past the end |
| 180 * @return true iff the iterator points to valid data |
|
| 181 */ |
159 */ |
| 182 #define cxIteratorValid(iter) (iter).base.valid(&(iter)) |
160 #define cxIteratorValid(iter) (iter).base.valid(&(iter)) |
| 183 |
161 |
| 184 /** |
162 /** |
| 185 * Returns a pointer to the current element. |
163 * Returns a pointer to the current element. |
| 186 * |
164 * |
| 187 * The behavior is undefined if this iterator is invalid. |
165 * The behavior is undefined if this iterator is invalid. |
| 188 * |
166 * |
| 189 * @param iter the iterator |
167 * @param iter the iterator |
| 190 * @return a pointer to the current element |
168 * @return a pointer to the current element |
| |
169 * @see cxIteratorValid() |
| 191 */ |
170 */ |
| 192 #define cxIteratorCurrent(iter) (iter).base.current(&iter) |
171 #define cxIteratorCurrent(iter) (iter).base.current(&iter) |
| 193 |
172 |
| 194 /** |
173 /** |
| 195 * Advances the iterator to the next element. |
174 * Advances the iterator to the next element. |
| 199 #define cxIteratorNext(iter) (iter).base.next(&iter) |
178 #define cxIteratorNext(iter) (iter).base.next(&iter) |
| 200 |
179 |
| 201 /** |
180 /** |
| 202 * Flags the current element for removal, if this iterator is mutating. |
181 * Flags the current element for removal, if this iterator is mutating. |
| 203 * |
182 * |
| |
183 * Does nothing for non-mutating iterators. |
| |
184 * |
| 204 * @param iter the iterator |
185 * @param iter the iterator |
| 205 */ |
186 */ |
| 206 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating |
187 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating |
| 207 |
188 |
| 208 /** |
189 /** |
| 209 * Obtains a reference to an arbitrary iterator. |
190 * Obtains a reference to an arbitrary iterator. |
| 210 * |
191 * |
| 211 * This is useful for APIs that expect some iterator as an argument. |
192 * This is useful for APIs that expect some iterator as an argument. |
| 212 * |
193 * |
| 213 * @param iter the iterator |
194 * @param iter the iterator |
| |
195 * @return (@c struct @c cx_iterator_base_s*) a pointer to the iterator |
| 214 */ |
196 */ |
| 215 #define cxIteratorRef(iter) &((iter).base) |
197 #define cxIteratorRef(iter) &((iter).base) |
| 216 |
198 |
| 217 /** |
199 /** |
| 218 * Loops over an iterator. |
200 * Loops over an iterator. |
| |
201 * |
| 219 * @param type the type of the elements |
202 * @param type the type of the elements |
| 220 * @param elem the name of the iteration variable |
203 * @param elem the name of the iteration variable |
| 221 * @param iter the iterator |
204 * @param iter the iterator |
| 222 */ |
205 */ |
| 223 #define cx_foreach(type, elem, iter) \ |
206 #define cx_foreach(type, elem, iter) \ |
| 225 |
208 |
| 226 |
209 |
| 227 /** |
210 /** |
| 228 * Creates an iterator for the specified plain array. |
211 * Creates an iterator for the specified plain array. |
| 229 * |
212 * |
| 230 * The \p array can be \c NULL in which case the iterator will be immediately |
213 * The @p array can be @c NULL in which case the iterator will be immediately |
| 231 * initialized such that #cxIteratorValid() returns \c false. |
214 * initialized such that #cxIteratorValid() returns @c false. |
| 232 * |
215 * |
| 233 * This iterator yields the addresses of the array elements. |
216 * This iterator yields the addresses of the array elements. |
| 234 * If you want to iterator over an array of pointers, you can |
217 * If you want to iterator over an array of pointers, you can |
| 235 * use cxIteratorPtr() to create an iterator which directly |
218 * use cxIteratorPtr() to create an iterator which directly |
| 236 * yields the stored pointers. |
219 * yields the stored pointers. |
| 237 * |
220 * |
| 238 * @param array a pointer to the array (can be \c NULL) |
221 * @param array a pointer to the array (can be @c NULL) |
| 239 * @param elem_size the size of one array element |
222 * @param elem_size the size of one array element |
| 240 * @param elem_count the number of elements in the array |
223 * @param elem_count the number of elements in the array |
| 241 * @return an iterator for the specified array |
224 * @return an iterator for the specified array |
| 242 * @see cxIteratorPtr() |
225 * @see cxIteratorPtr() |
| 243 */ |
226 */ |
| 244 cx_attr_nodiscard |
227 cx_attr_nodiscard |
| |
228 cx_attr_export |
| 245 CxIterator cxIterator( |
229 CxIterator cxIterator( |
| 246 const void *array, |
230 const void *array, |
| 247 size_t elem_size, |
231 size_t elem_size, |
| 248 size_t elem_count |
232 size_t elem_count |
| 249 ); |
233 ); |
| 253 * |
237 * |
| 254 * While the iterator is in use, the array may only be altered by removing |
238 * While the iterator is in use, the array may only be altered by removing |
| 255 * elements through #cxIteratorFlagRemoval(). Every other change to the array |
239 * elements through #cxIteratorFlagRemoval(). Every other change to the array |
| 256 * will bring this iterator to an undefined state. |
240 * will bring this iterator to an undefined state. |
| 257 * |
241 * |
| 258 * When \p remove_keeps_order is set to \c false, removing an element will only |
242 * When @p remove_keeps_order is set to @c false, removing an element will only |
| 259 * move the last element to the position of the removed element, instead of |
243 * move the last element to the position of the removed element, instead of |
| 260 * moving all subsequent elements by one. Usually, when the order of elements is |
244 * moving all subsequent elements by one. Usually, when the order of elements is |
| 261 * not important, this parameter should be set to \c false. |
245 * not important, this parameter should be set to @c false. |
| 262 * |
246 * |
| 263 * The \p array can be \c NULL in which case the iterator will be immediately |
247 * The @p array can be @c NULL in which case the iterator will be immediately |
| 264 * initialized such that #cxIteratorValid() returns \c false. |
248 * initialized such that #cxIteratorValid() returns @c false. |
| 265 * |
249 * |
| 266 * |
250 * |
| 267 * @param array a pointer to the array (can be \c NULL) |
251 * @param array a pointer to the array (can be @c NULL) |
| 268 * @param elem_size the size of one array element |
252 * @param elem_size the size of one array element |
| 269 * @param elem_count the number of elements in the array |
253 * @param elem_count the number of elements in the array |
| 270 * @param remove_keeps_order \c true if the order of elements must be preserved |
254 * @param remove_keeps_order @c true if the order of elements must be preserved |
| 271 * when removing an element |
255 * when removing an element |
| 272 * @return an iterator for the specified array |
256 * @return an iterator for the specified array |
| 273 */ |
257 */ |
| 274 cx_attr_nodiscard |
258 cx_attr_nodiscard |
| |
259 cx_attr_export |
| 275 CxIterator cxMutIterator( |
260 CxIterator cxMutIterator( |
| 276 void *array, |
261 void *array, |
| 277 size_t elem_size, |
262 size_t elem_size, |
| 278 size_t elem_count, |
263 size_t elem_count, |
| 279 bool remove_keeps_order |
264 bool remove_keeps_order |
| 285 * This iterator assumes that every element in the array is a pointer |
270 * This iterator assumes that every element in the array is a pointer |
| 286 * and yields exactly those pointers during iteration (while in contrast |
271 * and yields exactly those pointers during iteration (while in contrast |
| 287 * an iterator created with cxIterator() would return the addresses |
272 * an iterator created with cxIterator() would return the addresses |
| 288 * of those pointers within the array). |
273 * of those pointers within the array). |
| 289 * |
274 * |
| 290 * @param array a pointer to the array (can be \c NULL) |
275 * @param array a pointer to the array (can be @c NULL) |
| 291 * @param elem_count the number of elements in the array |
276 * @param elem_count the number of elements in the array |
| 292 * @return an iterator for the specified array |
277 * @return an iterator for the specified array |
| 293 * @see cxIterator() |
278 * @see cxIterator() |
| 294 */ |
279 */ |
| 295 cx_attr_nodiscard |
280 cx_attr_nodiscard |
| |
281 cx_attr_export |
| 296 CxIterator cxIteratorPtr( |
282 CxIterator cxIteratorPtr( |
| 297 const void *array, |
283 const void *array, |
| 298 size_t elem_count |
284 size_t elem_count |
| 299 ); |
285 ); |
| 300 |
286 |
| 302 * Creates a mutating iterator for the specified plain pointer array. |
288 * Creates a mutating iterator for the specified plain pointer array. |
| 303 * |
289 * |
| 304 * This is the mutating variant of cxIteratorPtr(). See also |
290 * This is the mutating variant of cxIteratorPtr(). See also |
| 305 * cxMutIterator(). |
291 * cxMutIterator(). |
| 306 * |
292 * |
| 307 * @param array a pointer to the array (can be \c NULL) |
293 * @param array a pointer to the array (can be @c NULL) |
| 308 * @param elem_count the number of elements in the array |
294 * @param elem_count the number of elements in the array |
| 309 * @param remove_keeps_order \c true if the order of elements must be preserved |
295 * @param remove_keeps_order @c true if the order of elements must be preserved |
| 310 * when removing an element |
296 * when removing an element |
| 311 * @return an iterator for the specified array |
297 * @return an iterator for the specified array |
| 312 * @see cxMutIterator() |
298 * @see cxMutIterator() |
| 313 * @see cxIteratorPtr() |
299 * @see cxIteratorPtr() |
| 314 */ |
300 */ |
| 315 cx_attr_nodiscard |
301 cx_attr_nodiscard |
| |
302 cx_attr_export |
| 316 CxIterator cxMutIteratorPtr( |
303 CxIterator cxMutIteratorPtr( |
| 317 void *array, |
304 void *array, |
| 318 size_t elem_count, |
305 size_t elem_count, |
| 319 bool remove_keeps_order |
306 bool remove_keeps_order |
| 320 ); |
307 ); |