rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <string.h>
|
nuclear@3
|
4 #include <errno.h>
|
nuclear@0
|
5 #include "treestore.h"
|
nuclear@0
|
6
|
nuclear@3
|
7 struct ts_node *ts_text_load(FILE *fp);
|
nuclear@3
|
8 int ts_text_save(struct ts_node *tree, FILE *fp);
|
nuclear@3
|
9
|
nuclear@0
|
10 /* ---- ts_value implementation ---- */
|
nuclear@0
|
11
|
nuclear@0
|
12 int ts_init_value(struct ts_value *tsv)
|
nuclear@0
|
13 {
|
nuclear@0
|
14 memset(tsv, 0, sizeof *tsv);
|
nuclear@0
|
15 return 0;
|
nuclear@0
|
16 }
|
nuclear@0
|
17
|
nuclear@0
|
18 void ts_destroy_value(struct ts_value *tsv)
|
nuclear@0
|
19 {
|
nuclear@0
|
20 int i;
|
nuclear@0
|
21
|
nuclear@0
|
22 free(tsv->str);
|
nuclear@0
|
23 free(tsv->vec);
|
nuclear@0
|
24
|
nuclear@0
|
25 for(i=0; i<tsv->array_size; i++) {
|
nuclear@0
|
26 ts_destroy_value(tsv->array + i);
|
nuclear@0
|
27 }
|
nuclear@0
|
28 }
|
nuclear@0
|
29
|
nuclear@0
|
30
|
nuclear@0
|
31 struct ts_value *ts_alloc_value(void)
|
nuclear@0
|
32 {
|
nuclear@0
|
33 struct ts_value *v = malloc(sizeof *v);
|
nuclear@0
|
34 if(!v || ts_init_value(v) == -1) {
|
nuclear@0
|
35 free(v);
|
nuclear@0
|
36 return 0;
|
nuclear@0
|
37 }
|
nuclear@0
|
38 return v;
|
nuclear@0
|
39 }
|
nuclear@0
|
40
|
nuclear@0
|
41 void ts_free_value(struct ts_value *tsv)
|
nuclear@0
|
42 {
|
nuclear@0
|
43 ts_destroy_value(tsv);
|
nuclear@0
|
44 free(tsv);
|
nuclear@0
|
45 }
|
nuclear@0
|
46
|
nuclear@0
|
47
|
nuclear@0
|
48 int ts_copy_value(struct ts_value *dest, struct ts_value *src)
|
nuclear@0
|
49 {
|
nuclear@0
|
50 int i;
|
nuclear@0
|
51
|
nuclear@0
|
52 if(dest == src) return 0;
|
nuclear@0
|
53
|
nuclear@0
|
54 *dest = *src;
|
nuclear@0
|
55
|
nuclear@0
|
56 dest->str = 0;
|
nuclear@0
|
57 dest->vec = 0;
|
nuclear@0
|
58 dest->array = 0;
|
nuclear@0
|
59
|
nuclear@0
|
60 if(src->str) {
|
nuclear@0
|
61 if(!(dest->str = malloc(strlen(src->str) + 1))) {
|
nuclear@0
|
62 goto fail;
|
nuclear@0
|
63 }
|
nuclear@0
|
64 strcpy(dest->str, src->str);
|
nuclear@0
|
65 }
|
nuclear@0
|
66 if(src->vec && src->vec_size > 0) {
|
nuclear@0
|
67 if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) {
|
nuclear@0
|
68 goto fail;
|
nuclear@0
|
69 }
|
nuclear@0
|
70 memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec);
|
nuclear@0
|
71 }
|
nuclear@0
|
72 if(src->array && src->array_size > 0) {
|
nuclear@0
|
73 if(!(dest->array = calloc(src->array_size, sizeof *src->array))) {
|
nuclear@0
|
74 goto fail;
|
nuclear@0
|
75 }
|
nuclear@0
|
76 for(i=0; i<src->array_size; i++) {
|
nuclear@0
|
77 if(ts_copy_value(dest->array + i, src->array + i) == -1) {
|
nuclear@0
|
78 goto fail;
|
nuclear@0
|
79 }
|
nuclear@0
|
80 }
|
nuclear@0
|
81 }
|
nuclear@0
|
82 return 0;
|
nuclear@0
|
83
|
nuclear@0
|
84 fail:
|
nuclear@0
|
85 free(dest->str);
|
nuclear@0
|
86 free(dest->vec);
|
nuclear@0
|
87 if(dest->array) {
|
nuclear@0
|
88 for(i=0; i<dest->array_size; i++) {
|
nuclear@0
|
89 ts_destroy_value(dest->array + i);
|
nuclear@0
|
90 }
|
nuclear@0
|
91 free(dest->array);
|
nuclear@0
|
92 }
|
nuclear@0
|
93 return -1;
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@4
|
96 struct val_list_node {
|
nuclear@4
|
97 struct ts_value val;
|
nuclear@4
|
98 struct val_list_node *next;
|
nuclear@4
|
99 };
|
nuclear@0
|
100
|
nuclear@0
|
101 int ts_set_value(struct ts_value *tsv, const char *str)
|
nuclear@0
|
102 {
|
nuclear@4
|
103 char *endp;
|
nuclear@4
|
104
|
nuclear@0
|
105 if(tsv->str) {
|
nuclear@0
|
106 ts_destroy_value(tsv);
|
nuclear@0
|
107 if(ts_init_value(tsv) == -1) {
|
nuclear@0
|
108 return -1;
|
nuclear@0
|
109 }
|
nuclear@0
|
110 }
|
nuclear@0
|
111
|
nuclear@4
|
112 tsv->type = TS_STRING;
|
nuclear@0
|
113 if(!(tsv->str = malloc(strlen(str) + 1))) {
|
nuclear@0
|
114 return -1;
|
nuclear@0
|
115 }
|
nuclear@0
|
116 strcpy(tsv->str, str);
|
nuclear@4
|
117
|
nuclear@4
|
118 /* try to parse the string and see if it fits any of the value types */
|
nuclear@4
|
119 if(*str == '[' || *str == '{') {
|
nuclear@4
|
120 /* try to parse as a vector */
|
nuclear@4
|
121 struct val_list_node *list = 0, *tail = 0, *node;
|
nuclear@4
|
122 int nelem = 0;
|
nuclear@4
|
123 char endsym = *str++ + 2; /* ']' is '[' + 2 and '}' is '{' + 2 */
|
nuclear@4
|
124
|
nuclear@4
|
125 while(*str && *str != endsym) {
|
nuclear@4
|
126 float val = strtod(str, &endp);
|
nuclear@4
|
127 if(endp == str || !(node = malloc(sizeof *node))) {
|
nuclear@4
|
128 break;
|
nuclear@4
|
129 }
|
nuclear@4
|
130 ts_init_value(&node->val);
|
nuclear@4
|
131 ts_set_valuef(&node->val, val);
|
nuclear@4
|
132 node->next = 0;
|
nuclear@4
|
133
|
nuclear@4
|
134 if(list) {
|
nuclear@4
|
135 tail->next = node;
|
nuclear@4
|
136 tail = node;
|
nuclear@4
|
137 } else {
|
nuclear@4
|
138 list = tail = node;
|
nuclear@4
|
139 }
|
nuclear@4
|
140 ++nelem;
|
nuclear@4
|
141 str = endp;
|
nuclear@4
|
142 }
|
nuclear@4
|
143
|
nuclear@4
|
144 if(nelem && (tsv->array = malloc(nelem * sizeof *tsv->array)) &&
|
nuclear@4
|
145 (tsv->vec = malloc(nelem * sizeof *tsv->vec))) {
|
nuclear@4
|
146 int idx = 0;
|
nuclear@4
|
147 while(list) {
|
nuclear@4
|
148 node = list;
|
nuclear@4
|
149 list = list->next;
|
nuclear@4
|
150
|
nuclear@4
|
151 tsv->array[idx] = node->val;
|
nuclear@4
|
152 tsv->vec[idx] = node->val.fnum;
|
nuclear@4
|
153 ++idx;
|
nuclear@4
|
154 free(node);
|
nuclear@4
|
155 }
|
nuclear@4
|
156 tsv->type = TS_VECTOR;
|
nuclear@4
|
157 }
|
nuclear@4
|
158
|
nuclear@4
|
159 } else if((tsv->fnum = strtod(str, &endp)), endp != str) {
|
nuclear@4
|
160 /* it's a number I guess... */
|
nuclear@4
|
161 tsv->type = TS_NUMBER;
|
nuclear@4
|
162 }
|
nuclear@4
|
163
|
nuclear@0
|
164 return 0;
|
nuclear@0
|
165 }
|
nuclear@0
|
166
|
nuclear@0
|
167 int ts_set_valueiv(struct ts_value *tsv, int count, ...)
|
nuclear@0
|
168 {
|
nuclear@0
|
169 int res;
|
nuclear@0
|
170 va_list ap;
|
nuclear@0
|
171 va_start(ap, count);
|
nuclear@0
|
172 res = ts_set_valueiv_va(tsv, count, ap);
|
nuclear@0
|
173 va_end(ap);
|
nuclear@0
|
174 return res;
|
nuclear@0
|
175 }
|
nuclear@0
|
176
|
nuclear@0
|
177 #define MAKE_NUMSTR_FUNC(typestr, fmt) \
|
nuclear@0
|
178 static char *make_##typestr##str(int x) \
|
nuclear@0
|
179 { \
|
nuclear@0
|
180 static char scrap[128]; \
|
nuclear@0
|
181 char *str; \
|
nuclear@0
|
182 int sz = snprintf(scrap, sizeof scrap, fmt, x); \
|
nuclear@0
|
183 if(!(str = malloc(sz + 1))) return 0; \
|
nuclear@0
|
184 sprintf(str, fmt, x); \
|
nuclear@0
|
185 return str; \
|
nuclear@0
|
186 }
|
nuclear@0
|
187
|
nuclear@0
|
188 MAKE_NUMSTR_FUNC(int, "%d")
|
nuclear@0
|
189 MAKE_NUMSTR_FUNC(float, "%d")
|
nuclear@0
|
190
|
nuclear@0
|
191 #define ARGS_ARE_INT ((enum ts_value_type)42)
|
nuclear@0
|
192
|
nuclear@0
|
193 int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap)
|
nuclear@0
|
194 {
|
nuclear@0
|
195 if(count < 1) return -1;
|
nuclear@0
|
196 if(count == 1) {
|
nuclear@0
|
197 int num = va_arg(ap, int);
|
nuclear@0
|
198 if(!(tsv->str = make_intstr(tsv->inum))) {
|
nuclear@0
|
199 return -1;
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 tsv->type = TS_NUMBER;
|
nuclear@0
|
203 tsv->inum = num;
|
nuclear@0
|
204 tsv->fnum = (float)num;
|
nuclear@0
|
205 return 0;
|
nuclear@0
|
206 }
|
nuclear@0
|
207
|
nuclear@0
|
208 /* otherwise it's an array, let ts_set_valuefv_va handle it */
|
nuclear@0
|
209 /* XXX: va_arg will need to be called with int instead of float. set a special
|
nuclear@0
|
210 * value to the type field before calling this, to signify that.
|
nuclear@0
|
211 */
|
nuclear@0
|
212 tsv->type = ARGS_ARE_INT;
|
nuclear@0
|
213 return ts_set_valuefv_va(tsv, count, ap);
|
nuclear@0
|
214 }
|
nuclear@0
|
215
|
nuclear@0
|
216 int ts_set_valuei(struct ts_value *tsv, int inum)
|
nuclear@0
|
217 {
|
nuclear@0
|
218 return ts_set_valueiv(tsv, 1, inum);
|
nuclear@0
|
219 }
|
nuclear@0
|
220
|
nuclear@0
|
221
|
nuclear@0
|
222 int ts_set_valuefv(struct ts_value *tsv, int count, ...)
|
nuclear@0
|
223 {
|
nuclear@0
|
224 int res;
|
nuclear@0
|
225 va_list ap;
|
nuclear@0
|
226 va_start(ap, count);
|
nuclear@0
|
227 res = ts_set_valuefv_va(tsv, count, ap);
|
nuclear@0
|
228 va_end(ap);
|
nuclear@0
|
229 return res;
|
nuclear@0
|
230 }
|
nuclear@0
|
231
|
nuclear@0
|
232 int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap)
|
nuclear@0
|
233 {
|
nuclear@0
|
234 int i;
|
nuclear@0
|
235
|
nuclear@0
|
236 if(count < 1) return -1;
|
nuclear@0
|
237 if(count == 1) {
|
nuclear@0
|
238 int num = va_arg(ap, int);
|
nuclear@0
|
239 if(!(tsv->str = make_floatstr(tsv->inum))) {
|
nuclear@0
|
240 return -1;
|
nuclear@0
|
241 }
|
nuclear@0
|
242
|
nuclear@0
|
243 tsv->type = TS_NUMBER;
|
nuclear@0
|
244 tsv->inum = num;
|
nuclear@0
|
245 tsv->fnum = (float)num;
|
nuclear@0
|
246 return 0;
|
nuclear@0
|
247 }
|
nuclear@0
|
248
|
nuclear@0
|
249 /* otherwise it's an array, we need to create the ts_value array, and
|
nuclear@0
|
250 * the simplified vector
|
nuclear@0
|
251 */
|
nuclear@0
|
252 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
|
nuclear@0
|
253 return -1;
|
nuclear@0
|
254 }
|
nuclear@0
|
255 tsv->vec_size = count;
|
nuclear@0
|
256
|
nuclear@0
|
257 for(i=0; i<count; i++) {
|
nuclear@0
|
258 if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */
|
nuclear@0
|
259 tsv->vec[i] = (float)va_arg(ap, int);
|
nuclear@0
|
260 } else {
|
nuclear@0
|
261 tsv->vec[i] = va_arg(ap, double);
|
nuclear@0
|
262 }
|
nuclear@0
|
263 }
|
nuclear@0
|
264
|
nuclear@0
|
265 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
|
nuclear@0
|
266 free(tsv->vec);
|
nuclear@0
|
267 }
|
nuclear@0
|
268 tsv->array_size = count;
|
nuclear@0
|
269
|
nuclear@0
|
270 for(i=0; i<count; i++) {
|
nuclear@0
|
271 ts_init_value(tsv->array + i);
|
nuclear@0
|
272 if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */
|
nuclear@0
|
273 ts_set_valuei(tsv->array + i, (int)tsv->vec[i]);
|
nuclear@0
|
274 } else {
|
nuclear@0
|
275 ts_set_valuef(tsv->array + i, tsv->vec[i]);
|
nuclear@0
|
276 }
|
nuclear@0
|
277 }
|
nuclear@0
|
278
|
nuclear@0
|
279 tsv->type = TS_VECTOR;
|
nuclear@0
|
280 return 0;
|
nuclear@0
|
281 }
|
nuclear@0
|
282
|
nuclear@4
|
283 int ts_set_valuef(struct ts_value *tsv, float fnum)
|
nuclear@0
|
284 {
|
nuclear@0
|
285 return ts_set_valuefv(tsv, 1, fnum);
|
nuclear@0
|
286 }
|
nuclear@0
|
287
|
nuclear@0
|
288
|
nuclear@0
|
289 int ts_set_valuev(struct ts_value *tsv, int count, ...)
|
nuclear@0
|
290 {
|
nuclear@0
|
291 int res;
|
nuclear@0
|
292 va_list ap;
|
nuclear@0
|
293 va_start(ap, count);
|
nuclear@0
|
294 res = ts_set_valuev_va(tsv, count, ap);
|
nuclear@0
|
295 va_end(ap);
|
nuclear@0
|
296 return res;
|
nuclear@0
|
297 }
|
nuclear@0
|
298
|
nuclear@0
|
299 int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap)
|
nuclear@0
|
300 {
|
nuclear@1
|
301 int i;
|
nuclear@1
|
302
|
nuclear@0
|
303 if(count <= 1) return -1;
|
nuclear@1
|
304
|
nuclear@1
|
305 if((tsv->array = malloc(count * sizeof *tsv->array))) {
|
nuclear@1
|
306 return -1;
|
nuclear@1
|
307 }
|
nuclear@1
|
308 tsv->array_size = count;
|
nuclear@1
|
309
|
nuclear@1
|
310 for(i=0; i<count; i++) {
|
nuclear@1
|
311 struct ts_value *src = va_arg(ap, struct ts_value*);
|
nuclear@1
|
312 ts_copy_value(tsv->array + i, src);
|
nuclear@1
|
313 }
|
nuclear@1
|
314 return 0;
|
nuclear@0
|
315 }
|
nuclear@1
|
316
|
nuclear@1
|
317
|
nuclear@1
|
318 /* ---- ts_attr implementation ---- */
|
nuclear@1
|
319
|
nuclear@1
|
320 int ts_init_attr(struct ts_attr *attr)
|
nuclear@1
|
321 {
|
nuclear@1
|
322 memset(attr, 0, sizeof *attr);
|
nuclear@1
|
323 return ts_init_value(&attr->val);
|
nuclear@1
|
324 }
|
nuclear@1
|
325
|
nuclear@1
|
326 void ts_destroy_attr(struct ts_attr *attr)
|
nuclear@1
|
327 {
|
nuclear@1
|
328 free(attr->name);
|
nuclear@1
|
329 ts_destroy_value(&attr->val);
|
nuclear@1
|
330 }
|
nuclear@1
|
331
|
nuclear@1
|
332 struct ts_attr *ts_alloc_attr(void)
|
nuclear@1
|
333 {
|
nuclear@1
|
334 struct ts_attr *attr = malloc(sizeof *attr);
|
nuclear@1
|
335 if(!attr || ts_init_attr(attr) == -1) {
|
nuclear@1
|
336 free(attr);
|
nuclear@1
|
337 return 0;
|
nuclear@1
|
338 }
|
nuclear@1
|
339 return attr;
|
nuclear@1
|
340 }
|
nuclear@1
|
341
|
nuclear@1
|
342 void ts_free_attr(struct ts_attr *attr)
|
nuclear@1
|
343 {
|
nuclear@1
|
344 ts_destroy_attr(attr);
|
nuclear@1
|
345 free(attr);
|
nuclear@1
|
346 }
|
nuclear@1
|
347
|
nuclear@1
|
348 int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src)
|
nuclear@1
|
349 {
|
nuclear@1
|
350 if(dest == src) return 0;
|
nuclear@1
|
351
|
nuclear@1
|
352 if(ts_set_attr_name(dest, src->name) == -1) {
|
nuclear@1
|
353 return -1;
|
nuclear@1
|
354 }
|
nuclear@1
|
355
|
nuclear@1
|
356 if(ts_copy_value(&dest->val, &src->val) == -1) {
|
nuclear@1
|
357 ts_destroy_attr(dest);
|
nuclear@1
|
358 return -1;
|
nuclear@1
|
359 }
|
nuclear@1
|
360 return 0;
|
nuclear@1
|
361 }
|
nuclear@1
|
362
|
nuclear@1
|
363 int ts_set_attr_name(struct ts_attr *attr, const char *name)
|
nuclear@1
|
364 {
|
nuclear@1
|
365 char *n = malloc(strlen(name) + 1);
|
nuclear@1
|
366 if(!n) return -1;
|
nuclear@1
|
367 strcpy(n, name);
|
nuclear@1
|
368
|
nuclear@1
|
369 free(attr->name);
|
nuclear@1
|
370 attr->name = n;
|
nuclear@1
|
371 return 0;
|
nuclear@1
|
372 }
|
nuclear@1
|
373
|
nuclear@1
|
374
|
nuclear@1
|
375 /* ---- ts_node implementation ---- */
|
nuclear@1
|
376
|
nuclear@1
|
377 int ts_init_node(struct ts_node *node)
|
nuclear@1
|
378 {
|
nuclear@1
|
379 memset(node, 0, sizeof *node);
|
nuclear@1
|
380 return 0;
|
nuclear@1
|
381 }
|
nuclear@1
|
382
|
nuclear@1
|
383 void ts_destroy_node(struct ts_node *node)
|
nuclear@1
|
384 {
|
nuclear@5
|
385 if(!node) return;
|
nuclear@5
|
386
|
nuclear@1
|
387 free(node->name);
|
nuclear@1
|
388
|
nuclear@1
|
389 while(node->attr_list) {
|
nuclear@1
|
390 struct ts_attr *attr = node->attr_list;
|
nuclear@1
|
391 node->attr_list = node->attr_list->next;
|
nuclear@1
|
392 ts_free_attr(attr);
|
nuclear@1
|
393 }
|
nuclear@1
|
394 }
|
nuclear@1
|
395
|
nuclear@1
|
396 struct ts_node *ts_alloc_node(void)
|
nuclear@1
|
397 {
|
nuclear@1
|
398 struct ts_node *node = malloc(sizeof *node);
|
nuclear@1
|
399 if(!node || ts_init_node(node) == -1) {
|
nuclear@1
|
400 free(node);
|
nuclear@1
|
401 return 0;
|
nuclear@1
|
402 }
|
nuclear@1
|
403 return node;
|
nuclear@1
|
404 }
|
nuclear@1
|
405
|
nuclear@1
|
406 void ts_free_node(struct ts_node *node)
|
nuclear@1
|
407 {
|
nuclear@1
|
408 ts_destroy_node(node);
|
nuclear@1
|
409 free(node);
|
nuclear@1
|
410 }
|
nuclear@1
|
411
|
nuclear@1
|
412 void ts_free_tree(struct ts_node *tree)
|
nuclear@1
|
413 {
|
nuclear@5
|
414 if(!tree) return;
|
nuclear@5
|
415
|
nuclear@1
|
416 while(tree->child_list) {
|
nuclear@2
|
417 struct ts_node *child = tree->child_list;
|
nuclear@1
|
418 tree->child_list = tree->child_list->next;
|
nuclear@1
|
419 ts_free_tree(child);
|
nuclear@1
|
420 }
|
nuclear@1
|
421
|
nuclear@1
|
422 ts_free_node(tree);
|
nuclear@1
|
423 }
|
nuclear@3
|
424
|
nuclear@3
|
425 void ts_add_attr(struct ts_node *node, struct ts_attr *attr)
|
nuclear@3
|
426 {
|
nuclear@3
|
427 attr->next = 0;
|
nuclear@3
|
428 if(node->attr_list) {
|
nuclear@3
|
429 node->attr_tail->next = attr;
|
nuclear@3
|
430 node->attr_tail = attr;
|
nuclear@3
|
431 } else {
|
nuclear@3
|
432 node->attr_list = node->attr_tail = attr;
|
nuclear@3
|
433 }
|
nuclear@3
|
434 }
|
nuclear@3
|
435
|
nuclear@3
|
436 struct ts_attr *ts_get_attr(struct ts_node *node, const char *name)
|
nuclear@3
|
437 {
|
nuclear@3
|
438 struct ts_attr *attr = node->attr_list;
|
nuclear@3
|
439 while(attr) {
|
nuclear@3
|
440 if(strcmp(attr->name, name) == 0) {
|
nuclear@3
|
441 return attr;
|
nuclear@3
|
442 }
|
nuclear@3
|
443 attr = attr->next;
|
nuclear@3
|
444 }
|
nuclear@3
|
445 return 0;
|
nuclear@3
|
446 }
|
nuclear@3
|
447
|
nuclear@4
|
448 const char *ts_get_attr_str(struct ts_node *node, const char *aname, const char *def_val)
|
nuclear@4
|
449 {
|
nuclear@4
|
450 struct ts_attr *attr = ts_get_attr(node, aname);
|
nuclear@4
|
451 if(!attr || !attr->val.str) {
|
nuclear@4
|
452 return def_val;
|
nuclear@4
|
453 }
|
nuclear@4
|
454 return attr->val.str;
|
nuclear@4
|
455 }
|
nuclear@4
|
456
|
nuclear@4
|
457 float ts_get_attr_num(struct ts_node *node, const char *aname, float def_val)
|
nuclear@4
|
458 {
|
nuclear@4
|
459 struct ts_attr *attr = ts_get_attr(node, aname);
|
nuclear@4
|
460 if(!attr || attr->val.type != TS_NUMBER) {
|
nuclear@4
|
461 return def_val;
|
nuclear@4
|
462 }
|
nuclear@4
|
463 return attr->val.fnum;
|
nuclear@4
|
464 }
|
nuclear@4
|
465
|
nuclear@4
|
466 int ts_get_attr_int(struct ts_node *node, const char *aname, int def_val)
|
nuclear@4
|
467 {
|
nuclear@4
|
468 struct ts_attr *attr = ts_get_attr(node, aname);
|
nuclear@4
|
469 if(!attr || attr->val.type != TS_NUMBER) {
|
nuclear@4
|
470 return def_val;
|
nuclear@4
|
471 }
|
nuclear@4
|
472 return attr->val.inum;
|
nuclear@4
|
473 }
|
nuclear@4
|
474
|
nuclear@4
|
475 float *ts_get_attr_vec(struct ts_node *node, const char *aname, float *def_val)
|
nuclear@4
|
476 {
|
nuclear@4
|
477 struct ts_attr *attr = ts_get_attr(node, aname);
|
nuclear@4
|
478 if(!attr || !attr->val.vec) {
|
nuclear@4
|
479 return def_val;
|
nuclear@4
|
480 }
|
nuclear@4
|
481 return attr->val.vec;
|
nuclear@4
|
482 }
|
nuclear@4
|
483
|
nuclear@4
|
484 struct ts_value *ts_get_attr_array(struct ts_node *node, const char *aname, struct ts_value *def_val)
|
nuclear@4
|
485 {
|
nuclear@4
|
486 struct ts_attr *attr = ts_get_attr(node, aname);
|
nuclear@4
|
487 if(!attr || !attr->val.array) {
|
nuclear@4
|
488 return def_val;
|
nuclear@4
|
489 }
|
nuclear@4
|
490 return attr->val.array;
|
nuclear@4
|
491 }
|
nuclear@4
|
492
|
nuclear@3
|
493 void ts_add_child(struct ts_node *node, struct ts_node *child)
|
nuclear@3
|
494 {
|
nuclear@3
|
495 if(child->parent) {
|
nuclear@3
|
496 if(child->parent == node) return;
|
nuclear@3
|
497 ts_remove_child(child->parent, child);
|
nuclear@3
|
498 }
|
nuclear@3
|
499 child->parent = node;
|
nuclear@3
|
500 child->next = 0;
|
nuclear@3
|
501
|
nuclear@3
|
502 if(node->child_list) {
|
nuclear@3
|
503 node->child_tail->next = child;
|
nuclear@3
|
504 node->child_tail = child;
|
nuclear@3
|
505 } else {
|
nuclear@3
|
506 node->child_list = node->child_tail = child;
|
nuclear@3
|
507 }
|
nuclear@3
|
508 }
|
nuclear@3
|
509
|
nuclear@3
|
510 int ts_remove_child(struct ts_node *node, struct ts_node *child)
|
nuclear@3
|
511 {
|
nuclear@3
|
512 struct ts_node dummy, *iter = &dummy;
|
nuclear@3
|
513 dummy.next = node->child_list;
|
nuclear@3
|
514
|
nuclear@3
|
515 while(iter->next && iter->next != child) {
|
nuclear@3
|
516 iter = iter->next;
|
nuclear@3
|
517 }
|
nuclear@3
|
518 if(!iter->next) {
|
nuclear@3
|
519 return -1;
|
nuclear@3
|
520 }
|
nuclear@3
|
521
|
nuclear@3
|
522 child->parent = 0;
|
nuclear@3
|
523
|
nuclear@3
|
524 iter->next = child->next;
|
nuclear@3
|
525 if(!iter->next) {
|
nuclear@3
|
526 node->child_tail = iter;
|
nuclear@3
|
527 }
|
nuclear@3
|
528 node->child_list = dummy.next;
|
nuclear@3
|
529 return 0;
|
nuclear@3
|
530 }
|
nuclear@3
|
531
|
nuclear@3
|
532 struct ts_node *ts_get_child(struct ts_node *node, const char *name)
|
nuclear@3
|
533 {
|
nuclear@3
|
534 struct ts_node *res = node->child_list;
|
nuclear@3
|
535 while(res) {
|
nuclear@3
|
536 if(strcmp(res->name, name) == 0) {
|
nuclear@3
|
537 return res;
|
nuclear@3
|
538 }
|
nuclear@3
|
539 res = res->next;
|
nuclear@3
|
540 }
|
nuclear@3
|
541 return 0;
|
nuclear@3
|
542 }
|
nuclear@3
|
543
|
nuclear@3
|
544 struct ts_node *ts_load(const char *fname)
|
nuclear@3
|
545 {
|
nuclear@3
|
546 FILE *fp;
|
nuclear@3
|
547 struct ts_node *root;
|
nuclear@3
|
548
|
nuclear@3
|
549 if(!(fp = fopen(fname, "rb"))) {
|
nuclear@3
|
550 fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno));
|
nuclear@3
|
551 return 0;
|
nuclear@3
|
552 }
|
nuclear@3
|
553
|
nuclear@3
|
554 root = ts_text_load(fp);
|
nuclear@3
|
555 fclose(fp);
|
nuclear@3
|
556 return root;
|
nuclear@3
|
557 }
|
nuclear@3
|
558
|
nuclear@3
|
559 int ts_save(struct ts_node *tree, const char *fname)
|
nuclear@3
|
560 {
|
nuclear@3
|
561 FILE *fp;
|
nuclear@3
|
562 int res;
|
nuclear@3
|
563
|
nuclear@3
|
564 if(!(fp = fopen(fname, "wb"))) {
|
nuclear@3
|
565 fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno));
|
nuclear@3
|
566 return 0;
|
nuclear@3
|
567 }
|
nuclear@3
|
568 res = ts_text_save(tree, fp);
|
nuclear@3
|
569 fclose(fp);
|
nuclear@3
|
570 return res;
|
nuclear@3
|
571 }
|