src/cx/tree.h

changeset 845
2615317311b7
parent 840
4f02995ce44e
child 848
6456036bbb37
equal deleted inserted replaced
844:3270ea9e41ef 845:2615317311b7
43 #ifdef __cplusplus 43 #ifdef __cplusplus
44 extern "C" { 44 extern "C" {
45 #endif 45 #endif
46 46
47 /** 47 /**
48 * Tree iterator. 48 * A depth-first tree iterator.
49 * 49 *
50 * 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
51 * 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.
52 * 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.
53 * 53 *
72 */ 72 */
73 bool exiting; 73 bool exiting;
74 /** 74 /**
75 * Offset in the node struct for the children linked list. 75 * Offset in the node struct for the children linked list.
76 */ 76 */
77 off_t loc_children; 77 ptrdiff_t loc_children;
78 /** 78 /**
79 * Offset in the node struct for the next pointer. 79 * Offset in the node struct for the next pointer.
80 */ 80 */
81 off_t loc_next; 81 ptrdiff_t loc_next;
82 /** 82 /**
83 * The total number of distinct nodes that have been passed so far. 83 * The total number of distinct nodes that have been passed so far.
84 */ 84 */
85 size_t counter; 85 size_t counter;
86 /** 86 /**
117 size_t depth; 117 size_t depth;
118 }; 118 };
119 } CxTreeIterator; 119 } CxTreeIterator;
120 120
121 /** 121 /**
122 * An element in a visitor queue.
123 */
124 struct cx_tree_visitor_queue_s {
125 /**
126 * The tree node to visit.
127 */
128 void *node;
129 /**
130 * The depth of the node.
131 */
132 size_t depth;
133 /**
134 * The next element in the queue or \c NULL.
135 */
136 struct cx_tree_visitor_queue_s *next;
137 };
138
139 /**
140 * A breadth-first tree iterator.
141 *
142 * This iterator needs to maintain a visitor queue that will be automatically freed once the iterator becomes invalid.
143 * If you want to discard the iterator before, you MUST manually call cxTreeVisitorDispose().
144 *
145 * This iterator is not position-aware in a strict sense, as it does not assume a particular order of elements in the
146 * tree. However, the iterator keeps track of the number of nodes it has passed in a counter variable.
147 * Each node, regardless of the number of passes, is counted only once.
148 *
149 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the
150 * underlying data structure is mutated by other means than this iterator (e.g. elements added or removed),
151 * the iterator becomes invalid (regardless of what cxIteratorValid() returns).
152 *
153 * @see CxIterator
154 */
155 typedef struct cx_tree_visitor_s {
156 /**
157 * The base properties of this iterator.
158 */
159 struct cx_iterator_base_s base;
160 /**
161 * Offset in the node struct for the children linked list.
162 */
163 ptrdiff_t loc_children;
164 /**
165 * Offset in the node struct for the next pointer.
166 */
167 ptrdiff_t loc_next;
168 /**
169 * The total number of distinct nodes that have been passed so far.
170 */
171 size_t counter;
172 /**
173 * The currently observed node.
174 *
175 * This is the same what cxIteratorCurrent() would return.
176 */
177 void *node;
178 /**
179 * The current depth in the tree.
180 */
181 size_t depth;
182 /**
183 * The next element in the visitor queue.
184 */
185 struct cx_tree_visitor_queue_s *queue_next;
186 /**
187 * The last element in the visitor queue.
188 */
189 struct cx_tree_visitor_queue_s *queue_last;
190 } CxTreeVisitor;
191
192 /**
122 * Releases internal memory of the given tree iterator. 193 * Releases internal memory of the given tree iterator.
123 * @param iter the iterator 194 * @param iter the iterator
124 */ 195 */
196 __attribute__((__nonnull__))
125 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) { 197 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
126 free(iter->stack); 198 free(iter->stack);
127 iter->stack = NULL; 199 iter->stack = NULL;
128 } 200 }
129 201
130 /** 202 /**
203 * Releases internal memory of the given tree visitor.
204 * @param visitor the visitor
205 */
206 __attribute__((__nonnull__))
207 static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
208 struct cx_tree_visitor_queue_s *q = visitor->queue_next;
209 while (q != NULL) {
210 struct cx_tree_visitor_queue_s *next = q->next;
211 free(q);
212 q = next;
213 }
214 }
215
216 /**
131 * Links a node to a (new) parent. 217 * Links a node to a (new) parent.
132 * 218 *
133 * If the node has already a parent, it is unlinked, first. 219 * If the node has already a parent, it is unlinked, first.
134 * If the parent has children already, the node is prepended to the list 220 * If the parent has children already, the node is \em prepended to the list
135 * of all currently existing children. 221 * of all currently existing children.
136 * 222 *
137 * @param parent the parent node 223 * @param parent the parent node
138 * @param node the node that shall be linked 224 * @param node the node that shall be linked
139 * @param loc_parent offset in the node struct for the parent pointer 225 * @param loc_parent offset in the node struct for the parent pointer
232 ptrdiff_t loc_children, 318 ptrdiff_t loc_children,
233 ptrdiff_t loc_next 319 ptrdiff_t loc_next
234 ); 320 );
235 321
236 /** 322 /**
237 * Creates an iterator for a tree with the specified root node. 323 * Creates a depth-first iterator for a tree with the specified root node.
238 * 324 *
239 * @note A tree iterator needs to maintain a stack of visited nodes, which is allocated using stdlib malloc(). 325 * @note A tree iterator needs to maintain a stack of visited nodes, which is allocated using stdlib malloc().
240 * When the iterator becomes invalid, this memory is automatically released. However, if you wish to cancel the 326 * When the iterator becomes invalid, this memory is automatically released. However, if you wish to cancel the
241 * iteration before the iterator becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release 327 * iteration before the iterator becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release
242 * the memory. 328 * the memory.
243 * 329 *
244 * @remark At the moment, the returned iterator does not support cxIteratorFlagRemoval(). 330 * @remark The returned iterator does not support cxIteratorFlagRemoval().
245 * 331 *
246 * @param root the root node 332 * @param root the root node
247 * @param visit_on_exit set to true, when the iterator shall visit a node again after processing all children 333 * @param visit_on_exit set to true, when the iterator shall visit a node again after processing all children
248 * @param loc_children offset in the node struct for the children linked list 334 * @param loc_children offset in the node struct for the children linked list
249 * @param loc_next offset in the node struct for the next pointer 335 * @param loc_next offset in the node struct for the next pointer
256 bool visit_on_exit, 342 bool visit_on_exit,
257 ptrdiff_t loc_children, 343 ptrdiff_t loc_children,
258 ptrdiff_t loc_next 344 ptrdiff_t loc_next
259 ); 345 );
260 346
347 /**
348 * Creates a breadth-first iterator for a tree with the specified root node.
349 *
350 * @note A tree visitor needs to maintain a queue of to be visited nodes, which is allocated using stdlib malloc().
351 * When the visitor becomes invalid, this memory is automatically released. However, if you wish to cancel the
352 * iteration before the visitor becomes invalid by itself, you MUST call cxTreeVisitorDispose() manually to release
353 * the memory.
354 *
355 * @remark The returned iterator does not support cxIteratorFlagRemoval().
356 *
357 * @param root the root node
358 * @param loc_children offset in the node struct for the children linked list
359 * @param loc_next offset in the node struct for the next pointer
360 * @return the new tree visitor
361 * @see cxTreeVisitorDispose()
362 */
363 __attribute__((__nonnull__))
364 CxTreeVisitor cx_tree_visitor(
365 void *root,
366 ptrdiff_t loc_children,
367 ptrdiff_t loc_next
368 );
369
261 #ifdef __cplusplus 370 #ifdef __cplusplus
262 } // extern "C" 371 } // extern "C"
263 #endif 372 #endif
264 373
265 #endif //UCX_TREE_H 374 #endif //UCX_TREE_H

mercurial