4 * Copyright (c) 2013-2014 project bchan
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source
31 #include <bsys/queue.h>
33 EXPORT VOID treebase_node_appendchild(treebase_node_t *node, treebase_node_t *child)
37 ok = treebase_node_haschild(node);
39 node->firstchild = child;
41 QueInsert(&child->sibling, &node->firstchild->sibling);
46 EXPORT W treebase_node_insertbefore(treebase_node_t *node, treebase_node_t *child, treebase_node_t *ref)
49 treebase_node_appendchild(node, child);
52 if (ref->parent != node) {
56 if (node->firstchild == ref) {
57 node->firstchild = child;
59 QueInsert(&child->sibling, &ref->sibling);
65 EXPORT VOID treebase_node_remove(treebase_node_t *node)
67 if (node->parent == NULL) { /* root node */
70 if (node->parent->firstchild == node) {
71 node->parent->firstchild = treebase_node_getnextsibling(node);
73 QueRemove(&node->sibling);
77 EXPORT treebase_node_t* treebase_node_getparent(treebase_node_t *node)
82 EXPORT treebase_node_t* treebase_node_getnextsibling(treebase_node_t *node)
85 treebase_node_t *parent, *last;
86 empty = isQueEmpty(&node->sibling);
90 parent = treebase_node_getparent(node);
94 last = treebase_node_getlastchild(parent);
98 return (treebase_node_t*)node->sibling.next;
101 EXPORT treebase_node_t* treebase_node_getprevsibling(treebase_node_t *node)
104 treebase_node_t *parent, *first;
105 empty = isQueEmpty(&node->sibling);
106 if (empty != False) {
109 parent = treebase_node_getparent(node);
110 if (parent == NULL) {
113 first = treebase_node_getfirstchild(parent);
117 return (treebase_node_t*)node->sibling.prev;
120 EXPORT treebase_node_t* treebase_node_getfirstchild(treebase_node_t *node)
122 return node->firstchild;
125 EXPORT treebase_node_t* treebase_node_getlastchild(treebase_node_t *node)
127 if (node->firstchild == NULL) {
130 return (treebase_node_t*)node->firstchild->sibling.prev;
133 EXPORT Bool treebase_node_haschild(treebase_node_t *node)
135 if (node->firstchild == NULL) {
141 EXPORT VOID treebase_node_initialize(treebase_node_t *node)
143 QueInit(&node->sibling);
144 node->firstchild = NULL;
148 EXPORT VOID treebase_node_finalize(treebase_node_t *node)
150 treebase_node_remove(node);
154 EXPORT Bool treebase_preordertraversal_next(treebase_preordertraversal_t *traversal, treebase_node_t **node, TREEBASE_TRAVERSAL_DIRECTION *dir)
156 treebase_node_t *child, *sibling;
158 if (traversal->current == NULL) {
162 *node = traversal->current;
163 *dir = traversal->dir;
165 if (traversal->dir == TREEBASE_TRAVERSAL_DIRECTION_DOWN) {
166 child = treebase_node_getfirstchild(traversal->current);
168 traversal->dir = TREEBASE_TRAVERSAL_DIRECTION_UP;
170 traversal->current = child;
173 sibling = treebase_node_getnextsibling(traversal->current);
174 if (sibling == NULL) {
175 if (traversal->current == traversal->root) {
176 traversal->current = NULL;
178 traversal->current = treebase_node_getparent(traversal->current);
181 traversal->current = sibling;
182 traversal->dir = TREEBASE_TRAVERSAL_DIRECTION_DOWN;
189 EXPORT VOID treebase_preordertraversal_initialize(treebase_preordertraversal_t *traversal, treebase_node_t *root)
191 traversal->root = root;
192 traversal->current = root;
193 traversal->dir = TREEBASE_TRAVERSAL_DIRECTION_DOWN;
196 EXPORT VOID treebase_preordertraversal_finalize(treebase_preordertraversal_t *traversal)
201 EXPORT Bool treebase_postordertraversal_next(treebase_postordertraversal_t *traversal, treebase_node_t **node, TREEBASE_TRAVERSAL_DIRECTION *dir)
203 treebase_node_t *child, *sibling;
205 if (traversal->current == NULL) {
209 *node = traversal->current;
210 *dir = traversal->dir;
212 if (traversal->dir == TREEBASE_TRAVERSAL_DIRECTION_DOWN) {
213 child = treebase_node_getlastchild(traversal->current);
215 traversal->dir = TREEBASE_TRAVERSAL_DIRECTION_UP;
217 traversal->current = child;
220 sibling = treebase_node_getprevsibling(traversal->current);
221 if (sibling == NULL) {
222 if (traversal->current == traversal->root) {
223 traversal->current = NULL;
225 traversal->current = treebase_node_getparent(traversal->current);
228 traversal->current = sibling;
229 traversal->dir = TREEBASE_TRAVERSAL_DIRECTION_DOWN;
236 EXPORT VOID treebase_postordertraversal_initialize(treebase_postordertraversal_t *traversal, treebase_node_t *root)
238 traversal->root = root;
239 traversal->current = root;
240 traversal->dir = TREEBASE_TRAVERSAL_DIRECTION_DOWN;
243 EXPORT VOID treebase_postordertraversal_finalize(treebase_postordertraversal_t *traversal)