7 #if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__DJGPP__)
13 struct ts_node *ts_text_load(FILE *fp);
14 int ts_text_save(struct ts_node *tree, FILE *fp);
16 /* ---- ts_value implementation ---- */
18 int ts_init_value(struct ts_value *tsv)
20 memset(tsv, 0, sizeof *tsv);
24 void ts_destroy_value(struct ts_value *tsv)
31 for(i=0; i<tsv->array_size; i++) {
32 ts_destroy_value(tsv->array + i);
38 struct ts_value *ts_alloc_value(void)
40 struct ts_value *v = malloc(sizeof *v);
41 if(!v || ts_init_value(v) == -1) {
48 void ts_free_value(struct ts_value *tsv)
50 ts_destroy_value(tsv);
55 int ts_copy_value(struct ts_value *dest, struct ts_value *src)
59 if(dest == src) return 0;
68 if(!(dest->str = malloc(strlen(src->str) + 1))) {
71 strcpy(dest->str, src->str);
73 if(src->vec && src->vec_size > 0) {
74 if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) {
77 memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec);
79 if(src->array && src->array_size > 0) {
80 if(!(dest->array = calloc(src->array_size, sizeof *src->array))) {
83 for(i=0; i<src->array_size; i++) {
84 if(ts_copy_value(dest->array + i, src->array + i) == -1) {
95 for(i=0; i<dest->array_size; i++) {
96 ts_destroy_value(dest->array + i);
103 #define MAKE_NUMSTR_FUNC(type, fmt) \
104 static char *make_##type##str(type x) \
106 static char scrap[128]; \
108 int sz = sprintf(scrap, fmt, x); \
109 if(!(str = malloc(sz + 1))) return 0; \
110 sprintf(str, fmt, x); \
114 MAKE_NUMSTR_FUNC(int, "%d")
115 MAKE_NUMSTR_FUNC(float, "%g")
118 struct val_list_node {
120 struct val_list_node *next;
123 int ts_set_value_str(struct ts_value *tsv, const char *str)
128 ts_destroy_value(tsv);
129 if(ts_init_value(tsv) == -1) {
134 tsv->type = TS_STRING;
135 if(!(tsv->str = malloc(strlen(str) + 1))) {
138 strcpy(tsv->str, str);
141 /* try to parse the string and see if it fits any of the value types */
142 if(*str == '[' || *str == '{') {
143 /* try to parse as a vector */
144 struct val_list_node *list = 0, *tail = 0, *node;
146 char endsym = *str++ + 2; /* ']' is '[' + 2 and '}' is '{' + 2 */
148 while(*str && *str != endsym) {
149 float val = strtod(str, &endp);
150 if(endp == str || !(node = malloc(sizeof *node))) {
153 ts_init_value(&node->val);
154 ts_set_valuef(&node->val, val);
167 if(nelem && (tsv->array = malloc(nelem * sizeof *tsv->array)) &&
168 (tsv->vec = malloc(nelem * sizeof *tsv->vec))) {
174 tsv->array[idx] = node->val;
175 tsv->vec[idx] = node->val.fnum;
179 tsv->type = TS_VECTOR;
182 } else if((tsv->fnum = strtod(str, &endp)), endp != str) {
183 /* it's a number I guess... */
184 tsv->type = TS_NUMBER;
191 int ts_set_valuei_arr(struct ts_value *tsv, int count, const int *arr)
195 if(count < 1) return -1;
197 if(!(tsv->str = make_intstr(*arr))) {
201 tsv->type = TS_NUMBER;
202 tsv->fnum = (float)*arr;
207 /* otherwise it's an array, we need to create the ts_value array, and
208 * the simplified vector
210 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
213 tsv->vec_size = count;
215 for(i=0; i<count; i++) {
216 tsv->vec[i] = arr[i];
219 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
222 tsv->array_size = count;
224 for(i=0; i<count; i++) {
225 ts_init_value(tsv->array + i);
226 ts_set_valuef(tsv->array + i, arr[i]);
229 tsv->type = TS_VECTOR;
233 int ts_set_valueiv(struct ts_value *tsv, int count, ...)
238 res = ts_set_valueiv_va(tsv, count, ap);
243 int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap)
247 if(count < 1) return -1;
249 int num = va_arg(ap, int);
250 ts_set_valuei(tsv, num);
254 vec = alloca(count * sizeof *vec);
255 for(i=0; i<count; i++) {
256 vec[i] = va_arg(ap, int);
258 return ts_set_valuei_arr(tsv, count, vec);
261 int ts_set_valuei(struct ts_value *tsv, int inum)
263 return ts_set_valuei_arr(tsv, 1, &inum);
266 int ts_set_valuef_arr(struct ts_value *tsv, int count, const float *arr)
270 if(count < 1) return -1;
272 if(!(tsv->str = make_floatstr(*arr))) {
276 tsv->type = TS_NUMBER;
278 tsv->inum = (int)*arr;
282 /* otherwise it's an array, we need to create the ts_value array, and
283 * the simplified vector
285 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
288 tsv->vec_size = count;
290 for(i=0; i<count; i++) {
291 tsv->vec[i] = arr[i];
294 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
297 tsv->array_size = count;
299 for(i=0; i<count; i++) {
300 ts_init_value(tsv->array + i);
301 ts_set_valuef(tsv->array + i, arr[i]);
304 tsv->type = TS_VECTOR;
308 int ts_set_valuefv(struct ts_value *tsv, int count, ...)
313 res = ts_set_valuefv_va(tsv, count, ap);
318 int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap)
323 if(count < 1) return -1;
325 float num = va_arg(ap, double);
326 ts_set_valuef(tsv, num);
330 vec = alloca(count * sizeof *vec);
331 for(i=0; i<count; i++) {
332 vec[i] = va_arg(ap, double);
334 return ts_set_valuef_arr(tsv, count, vec);
337 int ts_set_valuef(struct ts_value *tsv, float fnum)
339 return ts_set_valuef_arr(tsv, 1, &fnum);
342 int ts_set_value_arr(struct ts_value *tsv, int count, const struct ts_value *arr)
346 if(count <= 1) return -1;
348 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
351 tsv->array_size = count;
353 for(i=0; i<count; i++) {
354 if(arr[i].type != TS_NUMBER) {
357 if(ts_copy_value(tsv->array + i, (struct ts_value*)arr + i) == -1) {
359 ts_destroy_value(tsv->array + i);
368 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
369 ts_destroy_value(tsv);
372 tsv->type = TS_VECTOR;
374 for(i=0; i<count; i++) {
375 tsv->vec[i] = tsv->array[i].fnum;
378 tsv->type = TS_ARRAY;
383 int ts_set_valuev(struct ts_value *tsv, int count, ...)
388 res = ts_set_valuev_va(tsv, count, ap);
393 int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap)
397 if(count <= 1) return -1;
399 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
402 tsv->array_size = count;
404 for(i=0; i<count; i++) {
405 struct ts_value *src = va_arg(ap, struct ts_value*);
406 if(ts_copy_value(tsv->array + i, src) == -1) {
408 ts_destroy_value(tsv->array + i);
419 /* ---- ts_attr implementation ---- */
421 int ts_init_attr(struct ts_attr *attr)
423 memset(attr, 0, sizeof *attr);
424 return ts_init_value(&attr->val);
427 void ts_destroy_attr(struct ts_attr *attr)
430 ts_destroy_value(&attr->val);
433 struct ts_attr *ts_alloc_attr(void)
435 struct ts_attr *attr = malloc(sizeof *attr);
436 if(!attr || ts_init_attr(attr) == -1) {
443 void ts_free_attr(struct ts_attr *attr)
445 ts_destroy_attr(attr);
449 int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src)
451 if(dest == src) return 0;
453 if(ts_set_attr_name(dest, src->name) == -1) {
457 if(ts_copy_value(&dest->val, &src->val) == -1) {
458 ts_destroy_attr(dest);
464 int ts_set_attr_name(struct ts_attr *attr, const char *name)
466 char *n = malloc(strlen(name) + 1);
476 /* ---- ts_node implementation ---- */
478 int ts_init_node(struct ts_node *node)
480 memset(node, 0, sizeof *node);
484 void ts_destroy_node(struct ts_node *node)
490 while(node->attr_list) {
491 struct ts_attr *attr = node->attr_list;
492 node->attr_list = node->attr_list->next;
497 struct ts_node *ts_alloc_node(void)
499 struct ts_node *node = malloc(sizeof *node);
500 if(!node || ts_init_node(node) == -1) {
507 void ts_free_node(struct ts_node *node)
509 ts_destroy_node(node);
513 void ts_free_tree(struct ts_node *tree)
517 while(tree->child_list) {
518 struct ts_node *child = tree->child_list;
519 tree->child_list = tree->child_list->next;
526 void ts_add_attr(struct ts_node *node, struct ts_attr *attr)
529 if(node->attr_list) {
530 node->attr_tail->next = attr;
531 node->attr_tail = attr;
533 node->attr_list = node->attr_tail = attr;
537 struct ts_attr *ts_get_attr(struct ts_node *node, const char *name)
539 struct ts_attr *attr = node->attr_list;
541 if(strcmp(attr->name, name) == 0) {
549 const char *ts_get_attr_str(struct ts_node *node, const char *aname, const char *def_val)
551 struct ts_attr *attr = ts_get_attr(node, aname);
552 if(!attr || !attr->val.str) {
555 return attr->val.str;
558 float ts_get_attr_num(struct ts_node *node, const char *aname, float def_val)
560 struct ts_attr *attr = ts_get_attr(node, aname);
561 if(!attr || attr->val.type != TS_NUMBER) {
564 return attr->val.fnum;
567 int ts_get_attr_int(struct ts_node *node, const char *aname, int def_val)
569 struct ts_attr *attr = ts_get_attr(node, aname);
570 if(!attr || attr->val.type != TS_NUMBER) {
573 return attr->val.inum;
576 float *ts_get_attr_vec(struct ts_node *node, const char *aname, float *def_val)
578 struct ts_attr *attr = ts_get_attr(node, aname);
579 if(!attr || !attr->val.vec) {
582 return attr->val.vec;
585 struct ts_value *ts_get_attr_array(struct ts_node *node, const char *aname, struct ts_value *def_val)
587 struct ts_attr *attr = ts_get_attr(node, aname);
588 if(!attr || !attr->val.array) {
591 return attr->val.array;
594 void ts_add_child(struct ts_node *node, struct ts_node *child)
597 if(child->parent == node) return;
598 ts_remove_child(child->parent, child);
600 child->parent = node;
603 if(node->child_list) {
604 node->child_tail->next = child;
605 node->child_tail = child;
607 node->child_list = node->child_tail = child;
611 int ts_remove_child(struct ts_node *node, struct ts_node *child)
613 struct ts_node dummy, *iter = &dummy;
614 dummy.next = node->child_list;
616 while(iter->next && iter->next != child) {
625 iter->next = child->next;
627 node->child_tail = iter;
629 node->child_list = dummy.next;
633 struct ts_node *ts_get_child(struct ts_node *node, const char *name)
635 struct ts_node *res = node->child_list;
637 if(strcmp(res->name, name) == 0) {
645 struct ts_node *ts_load(const char *fname)
648 struct ts_node *root;
650 if(!(fp = fopen(fname, "rb"))) {
651 fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno));
655 root = ts_text_load(fp);
660 int ts_save(struct ts_node *tree, const char *fname)
665 if(!(fp = fopen(fname, "wb"))) {
666 fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno));
669 res = ts_text_save(tree, fp);
674 static const char *pathtok(const char *path, char *tok)
677 const char *dot = strchr(path, '.');
684 memcpy(tok, path, len);
689 struct ts_attr *ts_lookup(struct ts_node *node, const char *path)
691 char *name = alloca(strlen(path) + 1);
695 if(!(path = pathtok(path, name)) || strcmp(name, node->name) != 0) {
699 while((path = pathtok(path, name)) && (node = ts_get_child(node, name)));
701 if(path || !node) return 0;
702 return ts_get_attr(node, name);
705 const char *ts_lookup_str(struct ts_node *root, const char *path, const char *def_val)
707 struct ts_attr *attr = ts_lookup(root, path);
708 if(!attr || !attr->val.str) {
711 return attr->val.str;
714 float ts_lookup_num(struct ts_node *root, const char *path, float def_val)
716 struct ts_attr *attr = ts_lookup(root, path);
717 if(!attr || attr->val.type != TS_NUMBER) {
720 return attr->val.fnum;
723 int ts_lookup_int(struct ts_node *root, const char *path, int def_val)
725 struct ts_attr *attr = ts_lookup(root, path);
726 if(!attr || attr->val.type != TS_NUMBER) {
729 return attr->val.inum;
732 float *ts_lookup_vec(struct ts_node *root, const char *path, float *def_val)
734 struct ts_attr *attr = ts_lookup(root, path);
735 if(!attr || !attr->val.vec) {
738 return attr->val.vec;
741 struct ts_value *ts_lookup_array(struct ts_node *node, const char *path, struct ts_value *def_val)
743 struct ts_attr *attr = ts_lookup(node, path);
744 if(!attr || !attr->val.array) {
747 return attr->val.array;