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> |