Add new size type
[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
17         struct {
18                 struct node *next;
19                 struct node *prev;
20         } sibling;
21
22         struct node *child;
23 };
24
25 int errno; /* External symbol */
26
27 char *node_to_abspath(struct node *node)
28 {
29         char *path;
30         char *ptr;
31         struct node *tmp;
32         int len = 0;
33
34         tmp = node;
35         while (tmp && node_name(tmp)) {
36                 len += strlen(node_name(tmp)) + 1; /* trail '/' */
37                 tmp = node_parent(tmp);
38         }
39
40         path = malloc(len + 2); /* '/' and '\0' */
41         if (!path)
42                 return NULL;
43
44         if (!len) {
45                 path[0] = '/';
46                 path[1] = '\0';
47         } else {
48                 ptr = path + len;
49                 *ptr = '\0';
50                 tmp = node;
51                 while (tmp && node_name(tmp)) {
52                         ptr -= (strlen(node_name(tmp)) + 1);
53                         *ptr = '/';
54                         strncpy(ptr + 1, node_name(tmp), strlen(node_name(tmp)));
55                         tmp = node_parent(tmp);
56                 }
57         }
58
59         return path;
60 }
61
62 static inline int next_state(int from, char ch)
63 {
64         switch ( ch )
65         {
66                 case '/':
67                         return 1;
68                 case '.':
69                         if ( from == 1 ) return 2;
70                         if ( from == 2 ) return 3;
71         }
72
73         return 4;
74 }
75
76 static inline void abspath(char* pBuffer, char* pRet)
77 {
78         int idx=0;
79         int state = 1;
80         int from;
81         int src_idx = 0;
82         int src_len = strlen(pBuffer);
83         pRet[idx] = '/';
84         idx ++;
85
86         while (src_idx <= src_len) {
87                 from = state;
88                 state = next_state(from, pBuffer[src_idx]);
89
90                 switch (from) {
91                         case 1:
92                                 if ( state != 1 ) {
93                                         pRet[idx] = pBuffer[src_idx];
94                                         idx ++;
95                                 }
96                                 break;
97                         case 2:
98                                 if ( state == 1 ) {
99                                         if ( idx > 0 ) idx --;
100                                 } else {
101                                         pRet[idx] = pBuffer[src_idx];
102                                         idx ++;
103                                 }
104                                 break;
105                         case 3:
106                                 // Only can go to the 1 or 4
107                                 if ( state == 1 ) {
108                                         idx -= 2;
109                                         if ( idx < 0 ) idx = 0;
110
111                                         while ( idx > 0 && pRet[idx] != '/' ) idx --;
112                                         if ( idx > 0 && pRet[idx] == '/' ) idx --;
113                                         while ( idx > 0 && pRet[idx] != '/' ) idx --;
114                                 }
115                         case 4:
116                                 pRet[idx] = pBuffer[src_idx];
117                                 idx ++;
118                                 break;
119                 }
120
121                 pRet[idx] = '\0';
122                 src_idx ++;
123         }
124 }
125
126 struct node *node_find(const struct node *node, char *path)
127 {
128         int len;
129         char *ptr;
130         char *buffer;
131
132         buffer = malloc(strlen(path) + 3); /* add 2 more bytes */
133         if (!buffer)
134                 return NULL;
135
136         abspath(path, buffer);
137         ptr = buffer;
138
139         do {
140                 ptr += (*ptr == '/');
141                 for (len = 0; ptr[len] && ptr[len] != '/'; len++);
142                 if (!len)
143                         break;
144
145                 if (!strncmp("..", ptr, len)) {
146                         ptr += len;
147                         node = node->parent ? node->parent : node;
148                         continue;
149                 }
150
151                 if (!strncmp(".", ptr, len)) {
152                         ptr += len;
153                         continue;
154                 }
155
156                 node = node->child;
157                 if (!node) {
158                         free(buffer);
159                         return NULL;
160                 }
161
162                 while (node) {
163                         if (!strncmp(node->name, ptr, len) && node->name[len] == '\0') {
164                                 ptr += len;
165                                 break;
166                         }
167
168                         node = node->sibling.next;
169                 }
170         } while (*ptr && node);
171
172         free(buffer);
173         return (struct node *)node;
174 }
175
176 struct node *node_create(struct node *parent, const char *name, enum node_type type)
177 {
178         struct node *node;
179
180         node = malloc(sizeof(*node));
181         if (!node) {
182                 printf("Error: %s\n", strerror(errno));
183                 return NULL;
184         }
185
186         node->parent = parent;
187
188         if (name) {
189                 node->name = strdup(name);
190                 if (!node->name) {
191                         printf("Error: %s\n", strerror(errno));
192                         return NULL;
193                 }
194         } else {
195                 node->name = NULL;
196         }
197
198         node->type = type;
199
200         node->sibling.next = NULL;
201         node->sibling.prev = NULL;
202
203         node->child = NULL;
204         node->data = NULL;
205
206         if (parent) {
207                 if (parent->child) {
208                         struct node *tmp;
209                         tmp = parent->child;
210                         while (tmp->sibling.next)
211                                 tmp = tmp->sibling.next;
212
213                         tmp->sibling.next = node;
214                         node->sibling.prev = tmp;
215                 } else {
216                         parent->child = node;
217                 }
218         }
219         return node;
220 }
221
222 void node_destroy(struct node *node)
223 {
224         free(node->name);
225         free(node);
226 }
227
228 struct node * const node_next_sibling(const struct node *node)
229 {
230         return node->sibling.next;
231 }
232
233 struct node * const node_prev_sibling(const struct node *node)
234 {
235         return node->sibling.prev;
236 }
237
238 void node_set_mode(struct node *node, int mode)
239 {
240         node->mode = mode;
241 }
242
243 void node_set_data(struct node *node, void *data)
244 {
245         node->data = data;
246 }
247
248 void node_set_type(struct node *node, enum node_type type)
249 {
250         node->type = type;
251 }
252
253 struct node * const node_child(const struct node *node)
254 {
255         return node->child;
256 }
257
258 struct node * const node_parent(const struct node *node)
259 {
260         return node->parent;
261 }
262
263 const int const node_mode(const struct node *node)
264 {
265         return node->mode;
266 }
267
268 void * const node_data(const struct node *node)
269 {
270         return node->data;
271 }
272
273 const enum node_type const node_type(const struct node *node)
274 {
275         return node->type;
276 }
277
278 const char * const node_name(const struct node *node)
279 {
280         return node->name;
281 }
282
283 /* End of a file */