Sat, 29 Mar 2025 19:58:41 +0100
wrapping xml tree example
relates to #451
docs/Writerside/topics/tree.h.md | file | annotate | diff | comparison | revisions |
--- a/docs/Writerside/topics/tree.h.md Fri Mar 28 21:51:31 2025 +0100 +++ b/docs/Writerside/topics/tree.h.md Sat Mar 29 19:58:41 2025 +0100 @@ -27,9 +27,12 @@ The macro `cx_tree_node_base_layout` expands to the offsets of the above-mentioned pointers. It will become handy when calling the low-level tree functions which expect all offsets to be passed as arguments. -<warning> -TODO: forgot to mention that loc_last_child and loc_prev are optional in all functions. -</warning> +> In all functions, the `last_child` and `prev` pointers are completely optional. +> If your tree structure does not contain the `last_child` pointer, the last child will be determined by +> traversing all children from the first child. +> The same happens when it does not have a `prev` pointer, and the left sibling of a child is needed. +> The `children` pointer (which points to the first child), and the `next` pointer are mandatory, +> and so is the `parent` pointer. Before diving into the function definitions, there are four function pointer declarations you should know. @@ -99,10 +102,61 @@ On the other hand, `cxTreeCreateWrapped()` creates a `CxTree` structure with the specified layout and `root` node where `root` may already be the root of a larger tree. +If your wrapped tree structure does not have a `last_child` or a `prev` pointer, +you may specify a negative location to indicate the missing pointer. +All other pointers are mandatory and a non-negative location is expected. + Note, that a wrapped tree by default has no create or search functions assigned. Therefore, if you wish to use one of the functions below that needs those function pointers set, you will have to set them manually by assigning to the respective fields in the `CxTree` structure. +### Example for wrapping a libxml2 tree + +```C +#include <libxml/tree.h> +#include <cx/tree.h> + +CxTree *wrap_xml_tree(xmlNode *root) { + return cxTreeCreateWrapped( + cxDefaultAllocator, // or you can just write NULL + root, + offsetof(xmlNode, parent), + offsetof(xmlNode, children), + offsetof(xmlNode, last), + offsetof(xmlNode, prev), + offsetof(xmlNode, next) + ); +} +``` + +You do not need to specify any function pointers or destructors in the `CxTree` structure, +if you just want to use the resulting `CxTree` for [iterating](#iterator-and-visitor) over the nodes. + +You can, for example, print the XML structure with the following code: + +```C +// continued from above + +void print_xml_structure(CxTree *tree) { + // specify visit_on_exit argument = true + // so that we are visiting each node twice: on enter and on exit + CxTreeIterator iter = cxTreeIterate(tree, true); + + cx_foreach(xmlNode*, node, iter) { + if (node->type == XML_ELEMENT_NODE) { + // the exiting field from the iterator indicates + // whether we are entring or leaving the subtree + // of the current element + printf("%s - %s\n", + node->name, + iter.exiting ? "start" : "end" + ); + } + } + cxTreeIteratorDispose(&iter); +} +``` + ## Add Nodes ```C