diff options
Diffstat (limited to 'src/kernel/lib/data/generic_tree.c')
-rw-r--r-- | src/kernel/lib/data/generic_tree.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/kernel/lib/data/generic_tree.c b/src/kernel/lib/data/generic_tree.c new file mode 100644 index 0000000..38caccc --- /dev/null +++ b/src/kernel/lib/data/generic_tree.c @@ -0,0 +1,102 @@ +#include <kernel/lib/data/generic_tree.h> +#include <kernel/lib/data/list.h> +#include <kernel/memory/alloc.h> + +gtree_t *tree_create() +{ + return (gtree_t *)kcalloc(sizeof(gtree_t), 1); +} + +gtreenode_t *treenode_create(void *value) +{ + gtreenode_t *n = kcalloc(sizeof(gtreenode_t), 1); + n->value = value; + n->children = list_create(); + return n; +} + +gtreenode_t *tree_insert(gtree_t *tree, gtreenode_t *subroot, void *value) +{ + gtreenode_t *treenode = kcalloc(sizeof(gtreenode_t), 1); + treenode->children = list_create(); + treenode->value = value; + + if (!tree->root) { + tree->root = treenode; + return treenode; + } + list_insert_front(subroot->children, treenode); + return treenode; +} + +gtreenode_t *tree_find_parent(gtree_t *tree, gtreenode_t *remove_node, int *child_index) +{ + if (remove_node == tree->root) + return NULL; + return tree_find_parent_recur(tree, remove_node, tree->root, child_index); +} + +gtreenode_t *tree_find_parent_recur(gtree_t *tree, gtreenode_t *remove_node, gtreenode_t *subroot, + int *child_index) +{ + int idx; + if ((idx = list_contain(subroot->children, remove_node)) != -1) { + *child_index = idx; + return subroot; + } + foreach(child, subroot->children) + { + gtreenode_t *ret = + tree_find_parent_recur(tree, remove_node, child->val, child_index); + if (ret != NULL) { + return ret; + } + } + return NULL; +} + +void tree_remove(gtree_t *tree, gtreenode_t *remove_node) +{ + int child_index = -1; + gtreenode_t *parent = tree_find_parent(tree, remove_node, &child_index); + if (parent != NULL) { + gtreenode_t *freethis = list_remove_by_index(parent->children, child_index); + kfree(freethis); + } +} + +void tree2list_recur(gtreenode_t *subroot, list_t *list) +{ + if (subroot == NULL) + return; + foreach(child, subroot->children) + { + gtreenode_t *curr_treenode = (gtreenode_t *)child->val; + void *curr_val = curr_treenode->value; + list_insert_back(list, curr_val); + tree2list_recur(child->val, list); + } +} + +void tree2list(gtree_t *tree, list_t *list) +{ + tree2list_recur(tree->root, list); +} + +void tree2array(gtree_t *tree, void **array, int *size) +{ + tree2array_recur(tree->root, array, size); +} + +void tree2array_recur(gtreenode_t *subroot, void **array, int *size) +{ + if (subroot == NULL) + return; + void *curr_val = (void *)subroot->value; + array[*size] = curr_val; + *size = *size + 1; + foreach(child, subroot->children) + { + tree2array_recur(child->val, array, size); + } +}
\ No newline at end of file |