nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@3: #include nuclear@0: #include "treestore.h" nuclear@0: nuclear@3: struct ts_node *ts_text_load(FILE *fp); nuclear@3: int ts_text_save(struct ts_node *tree, FILE *fp); nuclear@3: nuclear@0: /* ---- ts_value implementation ---- */ nuclear@0: nuclear@0: int ts_init_value(struct ts_value *tsv) nuclear@0: { nuclear@0: memset(tsv, 0, sizeof *tsv); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void ts_destroy_value(struct ts_value *tsv) nuclear@0: { nuclear@0: int i; nuclear@0: nuclear@0: free(tsv->str); nuclear@0: free(tsv->vec); nuclear@0: nuclear@0: for(i=0; iarray_size; i++) { nuclear@0: ts_destroy_value(tsv->array + i); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: nuclear@0: struct ts_value *ts_alloc_value(void) nuclear@0: { nuclear@0: struct ts_value *v = malloc(sizeof *v); nuclear@0: if(!v || ts_init_value(v) == -1) { nuclear@0: free(v); nuclear@0: return 0; nuclear@0: } nuclear@0: return v; nuclear@0: } nuclear@0: nuclear@0: void ts_free_value(struct ts_value *tsv) nuclear@0: { nuclear@0: ts_destroy_value(tsv); nuclear@0: free(tsv); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: int ts_copy_value(struct ts_value *dest, struct ts_value *src) nuclear@0: { nuclear@0: int i; nuclear@0: nuclear@0: if(dest == src) return 0; nuclear@0: nuclear@0: *dest = *src; nuclear@0: nuclear@0: dest->str = 0; nuclear@0: dest->vec = 0; nuclear@0: dest->array = 0; nuclear@0: nuclear@0: if(src->str) { nuclear@0: if(!(dest->str = malloc(strlen(src->str) + 1))) { nuclear@0: goto fail; nuclear@0: } nuclear@0: strcpy(dest->str, src->str); nuclear@0: } nuclear@0: if(src->vec && src->vec_size > 0) { nuclear@0: if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) { nuclear@0: goto fail; nuclear@0: } nuclear@0: memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec); nuclear@0: } nuclear@0: if(src->array && src->array_size > 0) { nuclear@0: if(!(dest->array = calloc(src->array_size, sizeof *src->array))) { nuclear@0: goto fail; nuclear@0: } nuclear@0: for(i=0; iarray_size; i++) { nuclear@0: if(ts_copy_value(dest->array + i, src->array + i) == -1) { nuclear@0: goto fail; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: return 0; nuclear@0: nuclear@0: fail: nuclear@0: free(dest->str); nuclear@0: free(dest->vec); nuclear@0: if(dest->array) { nuclear@0: for(i=0; iarray_size; i++) { nuclear@0: ts_destroy_value(dest->array + i); nuclear@0: } nuclear@0: free(dest->array); nuclear@0: } nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: nuclear@0: int ts_set_value(struct ts_value *tsv, const char *str) nuclear@0: { nuclear@0: if(tsv->str) { nuclear@0: ts_destroy_value(tsv); nuclear@0: if(ts_init_value(tsv) == -1) { nuclear@0: return -1; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(!(tsv->str = malloc(strlen(str) + 1))) { nuclear@0: return -1; nuclear@0: } nuclear@0: strcpy(tsv->str, str); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: int ts_set_valueiv(struct ts_value *tsv, int count, ...) nuclear@0: { nuclear@0: int res; nuclear@0: va_list ap; nuclear@0: va_start(ap, count); nuclear@0: res = ts_set_valueiv_va(tsv, count, ap); nuclear@0: va_end(ap); nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: #define MAKE_NUMSTR_FUNC(typestr, fmt) \ nuclear@0: static char *make_##typestr##str(int x) \ nuclear@0: { \ nuclear@0: static char scrap[128]; \ nuclear@0: char *str; \ nuclear@0: int sz = snprintf(scrap, sizeof scrap, fmt, x); \ nuclear@0: if(!(str = malloc(sz + 1))) return 0; \ nuclear@0: sprintf(str, fmt, x); \ nuclear@0: return str; \ nuclear@0: } nuclear@0: nuclear@0: MAKE_NUMSTR_FUNC(int, "%d") nuclear@0: MAKE_NUMSTR_FUNC(float, "%d") nuclear@0: nuclear@0: #define ARGS_ARE_INT ((enum ts_value_type)42) nuclear@0: nuclear@0: int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap) nuclear@0: { nuclear@0: if(count < 1) return -1; nuclear@0: if(count == 1) { nuclear@0: int num = va_arg(ap, int); nuclear@0: if(!(tsv->str = make_intstr(tsv->inum))) { nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: tsv->type = TS_NUMBER; nuclear@0: tsv->inum = num; nuclear@0: tsv->fnum = (float)num; nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: /* otherwise it's an array, let ts_set_valuefv_va handle it */ nuclear@0: /* XXX: va_arg will need to be called with int instead of float. set a special nuclear@0: * value to the type field before calling this, to signify that. nuclear@0: */ nuclear@0: tsv->type = ARGS_ARE_INT; nuclear@0: return ts_set_valuefv_va(tsv, count, ap); nuclear@0: } nuclear@0: nuclear@0: int ts_set_valuei(struct ts_value *tsv, int inum) nuclear@0: { nuclear@0: return ts_set_valueiv(tsv, 1, inum); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: int ts_set_valuefv(struct ts_value *tsv, int count, ...) nuclear@0: { nuclear@0: int res; nuclear@0: va_list ap; nuclear@0: va_start(ap, count); nuclear@0: res = ts_set_valuefv_va(tsv, count, ap); nuclear@0: va_end(ap); nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap) nuclear@0: { nuclear@0: int i; nuclear@0: nuclear@0: if(count < 1) return -1; nuclear@0: if(count == 1) { nuclear@0: int num = va_arg(ap, int); nuclear@0: if(!(tsv->str = make_floatstr(tsv->inum))) { nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: tsv->type = TS_NUMBER; nuclear@0: tsv->inum = num; nuclear@0: tsv->fnum = (float)num; nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: /* otherwise it's an array, we need to create the ts_value array, and nuclear@0: * the simplified vector nuclear@0: */ nuclear@0: if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) { nuclear@0: return -1; nuclear@0: } nuclear@0: tsv->vec_size = count; nuclear@0: nuclear@0: for(i=0; itype == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */ nuclear@0: tsv->vec[i] = (float)va_arg(ap, int); nuclear@0: } else { nuclear@0: tsv->vec[i] = va_arg(ap, double); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(!(tsv->array = malloc(count * sizeof *tsv->array))) { nuclear@0: free(tsv->vec); nuclear@0: } nuclear@0: tsv->array_size = count; nuclear@0: nuclear@0: for(i=0; iarray + i); nuclear@0: if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */ nuclear@0: ts_set_valuei(tsv->array + i, (int)tsv->vec[i]); nuclear@0: } else { nuclear@0: ts_set_valuef(tsv->array + i, tsv->vec[i]); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: tsv->type = TS_VECTOR; nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: int ts_set_valuef(struct ts_value *tsv, int fnum) nuclear@0: { nuclear@0: return ts_set_valuefv(tsv, 1, fnum); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: int ts_set_valuev(struct ts_value *tsv, int count, ...) nuclear@0: { nuclear@0: int res; nuclear@0: va_list ap; nuclear@0: va_start(ap, count); nuclear@0: res = ts_set_valuev_va(tsv, count, ap); nuclear@0: va_end(ap); nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap) nuclear@0: { nuclear@1: int i; nuclear@1: nuclear@0: if(count <= 1) return -1; nuclear@1: nuclear@1: if((tsv->array = malloc(count * sizeof *tsv->array))) { nuclear@1: return -1; nuclear@1: } nuclear@1: tsv->array_size = count; nuclear@1: nuclear@1: for(i=0; iarray + i, src); nuclear@1: } nuclear@1: return 0; nuclear@0: } nuclear@1: nuclear@1: nuclear@1: /* ---- ts_attr implementation ---- */ nuclear@1: nuclear@1: int ts_init_attr(struct ts_attr *attr) nuclear@1: { nuclear@1: memset(attr, 0, sizeof *attr); nuclear@1: return ts_init_value(&attr->val); nuclear@1: } nuclear@1: nuclear@1: void ts_destroy_attr(struct ts_attr *attr) nuclear@1: { nuclear@1: free(attr->name); nuclear@1: ts_destroy_value(&attr->val); nuclear@1: } nuclear@1: nuclear@1: struct ts_attr *ts_alloc_attr(void) nuclear@1: { nuclear@1: struct ts_attr *attr = malloc(sizeof *attr); nuclear@1: if(!attr || ts_init_attr(attr) == -1) { nuclear@1: free(attr); nuclear@1: return 0; nuclear@1: } nuclear@1: return attr; nuclear@1: } nuclear@1: nuclear@1: void ts_free_attr(struct ts_attr *attr) nuclear@1: { nuclear@1: ts_destroy_attr(attr); nuclear@1: free(attr); nuclear@1: } nuclear@1: nuclear@1: int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src) nuclear@1: { nuclear@1: if(dest == src) return 0; nuclear@1: nuclear@1: if(ts_set_attr_name(dest, src->name) == -1) { nuclear@1: return -1; nuclear@1: } nuclear@1: nuclear@1: if(ts_copy_value(&dest->val, &src->val) == -1) { nuclear@1: ts_destroy_attr(dest); nuclear@1: return -1; nuclear@1: } nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: int ts_set_attr_name(struct ts_attr *attr, const char *name) nuclear@1: { nuclear@1: char *n = malloc(strlen(name) + 1); nuclear@1: if(!n) return -1; nuclear@1: strcpy(n, name); nuclear@1: nuclear@1: free(attr->name); nuclear@1: attr->name = n; nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: nuclear@1: /* ---- ts_node implementation ---- */ nuclear@1: nuclear@1: int ts_init_node(struct ts_node *node) nuclear@1: { nuclear@1: memset(node, 0, sizeof *node); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: void ts_destroy_node(struct ts_node *node) nuclear@1: { nuclear@1: free(node->name); nuclear@1: nuclear@1: while(node->attr_list) { nuclear@1: struct ts_attr *attr = node->attr_list; nuclear@1: node->attr_list = node->attr_list->next; nuclear@1: ts_free_attr(attr); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: struct ts_node *ts_alloc_node(void) nuclear@1: { nuclear@1: struct ts_node *node = malloc(sizeof *node); nuclear@1: if(!node || ts_init_node(node) == -1) { nuclear@1: free(node); nuclear@1: return 0; nuclear@1: } nuclear@1: return node; nuclear@1: } nuclear@1: nuclear@1: void ts_free_node(struct ts_node *node) nuclear@1: { nuclear@1: ts_destroy_node(node); nuclear@1: free(node); nuclear@1: } nuclear@1: nuclear@1: void ts_free_tree(struct ts_node *tree) nuclear@1: { nuclear@1: while(tree->child_list) { nuclear@2: struct ts_node *child = tree->child_list; nuclear@1: tree->child_list = tree->child_list->next; nuclear@1: ts_free_tree(child); nuclear@1: } nuclear@1: nuclear@1: ts_free_node(tree); nuclear@1: } nuclear@3: nuclear@3: void ts_add_attr(struct ts_node *node, struct ts_attr *attr) nuclear@3: { nuclear@3: attr->next = 0; nuclear@3: if(node->attr_list) { nuclear@3: node->attr_tail->next = attr; nuclear@3: node->attr_tail = attr; nuclear@3: } else { nuclear@3: node->attr_list = node->attr_tail = attr; nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: struct ts_attr *ts_get_attr(struct ts_node *node, const char *name) nuclear@3: { nuclear@3: struct ts_attr *attr = node->attr_list; nuclear@3: while(attr) { nuclear@3: if(strcmp(attr->name, name) == 0) { nuclear@3: return attr; nuclear@3: } nuclear@3: attr = attr->next; nuclear@3: } nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: void ts_add_child(struct ts_node *node, struct ts_node *child) nuclear@3: { nuclear@3: if(child->parent) { nuclear@3: if(child->parent == node) return; nuclear@3: ts_remove_child(child->parent, child); nuclear@3: } nuclear@3: child->parent = node; nuclear@3: child->next = 0; nuclear@3: nuclear@3: if(node->child_list) { nuclear@3: node->child_tail->next = child; nuclear@3: node->child_tail = child; nuclear@3: } else { nuclear@3: node->child_list = node->child_tail = child; nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: int ts_remove_child(struct ts_node *node, struct ts_node *child) nuclear@3: { nuclear@3: struct ts_node dummy, *iter = &dummy; nuclear@3: dummy.next = node->child_list; nuclear@3: nuclear@3: while(iter->next && iter->next != child) { nuclear@3: iter = iter->next; nuclear@3: } nuclear@3: if(!iter->next) { nuclear@3: return -1; nuclear@3: } nuclear@3: nuclear@3: child->parent = 0; nuclear@3: nuclear@3: iter->next = child->next; nuclear@3: if(!iter->next) { nuclear@3: node->child_tail = iter; nuclear@3: } nuclear@3: node->child_list = dummy.next; nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: struct ts_node *ts_get_child(struct ts_node *node, const char *name) nuclear@3: { nuclear@3: struct ts_node *res = node->child_list; nuclear@3: while(res) { nuclear@3: if(strcmp(res->name, name) == 0) { nuclear@3: return res; nuclear@3: } nuclear@3: res = res->next; nuclear@3: } nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: struct ts_node *ts_load(const char *fname) nuclear@3: { nuclear@3: FILE *fp; nuclear@3: struct ts_node *root; nuclear@3: nuclear@3: if(!(fp = fopen(fname, "rb"))) { nuclear@3: fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno)); nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: root = ts_text_load(fp); nuclear@3: fclose(fp); nuclear@3: return root; nuclear@3: } nuclear@3: nuclear@3: int ts_save(struct ts_node *tree, const char *fname) nuclear@3: { nuclear@3: FILE *fp; nuclear@3: int res; nuclear@3: nuclear@3: if(!(fp = fopen(fname, "wb"))) { nuclear@3: fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno)); nuclear@3: return 0; nuclear@3: } nuclear@3: res = ts_text_save(tree, fp); nuclear@3: fclose(fp); nuclear@3: return res; nuclear@3: }