36 #ifndef UCX_ITERATOR_H |
36 #ifndef UCX_ITERATOR_H |
37 #define UCX_ITERATOR_H |
37 #define UCX_ITERATOR_H |
38 |
38 |
39 #include "common.h" |
39 #include "common.h" |
40 |
40 |
41 /** |
41 #define CX_ITERATOR_BASE \ |
42 * The base of mutating and non-mutating iterators. |
42 /** \ |
43 */ |
43 * True iff the iterator points to valid data. \ |
44 struct cx_iterator_base_s { |
44 */ \ |
45 /** |
45 __attribute__ ((__nonnull__)) \ |
46 * True iff the iterator points to valid data. |
46 bool (*valid)(void const *); \ |
47 */ |
47 /** \ |
48 __attribute__ ((__nonnull__)) |
48 * Returns a pointer to the current element. \ |
49 bool (*valid)(void const *); |
49 * \ |
50 |
50 * When valid returns false, the behavior of this function is undefined. \ |
51 /** |
51 */ \ |
52 * Returns a pointer to the current element. |
52 __attribute__ ((__nonnull__)) \ |
53 * |
53 void *(*current)(void const *); \ |
54 * When valid returns false, the behavior of this function is undefined. |
54 /** \ |
55 */ |
55 * Original implementation in case the function needs to be wrapped. \ |
56 __attribute__ ((__nonnull__)) |
56 */ \ |
57 void *(*current)(void const *); |
57 __attribute__ ((__nonnull__)) \ |
58 |
58 void *(*current_impl)(void const *); \ |
59 /** |
59 /** \ |
60 * Original implementation in case the function needs to be wrapped. |
60 * Advances the iterator. \ |
61 */ |
61 * \ |
62 __attribute__ ((__nonnull__)) |
62 * When valid returns false, the behavior of this function is undefined. \ |
63 void *(*current_impl)(void const *); |
63 */ \ |
64 |
64 __attribute__ ((__nonnull__)) \ |
65 /** |
65 void (*next)(void *); \ |
66 * Advances the iterator. |
66 /** \ |
67 * |
67 * Indicates whether this iterator may remove elements. \ |
68 * When valid returns false, the behavior of this function is undefined. |
68 */ \ |
69 */ |
69 bool mutating; \ |
70 __attribute__ ((__nonnull__)) |
70 /** \ |
71 void (*next)(void *); |
71 * Internal flag for removing the current element when advancing. \ |
72 |
72 */ \ |
73 /** |
|
74 * Indicates whether this iterator may remove elements. |
|
75 */ |
|
76 bool mutating; |
|
77 |
|
78 /** |
|
79 * Internal flag for removing the current element when advancing. |
|
80 */ |
|
81 bool remove; |
73 bool remove; |
82 }; |
74 |
83 |
75 /** |
84 /** |
76 * Internal iterator struct - use CxIterator. |
85 * Internal iterator struct - use CxMutIterator. |
77 */ |
86 */ |
78 struct cx_iterator_s { |
87 struct cx_mut_iterator_s { |
79 CX_ITERATOR_BASE |
88 |
80 |
89 /** |
81 /** |
90 * The base properties of this iterator. |
82 * Handle for the current element. |
91 */ |
|
92 struct cx_iterator_base_s base; |
|
93 |
|
94 /** |
|
95 * Handle for the current element, if required. |
|
96 */ |
83 */ |
97 void *elem_handle; |
84 void *elem_handle; |
98 |
85 |
99 /** |
86 /** |
100 * Handle for the source collection, if any. |
87 * Handle for the source collection, if any. |
101 */ |
88 */ |
102 void *src_handle; |
89 union { |
|
90 /** |
|
91 * Access for mutating iterators. |
|
92 */ |
|
93 void *m; |
|
94 /** |
|
95 * Access for normal iterators. |
|
96 */ |
|
97 void const *c; |
|
98 } src_handle; |
103 |
99 |
104 /** |
100 /** |
105 * Field for storing a key-value pair. |
101 * Field for storing a key-value pair. |
106 * May be used by iterators that iterate over k/v-collections. |
102 * May be used by iterators that iterate over k/v-collections. |
107 */ |
103 */ |
139 */ |
135 */ |
140 size_t elem_count; |
136 size_t elem_count; |
141 }; |
137 }; |
142 |
138 |
143 /** |
139 /** |
144 * Mutating iterator value type. |
140 * Iterator type. |
145 * |
141 * |
146 * An iterator points to a certain element in an (possibly unbounded) chain of elements. |
|
147 * Iterators that are based on collections (which have a defined "first" element), are supposed |
|
148 * to be "position-aware", which means that they keep track of the current index within the collection. |
|
149 * |
|
150 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the |
|
151 * iterator is based on a collection and the underlying collection is mutated by other means than this iterator |
|
152 * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns) |
|
153 * and MUST be re-obtained from the collection. |
|
154 * |
|
155 * @see CxIterator |
|
156 */ |
|
157 typedef struct cx_mut_iterator_s CxMutIterator; |
|
158 |
|
159 /** |
|
160 * Internal iterator struct - use CxIterator. |
|
161 */ |
|
162 struct cx_iterator_s { |
|
163 |
|
164 /** |
|
165 * The base properties of this iterator. |
|
166 */ |
|
167 struct cx_iterator_base_s base; |
|
168 |
|
169 /** |
|
170 * Handle for the current element, if required. |
|
171 */ |
|
172 void *elem_handle; |
|
173 |
|
174 /** |
|
175 * Handle for the source collection, if any. |
|
176 */ |
|
177 void const *src_handle; |
|
178 |
|
179 /** |
|
180 * Field for storing a key-value pair. |
|
181 * May be used by iterators that iterate over k/v-collections. |
|
182 */ |
|
183 struct { |
|
184 /** |
|
185 * A pointer to the key. |
|
186 */ |
|
187 void const *key; |
|
188 /** |
|
189 * A pointer to the value. |
|
190 */ |
|
191 void *value; |
|
192 } kv_data; |
|
193 |
|
194 /** |
|
195 * Field for storing a slot number. |
|
196 * May be used by iterators that iterate over multi-bucket collections. |
|
197 */ |
|
198 size_t slot; |
|
199 |
|
200 /** |
|
201 * If the iterator is position-aware, contains the index of the element in the underlying collection. |
|
202 * Otherwise, this field is usually uninitialized. |
|
203 */ |
|
204 size_t index; |
|
205 |
|
206 /** |
|
207 * The size of an individual element. |
|
208 */ |
|
209 size_t elem_size; |
|
210 |
|
211 /** |
|
212 * May contain the total number of elements, if known. |
|
213 * Shall be set to \c SIZE_MAX when the total number is unknown during iteration. |
|
214 */ |
|
215 size_t elem_count; |
|
216 }; |
|
217 |
|
218 /** |
|
219 * Iterator value type. |
|
220 * An iterator points to a certain element in a (possibly unbounded) chain of elements. |
142 * An iterator points to a certain element in a (possibly unbounded) chain of elements. |
221 * Iterators that are based on collections (which have a defined "first" element), are supposed |
143 * Iterators that are based on collections (which have a defined "first" element), are supposed |
222 * to be "position-aware", which means that they keep track of the current index within the collection. |
144 * to be "position-aware", which means that they keep track of the current index within the collection. |
223 * |
145 * |
224 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, |
146 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, |
225 * this iterator cannot mutate the collection itself (add or remove elements) and any mutation of the |
147 * any concurrent mutation of the collection other than by this iterator makes this iterator invalid |
226 * collection by other means makes this iterator invalid (regardless of what cxIteratorValid() returns). |
148 * and it must not be used anymore. |
227 * |
|
228 * @see CxMutIterator |
|
229 */ |
149 */ |
230 typedef struct cx_iterator_s CxIterator; |
150 typedef struct cx_iterator_s CxIterator; |
231 |
151 |
232 /** |
152 /** |
233 * Checks if the iterator points to valid data. |
153 * Checks if the iterator points to valid data. |
235 * This is especially false for past-the-end iterators. |
155 * This is especially false for past-the-end iterators. |
236 * |
156 * |
237 * @param iter the iterator |
157 * @param iter the iterator |
238 * @return true iff the iterator points to valid data |
158 * @return true iff the iterator points to valid data |
239 */ |
159 */ |
240 #define cxIteratorValid(iter) (iter).base.valid(&(iter)) |
160 #define cxIteratorValid(iter) (iter).valid(&(iter)) |
241 |
161 |
242 /** |
162 /** |
243 * Returns a pointer to the current element. |
163 * Returns a pointer to the current element. |
244 * |
164 * |
245 * The behavior is undefined if this iterator is invalid. |
165 * The behavior is undefined if this iterator is invalid. |
246 * |
166 * |
247 * @param iter the iterator |
167 * @param iter the iterator |
248 * @return a pointer to the current element |
168 * @return a pointer to the current element |
249 */ |
169 */ |
250 #define cxIteratorCurrent(iter) (iter).base.current(&iter) |
170 #define cxIteratorCurrent(iter) (iter).current(&iter) |
251 |
171 |
252 /** |
172 /** |
253 * Advances the iterator to the next element. |
173 * Advances the iterator to the next element. |
254 * |
174 * |
255 * @param iter the iterator |
175 * @param iter the iterator |
256 */ |
176 */ |
257 #define cxIteratorNext(iter) (iter).base.next(&iter) |
177 #define cxIteratorNext(iter) (iter).next(&iter) |
258 |
178 |
259 /** |
179 /** |
260 * Flags the current element for removal, if this iterator is mutating. |
180 * Flags the current element for removal, if this iterator is mutating. |
261 * |
181 * |
262 * @param iter the iterator |
182 * @param iter the iterator |
263 */ |
183 */ |
264 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating |
184 #define cxIteratorFlagRemoval(iter) (iter).remove |= (iter).mutating |
265 |
185 |
266 /** |
186 /** |
267 * Loops over an iterator. |
187 * Loops over an iterator. |
268 * @param type the type of the elements |
188 * @param type the type of the elements |
269 * @param elem the name of the iteration variable |
189 * @param elem the name of the iteration variable |
314 * @param remove_keeps_order \c true if the order of elements must be preserved |
234 * @param remove_keeps_order \c true if the order of elements must be preserved |
315 * when removing an element |
235 * when removing an element |
316 * @return an iterator for the specified array |
236 * @return an iterator for the specified array |
317 */ |
237 */ |
318 __attribute__((__warn_unused_result__)) |
238 __attribute__((__warn_unused_result__)) |
319 CxMutIterator cxMutIterator( |
239 CxIterator cxMutIterator( |
320 void *array, |
240 void *array, |
321 size_t elem_size, |
241 size_t elem_size, |
322 size_t elem_count, |
242 size_t elem_count, |
323 bool remove_keeps_order |
243 bool remove_keeps_order |
324 ); |
244 ); |