summaryrefslogtreecommitdiffstats
path: root/libcnary/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcnary/node.c')
-rw-r--r--libcnary/node.c207
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 @@
1/*
2 * node.c
3 *
4 * Created on: Mar 7, 2011
5 * Author: posixninja
6 */
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "node.h"
12#include "node_list.h"
13#include "node_iterator.h"
14
15void node_destroy(node_t* node) {
16 if(!node) return;
17
18 if (node->children && node->children->count > 0) {
19 node_t* ch;
20 while ((ch = node->children->begin)) {
21 node_list_remove(node->children, ch);
22 node_destroy(ch);
23 }
24 }
25 node_list_destroy(node->children);
26 node->children = NULL;
27
28 free(node);
29}
30
31node_t* node_create(node_t* parent, void* data) {
32 int error = 0;
33
34 node_t* node = (node_t*) malloc(sizeof(node_t));
35 if(node == NULL) {
36 return NULL;
37 }
38 memset(node, '\0', sizeof(node_t));
39
40 node->data = data;
41 node->depth = 0;
42 node->next = NULL;
43 node->prev = NULL;
44 node->count = 0;
45 node->isLeaf = TRUE;
46 node->isRoot = TRUE;
47 node->parent = NULL;
48 node->children = node_list_create(node);
49
50 // Pass NULL to create a root node
51 if(parent != NULL) {
52 // This is a child node so attach it to it's parent
53 error = node_attach(parent, node);
54 if(error < 0) {
55 // Unable to attach nodes
56 printf("ERROR: %d \"Unable to attach nodes\"\n", error);
57 node_destroy(node);
58 return NULL;
59 }
60 }
61
62 return node;
63}
64
65int node_attach(node_t* parent, node_t* child) {
66 if (!parent || !child) return -1;
67 child->isLeaf = TRUE;
68 child->isRoot = FALSE;
69 child->parent = parent;
70 child->depth = parent->depth + 1;
71 if(parent->isLeaf == TRUE) {
72 parent->isLeaf = FALSE;
73 }
74 int res = node_list_add(parent->children, child);
75 if (res == 0) {
76 parent->count++;
77 }
78 return res;
79}
80
81int node_detach(node_t* parent, node_t* child) {
82 if (!parent || !child) return 0;
83 if (node_list_remove(parent->children, child) == 0) {
84 parent->count--;
85 }
86 return 0;
87}
88
89int node_insert(node_t* parent, unsigned int index, node_t* child)
90{
91 if (!parent || !child) return;
92 child->isLeaf = TRUE;
93 child->isRoot = FALSE;
94 child->parent = parent;
95 child->depth = parent->depth + 1;
96 if(parent->isLeaf == TRUE) {
97 parent->isLeaf = FALSE;
98 }
99 int res = node_list_insert(parent->children, index, child);
100 if (res == 0) {
101 parent->count++;
102 }
103 return res;
104}
105
106void node_debug(node_t* node) {
107 int i = 0;
108 node_t* current = NULL;
109 node_iterator_t* iter = NULL;
110 for(i = 0; i < node->depth; i++) {
111 printf("\t");
112 }
113 if(node->isRoot) {
114 printf("ROOT\n");
115 }
116
117 if(node->isLeaf && !node->isRoot) {
118 printf("LEAF\n");
119
120 } else {
121 if(!node->isRoot) {
122 printf("NODE\n");
123 }
124 iter = node_iterator_create(node->children);
125 for(current = iter->begin; current != NULL; current = iter->next(iter)) {
126 node_debug(current);
127 }
128 }
129
130}
131
132unsigned int node_n_children(struct node_t* node)
133{
134 if (!node) return 0;
135 return node->count;
136}
137
138node_t* node_nth_child(struct node_t* node, unsigned int n)
139{
140 if (!node || !node->children || !node->children->begin) return NULL;
141 int index = 0;
142 int found = 0;
143 node_t *ch;
144 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
145 if (index++ == n) {
146 found = 1;
147 break;
148 }
149 }
150 if (!found) {
151 return NULL;
152 }
153 return ch;
154}
155
156node_t* node_first_child(struct node_t* node)
157{
158 if (!node || !node->children) return NULL;
159 return node->children->begin;
160}
161
162node_t* node_prev_sibling(struct node_t* node)
163{
164 if (!node) return NULL;
165 return node->prev;
166}
167
168node_t* node_next_sibling(struct node_t* node)
169{
170 if (!node) return NULL;
171 return node->next;
172}
173
174int node_child_position(struct node_t* parent, node_t* child)
175{
176 if (!parent || !parent->children || !parent->children->begin || !child) return -1;
177 int index = 0;
178 int found = 0;
179 node_t *ch;
180 for (ch = node_first_child(parent); ch; ch = node_next_sibling(ch)) {
181 if (ch == child) {
182 found = 1;
183 break;
184 }
185 index++;
186 }
187 if (!found) {
188 return -1;
189 }
190 return index;
191}
192
193node_t* node_copy_deep(node_t* node, copy_func_t copy_func)
194{
195 if (!node) return NULL;
196 void *data;
197 if (copy_func) {
198 data = copy_func(node->data);
199 }
200 node_t* copy = node_create(NULL, data);
201 node_t* ch;
202 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
203 node_t* cc = node_copy_deep(ch, copy_func);
204 node_attach(copy, cc);
205 }
206 return copy;
207}