38 #define UCX_ITERATOR_H |
38 #define UCX_ITERATOR_H |
39 |
39 |
40 #include "common.h" |
40 #include "common.h" |
41 |
41 |
42 /** |
42 /** |
43 * Internal iterator struct - use CxIterator. |
43 * The base of mutating and non-mutating iterators. |
44 */ |
44 */ |
45 struct cx_iterator_s { |
45 struct cx_iterator_base_s { |
46 /** |
46 /** |
47 * True iff the iterator points to valid data. |
47 * True iff the iterator points to valid data. |
48 */ |
48 */ |
49 __attribute__ ((__nonnull__)) |
49 __attribute__ ((__nonnull__)) |
50 bool (*valid)(struct cx_iterator_s const *); |
50 bool (*valid)(void const *); |
51 |
51 |
52 /** |
52 /** |
53 * Returns a pointer to the current element. |
53 * Returns a pointer to the current element. |
54 */ |
54 */ |
55 __attribute__ ((__nonnull__)) |
55 __attribute__ ((__nonnull__)) |
56 void *(*current)(struct cx_iterator_s const *); |
56 void *(*current)(void const *); |
57 |
57 |
58 /** |
58 /** |
59 * Advances the iterator. |
59 * Advances the iterator. |
60 */ |
60 */ |
61 __attribute__ ((__nonnull__)) |
61 __attribute__ ((__nonnull__)) |
62 void (*next)(struct cx_iterator_s *); |
62 void (*next)(void *); |
|
63 |
|
64 /** |
|
65 * Flag current element for removal, if possible. |
|
66 */ |
|
67 __attribute__ ((__nonnull__)) |
|
68 bool (*flag_removal)(void *); |
|
69 |
|
70 /** |
|
71 * Indicates whether this iterator is muting. |
|
72 */ |
|
73 bool mutating; |
|
74 |
|
75 /** |
|
76 * Internal flag for removing the current element when advancing. |
|
77 */ |
|
78 bool remove; |
|
79 }; |
|
80 |
|
81 /** |
|
82 * Internal iterator struct - use CxMutIterator. |
|
83 */ |
|
84 struct cx_mut_iterator_s { |
|
85 |
|
86 /** |
|
87 * The base properties of this iterator. |
|
88 */ |
|
89 struct cx_iterator_base_s base; |
63 |
90 |
64 /** |
91 /** |
65 * Handle for the current element, if required. |
92 * Handle for the current element, if required. |
66 */ |
93 */ |
67 void *elem_handle; |
94 void *elem_handle; |
95 /** |
122 /** |
96 * 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. |
97 * Otherwise, this field is usually uninitialized. |
124 * Otherwise, this field is usually uninitialized. |
98 */ |
125 */ |
99 size_t index; |
126 size_t index; |
100 |
127 }; |
101 /** |
128 |
102 * Users may set this to true, if the current element shall be removed from the underlying collection |
129 /** |
103 * when the iterator advances. |
130 * Mutating iterator value type. |
104 * Has no effect on iterators that are not based on a collection. |
131 * |
105 */ |
132 * An iterator points to a certain element in an (possibly unbounded) chain of elements. |
106 bool remove; |
133 * Iterators that are based on collections (which have a defined "first" element), are supposed |
|
134 * to be "position-aware", which means that they keep track of the current index within the collection. |
|
135 * |
|
136 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the |
|
137 * iterator is based on a collection and the underlying collection is mutated by other means than this iterator |
|
138 * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns) |
|
139 * and MUST be re-obtained from the collection. |
|
140 * |
|
141 * @see CxIterator |
|
142 */ |
|
143 typedef struct cx_mut_iterator_s CxMutIterator; |
|
144 |
|
145 /** |
|
146 * Internal iterator struct - use CxIterator. |
|
147 */ |
|
148 struct cx_iterator_s { |
|
149 |
|
150 /** |
|
151 * The base properties of this iterator. |
|
152 */ |
|
153 struct cx_iterator_base_s base; |
|
154 |
|
155 /** |
|
156 * Handle for the current element, if required. |
|
157 */ |
|
158 void *elem_handle; |
|
159 |
|
160 /** |
|
161 * Handle for the source collection, if any. |
|
162 */ |
|
163 void const *src_handle; |
|
164 |
|
165 /** |
|
166 * Field for storing a key-value pair. |
|
167 * May be used by iterators that iterate over k/v-collections. |
|
168 */ |
|
169 struct { |
|
170 /** |
|
171 * A pointer to the key. |
|
172 */ |
|
173 void const *key; |
|
174 /** |
|
175 * A pointer to the value. |
|
176 */ |
|
177 void *value; |
|
178 } kv_data; |
|
179 |
|
180 /** |
|
181 * Field for storing a slot number. |
|
182 * May be used by iterators that iterate over multi-bucket collections. |
|
183 */ |
|
184 size_t slot; |
|
185 |
|
186 /** |
|
187 * If the iterator is position-aware, contains the index of the element in the underlying collection. |
|
188 * Otherwise, this field is usually uninitialized. |
|
189 */ |
|
190 size_t index; |
107 }; |
191 }; |
108 |
192 |
109 /** |
193 /** |
110 * Iterator value type. |
194 * Iterator value type. |
111 * An iterator points to a certain element in an (possibly unbounded) chain of elements. |
195 * An iterator points to a certain element in an (possibly unbounded) chain of elements. |
112 * Iterators that are based on collections (which have a defined "first" element), are supposed |
196 * Iterators that are based on collections (which have a defined "first" element), are supposed |
113 * to be "position-aware", which means that they keep track of the current index within the collection. |
197 * to be "position-aware", which means that they keep track of the current index within the collection. |
114 * |
198 * |
115 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the |
199 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, |
116 * iterator is based on a collection and the underlying collection is mutated (elements added or removed), |
200 * this iterator cannot mutate the collection itself (add or remove elements) and any mutation of the |
117 * the iterator becomes invalid (regardless of what cxIteratorValid() returns) and MUST be re-obtained |
201 * collection by other means make this iterator invalid (regardless of what cxIteratorValid() returns). |
118 * from the collection. |
202 * |
|
203 * @see CxMutIterator |
119 */ |
204 */ |
120 typedef struct cx_iterator_s CxIterator; |
205 typedef struct cx_iterator_s CxIterator; |
121 |
206 |
122 /** |
207 /** |
123 * Checks if the iterator points to valid data. |
208 * Checks if the iterator points to valid data. |
124 * |
209 * |
125 * This is especially false for past-the-end iterators. |
210 * This is especially false for past-the-end iterators. |
126 * |
211 * |
127 * @param iter a pointer to the iterator |
212 * @param iter the iterator |
128 * @return true iff the iterator points to valid data |
213 * @return true iff the iterator points to valid data |
129 */ |
214 */ |
130 __attribute__ ((__nonnull__)) |
215 #define cxIteratorValid(iter) (iter).base.valid(&(iter)) |
131 static inline bool cxIteratorValid(CxIterator const *iter) { |
|
132 return iter->valid(iter); |
|
133 } |
|
134 |
216 |
135 /** |
217 /** |
136 * Returns a pointer to the current element. |
218 * Returns a pointer to the current element. |
137 * |
219 * |
138 * The behavior is undefined if this iterator is invalid. |
220 * The behavior is undefined if this iterator is invalid. |
139 * |
221 * |
140 * @param iter a pointer to the iterator |
222 * @param iter the iterator |
141 * @return a pointer to the current element |
223 * @return a pointer to the current element |
142 */ |
224 */ |
143 __attribute__ ((__nonnull__)) |
225 #define cxIteratorCurrent(iter) (iter).base.current(&iter) |
144 static inline void *cxIteratorCurrent(CxIterator const *iter) { |
|
145 return iter->current(iter); |
|
146 } |
|
147 |
226 |
148 /** |
227 /** |
149 * Advances the iterator to the next element. |
228 * Advances the iterator to the next element. |
150 * |
229 * |
151 * @param iter a pointer to the iterator |
230 * @param iter the iterator |
152 */ |
231 */ |
153 __attribute__ ((__nonnull__)) |
232 #define cxIteratorNext(iter) (iter).base.next(&iter) |
154 static inline void cxIteratorNext(CxIterator *iter) { |
233 |
155 iter->next(iter); |
234 /** |
156 } |
235 * Flags the current element for removal. |
|
236 * |
|
237 * @param iter the iterator |
|
238 * @return false if this iterator cannot remove the element |
|
239 */ |
|
240 #define cxIteratorFlagRemoval(iter) (iter).base.flag_removal(&iter) |
157 |
241 |
158 /** |
242 /** |
159 * Loops over an iterator. |
243 * Loops over an iterator. |
160 * @param type the type of the elements |
244 * @param type the type of the elements |
161 * @param elem the name of the iteration variable |
245 * @param elem the name of the iteration variable |
162 * @param iter the iterator |
246 * @param iter the iterator |
163 */ |
247 */ |
164 #define cx_foreach(type, elem, iter) \ |
248 #define cx_foreach(type, elem, iter) \ |
165 for (type elem; cxIteratorValid(&iter) && (elem = (type)cxIteratorCurrent(&iter)) != NULL ; cxIteratorNext(&iter)) // NOLINT(bugprone-macro-parentheses) |
249 for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter)) |
166 |
250 |
167 #endif // UCX_ITERATOR_H |
251 #endif // UCX_ITERATOR_H |