16 struct ts_node *ts_text_load(struct ts_io *io);
17 int ts_text_save(struct ts_node *tree, struct ts_io *io);
19 static long io_read(void *buf, size_t bytes, void *uptr);
20 static long io_write(const void *buf, size_t bytes, void *uptr);
23 /* ---- ts_value implementation ---- */
25 int ts_init_value(struct ts_value *tsv)
27 memset(tsv, 0, sizeof *tsv);
31 void ts_destroy_value(struct ts_value *tsv)
38 for(i=0; i<tsv->array_size; i++) {
39 ts_destroy_value(tsv->array + i);
45 struct ts_value *ts_alloc_value(void)
47 struct ts_value *v = malloc(sizeof *v);
48 if(!v || ts_init_value(v) == -1) {
55 void ts_free_value(struct ts_value *tsv)
57 ts_destroy_value(tsv);
62 int ts_copy_value(struct ts_value *dest, struct ts_value *src)
66 if(dest == src) return 0;
75 if(!(dest->str = malloc(strlen(src->str) + 1))) {
78 strcpy(dest->str, src->str);
80 if(src->vec && src->vec_size > 0) {
81 if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) {
84 memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec);
86 if(src->array && src->array_size > 0) {
87 if(!(dest->array = calloc(src->array_size, sizeof *src->array))) {
90 for(i=0; i<src->array_size; i++) {
91 if(ts_copy_value(dest->array + i, src->array + i) == -1) {
102 for(i=0; i<dest->array_size; i++) {
103 ts_destroy_value(dest->array + i);
110 #define MAKE_NUMSTR_FUNC(type, fmt) \
111 static char *make_##type##str(type x) \
113 static char scrap[128]; \
115 int sz = snprintf(scrap, sizeof scrap, fmt, x); \
116 if(!(str = malloc(sz + 1))) return 0; \
117 sprintf(str, fmt, x); \
121 MAKE_NUMSTR_FUNC(int, "%d")
122 MAKE_NUMSTR_FUNC(float, "%g")
125 struct val_list_node {
127 struct val_list_node *next;
130 int ts_set_value_str(struct ts_value *tsv, const char *str)
133 ts_destroy_value(tsv);
134 if(ts_init_value(tsv) == -1) {
139 tsv->type = TS_STRING;
140 if(!(tsv->str = malloc(strlen(str) + 1))) {
143 strcpy(tsv->str, str);
146 /* try to parse the string and see if it fits any of the value types */
147 if(*str == '[' || *str == '{') {
148 /* try to parse as a vector */
149 struct val_list_node *list = 0, *tail = 0, *node;
151 char endsym = *str++ + 2; /* ']' is '[' + 2 and '}' is '{' + 2 */
153 while(*str && *str != endsym) {
154 float val = strtod(str, &endp);
155 if(endp == str || !(node = malloc(sizeof *node))) {
158 ts_init_value(&node->val);
159 ts_set_valuef(&node->val, val);
172 if(nelem && (tsv->array = malloc(nelem * sizeof *tsv->array)) &&
173 (tsv->vec = malloc(nelem * sizeof *tsv->vec))) {
179 tsv->array[idx] = node->val;
180 tsv->vec[idx] = node->val.fnum;
184 tsv->type = TS_VECTOR;
187 } else if((tsv->fnum = strtod(str, &endp)), endp != str) {
188 /* it's a number I guess... */
189 tsv->type = TS_NUMBER;
196 int ts_set_valuei_arr(struct ts_value *tsv, int count, const int *arr)
200 if(count < 1) return -1;
202 if(!(tsv->str = make_intstr(*arr))) {
206 tsv->type = TS_NUMBER;
207 tsv->fnum = (float)*arr;
212 /* otherwise it's an array, we need to create the ts_value array, and
213 * the simplified vector
215 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
218 tsv->vec_size = count;
220 for(i=0; i<count; i++) {
221 tsv->vec[i] = arr[i];
224 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
227 tsv->array_size = count;
229 for(i=0; i<count; i++) {
230 ts_init_value(tsv->array + i);
231 ts_set_valuef(tsv->array + i, arr[i]);
234 tsv->type = TS_VECTOR;
238 int ts_set_valueiv(struct ts_value *tsv, int count, ...)
243 res = ts_set_valueiv_va(tsv, count, ap);
248 int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap)
252 if(count < 1) return -1;
254 int num = va_arg(ap, int);
255 ts_set_valuei(tsv, num);
259 vec = alloca(count * sizeof *vec);
260 for(i=0; i<count; i++) {
261 vec[i] = va_arg(ap, int);
263 return ts_set_valuei_arr(tsv, count, vec);
266 int ts_set_valuei(struct ts_value *tsv, int inum)
268 return ts_set_valuei_arr(tsv, 1, &inum);
271 int ts_set_valuef_arr(struct ts_value *tsv, int count, const float *arr)
275 if(count < 1) return -1;
277 if(!(tsv->str = make_floatstr(*arr))) {
281 tsv->type = TS_NUMBER;
283 tsv->inum = (int)*arr;
287 /* otherwise it's an array, we need to create the ts_value array, and
288 * the simplified vector
290 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
293 tsv->vec_size = count;
295 for(i=0; i<count; i++) {
296 tsv->vec[i] = arr[i];
299 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
302 tsv->array_size = count;
304 for(i=0; i<count; i++) {
305 ts_init_value(tsv->array + i);
306 ts_set_valuef(tsv->array + i, arr[i]);
309 tsv->type = TS_VECTOR;
313 int ts_set_valuefv(struct ts_value *tsv, int count, ...)
318 res = ts_set_valuefv_va(tsv, count, ap);
323 int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap)
328 if(count < 1) return -1;
330 float num = va_arg(ap, double);
331 ts_set_valuef(tsv, num);
335 vec = alloca(count * sizeof *vec);
336 for(i=0; i<count; i++) {
337 vec[i] = va_arg(ap, double);
339 return ts_set_valuef_arr(tsv, count, vec);
342 int ts_set_valuef(struct ts_value *tsv, float fnum)
344 return ts_set_valuef_arr(tsv, 1, &fnum);
347 int ts_set_value_arr(struct ts_value *tsv, int count, const struct ts_value *arr)
351 if(count <= 1) return -1;
353 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
356 tsv->array_size = count;
358 for(i=0; i<count; i++) {
359 if(arr[i].type != TS_NUMBER) {
362 if(ts_copy_value(tsv->array + i, (struct ts_value*)arr + i) == -1) {
364 ts_destroy_value(tsv->array + i);
373 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
374 ts_destroy_value(tsv);
377 tsv->type = TS_VECTOR;
378 tsv->vec_size = count;
380 for(i=0; i<count; i++) {
381 tsv->vec[i] = tsv->array[i].fnum;
384 tsv->type = TS_ARRAY;
389 int ts_set_valuev(struct ts_value *tsv, int count, ...)
394 res = ts_set_valuev_va(tsv, count, ap);
399 int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap)
403 if(count <= 1) return -1;
405 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
408 tsv->array_size = count;
410 for(i=0; i<count; i++) {
411 struct ts_value *src = va_arg(ap, struct ts_value*);
412 if(ts_copy_value(tsv->array + i, src) == -1) {
414 ts_destroy_value(tsv->array + i);
425 /* ---- ts_attr implementation ---- */
427 int ts_init_attr(struct ts_attr *attr)
429 memset(attr, 0, sizeof *attr);
430 return ts_init_value(&attr->val);
433 void ts_destroy_attr(struct ts_attr *attr)
436 ts_destroy_value(&attr->val);
439 struct ts_attr *ts_alloc_attr(void)
441 struct ts_attr *attr = malloc(sizeof *attr);
442 if(!attr || ts_init_attr(attr) == -1) {
449 void ts_free_attr(struct ts_attr *attr)
451 ts_destroy_attr(attr);
455 int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src)
457 if(dest == src) return 0;
459 if(ts_set_attr_name(dest, src->name) == -1) {
463 if(ts_copy_value(&dest->val, &src->val) == -1) {
464 ts_destroy_attr(dest);
470 int ts_set_attr_name(struct ts_attr *attr, const char *name)
472 char *n = malloc(strlen(name) + 1);
482 /* ---- ts_node implementation ---- */
484 int ts_init_node(struct ts_node *node)
486 memset(node, 0, sizeof *node);
490 void ts_destroy_node(struct ts_node *node)
496 while(node->attr_list) {
497 struct ts_attr *attr = node->attr_list;
498 node->attr_list = node->attr_list->next;
503 struct ts_node *ts_alloc_node(void)
505 struct ts_node *node = malloc(sizeof *node);
506 if(!node || ts_init_node(node) == -1) {
513 void ts_free_node(struct ts_node *node)
515 ts_destroy_node(node);
519 void ts_free_tree(struct ts_node *tree)
523 while(tree->child_list) {
524 struct ts_node *child = tree->child_list;
525 tree->child_list = tree->child_list->next;
532 void ts_add_attr(struct ts_node *node, struct ts_attr *attr)
535 if(attr->node == node) return;
536 ts_remove_attr(attr->node, attr);
541 if(node->attr_list) {
542 node->attr_tail->next = attr;
543 node->attr_tail = attr;
545 node->attr_list = node->attr_tail = attr;
550 struct ts_attr *ts_get_attr(struct ts_node *node, const char *name)
552 struct ts_attr *attr = node->attr_list;
554 if(strcmp(attr->name, name) == 0) {
562 int ts_remove_attr(struct ts_node *node, struct ts_attr *attr)
564 struct ts_attr dummy, *iter = &dummy;
565 dummy.next = node->attr_list;
567 while(iter->next && iter->next != attr) {
576 iter->next = attr->next;
578 node->attr_tail = iter;
580 node->attr_list = dummy.next;
582 assert(node->attr_count >= 0);
586 const char *ts_get_attr_str(struct ts_node *node, const char *aname, const char *def_val)
588 struct ts_attr *attr = ts_get_attr(node, aname);
589 if(!attr || !attr->val.str) {
592 return attr->val.str;
595 float ts_get_attr_num(struct ts_node *node, const char *aname, float def_val)
597 struct ts_attr *attr = ts_get_attr(node, aname);
598 if(!attr || attr->val.type != TS_NUMBER) {
601 return attr->val.fnum;
604 int ts_get_attr_int(struct ts_node *node, const char *aname, int def_val)
606 struct ts_attr *attr = ts_get_attr(node, aname);
607 if(!attr || attr->val.type != TS_NUMBER) {
610 return attr->val.inum;
613 float *ts_get_attr_vec(struct ts_node *node, const char *aname, float *def_val)
615 struct ts_attr *attr = ts_get_attr(node, aname);
616 if(!attr || !attr->val.vec) {
619 return attr->val.vec;
622 struct ts_value *ts_get_attr_array(struct ts_node *node, const char *aname, struct ts_value *def_val)
624 struct ts_attr *attr = ts_get_attr(node, aname);
625 if(!attr || !attr->val.array) {
628 return attr->val.array;
631 void ts_add_child(struct ts_node *node, struct ts_node *child)
634 if(child->parent == node) return;
635 ts_remove_child(child->parent, child);
637 child->parent = node;
640 if(node->child_list) {
641 node->child_tail->next = child;
642 node->child_tail = child;
644 node->child_list = node->child_tail = child;
649 int ts_remove_child(struct ts_node *node, struct ts_node *child)
651 struct ts_node dummy, *iter = &dummy;
652 dummy.next = node->child_list;
654 while(iter->next && iter->next != child) {
663 iter->next = child->next;
665 node->child_tail = iter;
667 node->child_list = dummy.next;
669 assert(node->child_count >= 0);
673 struct ts_node *ts_get_child(struct ts_node *node, const char *name)
675 struct ts_node *res = node->child_list;
677 if(strcmp(res->name, name) == 0) {
685 struct ts_node *ts_load(const char *fname)
688 struct ts_node *root;
690 if(!(fp = fopen(fname, "rb"))) {
691 fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno));
695 root = ts_load_file(fp);
700 struct ts_node *ts_load_file(FILE *fp)
702 struct ts_io io = {0};
706 return ts_load_io(&io);
709 struct ts_node *ts_load_io(struct ts_io *io)
711 return ts_text_load(io);
714 int ts_save(struct ts_node *tree, const char *fname)
719 if(!(fp = fopen(fname, "wb"))) {
720 fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno));
723 res = ts_save_file(tree, fp);
728 int ts_save_file(struct ts_node *tree, FILE *fp)
730 struct ts_io io = {0};
734 return ts_save_io(tree, &io);
737 int ts_save_io(struct ts_node *tree, struct ts_io *io)
739 return ts_text_save(tree, io);
742 static const char *pathtok(const char *path, char *tok)
745 const char *dot = strchr(path, '.');
752 memcpy(tok, path, len);
757 struct ts_attr *ts_lookup(struct ts_node *node, const char *path)
759 char *name = alloca(strlen(path) + 1);
763 if(!(path = pathtok(path, name)) || strcmp(name, node->name) != 0) {
767 while((path = pathtok(path, name)) && (node = ts_get_child(node, name)));
769 if(path || !node) return 0;
770 return ts_get_attr(node, name);
773 const char *ts_lookup_str(struct ts_node *root, const char *path, const char *def_val)
775 struct ts_attr *attr = ts_lookup(root, path);
776 if(!attr || !attr->val.str) {
779 return attr->val.str;
782 float ts_lookup_num(struct ts_node *root, const char *path, float def_val)
784 struct ts_attr *attr = ts_lookup(root, path);
785 if(!attr || attr->val.type != TS_NUMBER) {
788 return attr->val.fnum;
791 int ts_lookup_int(struct ts_node *root, const char *path, int def_val)
793 struct ts_attr *attr = ts_lookup(root, path);
794 if(!attr || attr->val.type != TS_NUMBER) {
797 return attr->val.inum;
800 float *ts_lookup_vec(struct ts_node *root, const char *path, float *def_val)
802 struct ts_attr *attr = ts_lookup(root, path);
803 if(!attr || !attr->val.vec) {
806 return attr->val.vec;
809 struct ts_value *ts_lookup_array(struct ts_node *node, const char *path, struct ts_value *def_val)
811 struct ts_attr *attr = ts_lookup(node, path);
812 if(!attr || !attr->val.array) {
815 return attr->val.array;
818 static long io_read(void *buf, size_t bytes, void *uptr)
820 size_t sz = fread(buf, 1, bytes, uptr);
821 if(sz < bytes && errno) return -1;
825 static long io_write(const void *buf, size_t bytes, void *uptr)
827 size_t sz = fwrite(buf, 1, bytes, uptr);
828 if(sz < bytes && errno) return -1;