diff options
Diffstat (limited to 'libcnary/node.c')
-rw-r--r-- | libcnary/node.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/libcnary/node.c b/libcnary/node.c new file mode 100644 index 0000000..956ba2f --- /dev/null +++ b/libcnary/node.c @@ -0,0 +1,207 @@ +/* + * node.c + * + * Created on: Mar 7, 2011 + * Author: posixninja + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "node.h" +#include "node_list.h" +#include "node_iterator.h" + +void node_destroy(node_t* node) { + if(!node) return; + + if (node->children && node->children->count > 0) { + node_t* ch; + while ((ch = node->children->begin)) { + node_list_remove(node->children, ch); + node_destroy(ch); + } + } + node_list_destroy(node->children); + node->children = NULL; + + free(node); +} + +node_t* node_create(node_t* parent, void* data) { + int error = 0; + + node_t* node = (node_t*) malloc(sizeof(node_t)); + if(node == NULL) { + return NULL; + } + memset(node, '\0', sizeof(node_t)); + + node->data = data; + node->depth = 0; + node->next = NULL; + node->prev = NULL; + node->count = 0; + node->isLeaf = TRUE; + node->isRoot = TRUE; + node->parent = NULL; + node->children = node_list_create(node); + + // Pass NULL to create a root node + if(parent != NULL) { + // This is a child node so attach it to it's parent + error = node_attach(parent, node); + if(error < 0) { + // Unable to attach nodes + printf("ERROR: %d \"Unable to attach nodes\"\n", error); + node_destroy(node); + return NULL; + } + } + + return node; +} + +int node_attach(node_t* parent, node_t* child) { + if (!parent || !child) return -1; + child->isLeaf = TRUE; + child->isRoot = FALSE; + child->parent = parent; + child->depth = parent->depth + 1; + if(parent->isLeaf == TRUE) { + parent->isLeaf = FALSE; + } + int res = node_list_add(parent->children, child); + if (res == 0) { + parent->count++; + } + return res; +} + +int node_detach(node_t* parent, node_t* child) { + if (!parent || !child) return 0; + if (node_list_remove(parent->children, child) == 0) { + parent->count--; + } + return 0; +} + +int node_insert(node_t* parent, unsigned int index, node_t* child) +{ + if (!parent || !child) return; + child->isLeaf = TRUE; + child->isRoot = FALSE; + child->parent = parent; + child->depth = parent->depth + 1; + if(parent->isLeaf == TRUE) { + parent->isLeaf = FALSE; + } + int res = node_list_insert(parent->children, index, child); + if (res == 0) { + parent->count++; + } + return res; +} + +void node_debug(node_t* node) { + int i = 0; + node_t* current = NULL; + node_iterator_t* iter = NULL; + for(i = 0; i < node->depth; i++) { + printf("\t"); + } + if(node->isRoot) { + printf("ROOT\n"); + } + + if(node->isLeaf && !node->isRoot) { + printf("LEAF\n"); + + } else { + if(!node->isRoot) { + printf("NODE\n"); + } + iter = node_iterator_create(node->children); + for(current = iter->begin; current != NULL; current = iter->next(iter)) { + node_debug(current); + } + } + +} + +unsigned int node_n_children(struct node_t* node) +{ + if (!node) return 0; + return node->count; +} + +node_t* node_nth_child(struct node_t* node, unsigned int n) +{ + if (!node || !node->children || !node->children->begin) return NULL; + int index = 0; + int found = 0; + node_t *ch; + for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { + if (index++ == n) { + found = 1; + break; + } + } + if (!found) { + return NULL; + } + return ch; +} + +node_t* node_first_child(struct node_t* node) +{ + if (!node || !node->children) return NULL; + return node->children->begin; +} + +node_t* node_prev_sibling(struct node_t* node) +{ + if (!node) return NULL; + return node->prev; +} + +node_t* node_next_sibling(struct node_t* node) +{ + if (!node) return NULL; + return node->next; +} + +int node_child_position(struct node_t* parent, node_t* child) +{ + if (!parent || !parent->children || !parent->children->begin || !child) return -1; + int index = 0; + int found = 0; + node_t *ch; + for (ch = node_first_child(parent); ch; ch = node_next_sibling(ch)) { + if (ch == child) { + found = 1; + break; + } + index++; + } + if (!found) { + return -1; + } + return index; +} + +node_t* node_copy_deep(node_t* node, copy_func_t copy_func) +{ + if (!node) return NULL; + void *data; + if (copy_func) { + data = copy_func(node->data); + } + node_t* copy = node_create(NULL, data); + node_t* ch; + for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { + node_t* cc = node_copy_deep(ch, copy_func); + node_attach(copy, cc); + } + return copy; +} |