8 #if defined(__WATCOMC__) || defined(_WIN32) || defined(__DJGPP__)
14 #if defined(_MSC_VER) || defined(__WATCOMC__)
15 #define snprintf _snprintf
18 struct ts_node *ts_text_load(struct ts_io *io);
19 int ts_text_save(struct ts_node *tree, struct ts_io *io);
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);
25 /* ---- ts_value implementation ---- */
27 int ts_init_value(struct ts_value *tsv)
29 memset(tsv, 0, sizeof *tsv);
33 void ts_destroy_value(struct ts_value *tsv)
40 for(i=0; i<tsv->array_size; i++) {
41 ts_destroy_value(tsv->array + i);
47 struct ts_value *ts_alloc_value(void)
49 struct ts_value *v = malloc(sizeof *v);
50 if(!v || ts_init_value(v) == -1) {
57 void ts_free_value(struct ts_value *tsv)
59 ts_destroy_value(tsv);
64 int ts_copy_value(struct ts_value *dest, struct ts_value *src)
68 if(dest == src) return 0;
77 if(!(dest->str = malloc(strlen(src->str) + 1))) {
80 strcpy(dest->str, src->str);
82 if(src->vec && src->vec_size > 0) {
83 if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) {
86 memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec);
88 if(src->array && src->array_size > 0) {
89 if(!(dest->array = calloc(src->array_size, sizeof *src->array))) {
92 for(i=0; i<src->array_size; i++) {
93 if(ts_copy_value(dest->array + i, src->array + i) == -1) {
104 for(i=0; i<dest->array_size; i++) {
105 ts_destroy_value(dest->array + i);
112 #define MAKE_NUMSTR_FUNC(type, fmt) \
113 static char *make_##type##str(type x) \
115 static char scrap[128]; \
117 int sz = snprintf(scrap, sizeof scrap, fmt, x); \
118 if(!(str = malloc(sz + 1))) return 0; \
119 sprintf(str, fmt, x); \
123 MAKE_NUMSTR_FUNC(int, "%d")
124 MAKE_NUMSTR_FUNC(float, "%g")
127 struct val_list_node {
129 struct val_list_node *next;
132 int ts_set_value_str(struct ts_value *tsv, const char *str)
135 ts_destroy_value(tsv);
136 if(ts_init_value(tsv) == -1) {
141 tsv->type = TS_STRING;
142 if(!(tsv->str = malloc(strlen(str) + 1))) {
145 strcpy(tsv->str, str);
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;
153 char endsym = *str++ + 2; /* ']' is '[' + 2 and '}' is '{' + 2 */
155 while(*str && *str != endsym) {
156 float val = strtod(str, &endp);
157 if(endp == str || !(node = malloc(sizeof *node))) {
160 ts_init_value(&node->val);
161 ts_set_valuef(&node->val, val);
174 if(nelem && (tsv->array = malloc(nelem * sizeof *tsv->array)) &&
175 (tsv->vec = malloc(nelem * sizeof *tsv->vec))) {
181 tsv->array[idx] = node->val;
182 tsv->vec[idx] = node->val.fnum;
186 tsv->type = TS_VECTOR;
189 } else if((tsv->fnum = strtod(str, &endp)), endp != str) {
190 /* it's a number I guess... */
191 tsv->type = TS_NUMBER;
198 int ts_set_valuei_arr(struct ts_value *tsv, int count, const int *arr)
202 if(count < 1) return -1;
204 if(!(tsv->str = make_intstr(*arr))) {
208 tsv->type = TS_NUMBER;
209 tsv->fnum = (float)*arr;
214 /* otherwise it's an array, we need to create the ts_value array, and
215 * the simplified vector
217 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
220 tsv->vec_size = count;
222 for(i=0; i<count; i++) {
223 tsv->vec[i] = arr[i];
226 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
229 tsv->array_size = count;
231 for(i=0; i<count; i++) {
232 ts_init_value(tsv->array + i);
233 ts_set_valuef(tsv->array + i, arr[i]);
236 tsv->type = TS_VECTOR;
240 int ts_set_valueiv(struct ts_value *tsv, int count, ...)
245 res = ts_set_valueiv_va(tsv, count, ap);
250 int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap)
254 if(count < 1) return -1;
256 int num = va_arg(ap, int);
257 ts_set_valuei(tsv, num);
261 vec = alloca(count * sizeof *vec);
262 for(i=0; i<count; i++) {
263 vec[i] = va_arg(ap, int);
265 return ts_set_valuei_arr(tsv, count, vec);
268 int ts_set_valuei(struct ts_value *tsv, int inum)
270 return ts_set_valuei_arr(tsv, 1, &inum);
273 int ts_set_valuef_arr(struct ts_value *tsv, int count, const float *arr)
277 if(count < 1) return -1;
279 if(!(tsv->str = make_floatstr(*arr))) {
283 tsv->type = TS_NUMBER;
285 tsv->inum = (int)*arr;
289 /* otherwise it's an array, we need to create the ts_value array, and
290 * the simplified vector
292 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
295 tsv->vec_size = count;
297 for(i=0; i<count; i++) {
298 tsv->vec[i] = arr[i];
301 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
304 tsv->array_size = count;
306 for(i=0; i<count; i++) {
307 ts_init_value(tsv->array + i);
308 ts_set_valuef(tsv->array + i, arr[i]);
311 tsv->type = TS_VECTOR;
315 int ts_set_valuefv(struct ts_value *tsv, int count, ...)
320 res = ts_set_valuefv_va(tsv, count, ap);
325 int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap)
330 if(count < 1) return -1;
332 float num = va_arg(ap, double);
333 ts_set_valuef(tsv, num);
337 vec = alloca(count * sizeof *vec);
338 for(i=0; i<count; i++) {
339 vec[i] = va_arg(ap, double);
341 return ts_set_valuef_arr(tsv, count, vec);
344 int ts_set_valuef(struct ts_value *tsv, float fnum)
346 return ts_set_valuef_arr(tsv, 1, &fnum);
349 int ts_set_value_arr(struct ts_value *tsv, int count, const struct ts_value *arr)
353 if(count <= 1) return -1;
355 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
358 tsv->array_size = count;
360 for(i=0; i<count; i++) {
361 if(arr[i].type != TS_NUMBER) {
364 if(ts_copy_value(tsv->array + i, (struct ts_value*)arr + i) == -1) {
366 ts_destroy_value(tsv->array + i);
375 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
376 ts_destroy_value(tsv);
379 tsv->type = TS_VECTOR;
380 tsv->vec_size = count;
382 for(i=0; i<count; i++) {
383 tsv->vec[i] = tsv->array[i].fnum;
386 tsv->type = TS_ARRAY;
391 int ts_set_valuev(struct ts_value *tsv, int count, ...)
396 res = ts_set_valuev_va(tsv, count, ap);
401 int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap)
405 if(count <= 1) return -1;
407 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
410 tsv->array_size = count;
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) {
416 ts_destroy_value(tsv->array + i);
427 /* ---- ts_attr implementation ---- */
429 int ts_init_attr(struct ts_attr *attr)
431 memset(attr, 0, sizeof *attr);
432 return ts_init_value(&attr->val);
435 void ts_destroy_attr(struct ts_attr *attr)
438 ts_destroy_value(&attr->val);
441 struct ts_attr *ts_alloc_attr(void)
443 struct ts_attr *attr = malloc(sizeof *attr);
444 if(!attr || ts_init_attr(attr) == -1) {
451 void ts_free_attr(struct ts_attr *attr)
453 ts_destroy_attr(attr);
457 int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src)
459 if(dest == src) return 0;
461 if(ts_set_attr_name(dest, src->name) == -1) {
465 if(ts_copy_value(&dest->val, &src->val) == -1) {
466 ts_destroy_attr(dest);
472 int ts_set_attr_name(struct ts_attr *attr, const char *name)
474 char *n = malloc(strlen(name) + 1);
484 /* ---- ts_node implementation ---- */
486 int ts_init_node(struct ts_node *node)
488 memset(node, 0, sizeof *node);
492 void ts_destroy_node(struct ts_node *node)
498 while(node->attr_list) {
499 struct ts_attr *attr = node->attr_list;
500 node->attr_list = node->attr_list->next;
505 struct ts_node *ts_alloc_node(void)
507 struct ts_node *node = malloc(sizeof *node);
508 if(!node || ts_init_node(node) == -1) {
515 void ts_free_node(struct ts_node *node)
517 ts_destroy_node(node);
521 void ts_free_tree(struct ts_node *tree)
525 while(tree->child_list) {
526 struct ts_node *child = tree->child_list;
527 tree->child_list = tree->child_list->next;
534 int ts_set_node_name(struct ts_node *node, const char *name)
536 char *n = malloc(strlen(name) + 1);
545 void ts_add_attr(struct ts_node *node, struct ts_attr *attr)
548 if(node->attr_list) {
549 node->attr_tail->next = attr;
550 node->attr_tail = attr;
552 node->attr_list = node->attr_tail = attr;
557 struct ts_attr *ts_get_attr(struct ts_node *node, const char *name)
559 struct ts_attr *attr = node->attr_list;
561 if(strcmp(attr->name, name) == 0) {
569 const char *ts_get_attr_str(struct ts_node *node, const char *aname, const char *def_val)
571 struct ts_attr *attr = ts_get_attr(node, aname);
572 if(!attr || !attr->val.str) {
575 return attr->val.str;
578 float ts_get_attr_num(struct ts_node *node, const char *aname, float def_val)
580 struct ts_attr *attr = ts_get_attr(node, aname);
581 if(!attr || attr->val.type != TS_NUMBER) {
584 return attr->val.fnum;
587 int ts_get_attr_int(struct ts_node *node, const char *aname, int def_val)
589 struct ts_attr *attr = ts_get_attr(node, aname);
590 if(!attr || attr->val.type != TS_NUMBER) {
593 return attr->val.inum;
596 float *ts_get_attr_vec(struct ts_node *node, const char *aname, float *def_val)
598 struct ts_attr *attr = ts_get_attr(node, aname);
599 if(!attr || !attr->val.vec) {
602 return attr->val.vec;
605 struct ts_value *ts_get_attr_array(struct ts_node *node, const char *aname, struct ts_value *def_val)
607 struct ts_attr *attr = ts_get_attr(node, aname);
608 if(!attr || !attr->val.array) {
611 return attr->val.array;
614 void ts_add_child(struct ts_node *node, struct ts_node *child)
617 if(child->parent == node) return;
618 ts_remove_child(child->parent, child);
620 child->parent = node;
623 if(node->child_list) {
624 node->child_tail->next = child;
625 node->child_tail = child;
627 node->child_list = node->child_tail = child;
632 int ts_remove_child(struct ts_node *node, struct ts_node *child)
634 struct ts_node dummy, *iter = &dummy;
635 dummy.next = node->child_list;
637 while(iter->next && iter->next != child) {
646 iter->next = child->next;
648 node->child_tail = iter;
650 node->child_list = dummy.next;
652 assert(node->child_count >= 0);
656 struct ts_node *ts_get_child(struct ts_node *node, const char *name)
658 struct ts_node *res = node->child_list;
660 if(strcmp(res->name, name) == 0) {
668 struct ts_node *ts_load(const char *fname)
671 struct ts_node *root;
673 if(!(fp = fopen(fname, "rb"))) {
674 fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno));
678 root = ts_load_file(fp);
683 struct ts_node *ts_load_file(FILE *fp)
685 struct ts_io io = {0};
689 return ts_load_io(&io);
692 struct ts_node *ts_load_io(struct ts_io *io)
694 return ts_text_load(io);
697 int ts_save(struct ts_node *tree, const char *fname)
702 if(!(fp = fopen(fname, "wb"))) {
703 fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno));
706 res = ts_save_file(tree, fp);
711 int ts_save_file(struct ts_node *tree, FILE *fp)
713 struct ts_io io = {0};
717 return ts_save_io(tree, &io);
720 int ts_save_io(struct ts_node *tree, struct ts_io *io)
722 return ts_text_save(tree, io);
725 static const char *pathtok(const char *path, char *tok)
728 const char *dot = strchr(path, '.');
735 memcpy(tok, path, len);
740 struct ts_attr *ts_lookup(struct ts_node *node, const char *path)
742 char *name = alloca(strlen(path) + 1);
746 if(!(path = pathtok(path, name)) || strcmp(name, node->name) != 0) {
750 while((path = pathtok(path, name)) && (node = ts_get_child(node, name)));
752 if(path || !node) return 0;
753 return ts_get_attr(node, name);
756 const char *ts_lookup_str(struct ts_node *root, const char *path, const char *def_val)
758 struct ts_attr *attr = ts_lookup(root, path);
759 if(!attr || !attr->val.str) {
762 return attr->val.str;
765 float ts_lookup_num(struct ts_node *root, const char *path, float def_val)
767 struct ts_attr *attr = ts_lookup(root, path);
768 if(!attr || attr->val.type != TS_NUMBER) {
771 return attr->val.fnum;
774 int ts_lookup_int(struct ts_node *root, const char *path, int def_val)
776 struct ts_attr *attr = ts_lookup(root, path);
777 if(!attr || attr->val.type != TS_NUMBER) {
780 return attr->val.inum;
783 float *ts_lookup_vec(struct ts_node *root, const char *path, float *def_val)
785 struct ts_attr *attr = ts_lookup(root, path);
786 if(!attr || !attr->val.vec) {
789 return attr->val.vec;
792 struct ts_value *ts_lookup_array(struct ts_node *node, const char *path, struct ts_value *def_val)
794 struct ts_attr *attr = ts_lookup(node, path);
795 if(!attr || !attr->val.array) {
798 return attr->val.array;
801 static long io_read(void *buf, size_t bytes, void *uptr)
803 size_t sz = fread(buf, 1, bytes, uptr);
804 if(sz < bytes && errno) return -1;
808 static long io_write(const void *buf, size_t bytes, void *uptr)
810 size_t sz = fwrite(buf, 1, bytes, uptr);
811 if(sz < bytes && errno) return -1;