libtreestore

changeset 3:48d75df3ef04

picking this up again, converted to cmake, and started a text format reader/writer
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 10 Nov 2016 16:19:44 +0200
parents e1a825be0eee
children bb873449cf59
files .hgignore CMakeLists.txt Makefile include/treestore.h src/text.c src/treestore.c src/treestore.h src/treestorepp.h
diffstat 8 files changed, 496 insertions(+), 236 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Sat Apr 12 13:50:01 2014 +0300
     1.2 +++ b/.hgignore	Thu Nov 10 16:19:44 2016 +0200
     1.3 @@ -2,4 +2,8 @@
     1.4  \.d$
     1.5  \.swp$
     1.6  \.so\.
     1.7 +\.so$
     1.8  \.a$
     1.9 +CMakeFiles/
    1.10 +\.cmake$
    1.11 +\.txt$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/CMakeLists.txt	Thu Nov 10 16:19:44 2016 +0200
     2.3 @@ -0,0 +1,36 @@
     2.4 +cmake_minimum_required(VERSION 3.0)
     2.5 +project(libtreestore)
     2.6 +
     2.7 +include(GNUInstallDirs)
     2.8 +
     2.9 +set(SO_MAJOR 0)
    2.10 +set(SO_MINOR 1)
    2.11 +
    2.12 +file(GLOB src "src/*.c")
    2.13 +file(GLOB hdr "src/*.h")
    2.14 +file(GLOB pubhdr "include/*.h")
    2.15 +
    2.16 +add_library(treestore SHARED ${src} ${hdr} ${pubhdr})
    2.17 +add_library(treestore-static STATIC ${src} ${hdr} ${pubhdr})
    2.18 +
    2.19 +set_target_properties(treestore PROPERTIES VERSION ${SO_MAJOR}.${SO_MINOR})
    2.20 +set_target_properties(treestore PROPERTIES SOVERSION ${SO_MAJOR})
    2.21 +
    2.22 +if(NOT WIN32)
    2.23 +	set_target_properties(treestore-static PROPERTIES OUTPUT_NAME treestore)
    2.24 +endif()
    2.25 +
    2.26 +target_include_directories(treestore PUBLIC include)
    2.27 +target_include_directories(treestore-static PUBLIC include)
    2.28 +
    2.29 +install(TARGETS treestore
    2.30 +	RUNTIME DESTINATION bin
    2.31 +	LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    2.32 +	ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
    2.33 +
    2.34 +install(TARGETS treestore-static
    2.35 +	RUNTIME DESTINATION bin
    2.36 +	LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    2.37 +	ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
    2.38 +
    2.39 +install(FILES ${pubhdr} DESTINATION include)
     3.1 --- a/Makefile	Sat Apr 12 13:50:01 2014 +0300
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,89 +0,0 @@
     3.4 -PREFIX = /usr/local
     3.5 -
     3.6 -csrc = $(wildcard src/*.c)
     3.7 -ccsrc = $(wildcard src/*.cc)
     3.8 -cobj = $(csrc:.c=.o)
     3.9 -ccobj = $(ccsrc:.cc=.o)
    3.10 -obj = $(cobj) $(ccobj)
    3.11 -dep = $(obj:.o=.d) 
    3.12 -
    3.13 -cname = treestore
    3.14 -ccname = treestorepp
    3.15 -
    3.16 -capi_major = 0
    3.17 -capi_minor = 1
    3.18 -ccapi_major = 0
    3.19 -ccapi_minor = 1
    3.20 -
    3.21 -clib_a = lib$(cname).a
    3.22 -cclib_a = lib$(ccname).a
    3.23 -
    3.24 -ifeq ($(shell uname -s), Darwin)
    3.25 -	clib_so = lib$(cname).dylib
    3.26 -	cclib_so = lib$(ccname).dylib
    3.27 -	cshared = -dynamiclib
    3.28 -	ccshared = -dynamiclib
    3.29 -else
    3.30 -	clib_so = lib$(cname).so.$(capi_major).$(capi_minor)
    3.31 -	csoname = lib$(cname).so.$(capi_major)
    3.32 -	cdevlink = lib$(cname).so
    3.33 -	cclib_so = lib$(ccname).so.$(ccapi_major).$(ccapi_minor)
    3.34 -	ccsoname = lib$(ccname).so.$(ccapi_major)
    3.35 -	ccdevlink = lib$(ccname).so
    3.36 -
    3.37 -	cshared = -shared -Wl,-soname=$(csoname)
    3.38 -	ccshared = -shared -Wl,-soname=$(ccsoname)
    3.39 -	pic = -fPIC
    3.40 -endif
    3.41 -
    3.42 -dbg = -g
    3.43 -cxx11 = -std=c++11 -DTS_USE_CPP11
    3.44 -
    3.45 -CFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic)
    3.46 -CXXFLAGS = $(cxx11) $(CFLAGS)
    3.47 -
    3.48 -.PHONY: all
    3.49 -all: $(clib_so) $(clib_a) $(cclib_so) $(cclib_a)
    3.50 -
    3.51 -$(clib_a): $(cobj)
    3.52 -	$(AR) rcs $@ $(cobj)
    3.53 -
    3.54 -$(clib_so): $(cobj)
    3.55 -	$(CC) -o $@ $(cshared) $(cobj) $(LDFLAGS)
    3.56 -
    3.57 -$(cclib_a): $(ccobj)
    3.58 -	$(AR) rcs $@ $(ccobj)
    3.59 -
    3.60 -$(cclib_so): $(ccobj)
    3.61 -	$(CXX) -o $@ $(ccshared) $(ccobj) $(LDFLAGS)
    3.62 -
    3.63 --include $(dep)
    3.64 -
    3.65 -%.d: %.c
    3.66 -	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    3.67 -
    3.68 -%.d: %.cc
    3.69 -	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    3.70 -
    3.71 -.PHONY: clean
    3.72 -clean:
    3.73 -	rm -f $(obj) $(clib_so) $(cclib_so) $(clib_a) $(cclib_a)
    3.74 -
    3.75 -.PHONY: cleandep
    3.76 -cleandep: clean
    3.77 -	rm -f $(dep)
    3.78 -
    3.79 -
    3.80 -.PHONY: install
    3.81 -install: all
    3.82 -	mkdir -p $(DESTDIR)$(PREFIX)/include $(DESTDIR)$(PREFIX)/lib
    3.83 -	cp src/treestore.h src/treestorepp.h $(DESTDIR)$(PREFIX)/include
    3.84 -	cp $(clib_a) $(clib_so) $(cclib_a) $(cclib_so) $(DESTDIR)$(PREFIX)/lib
    3.85 -	[ -n "$(csoname)" ] && \
    3.86 -		cd $(DESTDIR)$(PREFIX) && \
    3.87 -		rm -f $(csoname) $(cdevlink) $(ccsoname) $(ccdevlink) && \
    3.88 -		ln -s $(clib_so) $(csoname) && \
    3.89 -		ln -s $(cclib_so) $(ccsoname) && \
    3.90 -		ln -s $(csoname) $(cdevlink) && \
    3.91 -		ln -s $(ccsoname) $(ccdevlink) || \
    3.92 -		true
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/include/treestore.h	Thu Nov 10 16:19:44 2016 +0200
     4.3 @@ -0,0 +1,114 @@
     4.4 +#ifndef TREESTORE_H_
     4.5 +#define TREESTORE_H_
     4.6 +
     4.7 +#include <stdarg.h>
     4.8 +
     4.9 +#ifdef __cplusplus
    4.10 +extern "C" {
    4.11 +#endif
    4.12 +
    4.13 +enum ts_value_type { TS_UNKNOWN, TS_NUMBER, TS_VECTOR, TS_ARRAY };
    4.14 +
    4.15 +/** treestore node attribute value */
    4.16 +struct ts_value {
    4.17 +	enum ts_value_type type;
    4.18 +
    4.19 +	char *str;		/**< all values have a string representation */
    4.20 +	int inum;		/**< numeric values TS_NUMBER will have this set */
    4.21 +	float fnum;		/**< numeric values TS_NUMBER will have this set */
    4.22 +
    4.23 +	/** vector values (arrays containing ONLY numbers) will have this set */
    4.24 +	float *vec;		/**< elements of the vector */
    4.25 +	int vec_size;	/**< size of the vector (in elements), same as array_size */
    4.26 +
    4.27 +	/** array values (including vectors) will have this set */
    4.28 +	struct ts_value *array;	/**< elements of the array */
    4.29 +	int array_size;			/**< size of the array (in elements) */
    4.30 +};
    4.31 +
    4.32 +int ts_init_value(struct ts_value *tsv);
    4.33 +void ts_destroy_value(struct ts_value *tsv);
    4.34 +
    4.35 +struct ts_value *ts_alloc_value(void);		/**< also calls ts_init_value */
    4.36 +void ts_free_value(struct ts_value *tsv);	/**< also calls ts_destroy_value */
    4.37 +
    4.38 +/** perform a deep-copy of a ts_value */
    4.39 +int ts_copy_value(struct ts_value *dest, struct ts_value *src);
    4.40 +
    4.41 +/** ts_set_value will try to parse the string and initialize the value type fields */
    4.42 +int ts_set_value(struct ts_value *tsv, const char *str);
    4.43 +
    4.44 +/** set a ts_value from a list of integers */
    4.45 +int ts_set_valueiv(struct ts_value *tsv, int count, ...);
    4.46 +int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap);
    4.47 +int ts_set_valuei(struct ts_value *tsv, int inum);	/**< equiv: ts_set_valueiv(val, 1, inum) */
    4.48 +
    4.49 +/** set a ts_value from a list of floats */
    4.50 +int ts_set_valuefv(struct ts_value *tsv, int count, ...);
    4.51 +int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap);
    4.52 +int ts_set_valuef(struct ts_value *tsv, int fnum);	/**< equiv: ts_set_valuefv(val, 1, fnum) */
    4.53 +
    4.54 +/** set a ts_value from a list of ts_value pointers. they are deep-copied as per ts_copy_value */
    4.55 +int ts_set_valuev(struct ts_value *tsv, int count, ...);
    4.56 +int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap);
    4.57 +
    4.58 +
    4.59 +/** treestore node attribute */
    4.60 +struct ts_attr {
    4.61 +	char *name;
    4.62 +	struct ts_value val;
    4.63 +
    4.64 +	struct ts_attr *next;
    4.65 +};
    4.66 +
    4.67 +int ts_init_attr(struct ts_attr *attr);
    4.68 +void ts_destroy_attr(struct ts_attr *attr);
    4.69 +
    4.70 +struct ts_attr *ts_alloc_attr(void);		/**< also calls ts_init_attr */
    4.71 +void ts_free_attr(struct ts_attr *attr);	/**< also calls ts_destroy_attr */
    4.72 +
    4.73 +/** perform a deep-copy of a ts_attr */
    4.74 +int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src);
    4.75 +
    4.76 +int ts_set_attr_name(struct ts_attr *attr, const char *name);
    4.77 +
    4.78 +
    4.79 +
    4.80 +/** treestore node */
    4.81 +struct ts_node {
    4.82 +	char *name;
    4.83 +
    4.84 +	int attr_count;
    4.85 +	struct ts_attr *attr_list, *attr_tail;
    4.86 +
    4.87 +	int child_count;
    4.88 +	struct ts_node *child_list, *child_tail;
    4.89 +	struct ts_node *parent;
    4.90 +
    4.91 +	struct ts_node *next;	/* next sibling */
    4.92 +};
    4.93 +
    4.94 +int ts_init_node(struct ts_node *node);
    4.95 +void ts_destroy_node(struct ts_node *node);
    4.96 +
    4.97 +struct ts_node *ts_alloc_node(void);	/**< also calls ts_init_node */
    4.98 +void ts_free_node(struct ts_node *n);	/**< also calls ts_destroy_node */
    4.99 +
   4.100 +/** recursively destroy all the nodes of the tree */
   4.101 +void ts_free_tree(struct ts_node *tree);
   4.102 +
   4.103 +void ts_add_attr(struct ts_node *node, struct ts_attr *attr);
   4.104 +struct ts_attr *ts_get_attr(struct ts_node *node, const char *name);
   4.105 +
   4.106 +void ts_add_child(struct ts_node *node, struct ts_node *child);
   4.107 +int ts_remove_child(struct ts_node *node, struct ts_node *child);
   4.108 +struct ts_node *ts_get_child(struct ts_node *node, const char *name);
   4.109 +
   4.110 +struct ts_node *ts_load(const char *fname);
   4.111 +int ts_save(struct ts_node *tree, const char *fname);
   4.112 +
   4.113 +#ifdef __cplusplus
   4.114 +}
   4.115 +#endif
   4.116 +
   4.117 +#endif	/* TREESTORE_H_ */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/text.c	Thu Nov 10 16:19:44 2016 +0200
     5.3 @@ -0,0 +1,235 @@
     5.4 +#include <stdio.h>
     5.5 +#include <stdlib.h>
     5.6 +#include <string.h>
     5.7 +#include <ctype.h>
     5.8 +#include "treestore.h"
     5.9 +
    5.10 +enum { TOK_SYM, TOK_ID, TOK_NUM, TOK_STR };
    5.11 +
    5.12 +static struct ts_node *read_node(FILE *fp);
    5.13 +static int next_token(FILE *fp, char *buf, int bsz);
    5.14 +
    5.15 +static void print_attr(struct ts_attr *attr, FILE *fp, int level);
    5.16 +static void print_value(struct ts_value *value, FILE *fp);
    5.17 +static int tree_level(struct ts_node *n);
    5.18 +static const char *indent(int x);
    5.19 +
    5.20 +struct ts_node *ts_text_load(FILE *fp)
    5.21 +{
    5.22 +	char token[256];
    5.23 +	struct ts_node *node;
    5.24 +
    5.25 +	if(next_token(fp, token, sizeof token) != TOK_ID ||
    5.26 +			!(next_token(fp, token, sizeof token) == TOK_SYM && token[0] == '{')) {
    5.27 +		fprintf(stderr, "ts_text_load: invalid file format\n");
    5.28 +		return 0;
    5.29 +	}
    5.30 +	if(!(node = read_node(fp))) {
    5.31 +		return 0;
    5.32 +	}
    5.33 +	if(!(node->name = strdup(token))) {
    5.34 +		perror("failed to allocate node name");
    5.35 +		free(node);
    5.36 +		return 0;
    5.37 +	}
    5.38 +	return node;
    5.39 +}
    5.40 +
    5.41 +
    5.42 +#define EXPECT(type) \
    5.43 +	if(next_token(fp, token, sizeof token) != (type)) goto err
    5.44 +#define EXPECT_SYM(c) \
    5.45 +	if(next_token(fp, token, sizeof token) != TOK_SYM || token[0] != (c)) goto err
    5.46 +
    5.47 +static struct ts_node *read_node(FILE *fp)
    5.48 +{
    5.49 +	char token[256];
    5.50 +	struct ts_node *node;
    5.51 +
    5.52 +	if(!(node = ts_alloc_node())) {
    5.53 +		perror("failed to allocate treestore node");
    5.54 +		return 0;
    5.55 +	}
    5.56 +
    5.57 +	while(next_token(fp, token, sizeof token) == TOK_ID) {
    5.58 +		char *id;
    5.59 +
    5.60 +		if(!(id = strdup(token))) {
    5.61 +			goto err;
    5.62 +		}
    5.63 +
    5.64 +		EXPECT(TOK_SYM);
    5.65 +
    5.66 +		if(token[0] == '=') {
    5.67 +			/* attribute */
    5.68 +			struct ts_attr *attr;
    5.69 +			int toktype;
    5.70 +
    5.71 +			if(!(attr = ts_alloc_attr())) {
    5.72 +				goto err;
    5.73 +			}
    5.74 +
    5.75 +			if((toktype = next_token(fp, token, sizeof token)) == -1) {
    5.76 +				ts_free_attr(attr);
    5.77 +				goto err;
    5.78 +			}
    5.79 +			attr->name = id;
    5.80 +			ts_set_value(&attr->val, token);
    5.81 +
    5.82 +			ts_add_attr(node, attr);
    5.83 +
    5.84 +		} else if(token[0] == '{') {
    5.85 +			/* child */
    5.86 +			struct ts_node *child;
    5.87 +
    5.88 +			if(!(child = read_node(fp))) {
    5.89 +				ts_free_node(node);
    5.90 +				return 0;
    5.91 +			}
    5.92 +			child->name = id;
    5.93 +
    5.94 +			ts_add_child(node, child);
    5.95 +
    5.96 +		} else {
    5.97 +			fprintf(stderr, "unexpected token: %s\n", token);
    5.98 +			goto err;
    5.99 +		}
   5.100 +	}
   5.101 +
   5.102 +err:
   5.103 +	fprintf(stderr, "treestore read_node failed\n");
   5.104 +	ts_free_node(node);
   5.105 +	return 0;
   5.106 +}
   5.107 +
   5.108 +static int next_token(FILE *fp, char *buf, int bsz)
   5.109 +{
   5.110 +	int c;
   5.111 +	char *ptr;
   5.112 +
   5.113 +	// skip whitespace
   5.114 +	while((c = fgetc(fp)) != -1 && isspace(c)) {
   5.115 +		if(c == '#') { // skip to end of line
   5.116 +			while((c = fgetc(fp)) != -1 && c != '\n');
   5.117 +			if(c == -1) return -1;
   5.118 +		}
   5.119 +	}
   5.120 +	if(c == -1) return -1;
   5.121 +
   5.122 +	buf[0] = c;
   5.123 +	buf[1] = 0;
   5.124 +
   5.125 +	if(isdigit(c)) {
   5.126 +		// token is a number
   5.127 +		ptr = buf + 1;
   5.128 +		while((c = fgetc(fp)) != -1 && isdigit(c)) {
   5.129 +			*ptr++ = c;
   5.130 +		}
   5.131 +		if(c != -1) ungetc(c, fp);
   5.132 +		*ptr = 0;
   5.133 +		return TOK_NUM;
   5.134 +	}
   5.135 +	if(isalpha(c)) {
   5.136 +		// token is an identifier
   5.137 +		ptr = buf + 1;
   5.138 +		while((c = fgetc(fp)) != -1 && isalnum(c)) {
   5.139 +			*ptr++ = c;
   5.140 +		}
   5.141 +		if(c != -1) ungetc(c, fp);
   5.142 +		*ptr = 0;
   5.143 +		return TOK_ID;
   5.144 +	}
   5.145 +	if(c == '"') {
   5.146 +		// token is a string constant
   5.147 +		ptr = buf;
   5.148 +		while((c = fgetc(fp)) != -1 && c != '"' && c != '\r' && c != '\n') {
   5.149 +			*ptr++ = c;
   5.150 +		}
   5.151 +		if(c != '"') {
   5.152 +			return -1;
   5.153 +		}
   5.154 +		*ptr = 0;
   5.155 +		return TOK_STR;
   5.156 +	}
   5.157 +
   5.158 +	return TOK_SYM;
   5.159 +}
   5.160 +
   5.161 +int ts_text_save(struct ts_node *tree, FILE *fp)
   5.162 +{
   5.163 +	struct ts_node *c;
   5.164 +	struct ts_attr *attr;
   5.165 +	int lvl = tree_level(tree);
   5.166 +
   5.167 +	fprintf(fp, "%s%s {\n", indent(lvl), tree->name);
   5.168 +
   5.169 +	attr = tree->attr_list;
   5.170 +	while(attr) {
   5.171 +		print_attr(attr, fp, lvl);
   5.172 +		attr = attr->next;
   5.173 +	}
   5.174 +
   5.175 +	c = tree->child_list;
   5.176 +	while(c) {
   5.177 +		ts_text_save(c, fp);
   5.178 +	}
   5.179 +
   5.180 +	fprintf(fp, "%s}\n", indent(lvl));
   5.181 +}
   5.182 +
   5.183 +static void print_attr(struct ts_attr *attr, FILE *fp, int level)
   5.184 +{
   5.185 +	fprintf(fp, "%s%s = ", indent(level + 1), attr->name);
   5.186 +	print_value(&attr->val, fp);
   5.187 +	fputc('\n', fp);
   5.188 +}
   5.189 +
   5.190 +static void print_value(struct ts_value *value, FILE *fp)
   5.191 +{
   5.192 +	int i;
   5.193 +
   5.194 +	switch(value->type) {
   5.195 +	case TS_NUMBER:
   5.196 +		fprintf(fp, "%g", value->fnum);
   5.197 +		break;
   5.198 +
   5.199 +	case TS_VECTOR:
   5.200 +		fputc('[', fp);
   5.201 +		for(i=0; i<value->vec_size; i++) {
   5.202 +			if(i == 0) {
   5.203 +				fprintf(fp, "%g", value->vec[i]);
   5.204 +			} else {
   5.205 +				fprintf(fp, ", %g", value->vec[i]);
   5.206 +			}
   5.207 +		}
   5.208 +		fputc(']', fp);
   5.209 +		break;
   5.210 +
   5.211 +	case TS_ARRAY:
   5.212 +		fputc('[', fp);
   5.213 +		for(i=0; i<value->array_size; i++) {
   5.214 +			if(i > 0) {
   5.215 +				fprintf(fp, ", ");
   5.216 +			}
   5.217 +			print_value(value->array + i, fp);
   5.218 +		}
   5.219 +		fputc(']', fp);
   5.220 +		break;
   5.221 +
   5.222 +	default:
   5.223 +		fputs(value->str, fp);
   5.224 +	}
   5.225 +}
   5.226 +
   5.227 +static int tree_level(struct ts_node *n)
   5.228 +{
   5.229 +	if(!n->parent) return 0;
   5.230 +	return tree_level(n->parent) + 1;
   5.231 +}
   5.232 +
   5.233 +static const char *indent(int x)
   5.234 +{
   5.235 +	static const char *buf = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
   5.236 +	const char *end = buf + sizeof buf - 1;
   5.237 +	return x > sizeof buf - 1 ? buf : end - x;
   5.238 +}
     6.1 --- a/src/treestore.c	Sat Apr 12 13:50:01 2014 +0300
     6.2 +++ b/src/treestore.c	Thu Nov 10 16:19:44 2016 +0200
     6.3 @@ -1,8 +1,12 @@
     6.4  #include <stdio.h>
     6.5  #include <stdlib.h>
     6.6  #include <string.h>
     6.7 +#include <errno.h>
     6.8  #include "treestore.h"
     6.9  
    6.10 +struct ts_node *ts_text_load(FILE *fp);
    6.11 +int ts_text_save(struct ts_node *tree, FILE *fp);
    6.12 +
    6.13  /* ---- ts_value implementation ---- */
    6.14  
    6.15  int ts_init_value(struct ts_value *tsv)
    6.16 @@ -359,3 +363,106 @@
    6.17  
    6.18  	ts_free_node(tree);
    6.19  }
    6.20 +
    6.21 +void ts_add_attr(struct ts_node *node, struct ts_attr *attr)
    6.22 +{
    6.23 +	attr->next = 0;
    6.24 +	if(node->attr_list) {
    6.25 +		node->attr_tail->next = attr;
    6.26 +		node->attr_tail = attr;
    6.27 +	} else {
    6.28 +		node->attr_list = node->attr_tail = attr;
    6.29 +	}
    6.30 +}
    6.31 +
    6.32 +struct ts_attr *ts_get_attr(struct ts_node *node, const char *name)
    6.33 +{
    6.34 +	struct ts_attr *attr = node->attr_list;
    6.35 +	while(attr) {
    6.36 +		if(strcmp(attr->name, name) == 0) {
    6.37 +			return attr;
    6.38 +		}
    6.39 +		attr = attr->next;
    6.40 +	}
    6.41 +	return 0;
    6.42 +}
    6.43 +
    6.44 +void ts_add_child(struct ts_node *node, struct ts_node *child)
    6.45 +{
    6.46 +	if(child->parent) {
    6.47 +		if(child->parent == node) return;
    6.48 +		ts_remove_child(child->parent, child);
    6.49 +	}
    6.50 +	child->parent = node;
    6.51 +	child->next = 0;
    6.52 +
    6.53 +	if(node->child_list) {
    6.54 +		node->child_tail->next = child;
    6.55 +		node->child_tail = child;
    6.56 +	} else {
    6.57 +		node->child_list = node->child_tail = child;
    6.58 +	}
    6.59 +}
    6.60 +
    6.61 +int ts_remove_child(struct ts_node *node, struct ts_node *child)
    6.62 +{
    6.63 +	struct ts_node dummy, *iter = &dummy;
    6.64 +	dummy.next = node->child_list;
    6.65 +
    6.66 +	while(iter->next && iter->next != child) {
    6.67 +		iter = iter->next;
    6.68 +	}
    6.69 +	if(!iter->next) {
    6.70 +		return -1;
    6.71 +	}
    6.72 +
    6.73 +	child->parent = 0;
    6.74 +
    6.75 +	iter->next = child->next;
    6.76 +	if(!iter->next) {
    6.77 +		node->child_tail = iter;
    6.78 +	}
    6.79 +	node->child_list = dummy.next;
    6.80 +	return 0;
    6.81 +}
    6.82 +
    6.83 +struct ts_node *ts_get_child(struct ts_node *node, const char *name)
    6.84 +{
    6.85 +	struct ts_node *res = node->child_list;
    6.86 +	while(res) {
    6.87 +		if(strcmp(res->name, name) == 0) {
    6.88 +			return res;
    6.89 +		}
    6.90 +		res = res->next;
    6.91 +	}
    6.92 +	return 0;
    6.93 +}
    6.94 +
    6.95 +struct ts_node *ts_load(const char *fname)
    6.96 +{
    6.97 +	FILE *fp;
    6.98 +	struct ts_node *root;
    6.99 +
   6.100 +	if(!(fp = fopen(fname, "rb"))) {
   6.101 +		fprintf(stderr, "ts_load: failed to open file: %s: %s\n", fname, strerror(errno));
   6.102 +		return 0;
   6.103 +	}
   6.104 +
   6.105 +	root = ts_text_load(fp);
   6.106 +	fclose(fp);
   6.107 +	return root;
   6.108 +}
   6.109 +
   6.110 +int ts_save(struct ts_node *tree, const char *fname)
   6.111 +{
   6.112 +	FILE *fp;
   6.113 +	int res;
   6.114 +
   6.115 +	if(!(fp = fopen(fname, "wb"))) {
   6.116 +		fprintf(stderr, "ts_save: failed to open file: %s: %s\n", fname, strerror(errno));
   6.117 +		return 0;
   6.118 +	}
   6.119 +	res = ts_text_save(tree, fp);
   6.120 +	fclose(fp);
   6.121 +	return res;
   6.122 +}
     7.1 --- a/src/treestore.h	Sat Apr 12 13:50:01 2014 +0300
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,103 +0,0 @@
     7.4 -#ifndef TREESTORE_H_
     7.5 -#define TREESTORE_H_
     7.6 -
     7.7 -#include <stdarg.h>
     7.8 -
     7.9 -#ifdef __cplusplus
    7.10 -extern "C" {
    7.11 -#endif
    7.12 -
    7.13 -enum ts_value_type { TS_UNKNOWN, TS_NUMBER, TS_VECTOR, TS_ARRAY };
    7.14 -
    7.15 -/** treestore node attribute value */
    7.16 -struct ts_value {
    7.17 -	enum ts_value_type type;
    7.18 -
    7.19 -	char *str;		/**< all values have a string representation */
    7.20 -	int inum;		/**< numeric values (TS_INT/TS_FLOAT) will have this set */
    7.21 -	float fnum;		/**< numeric values (TS_INT/TS_FLOAT) will have this set */
    7.22 -
    7.23 -	/** vector values (arrays containing ONLY numbers) will have this set */
    7.24 -	float *vec;		/**< elements of the vector */
    7.25 -	int vec_size;	/**< size of the vector (in elements), same as array_size */
    7.26 -
    7.27 -	/** array values (including vectors) will have this set */
    7.28 -	struct ts_value *array;	/**< elements of the array */
    7.29 -	int array_size;			/**< size of the array (in elements) */
    7.30 -};
    7.31 -
    7.32 -int ts_init_value(struct ts_value *tsv);
    7.33 -void ts_destroy_value(struct ts_value *tsv);
    7.34 -
    7.35 -struct ts_value *ts_alloc_value(void);		/**< also calls ts_init_value */
    7.36 -void ts_free_value(struct ts_value *tsv);	/**< also calls ts_destroy_value */
    7.37 -
    7.38 -/** perform a deep-copy of a ts_value */
    7.39 -int ts_copy_value(struct ts_value *dest, struct ts_value *src);
    7.40 -
    7.41 -/** ts_set_value will try to parse the string and initialize the value type fields */
    7.42 -int ts_set_value(struct ts_value *tsv, const char *str);
    7.43 -
    7.44 -/** set a ts_value from a list of integers */
    7.45 -int ts_set_valueiv(struct ts_value *tsv, int count, ...);
    7.46 -int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap);
    7.47 -int ts_set_valuei(struct ts_value *tsv, int inum);	/**< equiv: ts_set_valueiv(val, 1, inum) */
    7.48 -
    7.49 -/** set a ts_value from a list of floats */
    7.50 -int ts_set_valuefv(struct ts_value *tsv, int count, ...);
    7.51 -int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap);
    7.52 -int ts_set_valuef(struct ts_value *tsv, int fnum);	/**< equiv: ts_set_valuefv(val, 1, fnum) */
    7.53 -
    7.54 -/** set a ts_value from a list of ts_value pointers. they are deep-copied as per ts_copy_value */
    7.55 -int ts_set_valuev(struct ts_value *tsv, int count, ...);
    7.56 -int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap);
    7.57 -
    7.58 -
    7.59 -/** treestore node attribute */
    7.60 -struct ts_attr {
    7.61 -	char *name;
    7.62 -	struct ts_value val;
    7.63 -
    7.64 -	struct ts_attr *next;
    7.65 -};
    7.66 -
    7.67 -int ts_init_attr(struct ts_attr *attr);
    7.68 -void ts_destroy_attr(struct ts_attr *attr);
    7.69 -
    7.70 -struct ts_attr *ts_alloc_attr(void);		/**< also calls ts_init_attr */
    7.71 -void ts_free_attr(struct ts_attr *attr);	/**< also calls ts_destroy_attr */
    7.72 -
    7.73 -/** perform a deep-copy of a ts_attr */
    7.74 -int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src);
    7.75 -
    7.76 -int ts_set_attr_name(struct ts_attr *attr, const char *name);
    7.77 -
    7.78 -
    7.79 -
    7.80 -/** treestore node */
    7.81 -struct ts_node {
    7.82 -	char *name;
    7.83 -
    7.84 -	int attr_count;
    7.85 -	struct ts_attr *attr_list, *attr_tail;
    7.86 -
    7.87 -	int child_count;
    7.88 -	struct ts_node *child_list, *child_tail;
    7.89 -	struct ts_node *parent;
    7.90 -
    7.91 -	struct ts_node *next;	/* next sibling */
    7.92 -};
    7.93 -
    7.94 -int ts_init_node(struct ts_node *node);
    7.95 -void ts_destroy_node(struct ts_node *node);
    7.96 -
    7.97 -struct ts_node *ts_alloc_node(void);	/**< also calls ts_init_node */
    7.98 -void ts_free_node(struct ts_node *n);	/**< also calls ts_destroy_node */
    7.99 -
   7.100 -void ts_free_tree(struct ts_node *tree);
   7.101 -
   7.102 -#ifdef __cplusplus
   7.103 -}
   7.104 -#endif
   7.105 -
   7.106 -#endif	/* TREESTORE_H_ */
     8.1 --- a/src/treestorepp.h	Sat Apr 12 13:50:01 2014 +0300
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,44 +0,0 @@
     8.4 -#ifndef TREESTOREPP_H_
     8.5 -#define TREESTOREPP_H_
     8.6 -
     8.7 -#include "treestore.h"
     8.8 -
     8.9 -/// wraps a C ts_value in a convenient class
    8.10 -class TSValue {
    8.11 -private:
    8.12 -	ts_value *ctsv;
    8.13 -
    8.14 -public:
    8.15 -	TSValue();
    8.16 -	~TSValue();
    8.17 -
    8.18 -	TSValue(const TSValue &tsv);
    8.19 -	TSValue &operator =(const TSValue &tsv);
    8.20 -
    8.21 -#ifdef TS_USE_CPP11
    8.22 -	TSValue(const TSValue &&tsv);
    8.23 -	TSValue &operator =(const TSValue &&tsv);
    8.24 -#endif
    8.25 -
    8.26 -	bool set(const char *str);
    8.27 -	bool set_int(int inum);
    8.28 -	bool set_int(int count, ...);
    8.29 -	bool set_float(float fnum);
    8.30 -	bool set_float(int count, ...);
    8.31 -	bool set_array(int count, const TSValue &v0, ...);
    8.32 -
    8.33 -	const char *get() const;
    8.34 -
    8.35 -	int get_int() const;
    8.36 -	int *get_intv() const;
    8.37 -
    8.38 -	float get_float() const;
    8.39 -	float *get_floatv() const;
    8.40 -
    8.41 -	const TSValue *get_array() const;
    8.42 -	int get_array_size() const;
    8.43 -
    8.44 -	int get_vec_size() const;	//< equiv: get_array_size */
    8.45 -};
    8.46 -
    8.47 -#endif	// TREESTOREPP_H_