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