bbe99290ef571f301da39e9143973c172c074780
[platform/framework/web/data-provider-master.git] / util_liveinfo / src / node.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5
6 #include "node.h"
7
8 struct node {
9         char *name;
10         enum node_type type;
11
12         void *data;
13
14         struct node *parent;
15         unsigned char mode;
16         int age;
17
18         struct {
19                 struct node *next;
20                 struct node *prev;
21         } sibling;
22
23         struct node *child;
24 };
25
26 int errno; /* External symbol */
27
28 char *node_to_abspath(const struct node *node)
29 {
30         char *path;
31         char *ptr;
32         const struct node *tmp;
33         int len = 0;
34
35         tmp = node;
36         while (tmp && node_name(tmp)) {
37                 len += strlen(node_name(tmp)) + 1; /* trail '/' */
38                 tmp = node_parent(tmp);
39         }
40
41         path = malloc(len + 3); /* '/' and '\0' */
42         if (!path) {
43                 return NULL;
44         }
45
46         if (!len) {
47                 path[0] = '/';
48                 path[1] = '\0';
49         } else {
50                 ptr = path + len + 1;
51                 *ptr = '\0';
52                 ptr--;
53                 *ptr = '/';
54                 tmp = node;
55                 while (tmp && node_name(tmp)) {
56                         ptr -= (strlen(node_name(tmp)) + 1);
57                         *ptr = '/';
58                         strncpy(ptr + 1, node_name(tmp), strlen(node_name(tmp)));
59                         tmp = node_parent(tmp);
60                 }
61         }
62
63         return path;
64 }
65
66 static inline int next_state(int from, char ch)
67 {
68         switch (ch) {
69         case '\0':
70         case '/':
71                 return 1;
72         case '.':
73                 if (from == 1) {
74                         return 2;
75                 }
76
77                 if (from == 2) {
78                         return 3;
79                 }
80         }
81
82         return 4;
83 }
84
85 static inline void abspath(const char* pBuffer, char* pRet)
86 {
87         int idx=0;
88         int state = 1;
89         int from;
90         int src_idx = 0;
91         int src_len = strlen(pBuffer);
92         pRet[idx] = '/';
93         idx++;
94
95         while (src_idx <= src_len) {
96                 from = state;
97                 state = next_state(from, pBuffer[src_idx]);
98
99                 switch (from) {
100                 case 1:
101                         if (state != 1) {
102                                 pRet[idx] = pBuffer[src_idx];
103                                 idx++;
104                         }
105                         break;
106                 case 2:
107                         if (state == 1) {
108                                 if (idx > 1) {
109                                         idx--;
110                                 }
111                         } else {
112                                 pRet[idx] = pBuffer[src_idx];
113                                 idx ++;
114                         }
115                         break;
116                 case 3:
117                         // Only can go to the 1 or 4
118                         if (state == 1) {
119                                 idx -= 2;
120                                 if (idx < 1) {
121                                         idx = 1;
122                                 }
123
124                                 while (idx > 1 && pRet[idx] != '/') {
125                                         idx--; /* Remove .. */
126                                 }
127                                 if (idx > 1 && pRet[idx] == '/') {
128                                         idx--;
129                                 }
130                                 while (idx > 1 && pRet[idx] != '/') {
131                                         idx--; /* Remove parent folder */
132                                 }
133                         }
134                 case 4:
135                         pRet[idx] = pBuffer[src_idx];
136                         idx++;
137                         break;
138                 }
139
140                 pRet[idx] = '\0';
141                 src_idx++;
142         }
143 }
144
145 struct node *node_find(const struct node *node, const char *path)
146 {
147         int len = 0;
148         char *ptr;
149         char *buffer;
150
151         if (*path != '/') {
152                 while (node->parent && path[0] == '.' && path[1] == '.') {
153                         if (path[2] != '/' && path[2] != '\0') {
154                                 break;
155                         }
156
157                         path += 2;
158                         path += (path[2] == '/');
159                         node = node->parent;
160                 }
161         }
162
163         buffer = malloc(strlen(path) + 3); /* add 2 more bytes */
164         if (!buffer) {
165                 printf("Error: %s\n", strerror(errno));
166                 return NULL;
167         }
168
169         abspath(path, buffer);
170
171         ptr = buffer;
172         do {
173                 ptr += (*ptr == '/');
174                 for (len = 0; ptr[len] && ptr[len] != '/'; len++);
175                 if (!len) {
176                         break;
177                 }
178
179                 if (!strncmp("..", ptr, len)) {
180                         ptr += len;
181                         node = node->parent ? node->parent : node;
182                         continue;
183                 }
184
185                 if (!strncmp(".", ptr, len)) {
186                         ptr += len;
187                         continue;
188                 }
189
190                 node = node->child;
191                 if (!node) {
192                         break;
193                 }
194
195                 while (node) {
196                         if (!strncmp(node->name, ptr, len) && node->name[len] == '\0') {
197                                 ptr += len;
198                                 break;
199                         }
200
201                         node = node->sibling.next;
202                 }
203         } while (*ptr && node);
204
205         free(buffer);
206         return (struct node *)node;
207 }
208
209 struct node *node_create(struct node *parent, const char *name, enum node_type type)
210 {
211         struct node *node;
212
213         node = malloc(sizeof(*node));
214         if (!node) {
215                 printf("Error: %s\n", strerror(errno));
216                 return NULL;
217         }
218
219         node->parent = parent;
220
221         if (name) {
222                 node->name = strdup(name);
223                 if (!node->name) {
224                         printf("Error: %s\n", strerror(errno));
225                         free(node);
226                         return NULL;
227                 }
228         } else {
229                 node->name = NULL;
230         }
231
232         node->type = type;
233
234         node->sibling.next = NULL;
235         node->sibling.prev = NULL;
236
237         node->child = NULL;
238         node->data = NULL;
239
240         if (parent) {
241                 if (parent->child) {
242                         struct node *tmp;
243                         tmp = parent->child;
244                         while (tmp->sibling.next) {
245                                 tmp = tmp->sibling.next;
246                         }
247
248                         tmp->sibling.next = node;
249                         node->sibling.prev = tmp;
250                 } else {
251                         parent->child = node;
252                 }
253         }
254         return node;
255 }
256
257 void *node_destroy(struct node *node)
258 {
259         void *data;
260
261         data = node->data;
262         free(node->name);
263         free(node);
264
265         return data;
266 }
267
268 void node_delete(struct node *node, void (del_cb)(struct node *node))
269 {
270         struct node *tmp;
271         struct node *next;
272         struct node *parent;
273
274         if (node->sibling.prev) {
275                 node->sibling.prev->sibling.next = node->sibling.next;
276         }
277
278         if (node->sibling.next) {
279                 node->sibling.next->sibling.prev = node->sibling.prev;
280         }
281
282         /* Isolate the node */
283         node->sibling.prev = NULL;
284         node->sibling.next = NULL;
285
286         if (node->parent) {
287                 if (node->parent->child == node) {
288                         node->parent->child = NULL;
289                 }
290
291                 node->parent = NULL;
292         }
293
294         tmp = node;
295         while (tmp) {
296                 /* Reach to the leaf node */
297                 while (tmp->child) {
298                         tmp = tmp->child;
299                 }
300
301                 parent = tmp->parent;
302                 next = tmp->sibling.next;
303
304                 if (parent && parent->child == tmp) {
305                         parent->child = NULL;
306                 }
307
308                 if (del_cb) {
309                         del_cb(tmp);
310                 }
311
312                 node_destroy(tmp);
313
314                 if (next) {
315                         tmp = next;
316                 } else if (parent) {
317                         tmp = parent;
318                 } else {
319                         tmp = NULL;
320                 }
321         }
322 }
323
324 struct node * const node_next_sibling(const struct node *node)
325 {
326         return node->sibling.next;
327 }
328
329 struct node * const node_prev_sibling(const struct node *node)
330 {
331         return node->sibling.prev;
332 }
333
334 void node_set_mode(struct node *node, int mode)
335 {
336         node->mode = mode;
337 }
338
339 void node_set_data(struct node *node, void *data)
340 {
341         node->data = data;
342 }
343
344 void node_set_type(struct node *node, enum node_type type)
345 {
346         node->type = type;
347 }
348
349 struct node * const node_child(const struct node *node)
350 {
351         return node->child;
352 }
353
354 struct node * const node_parent(const struct node *node)
355 {
356         return node->parent;
357 }
358
359 const int const node_mode(const struct node *node)
360 {
361         return node->mode;
362 }
363
364 void * const node_data(const struct node *node)
365 {
366         return node->data;
367 }
368
369 const enum node_type const node_type(const struct node *node)
370 {
371         return node->type;
372 }
373
374 const char * const node_name(const struct node *node)
375 {
376         return node->name;
377 }
378
379 void node_set_age(struct node *node, int age)
380 {
381         node->age = age;
382 }
383
384 int node_age(struct node *node)
385 {
386         return node->age;
387 }
388
389 /* End of a file */