43 #ifdef __cplusplus |
43 #ifdef __cplusplus |
44 extern "C" { |
44 extern "C" { |
45 #endif |
45 #endif |
46 |
46 |
47 /** |
47 /** |
48 * When entering a node. |
|
49 * |
|
50 * When this is the first sibling, source is the parent, otherwise it is the previous child. |
|
51 */ |
|
52 #define CX_TREE_ITERATOR_ENTER 0x1 |
|
53 /** |
|
54 * When advancing to the next child. |
|
55 * |
|
56 * The visited node is the next child and the source is the previous child. |
|
57 * This pass is triggered after exiting the previous child and before entering the next child. |
|
58 */ |
|
59 #define CX_TREE_ITERATOR_NEXT_CHILD 0x2 |
|
60 /** |
|
61 * When exiting the node. |
|
62 * |
|
63 * The visited node is the node being exited and source is the previously entered node |
|
64 * (usually the last child of the exited node, unless it has no children, in which case it is the node itself). |
|
65 * When advancing to the next child in a list of siblings, the previous child is exited, first. |
|
66 */ |
|
67 #define CX_TREE_ITERATOR_EXIT 0x4 |
|
68 |
|
69 /** |
|
70 * Tree iterator. |
48 * Tree iterator. |
71 * |
49 * |
72 * This iterator is not position-aware in a strict sense, as it does not assume a particular order of elements in the |
50 * This iterator is not position-aware in a strict sense, as it does not assume a particular order of elements in the |
73 * tree. However, the iterator keeps track of the number of nodes it has passed in a counter variable. |
51 * tree. However, the iterator keeps track of the number of nodes it has passed in a counter variable. |
74 * Each node, regardless of the number of passes, is counted only once. |
52 * Each node, regardless of the number of passes, is counted only once. |
75 * |
53 * |
76 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the |
54 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the |
77 * iterator is based on a collection and the underlying collection is mutated by other means than this iterator |
55 * underlying data structure is mutated by other means than this iterator (e.g. elements added or removed), |
78 * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns) |
56 * the iterator becomes invalid (regardless of what cxIteratorValid() returns). |
79 * and MUST be re-obtained from the collection. |
|
80 * |
57 * |
81 * @see CxIterator |
58 * @see CxIterator |
82 */ |
59 */ |
83 typedef struct cx_tree_iterator_s { |
60 typedef struct cx_tree_iterator_s { |
84 /** |
61 /** |
85 * The base properties of this iterator. |
62 * The base properties of this iterator. |
86 */ |
63 */ |
87 struct cx_iterator_base_s base; |
64 struct cx_iterator_base_s base; |
88 /** |
65 /** |
89 * The passes that are requested by this iterator. |
66 * Set to true, when the iterator shall visit a node again |
90 * A combination of the flags #CX_TREE_ITERATOR_ENTER, #CX_TREE_ITERATOR_NEXT_CHILD, #CX_TREE_ITERATOR_EXIT. |
67 * when all it's children have been processed. |
91 * |
68 */ |
92 * Changing the value after beginning the iteration is unspecified. |
69 bool visit_on_exit; |
93 */ |
70 /** |
94 uint8_t requested_passes; |
71 * True, if this iterator is currently leaving the node. |
95 /** |
72 */ |
96 * The current pass. |
73 bool exiting; |
97 * |
|
98 * @see CX_TREE_ITERATOR_ENTER |
|
99 * @see CX_TREE_ITERATOR_NEXT_CHILD |
|
100 * @see CX_TREE_ITERATOR_EXIT |
|
101 */ |
|
102 uint8_t current_pass; |
|
103 /** |
74 /** |
104 * Offset in the node struct for the children linked list. |
75 * Offset in the node struct for the children linked list. |
105 */ |
76 */ |
106 off_t loc_children; |
77 off_t loc_children; |
107 /** |
78 /** |
116 * The currently observed node. |
87 * The currently observed node. |
117 * |
88 * |
118 * This is the same what cxIteratorCurrent() would return. |
89 * This is the same what cxIteratorCurrent() would return. |
119 */ |
90 */ |
120 void *node; |
91 void *node; |
121 /** |
|
122 * The node where we came from. |
|
123 * |
|
124 * - When entering the root node, this is \c NULL. |
|
125 * - When entering another node, this is the node's parent. |
|
126 * - When advancing to the next child, this is the previous child. |
|
127 */ |
|
128 void *source; |
|
129 /** |
92 /** |
130 * Internal stack. |
93 * Internal stack. |
131 * Will be automatically freed once the iterator becomes invalid. |
94 * Will be automatically freed once the iterator becomes invalid. |
132 * |
95 * |
133 * If you want to discard the iterator before, you need to manually |
96 * If you want to discard the iterator before, you need to manually |
259 ); |
228 ); |
260 |
229 |
261 /** |
230 /** |
262 * Creates an iterator for a tree with the specified root node. |
231 * Creates an iterator for a tree with the specified root node. |
263 * |
232 * |
264 * The \p passes argument is supposed to be a combination of the flags |
|
265 * #CX_TREE_ITERATOR_ENTER, #CX_TREE_ITERATOR_NEXT_CHILD, and #CX_TREE_ITERATOR_EXIT. |
|
266 * Alternatively, the integer 1 is equivalent to just specifying #CX_TREE_ITERATOR_ENTER |
|
267 * which will cause the iterator to pass every node only once (when entering the node). |
|
268 * |
|
269 * When #CX_TREE_ITERATOR_EXIT is set, the iterator will visit a parent node again, |
|
270 * when \em every of it's children has been visited (including the case when the node does not have any children). |
|
271 * |
|
272 * When #CX_TREE_ITERATOR_NEXT_CHILD is set, the iterator will visit a parent node again, |
|
273 * when advancing from one child to the next. |
|
274 * |
|
275 * @note A tree iterator needs to maintain a stack of visited nodes, which is allocated using stdlib malloc(). |
233 * @note A tree iterator needs to maintain a stack of visited nodes, which is allocated using stdlib malloc(). |
276 * When the iterator becomes invalid, this memory is automatically released. However, if you wish to cancel the |
234 * When the iterator becomes invalid, this memory is automatically released. However, if you wish to cancel the |
277 * iteration before the iterator becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release |
235 * iteration before the iterator becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release |
278 * the memory. |
236 * the memory. |
279 * |
237 * |
280 * @remark At the moment, the returned iterator does not support cxIteratorFlagRemoval(). |
238 * @remark At the moment, the returned iterator does not support cxIteratorFlagRemoval(). |
281 * |
239 * |
282 * @param root the root node |
240 * @param root the root node |
283 * @param passes the passes this iterator shall perform |
241 * @param visit_on_exit set to true, when the iterator shall visit a node again after processing all children |
284 * @param loc_children offset in the node struct for the children linked list |
242 * @param loc_children offset in the node struct for the children linked list |
285 * @param loc_next offset in the node struct for the next pointer |
243 * @param loc_next offset in the node struct for the next pointer |
286 * @return the new tree iterator |
244 * @return the new tree iterator |
287 * @see cxTreeIteratorDispose() |
245 * @see cxTreeIteratorDispose() |
288 */ |
246 */ |
289 __attribute__((__nonnull__)) |
247 __attribute__((__nonnull__)) |
290 CxTreeIterator cx_tree_iterator( |
248 CxTreeIterator cx_tree_iterator( |
291 void *root, |
249 void *root, |
292 int passes, |
250 bool visit_on_exit, |
293 ptrdiff_t loc_children, |
251 ptrdiff_t loc_children, |
294 ptrdiff_t loc_next |
252 ptrdiff_t loc_next |
295 ); |
253 ); |
296 |
254 |
297 #ifdef __cplusplus |
255 #ifdef __cplusplus |