libtreestore
view src/treestore.c @ 1:a31eae25c0e6
partial implementation of ts_node and ts_attr
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 12 Apr 2014 13:46:00 +0300 |
parents | 740fec9866b1 |
children | e1a825be0eee |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "treestore.h"
6 /* ---- ts_value implementation ---- */
8 int ts_init_value(struct ts_value *tsv)
9 {
10 memset(tsv, 0, sizeof *tsv);
11 return 0;
12 }
14 void ts_destroy_value(struct ts_value *tsv)
15 {
16 int i;
18 free(tsv->str);
19 free(tsv->vec);
21 for(i=0; i<tsv->array_size; i++) {
22 ts_destroy_value(tsv->array + i);
23 }
24 }
27 struct ts_value *ts_alloc_value(void)
28 {
29 struct ts_value *v = malloc(sizeof *v);
30 if(!v || ts_init_value(v) == -1) {
31 free(v);
32 return 0;
33 }
34 return v;
35 }
37 void ts_free_value(struct ts_value *tsv)
38 {
39 ts_destroy_value(tsv);
40 free(tsv);
41 }
44 int ts_copy_value(struct ts_value *dest, struct ts_value *src)
45 {
46 int i;
48 if(dest == src) return 0;
50 *dest = *src;
52 dest->str = 0;
53 dest->vec = 0;
54 dest->array = 0;
56 if(src->str) {
57 if(!(dest->str = malloc(strlen(src->str) + 1))) {
58 goto fail;
59 }
60 strcpy(dest->str, src->str);
61 }
62 if(src->vec && src->vec_size > 0) {
63 if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) {
64 goto fail;
65 }
66 memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec);
67 }
68 if(src->array && src->array_size > 0) {
69 if(!(dest->array = calloc(src->array_size, sizeof *src->array))) {
70 goto fail;
71 }
72 for(i=0; i<src->array_size; i++) {
73 if(ts_copy_value(dest->array + i, src->array + i) == -1) {
74 goto fail;
75 }
76 }
77 }
78 return 0;
80 fail:
81 free(dest->str);
82 free(dest->vec);
83 if(dest->array) {
84 for(i=0; i<dest->array_size; i++) {
85 ts_destroy_value(dest->array + i);
86 }
87 free(dest->array);
88 }
89 return -1;
90 }
93 int ts_set_value(struct ts_value *tsv, const char *str)
94 {
95 if(tsv->str) {
96 ts_destroy_value(tsv);
97 if(ts_init_value(tsv) == -1) {
98 return -1;
99 }
100 }
102 if(!(tsv->str = malloc(strlen(str) + 1))) {
103 return -1;
104 }
105 strcpy(tsv->str, str);
106 return 0;
107 }
109 int ts_set_valueiv(struct ts_value *tsv, int count, ...)
110 {
111 int res;
112 va_list ap;
113 va_start(ap, count);
114 res = ts_set_valueiv_va(tsv, count, ap);
115 va_end(ap);
116 return res;
117 }
119 #define MAKE_NUMSTR_FUNC(typestr, fmt) \
120 static char *make_##typestr##str(int x) \
121 { \
122 static char scrap[128]; \
123 char *str; \
124 int sz = snprintf(scrap, sizeof scrap, fmt, x); \
125 if(!(str = malloc(sz + 1))) return 0; \
126 sprintf(str, fmt, x); \
127 return str; \
128 }
130 MAKE_NUMSTR_FUNC(int, "%d")
131 MAKE_NUMSTR_FUNC(float, "%d")
133 #define ARGS_ARE_INT ((enum ts_value_type)42)
135 int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap)
136 {
137 if(count < 1) return -1;
138 if(count == 1) {
139 int num = va_arg(ap, int);
140 if(!(tsv->str = make_intstr(tsv->inum))) {
141 return -1;
142 }
144 tsv->type = TS_NUMBER;
145 tsv->inum = num;
146 tsv->fnum = (float)num;
147 return 0;
148 }
150 /* otherwise it's an array, let ts_set_valuefv_va handle it */
151 /* XXX: va_arg will need to be called with int instead of float. set a special
152 * value to the type field before calling this, to signify that.
153 */
154 tsv->type = ARGS_ARE_INT;
155 return ts_set_valuefv_va(tsv, count, ap);
156 }
158 int ts_set_valuei(struct ts_value *tsv, int inum)
159 {
160 return ts_set_valueiv(tsv, 1, inum);
161 }
164 int ts_set_valuefv(struct ts_value *tsv, int count, ...)
165 {
166 int res;
167 va_list ap;
168 va_start(ap, count);
169 res = ts_set_valuefv_va(tsv, count, ap);
170 va_end(ap);
171 return res;
172 }
174 int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap)
175 {
176 int i;
178 if(count < 1) return -1;
179 if(count == 1) {
180 int num = va_arg(ap, int);
181 if(!(tsv->str = make_floatstr(tsv->inum))) {
182 return -1;
183 }
185 tsv->type = TS_NUMBER;
186 tsv->inum = num;
187 tsv->fnum = (float)num;
188 return 0;
189 }
191 /* otherwise it's an array, we need to create the ts_value array, and
192 * the simplified vector
193 */
194 if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) {
195 return -1;
196 }
197 tsv->vec_size = count;
199 for(i=0; i<count; i++) {
200 if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */
201 tsv->vec[i] = (float)va_arg(ap, int);
202 } else {
203 tsv->vec[i] = va_arg(ap, double);
204 }
205 }
207 if(!(tsv->array = malloc(count * sizeof *tsv->array))) {
208 free(tsv->vec);
209 }
210 tsv->array_size = count;
212 for(i=0; i<count; i++) {
213 ts_init_value(tsv->array + i);
214 if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */
215 ts_set_valuei(tsv->array + i, (int)tsv->vec[i]);
216 } else {
217 ts_set_valuef(tsv->array + i, tsv->vec[i]);
218 }
219 }
221 tsv->type = TS_VECTOR;
222 return 0;
223 }
225 int ts_set_valuef(struct ts_value *tsv, int fnum)
226 {
227 return ts_set_valuefv(tsv, 1, fnum);
228 }
231 int ts_set_valuev(struct ts_value *tsv, int count, ...)
232 {
233 int res;
234 va_list ap;
235 va_start(ap, count);
236 res = ts_set_valuev_va(tsv, count, ap);
237 va_end(ap);
238 return res;
239 }
241 int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap)
242 {
243 int i;
245 if(count <= 1) return -1;
247 if((tsv->array = malloc(count * sizeof *tsv->array))) {
248 return -1;
249 }
250 tsv->array_size = count;
252 for(i=0; i<count; i++) {
253 struct ts_value *src = va_arg(ap, struct ts_value*);
254 ts_copy_value(tsv->array + i, src);
255 }
256 return 0;
257 }
260 /* ---- ts_attr implementation ---- */
262 int ts_init_attr(struct ts_attr *attr)
263 {
264 memset(attr, 0, sizeof *attr);
265 return ts_init_value(&attr->val);
266 }
268 void ts_destroy_attr(struct ts_attr *attr)
269 {
270 free(attr->name);
271 ts_destroy_value(&attr->val);
272 }
274 struct ts_attr *ts_alloc_attr(void)
275 {
276 struct ts_attr *attr = malloc(sizeof *attr);
277 if(!attr || ts_init_attr(attr) == -1) {
278 free(attr);
279 return 0;
280 }
281 return attr;
282 }
284 void ts_free_attr(struct ts_attr *attr)
285 {
286 ts_destroy_attr(attr);
287 free(attr);
288 }
290 int ts_copy_attr(struct ts_attr *dest, struct ts_attr *src)
291 {
292 if(dest == src) return 0;
294 if(ts_set_attr_name(dest, src->name) == -1) {
295 return -1;
296 }
298 if(ts_copy_value(&dest->val, &src->val) == -1) {
299 ts_destroy_attr(dest);
300 return -1;
301 }
302 return 0;
303 }
305 int ts_set_attr_name(struct ts_attr *attr, const char *name)
306 {
307 char *n = malloc(strlen(name) + 1);
308 if(!n) return -1;
309 strcpy(n, name);
311 free(attr->name);
312 attr->name = n;
313 return 0;
314 }
317 /* ---- ts_node implementation ---- */
319 int ts_init_node(struct ts_node *node)
320 {
321 memset(node, 0, sizeof *node);
322 return 0;
323 }
325 void ts_destroy_node(struct ts_node *node)
326 {
327 free(node->name);
329 while(node->attr_list) {
330 struct ts_attr *attr = node->attr_list;
331 node->attr_list = node->attr_list->next;
332 ts_free_attr(attr);
333 }
334 }
336 struct ts_node *ts_alloc_node(void)
337 {
338 struct ts_node *node = malloc(sizeof *node);
339 if(!node || ts_init_node(node) == -1) {
340 free(node);
341 return 0;
342 }
343 return node;
344 }
346 void ts_free_node(struct ts_node *node)
347 {
348 ts_destroy_node(node);
349 free(node);
350 }
352 void ts_free_tree(struct ts_node *tree)
353 {
354 while(tree->child_list) {
355 struct ts_tree *child = tree->child_list;
356 tree->child_list = tree->child_list->next;
357 ts_free_tree(child);
358 }
360 ts_free_node(tree);
361 }