ucx/cx/iterator.h

branch
ucx-3.1
changeset 816
839fefbdedc7
parent 776
96555c0ed875
equal deleted inserted replaced
815:1f40ca07ae1b 816:839fefbdedc7
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 * \version 3.0
34 * \copyright 2-Clause BSD License 33 * \copyright 2-Clause BSD License
35 */ 34 */
36 35
37 #ifndef UCX_ITERATOR_H 36 #ifndef UCX_ITERATOR_H
38 #define UCX_ITERATOR_H 37 #define UCX_ITERATOR_H
39 38
40 #include "common.h" 39 #include "common.h"
41 40
42 /**
43 * The base of mutating and non-mutating iterators.
44 */
45 struct cx_iterator_base_s { 41 struct cx_iterator_base_s {
46 /** 42 /**
47 * True iff the iterator points to valid data. 43 * True iff the iterator points to valid data.
48 */ 44 */
49 __attribute__ ((__nonnull__)) 45 __attribute__ ((__nonnull__))
68 * 64 *
69 * When valid returns false, the behavior of this function is undefined. 65 * When valid returns false, the behavior of this function is undefined.
70 */ 66 */
71 __attribute__ ((__nonnull__)) 67 __attribute__ ((__nonnull__))
72 void (*next)(void *); 68 void (*next)(void *);
73
74 /**
75 * Flag current element for removal, if possible.
76 *
77 * When valid returns false, the behavior of this function is undefined.
78 */
79 __attribute__ ((__nonnull__))
80 bool (*flag_removal)(void *);
81
82 /** 69 /**
83 * Indicates whether this iterator may remove elements. 70 * Indicates whether this iterator may remove elements.
84 */ 71 */
85 bool mutating; 72 bool mutating;
86
87 /** 73 /**
88 * Internal flag for removing the current element when advancing. 74 * Internal flag for removing the current element when advancing.
89 */ 75 */
90 bool remove; 76 bool remove;
91 }; 77 };
92 78
93 /** 79 /**
94 * Internal iterator struct - use CxMutIterator. 80 * Declares base attributes for an iterator.
95 */ 81 */
96 struct cx_mut_iterator_s { 82 #define CX_ITERATOR_BASE struct cx_iterator_base_s base
97 83
98 /** 84 /**
99 * The base properties of this iterator. 85 * Internal iterator struct - use CxIterator.
100 */ 86 */
101 struct cx_iterator_base_s base; 87 struct cx_iterator_s {
102 88 CX_ITERATOR_BASE;
103 /** 89
104 * Handle for the current element, if required. 90 /**
91 * Handle for the current element.
105 */ 92 */
106 void *elem_handle; 93 void *elem_handle;
107 94
108 /** 95 /**
109 * Handle for the source collection, if any. 96 * Handle for the source collection, if any.
110 */ 97 */
111 void *src_handle; 98 union {
99 /**
100 * Access for mutating iterators.
101 */
102 void *m;
103 /**
104 * Access for normal iterators.
105 */
106 void const *c;
107 } src_handle;
112 108
113 /** 109 /**
114 * Field for storing a key-value pair. 110 * Field for storing a key-value pair.
115 * May be used by iterators that iterate over k/v-collections. 111 * May be used by iterators that iterate over k/v-collections.
116 */ 112 */
134 /** 130 /**
135 * If the iterator is position-aware, contains the index of the element in the underlying collection. 131 * If the iterator is position-aware, contains the index of the element in the underlying collection.
136 * Otherwise, this field is usually uninitialized. 132 * Otherwise, this field is usually uninitialized.
137 */ 133 */
138 size_t index; 134 size_t index;
135
136 /**
137 * The size of an individual element.
138 */
139 size_t elem_size;
140
141 /**
142 * May contain the total number of elements, if known.
143 * Shall be set to \c SIZE_MAX when the total number is unknown during iteration.
144 */
145 size_t elem_count;
139 }; 146 };
140 147
141 /** 148 /**
142 * Mutating iterator value type. 149 * Iterator type.
143 * 150 *
144 * An iterator points to a certain element in an (possibly unbounded) chain of elements.
145 * Iterators that are based on collections (which have a defined "first" element), are supposed
146 * to be "position-aware", which means that they keep track of the current index within the collection.
147 *
148 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the
149 * iterator is based on a collection and the underlying collection is mutated by other means than this iterator
150 * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns)
151 * and MUST be re-obtained from the collection.
152 *
153 * @see CxIterator
154 */
155 typedef struct cx_mut_iterator_s CxMutIterator;
156
157 /**
158 * Internal iterator struct - use CxIterator.
159 */
160 struct cx_iterator_s {
161
162 /**
163 * The base properties of this iterator.
164 */
165 struct cx_iterator_base_s base;
166
167 /**
168 * Handle for the current element, if required.
169 */
170 void *elem_handle;
171
172 /**
173 * Handle for the source collection, if any.
174 */
175 void const *src_handle;
176
177 /**
178 * Field for storing a key-value pair.
179 * May be used by iterators that iterate over k/v-collections.
180 */
181 struct {
182 /**
183 * A pointer to the key.
184 */
185 void const *key;
186 /**
187 * A pointer to the value.
188 */
189 void *value;
190 } kv_data;
191
192 /**
193 * Field for storing a slot number.
194 * May be used by iterators that iterate over multi-bucket collections.
195 */
196 size_t slot;
197
198 /**
199 * If the iterator is position-aware, contains the index of the element in the underlying collection.
200 * Otherwise, this field is usually uninitialized.
201 */
202 size_t index;
203 };
204
205 /**
206 * Iterator value type.
207 * An iterator points to a certain element in a (possibly unbounded) chain of elements. 151 * An iterator points to a certain element in a (possibly unbounded) chain of elements.
208 * Iterators that are based on collections (which have a defined "first" element), are supposed 152 * Iterators that are based on collections (which have a defined "first" element), are supposed
209 * to be "position-aware", which means that they keep track of the current index within the collection. 153 * to be "position-aware", which means that they keep track of the current index within the collection.
210 * 154 *
211 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, 155 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However,
212 * this iterator cannot mutate the collection itself (add or remove elements) and any mutation of the 156 * any concurrent mutation of the collection other than by this iterator makes this iterator invalid
213 * collection by other means makes this iterator invalid (regardless of what cxIteratorValid() returns). 157 * and it must not be used anymore.
214 *
215 * @see CxMutIterator
216 */ 158 */
217 typedef struct cx_iterator_s CxIterator; 159 typedef struct cx_iterator_s CxIterator;
218 160
219 /** 161 /**
220 * Checks if the iterator points to valid data. 162 * Checks if the iterator points to valid data.
242 * @param iter the iterator 184 * @param iter the iterator
243 */ 185 */
244 #define cxIteratorNext(iter) (iter).base.next(&iter) 186 #define cxIteratorNext(iter) (iter).base.next(&iter)
245 187
246 /** 188 /**
247 * Flags the current element for removal. 189 * Flags the current element for removal, if this iterator is mutating.
248 * 190 *
249 * @param iter the iterator 191 * @param iter the iterator
250 * @return false if this iterator cannot remove the element 192 */
251 */ 193 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating
252 #define cxIteratorFlagRemoval(iter) (iter).base.flag_removal(&iter)
253 194
254 /** 195 /**
255 * Loops over an iterator. 196 * Loops over an iterator.
256 * @param type the type of the elements 197 * @param type the type of the elements
257 * @param elem the name of the iteration variable 198 * @param elem the name of the iteration variable
258 * @param iter the iterator 199 * @param iter the iterator
259 */ 200 */
260 #define cx_foreach(type, elem, iter) \ 201 #define cx_foreach(type, elem, iter) \
261 for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter)) 202 for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter))
262 203
204
205 /**
206 * Creates an iterator for the specified plain array.
207 *
208 * The \p array can be \c NULL in which case the iterator will be immediately
209 * initialized such that #cxIteratorValid() returns \c false.
210 *
211 *
212 * @param array a pointer to the array (can be \c NULL)
213 * @param elem_size the size of one array element
214 * @param elem_count the number of elements in the array
215 * @return an iterator for the specified array
216 */
217 __attribute__((__warn_unused_result__))
218 CxIterator cxIterator(
219 void const *array,
220 size_t elem_size,
221 size_t elem_count
222 );
223
224 /**
225 * Creates a mutating iterator for the specified plain array.
226 *
227 * While the iterator is in use, the array may only be altered by removing
228 * elements through #cxIteratorFlagRemoval(). Every other change to the array
229 * will bring this iterator to an undefined state.
230 *
231 * When \p remove_keeps_order is set to \c false, removing an element will only
232 * move the last element to the position of the removed element, instead of
233 * moving all subsequent elements by one. Usually, when the order of elements is
234 * not important, this parameter should be set to \c false.
235 *
236 * The \p array can be \c NULL in which case the iterator will be immediately
237 * initialized such that #cxIteratorValid() returns \c false.
238 *
239 *
240 * @param array a pointer to the array (can be \c NULL)
241 * @param elem_size the size of one array element
242 * @param elem_count the number of elements in the array
243 * @param remove_keeps_order \c true if the order of elements must be preserved
244 * when removing an element
245 * @return an iterator for the specified array
246 */
247 __attribute__((__warn_unused_result__))
248 CxIterator cxMutIterator(
249 void *array,
250 size_t elem_size,
251 size_t elem_count,
252 bool remove_keeps_order
253 );
254
263 #endif // UCX_ITERATOR_H 255 #endif // UCX_ITERATOR_H

mercurial