tizen 2.3 release
[apps/livebox/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     {
70         case '\0':
71         case '/':
72             return 1;
73         case '.':
74             if (from == 1) {
75                 return 2;
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, int mode)
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
255     node->mode = mode;
256     return node;
257 }
258
259 void *node_destroy(struct node *node)
260 {
261     void *data;
262
263     data = node->data;
264     free(node->name);
265     free(node);
266
267     return data;
268 }
269
270 void node_delete(struct node *node, void (del_cb)(struct node *node))
271 {
272     struct node *tmp;
273     struct node *next;
274     struct node *parent;
275
276     if (node->sibling.prev) {
277         node->sibling.prev->sibling.next = node->sibling.next;
278     }
279
280     if (node->sibling.next) {
281         node->sibling.next->sibling.prev = node->sibling.prev;
282     }
283
284     /* Isolate the node */
285     node->sibling.prev = NULL;
286     node->sibling.next = NULL;
287
288     if (node->parent) {
289         if (node->parent->child == node) {
290             node->parent->child = NULL;
291         }
292
293         node->parent = NULL;
294     }
295
296     tmp = node;
297     while (tmp) {
298         /* Reach to the leaf node */
299         while (tmp->child) {
300             tmp = tmp->child;
301         }
302
303         parent = tmp->parent;
304         next = tmp->sibling.next;
305
306         if (parent && parent->child == tmp) {
307             parent->child = NULL;
308         }
309
310         if (del_cb) {
311             del_cb(tmp);
312         }
313
314         node_destroy(tmp);
315
316         if (next) {
317             tmp = next;
318         } else if (parent) {
319             tmp = parent;
320         } else {
321             tmp = NULL;
322         }
323     }
324 }
325
326 struct node * const node_next_sibling(const struct node *node)
327 {
328     return node->sibling.next;
329 }
330
331 struct node * const node_prev_sibling(const struct node *node)
332 {
333     return node->sibling.prev;
334 }
335
336 void node_set_mode(struct node *node, int mode)
337 {
338     node->mode = mode;
339 }
340
341 void node_set_data(struct node *node, void *data)
342 {
343     node->data = data;
344 }
345
346 void node_set_type(struct node *node, enum node_type type)
347 {
348     node->type = type;
349 }
350
351 struct node * const node_child(const struct node *node)
352 {
353     return node->child;
354 }
355
356 struct node * const node_parent(const struct node *node)
357 {
358     return node->parent;
359 }
360
361 const int const node_mode(const struct node *node)
362 {
363     return node->mode;
364 }
365
366 void * const node_data(const struct node *node)
367 {
368     return node->data;
369 }
370
371 const enum node_type const node_type(const struct node *node)
372 {
373     return node->type;
374 }
375
376 const char * const node_name(const struct node *node)
377 {
378     return node->name;
379 }
380
381 void node_set_age(struct node *node, int age)
382 {
383     node->age = age;
384 }
385
386 int node_age(struct node *node)
387 {
388     return node->age;
389 }
390
391 /* End of a file */