| 137 void cxTreeSetParent(CxTree *tree, void *parent, void *child); |
137 void cxTreeSetParent(CxTree *tree, void *parent, void *child); |
| 138 |
138 |
| 139 void *cxTreeSetRoot(CxTree *tree, void *root); |
139 void *cxTreeSetRoot(CxTree *tree, void *root); |
| 140 ``` |
140 ``` |
| 141 |
141 |
| |
142 The above functions are used to add nodes to a tree. |
| |
143 |
| 142 The low-level function `cx_tree_add()` adds a `node` to a new `parent`, unlinking it from its previous parent, if required. |
144 The low-level function `cx_tree_add()` adds a `node` to a new `parent`, unlinking it from its previous parent, if required. |
| 143 |
145 |
| 144 When you have created a high-level tree that is still empty, you can create a root node with `cxTreeCreateRoot()` or `cxTreeCreateRootData()`. |
146 When you have created a high-level tree that is still empty, you can create a root node with `cxTreeCreateRoot()` or `cxTreeCreateRootData()`. |
| 145 Both functions return an existing root node, if present, and `NULL` when the allocation of a new node failed. |
147 Both functions return an existing root node, if present, and `NULL` when the allocation of a new node failed. |
| 146 |
148 |
| 147 The functions `cxTreeAddData()`, `cxTreeAddNode()`, and `cxTreeSetParent()` are similar to `cx_tree_add()`. |
149 The functions `cxTreeAddData()`, `cxTreeAddNode()`, and `cxTreeSetParent()` are similar to `cx_tree_add()`. |
| 148 The difference between `cxTreeAddData()` and `cxTreeAddNode()` is, |
150 The difference between `cxTreeAddData()` and `cxTreeAddNode()` is |
| 149 that `cxTreeAddData()` uses the allocator of the `CxTree` to create the node first, before adding it. |
151 that `cxTreeAddData()` uses the allocator of the `CxTree` to create the node first before adding it. |
| 150 The function returns `NULL` in case the creation of the node fails, or the created node when creation was successful. |
152 The function returns `NULL` in case the creation of the node fails, or the created node when creation was successful. |
| 151 The difference between `cxTreeSetParent()` and `cxTreeAddNode()` is, |
153 The difference between `cxTreeSetParent()` and `cxTreeAddNode()` is |
| 152 that `cxTreeSetParent()` does not increase the tree size, when `child` already had a parent. |
154 that `cxTreeSetParent()` does not increase the tree size when `child` already had a parent. |
| 153 |
155 |
| 154 When you want to use `cxTreeCreateRootData()` or `cxTreeAddData()`, |
156 When you want to use `cxTreeCreateRootData()` or `cxTreeAddData()`, |
| 155 the `loc_data` parameter of `cxTreeCreate()` must have been set to a non-negative value. |
157 the `loc_data` parameter of `cxTreeCreate()` must have been set to a non-negative value. |
| 156 Otherwise, the functions will return `NULL`. |
158 Otherwise, the functions will return `NULL`. |
| 157 |
159 |
| 213 const void *data, cx_tree_search_func sfunc, void **result, |
215 const void *data, cx_tree_search_func sfunc, void **result, |
| 214 bool use_dfs, ptrdiff_t loc_children, ptrdiff_t loc_next); |
216 bool use_dfs, ptrdiff_t loc_children, ptrdiff_t loc_next); |
| 215 |
217 |
| 216 void *cxTreeFindFast(CxTree *tree, const void *data, |
218 void *cxTreeFindFast(CxTree *tree, const void *data, |
| 217 cx_tree_search_func sfunc); |
219 cx_tree_search_func sfunc); |
| |
220 |
| |
221 void *cxTreeFindFastInSubtree(CxTree *tree, const void *data, |
| |
222 cx_tree_search_func sfunc, |
| |
223 void *subtree_root, size_t max_depth); |
| 218 |
224 |
| 219 void *cxTreeFind(CxTree *tree, const void *data, bool use_dfs); |
225 void *cxTreeFind(CxTree *tree, const void *data, bool use_dfs); |
| 220 |
226 |
| 221 void *cxTreeFindInSubtree(CxTree *tree, const void *data, |
227 void *cxTreeFindInSubtree(CxTree *tree, const void *data, |
| 222 void *subtree_root, size_t max_depth, bool use_dfs); |
228 void *subtree_root, size_t max_depth, bool use_dfs); |
| 225 The function `cx_tree_search()` efficiently finds a node in the tree. |
231 The function `cx_tree_search()` efficiently finds a node in the tree. |
| 226 |
232 |
| 227 The search proceeds as follows, starting with the `root` node: |
233 The search proceeds as follows, starting with the `root` node: |
| 228 |
234 |
| 229 1. The current node is compared with `data` using the `sfunc`. |
235 1. The current node is compared with `data` using the `sfunc`. |
| 230 2. If `sfunc` returns zero, a matching node has been found and the pointer to that node is stored at the location given by `result`. |
236 2. If `sfunc` returns zero, a matching node has been found, and the pointer to that node is stored at the location given by `result`. |
| 231 3. If `sfunc` returns a negative number, the entire subtree is skipped. |
237 3. If `sfunc` returns a negative number, the entire subtree is skipped. |
| 232 4. If `sfunc` returns a positive number, the subtree is searched, unless the number is larger than the number of an already searched subtree. The best match will be stored at the location given by `result`. |
238 4. If `sfunc` returns a positive number, the subtree is searched, unless the number is larger than the number of an already searched subtree. The best match will be stored at the location given by `result`. |
| 233 5. The return value will be the return value of the `sfunc` for node that was stored in the `result`, or a negative number when no match was found |
239 5. The return value will be the return value of the `sfunc` for node, that was stored in the `result`, or a negative number when no match was found |
| 234 |
240 |
| 235 > If the `sfunc` implements some kind of metric, the search functions will return the best match in the tree with respect to that metric. |
241 > If the `sfunc` implements some kind of metric, the search functions will return the best match in the tree with respect to that metric. |
| 236 > When a positive number is returned, it means that a new node with the searched data could be added as a child of the found node. |
242 > When a positive number is returned, it means that a new node with the searched data could be added as a child of the found node. |
| 237 |
243 |
| 238 The function `cxTreeFindFast()` uses the `sfunc` to find the `data` in the tree, and returns a pointer to the node when the data was found (or `NULL`, otherwise). |
244 The function `cxTreeFindFast()` uses the `sfunc` to find the `data` in the tree and returns a pointer to the node when the data was found (or `NULL`, otherwise). |
| 239 |
245 |
| 240 The function `cxTreeFind()` instead traverses the entire tree (either with breadth-first search or depth-first search) |
246 The function `cxTreeFind()` instead traverses the entire tree (either with breadth-first search or depth-first search) |
| 241 and compares the `data` with the collections [comparator function](collection.h.md#comparator-functions). |
247 and compares the `data` with the collections [comparator function](collection.h.md#comparator-functions). |
| 242 For this it is necessary that the `loc_data` was specified when creating the tree, or the function will immediately return `NULL`. |
248 For this it is necessary that the `loc_data` was specified when creating the tree, or the function will immediately return `NULL`. |
| 243 |
249 |
| 244 The functions `cxTreeFindFastInSubtree()` and `cxTreeFindInSubtree()` are similar, except that they restrict the search to nodes |
250 The functions `cxTreeFindFastInSubtree()` and `cxTreeFindInSubtree()` are similar, except that they restrict the search to nodes |
| 245 in the subtree starting with (and including) `subtree_root`, and skipping all nodes below the `max_depth`. |
251 in the subtree starting with (and including) `subtree_root`, and skipping all nodes below the `max_depth`. |
| 246 Note, that the `max_depth` is specified in relation to the `subtree_root` and not in relation to the entire tree. |
252 Note that the `max_depth` is specified in relation to the `subtree_root` and not in relation to the entire tree. |
| 247 |
253 |
| 248 ## Iterator and Visitor |
254 ## Iterator and Visitor |
| 249 |
255 |
| 250 ```C |
256 ```C |
| 251 #include <cx/tree.h> |
257 #include <cx/tree.h> |
| 288 |
294 |
| 289 > It is recommended to always invoke the dispose functions, even when it seems not necessary. |
295 > It is recommended to always invoke the dispose functions, even when it seems not necessary. |
| 290 > In the best case it just does nothing, but calling them guarantees that no memory can be leaking, even when your code will change in the future. |
296 > In the best case it just does nothing, but calling them guarantees that no memory can be leaking, even when your code will change in the future. |
| 291 >{style="note"} |
297 >{style="note"} |
| 292 |
298 |
| 293 The macro `cxTreeIteratorContinue()` instruct the iterator to skip the subtree below the currently inspected node. |
299 The macro `cxTreeIteratorContinue()` instructs the iterator to skip the subtree below the currently inspected node. |
| 294 |
300 |
| 295 > In contrast to iterators over [lists](list.h.md#iterators) or [maps](map.h.md#iterators), |
301 > In contrast to iterators over [lists](list.h.md#iterators) or [maps](map.h.md#iterators), |
| 296 > a tree iterator is _always_ iterating over the nodes. |
302 > a tree iterator is _always_ iterating over the nodes. |
| 297 > That means, the pointer in a `cx_foreach` loop is always expected to be a pointer to a node and not a pointer to |
303 > That means, the pointer in a `cx_foreach` loop is always expected to be a pointer to a node and not a pointer to |
| 298 > the element / payload within the node. |
304 > the element / payload within the node. |
| 322 The high-level counterpart is `cxTreeRemoveSubtree()`. |
328 The high-level counterpart is `cxTreeRemoveSubtree()`. |
| 323 |
329 |
| 324 The function `cxTreeRemoveNode()`, on the other hand, _only_ removes the `node` from the tree, |
330 The function `cxTreeRemoveNode()`, on the other hand, _only_ removes the `node` from the tree, |
| 325 links all children of `node` to the former parent of `node`, |
331 links all children of `node` to the former parent of `node`, |
| 326 and calls the optional `relink_func` for every former child of `node` which will be relinked to a new parent. |
332 and calls the optional `relink_func` for every former child of `node` which will be relinked to a new parent. |
| 327 Therefore, calling `cxTreeRemoveNode()` on the `root` node is an error and the function returns non-zero. |
333 Therefore, calling `cxTreeRemoveNode()` on the `root` node is an error, and the function returns non-zero. |
| 328 In all other cases, the function returns zero. |
334 In all other cases, the function returns zero. |
| 329 |
335 |
| 330 > When your tree is storing a scene graph, for example, a possible use-case for the `relink_func` might be updating |
336 > When your tree is storing a scene graph, for example, a possible use-case for the `relink_func` might be updating |
| 331 > the world transform matrices in the subtree of the removed node. |
337 > the world transform matrices in the subtree of the removed node. |
| 332 |
338 |
| 355 That means this function does not deallocate the memory for the node on its own and leaves that entirely to the destructor functions. |
361 That means this function does not deallocate the memory for the node on its own and leaves that entirely to the destructor functions. |
| 356 |
362 |
| 357 The function `cxTreeDestroySubtree()` performs the above actions for the entire subtree starting with `node`. |
363 The function `cxTreeDestroySubtree()` performs the above actions for the entire subtree starting with `node`. |
| 358 The order in which the destructor functions for the nodes of the subtree are called is determined by a [tree iterator](#iterator-and-visitor). |
364 The order in which the destructor functions for the nodes of the subtree are called is determined by a [tree iterator](#iterator-and-visitor). |
| 359 |
365 |
| 360 The function `cxTreeClear()` is a shorthand for invoking `cxTreeDestroySubtree()` on the root node of the tree. |
366 The function `cxTreeClear()` is short for invoking `cxTreeDestroySubtree()` on the root node of the tree if it exists. |
| 361 |
367 |
| 362 The function `cxTreeFree()` behaves like `cxTreeClear()` and then deallocates the memory for the `CxTree` structure. |
368 The function `cxTreeFree()` behaves like `cxTreeClear()` and then deallocates the memory for the `CxTree` structure. |
| 363 |
369 |
| 364 > In contrast to other collections, the destructor functions of a `CxTree` are _always_ invoked with pointers to the _nodes_ |
370 > In contrast to other collections, the destructor functions of a `CxTree` are _always_ invoked with pointers to the _nodes_ |
| 365 > and not to pointers to the elements / the payload of the nodes. |
371 > and not to pointers to the elements / the payload of the nodes. |