- load rudimentary level file
[cyberay] / libs / treestore / treestore.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include "treestore.h"
7
8 #ifdef WIN32
9 #include <malloc.h>
10 #else
11 #include <alloca.h>
12 #endif
13
14 struct ts_node *ts_text_load(struct ts_io *io);
15 int ts_text_save(struct ts_node *tree, struct ts_io *io);
16
17 static long io_read(void *buf, size_t bytes, void *uptr);
18 static long io_write(const void *buf, size_t bytes, void *uptr);
19
20
21 /* ---- ts_value implementation ---- */
22
23 int ts_init_value(struct ts_value *tsv)
24 {
25         memset(tsv, 0, sizeof *tsv);
26         return 0;
27 }
28
29 void ts_destroy_value(struct ts_value *tsv)
30 {
31         int i;
32
33         free(tsv->str);
34         free(tsv->vec);
35
36         for(i=0; i<tsv->array_size; i++) {
37                 ts_destroy_value(tsv->array + i);
38         }
39         free(tsv->array);
40 }
41
42
43 struct ts_value *ts_alloc_value(void)
44 {
45         struct ts_value *v = malloc(sizeof *v);
46         if(!v || ts_init_value(v) == -1) {
47                 free(v);
48                 return 0;
49         }
50         return v;
51 }
52
53 void ts_free_value(struct ts_value *tsv)
54 {
55         ts_destroy_value(tsv);
56         free(tsv);
57 }
58
59
60 int ts_copy_value(struct ts_value *dest, struct ts_value *src)
61 {
62         int i;
63
64         if(dest == src) return 0;
65
66         *dest = *src;
67
68         dest->str = 0;
69         dest->vec = 0;
70         dest->array = 0;
71
72         if(src->str) {
73                 if(!(dest->str = malloc(strlen(src->str) + 1))) {
74                         goto fail;
75                 }
76                 strcpy(dest->str, src->str);
77         }
78         if(src->vec && src->vec_size > 0) {
79                 if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) {
80                         goto fail;
81                 }
82                 memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec);
83         }
84         if(src->array && src->array_size > 0) {
85                 if(!(dest->array = calloc(src->array_size, sizeof *src->array))) {
86                         goto fail;
87                 }
88                 for(i=0; i<src->array_size; i++) {
89                         if(ts_copy_value(dest->array + i, src->array + i) == -1) {
90                                 goto fail;
91                         }
92                 }
93         }
94         return 0;
95
96 fail:
97         free(dest->str);
98         free(dest->vec);
99         if(dest->array) {
100                 for(i=0; i<dest->array_size; i++) {
101                         ts_destroy_value(dest->array + i);
102                 }
103                 free(dest->array);
104         }
105         return -1;
106 }
107
108 #define MAKE_NUMSTR_FUNC(type, fmt) \
109         static char *make_##type##str(type x) \
110         { \
111                 static char scrap[128]; \
112                 char *str; \
113                 int sz = snprintf(scrap, sizeof scrap, fmt, x); \
114                 if(!(str = malloc(sz + 1))) return 0; \
115                 sprintf(str, fmt, x); \
116                 return str; \
117         }
118
119 MAKE_NUMSTR_FUNC(int, "%d")
120 MAKE_NUMSTR_FUNC(float, "%g")
121
122
123 struct val_list_node {
124         struct ts_value val;
125         struct val_list_node *next;
126 };
127
128 int ts_set_value_str(struct ts_value *tsv, const char *str)
129 {
130         if(tsv->str) {
131                 ts_destroy_value(tsv);
132                 if(ts_init_value(tsv) == -1) {
133                         return -1;
134                 }
135         }
136
137         tsv->type = TS_STRING;
138         if(!(tsv->str = malloc(strlen(str) + 1))) {
139                 return -1;
140         }
141         strcpy(tsv->str, str);
142
143 #if 0
144         /* try to parse the string and see if it fits any of the value types */
145         if(*str == '[' || *str == '{') {
146                 /* try to parse as a vector */
147                 struct val_list_node *list = 0, *tail = 0, *node;
148                 int nelem = 0;
149                 char endsym = *str++ + 2;       /* ']' is '[' + 2 and '}' is '{' + 2 */
150
151                 while(*str && *str != endsym) {
152                         float val = strtod(str, &endp);
153                         if(endp == str || !(node = malloc(sizeof *node))) {
154                                 break;
155                         }
156                         ts_init_value(&node->val);
157                         ts_set_valuef(&node->val, val);
158                         node->next = 0;
159
160                         if(list) {
161                                 tail->next = node;
162                                 tail = node;
163                         } else {
164                                 list = tail = node;
165                         }
166                         ++nelem;
167                         str = endp;
168                 }
169
170                 if(nelem && (tsv->array = malloc(nelem * sizeof *tsv->array)) &&
171                                 (tsv->vec = malloc(nelem * sizeof *tsv->vec))) {
172                         int idx = 0;
173                         while(list) {
174                                 node = list;
175                                 list = list->next;
176
177                                 tsv->array[idx] = node->val;
178                                 tsv->vec[idx] = node->val.fnum;
179                                 ++idx;
180                                 free(node);
181                         }
182                         tsv->type = TS_VECTOR;
183                 }
184
185         } else if((tsv->fnum = strtod(str, &endp)), endp != str) {
186                 /* it's a number I guess... */
187                 tsv->type = TS_NUMBER;
188         }
189 #endif
190
191         return 0;
192 }
193
194 int ts_set_valuei_arr(struct ts_value *tsv, int count, const int *arr)
195 {
196         int i;
197
198         if(count < 1) return -1;
199         if(count == 1) {
200                 if(!(tsv->str = make_intstr(*arr))) {
201                         return -1;
202                 }
203
204                 tsv->type = TS_NUMBER;
205                 tsv->fnum = (float)*arr;
206                 tsv->inum = *arr;
207                 return 0;
208         }
209
210         /* otherwise it's an array, we need to create the ts_value array, and
211          * the simplified vector
212          */
213         if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
214                 return -1;
215         }
216         tsv->vec_size = count;
217
218         for(i=0; i<count; i++) {
219                 tsv->vec[i] = arr[i];
220         }
221
222         if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
223                 free(tsv->vec);
224         }
225         tsv->array_size = count;
226
227         for(i=0; i<count; i++) {
228                 ts_init_value(tsv->array + i);
229                 ts_set_valuef(tsv->array + i, arr[i]);
230         }
231
232         tsv->type = TS_VECTOR;
233         return 0;
234 }
235
236 int ts_set_valueiv(struct ts_value *tsv, int count, ...)
237 {
238         int res;
239         va_list ap;
240         va_start(ap, count);
241         res = ts_set_valueiv_va(tsv, count, ap);
242         va_end(ap);
243         return res;
244 }
245
246 int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap)
247 {
248         int i, *vec;
249
250         if(count < 1) return -1;
251         if(count == 1) {
252                 int num = va_arg(ap, int);
253                 ts_set_valuei(tsv, num);
254                 return 0;
255         }
256
257         vec = alloca(count * sizeof *vec);
258         for(i=0; i<count; i++) {
259                 vec[i] = va_arg(ap, int);
260         }
261         return ts_set_valuei_arr(tsv, count, vec);
262 }
263
264 int ts_set_valuei(struct ts_value *tsv, int inum)
265 {
266         return ts_set_valuei_arr(tsv, 1, &inum);
267 }
268
269 int ts_set_valuef_arr(struct ts_value *tsv, int count, const float *arr)
270 {
271         int i;
272
273         if(count < 1) return -1;
274         if(count == 1) {
275                 if(!(tsv->str = make_floatstr(*arr))) {
276                         return -1;
277                 }
278
279                 tsv->type = TS_NUMBER;
280                 tsv->fnum = *arr;
281                 tsv->inum = (int)*arr;
282                 return 0;
283         }
284
285         /* otherwise it's an array, we need to create the ts_value array, and
286          * the simplified vector
287          */
288         if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
289                 return -1;
290         }
291         tsv->vec_size = count;
292
293         for(i=0; i<count; i++) {
294                 tsv->vec[i] = arr[i];
295         }
296
297         if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
298                 free(tsv->vec);
299         }
300         tsv->array_size = count;
301
302         for(i=0; i<count; i++) {
303                 ts_init_value(tsv->array + i);
304                 ts_set_valuef(tsv->array + i, arr[i]);
305         }
306
307         tsv->type = TS_VECTOR;
308         return 0;
309 }
310
311 int ts_set_valuefv(struct ts_value *tsv, int count, ...)
312 {
313         int res;
314         va_list ap;
315         va_start(ap, count);
316         res = ts_set_valuefv_va(tsv, count, ap);
317         va_end(ap);
318         return res;
319 }
320
321 int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap)
322 {
323         int i;
324         float *vec;
325
326         if(count < 1) return -1;
327         if(count == 1) {
328                 float num = va_arg(ap, double);
329                 ts_set_valuef(tsv, num);
330                 return 0;
331         }
332
333         vec = alloca(count * sizeof *vec);
334         for(i=0; i<count; i++) {
335                 vec[i] = va_arg(ap, double);
336         }
337         return ts_set_valuef_arr(tsv, count, vec);
338 }
339
340 int ts_set_valuef(struct ts_value *tsv, float fnum)
341 {
342         return ts_set_valuef_arr(tsv, 1, &fnum);
343 }
344
345 int ts_set_value_arr(struct ts_value *tsv, int count, const struct ts_value *arr)
346 {
347         int i, allnum = 1;
348
349         if(count <= 1) return -1;
350
351         if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
352                 return -1;
353         }
354         tsv->array_size = count;
355
356         for(i=0; i<count; i++) {
357                 if(arr[i].type != TS_NUMBER) {
358                         allnum = 0;
359                 }
360                 if(ts_copy_value(tsv->array + i, (struct ts_value*)arr + i) == -1) {
361                         while(--i >= 0) {
362                                 ts_destroy_value(tsv->array + i);
363                         }
364                         free(tsv->array);
365                         tsv->array = 0;
366                         return -1;
367                 }
368         }
369
370         if(allnum) {
371                 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
372                         ts_destroy_value(tsv);
373                         return -1;
374                 }
375                 tsv->type = TS_VECTOR;
376                 tsv->vec_size = count;
377
378                 for(i=0; i<count; i++) {
379                         tsv->vec[i] = tsv->array[i].fnum;
380                 }
381         } else {
382                 tsv->type = TS_ARRAY;
383         }
384         return 0;
385 }
386
387 int ts_set_valuev(struct ts_value *tsv, int count, ...)
388 {
389         int res;
390         va_list ap;
391         va_start(ap, count);
392         res = ts_set_valuev_va(tsv, count, ap);
393         va_end(ap);
394         return res;
395 }
396
397 int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap)
398 {
399         int i;
400
401         if(count <= 1) return -1;
402
403         if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
404                 return -1;
405         }
406         tsv->array_size = count;
407
408         for(i=0; i<count; i++) {
409                 struct ts_value *src = va_arg(ap, struct ts_value*);
410                 if(ts_copy_value(tsv->array + i, src) == -1) {
411                         while(--i >= 0) {
412                                 ts_destroy_value(tsv->array + i);
413                         }
414                         free(tsv->array);
415                         tsv->array = 0;
416                         return -1;
417                 }
418         }
419         return 0;
420 }
421
422
423 /* ---- ts_attr implementation ---- */
424
425 int ts_init_attr(struct ts_attr *attr)
426 {
427         memset(attr, 0, sizeof *attr);
428         return ts_init_value(&attr->val);
429 }
430
431 void ts_destroy_attr(struct ts_attr *attr)
432 {
433         free(attr->name);
434         ts_destroy_value(&attr->val);
435 }
436
437 struct ts_attr *ts_alloc_attr(void)
438 {
439         struct ts_attr *attr = malloc(sizeof *attr);
440         if(!attr || ts_init_attr(attr) == -1) {
441                 free(attr);
442                 return 0;
443         }
444         return attr;
445 }
446
447 void ts_free_attr(struct ts_attr *attr)
448 {
449         ts_destroy_attr(attr);
450         free(attr);
451 }
452
453 int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src)
454 {
455         if(dest == src) return 0;
456
457         if(ts_set_attr_name(dest, src->name) == -1) {
458                 return -1;
459         }
460
461         if(ts_copy_value(&dest->val, &src->val) == -1) {
462                 ts_destroy_attr(dest);
463                 return -1;
464         }
465         return 0;
466 }
467
468 int ts_set_attr_name(struct ts_attr *attr, const char *name)
469 {
470         char *n = malloc(strlen(name) + 1);
471         if(!n) return -1;
472         strcpy(n, name);
473
474         free(attr->name);
475         attr->name = n;
476         return 0;
477 }
478
479
480 /* ---- ts_node implementation ---- */
481
482 int ts_init_node(struct ts_node *node)
483 {
484         memset(node, 0, sizeof *node);
485         return 0;
486 }
487
488 void ts_destroy_node(struct ts_node *node)
489 {
490         if(!node) return;
491
492         free(node->name);
493
494         while(node->attr_list) {
495                 struct ts_attr *attr = node->attr_list;
496                 node->attr_list = node->attr_list->next;
497                 ts_free_attr(attr);
498         }
499 }
500
501 struct ts_node *ts_alloc_node(void)
502 {
503         struct ts_node *node = malloc(sizeof *node);
504         if(!node || ts_init_node(node) == -1) {
505                 free(node);
506                 return 0;
507         }
508         return node;
509 }
510
511 void ts_free_node(struct ts_node *node)
512 {
513         ts_destroy_node(node);
514         free(node);
515 }
516
517 void ts_free_tree(struct ts_node *tree)
518 {
519         if(!tree) return;
520
521         while(tree->child_list) {
522                 struct ts_node *child = tree->child_list;
523                 tree->child_list = tree->child_list->next;
524                 ts_free_tree(child);
525         }
526
527         ts_free_node(tree);
528 }
529
530 void ts_add_attr(struct ts_node *node, struct ts_attr *attr)
531 {
532         attr->next = 0;
533         if(node->attr_list) {
534                 node->attr_tail->next = attr;
535                 node->attr_tail = attr;
536         } else {
537                 node->attr_list = node->attr_tail = attr;
538         }
539         node->attr_count++;
540 }
541
542 struct ts_attr *ts_get_attr(struct ts_node *node, const char *name)
543 {
544         struct ts_attr *attr = node->attr_list;
545         while(attr) {
546                 if(strcmp(attr->name, name) == 0) {
547                         return attr;
548                 }
549                 attr = attr->next;
550         }
551         return 0;
552 }
553
554 const char *ts_get_attr_str(struct ts_node *node, const char *aname, const char *def_val)
555 {
556         struct ts_attr *attr = ts_get_attr(node, aname);
557         if(!attr || !attr->val.str) {
558                 return def_val;
559         }
560         return attr->val.str;
561 }
562
563 float ts_get_attr_num(struct ts_node *node, const char *aname, float def_val)
564 {
565         struct ts_attr *attr = ts_get_attr(node, aname);
566         if(!attr || attr->val.type != TS_NUMBER) {
567                 return def_val;
568         }
569         return attr->val.fnum;
570 }
571
572 int ts_get_attr_int(struct ts_node *node, const char *aname, int def_val)
573 {
574         struct ts_attr *attr = ts_get_attr(node, aname);
575         if(!attr || attr->val.type != TS_NUMBER) {
576                 return def_val;
577         }
578         return attr->val.inum;
579 }
580
581 float *ts_get_attr_vec(struct ts_node *node, const char *aname, float *def_val)
582 {
583         struct ts_attr *attr = ts_get_attr(node, aname);
584         if(!attr || !attr->val.vec) {
585                 return def_val;
586         }
587         return attr->val.vec;
588 }
589
590 struct ts_value *ts_get_attr_array(struct ts_node *node, const char *aname, struct ts_value *def_val)
591 {
592         struct ts_attr *attr = ts_get_attr(node, aname);
593         if(!attr || !attr->val.array) {
594                 return def_val;
595         }
596         return attr->val.array;
597 }
598
599 void ts_add_child(struct ts_node *node, struct ts_node *child)
600 {
601         if(child->parent) {
602                 if(child->parent == node) return;
603                 ts_remove_child(child->parent, child);
604         }
605         child->parent = node;
606         child->next = 0;
607
608         if(node->child_list) {
609                 node->child_tail->next = child;
610                 node->child_tail = child;
611         } else {
612                 node->child_list = node->child_tail = child;
613         }
614         node->child_count++;
615 }
616
617 int ts_remove_child(struct ts_node *node, struct ts_node *child)
618 {
619         struct ts_node dummy, *iter = &dummy;
620         dummy.next = node->child_list;
621
622         while(iter->next && iter->next != child) {
623                 iter = iter->next;
624         }
625         if(!iter->next) {
626                 return -1;
627         }
628
629         child->parent = 0;
630
631         iter->next = child->next;
632         if(!iter->next) {
633                 node->child_tail = iter;
634         }
635         node->child_list = dummy.next;
636         node->child_count--;
637         assert(node->child_count >= 0);
638         return 0;
639 }
640
641 struct ts_node *ts_get_child(struct ts_node *node, const char *name)
642 {
643         struct ts_node *res = node->child_list;
644         while(res) {
645                 if(strcmp(res->name, name) == 0) {
646                         return res;
647                 }
648                 res = res->next;
649         }
650         return 0;
651 }
652
653 struct ts_node *ts_load(const char *fname)
654 {
655         FILE *fp;
656         struct ts_node *root;
657
658         if(!(fp = fopen(fname, "rb"))) {
659                 fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno));
660                 return 0;
661         }
662
663         root = ts_load_file(fp);
664         fclose(fp);
665         return root;
666 }
667
668 struct ts_node *ts_load_file(FILE *fp)
669 {
670         struct ts_io io = {0};
671         io.data = fp;
672         io.read = io_read;
673
674         return ts_load_io(&io);
675 }
676
677 struct ts_node *ts_load_io(struct ts_io *io)
678 {
679         return ts_text_load(io);
680 }
681
682 int ts_save(struct ts_node *tree, const char *fname)
683 {
684         FILE *fp;
685         int res;
686
687         if(!(fp = fopen(fname, "wb"))) {
688                 fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno));
689                 return 0;
690         }
691         res = ts_save_file(tree, fp);
692         fclose(fp);
693         return res;
694 }
695
696 int ts_save_file(struct ts_node *tree, FILE *fp)
697 {
698         struct ts_io io = {0};
699         io.data = fp;
700         io.write = io_write;
701
702         return ts_save_io(tree, &io);
703 }
704
705 int ts_save_io(struct ts_node *tree, struct ts_io *io)
706 {
707         return ts_text_save(tree, io);
708 }
709
710 static const char *pathtok(const char *path, char *tok)
711 {
712         int len;
713         const char *dot = strchr(path, '.');
714         if(!dot) {
715                 strcpy(tok, path);
716                 return 0;
717         }
718
719         len = dot - path;
720         memcpy(tok, path, len);
721         tok[len] = 0;
722         return dot + 1;
723 }
724
725 struct ts_attr *ts_lookup(struct ts_node *node, const char *path)
726 {
727         char *name = alloca(strlen(path) + 1);
728
729         if(!node) return 0;
730
731         if(!(path = pathtok(path, name)) || strcmp(name, node->name) != 0) {
732                 return 0;
733         }
734
735         while((path = pathtok(path, name)) && (node = ts_get_child(node, name)));
736
737         if(path || !node) return 0;
738         return ts_get_attr(node, name);
739 }
740
741 const char *ts_lookup_str(struct ts_node *root, const char *path, const char *def_val)
742 {
743         struct ts_attr *attr = ts_lookup(root, path);
744         if(!attr || !attr->val.str) {
745                 return def_val;
746         }
747         return attr->val.str;
748 }
749
750 float ts_lookup_num(struct ts_node *root, const char *path, float def_val)
751 {
752         struct ts_attr *attr = ts_lookup(root, path);
753         if(!attr || attr->val.type != TS_NUMBER) {
754                 return def_val;
755         }
756         return attr->val.fnum;
757 }
758
759 int ts_lookup_int(struct ts_node *root, const char *path, int def_val)
760 {
761         struct ts_attr *attr = ts_lookup(root, path);
762         if(!attr || attr->val.type != TS_NUMBER) {
763                 return def_val;
764         }
765         return attr->val.inum;
766 }
767
768 float *ts_lookup_vec(struct ts_node *root, const char *path, float *def_val)
769 {
770         struct ts_attr *attr = ts_lookup(root, path);
771         if(!attr || !attr->val.vec) {
772                 return def_val;
773         }
774         return attr->val.vec;
775 }
776
777 struct ts_value *ts_lookup_array(struct ts_node *node, const char *path, struct ts_value *def_val)
778 {
779         struct ts_attr *attr = ts_lookup(node, path);
780         if(!attr || !attr->val.array) {
781                 return def_val;
782         }
783         return attr->val.array;
784 }
785
786 static long io_read(void *buf, size_t bytes, void *uptr)
787 {
788         size_t sz = fread(buf, 1, bytes, uptr);
789         if(sz < bytes && errno) return -1;
790         return sz;
791 }
792
793 static long io_write(const void *buf, size_t bytes, void *uptr)
794 {
795         size_t sz = fwrite(buf, 1, bytes, uptr);
796         if(sz < bytes && errno) return -1;
797         return sz;
798 }