| 25 ``` |
25 ``` |
| 26 |
26 |
| 27 The macro `cx_tree_node_base_layout` expands to the offsets of the above-mentioned pointers. |
27 The macro `cx_tree_node_base_layout` expands to the offsets of the above-mentioned pointers. |
| 28 It will become handy when calling the low-level tree functions which expect all offsets to be passed as arguments. |
28 It will become handy when calling the low-level tree functions which expect all offsets to be passed as arguments. |
| 29 |
29 |
| 30 <warning> |
30 > In all functions, the `last_child` and `prev` pointers are completely optional. |
| 31 TODO: forgot to mention that loc_last_child and loc_prev are optional in all functions. |
31 > If your tree structure does not contain the `last_child` pointer, the last child will be determined by |
| 32 </warning> |
32 > traversing all children from the first child. |
| |
33 > The same happens when it does not have a `prev` pointer, and the left sibling of a child is needed. |
| |
34 > The `children` pointer (which points to the first child), and the `next` pointer are mandatory, |
| |
35 > and so is the `parent` pointer. |
| 33 |
36 |
| 34 Before diving into the function definitions, there are four function pointer declarations you should know. |
37 Before diving into the function definitions, there are four function pointer declarations you should know. |
| 35 |
38 |
| 36 ```C |
39 ```C |
| 37 #include <cx/tree.h> |
40 #include <cx/tree.h> |
| 97 |
100 |
| 98 In both cases the tree will be created empty, that is with no nodes, not even a root node. |
101 In both cases the tree will be created empty, that is with no nodes, not even a root node. |
| 99 On the other hand, `cxTreeCreateWrapped()` creates a `CxTree` structure with the specified layout and `root` node |
102 On the other hand, `cxTreeCreateWrapped()` creates a `CxTree` structure with the specified layout and `root` node |
| 100 where `root` may already be the root of a larger tree. |
103 where `root` may already be the root of a larger tree. |
| 101 |
104 |
| |
105 If your wrapped tree structure does not have a `last_child` or a `prev` pointer, |
| |
106 you may specify a negative location to indicate the missing pointer. |
| |
107 All other pointers are mandatory and a non-negative location is expected. |
| |
108 |
| 102 Note, that a wrapped tree by default has no create or search functions assigned. |
109 Note, that a wrapped tree by default has no create or search functions assigned. |
| 103 Therefore, if you wish to use one of the functions below that needs those function pointers set, |
110 Therefore, if you wish to use one of the functions below that needs those function pointers set, |
| 104 you will have to set them manually by assigning to the respective fields in the `CxTree` structure. |
111 you will have to set them manually by assigning to the respective fields in the `CxTree` structure. |
| |
112 |
| |
113 ### Example for wrapping a libxml2 tree |
| |
114 |
| |
115 ```C |
| |
116 #include <libxml/tree.h> |
| |
117 #include <cx/tree.h> |
| |
118 |
| |
119 CxTree *wrap_xml_tree(xmlNode *root) { |
| |
120 return cxTreeCreateWrapped( |
| |
121 cxDefaultAllocator, // or you can just write NULL |
| |
122 root, |
| |
123 offsetof(xmlNode, parent), |
| |
124 offsetof(xmlNode, children), |
| |
125 offsetof(xmlNode, last), |
| |
126 offsetof(xmlNode, prev), |
| |
127 offsetof(xmlNode, next) |
| |
128 ); |
| |
129 } |
| |
130 ``` |
| |
131 |
| |
132 You do not need to specify any function pointers or destructors in the `CxTree` structure, |
| |
133 if you just want to use the resulting `CxTree` for [iterating](#iterator-and-visitor) over the nodes. |
| |
134 |
| |
135 You can, for example, print the XML structure with the following code: |
| |
136 |
| |
137 ```C |
| |
138 // continued from above |
| |
139 |
| |
140 void print_xml_structure(CxTree *tree) { |
| |
141 // specify visit_on_exit argument = true |
| |
142 // so that we are visiting each node twice: on enter and on exit |
| |
143 CxTreeIterator iter = cxTreeIterate(tree, true); |
| |
144 |
| |
145 cx_foreach(xmlNode*, node, iter) { |
| |
146 if (node->type == XML_ELEMENT_NODE) { |
| |
147 // the exiting field from the iterator indicates |
| |
148 // whether we are entring or leaving the subtree |
| |
149 // of the current element |
| |
150 printf("%s - %s\n", |
| |
151 node->name, |
| |
152 iter.exiting ? "start" : "end" |
| |
153 ); |
| |
154 } |
| |
155 } |
| |
156 cxTreeIteratorDispose(&iter); |
| |
157 } |
| |
158 ``` |
| 105 |
159 |
| 106 ## Add Nodes |
160 ## Add Nodes |
| 107 |
161 |
| 108 ```C |
162 ```C |
| 109 #include <cx/tree.h> |
163 #include <cx/tree.h> |