libtreestore
diff src/treestore.c @ 0:740fec9866b1
treestore initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 11 Apr 2014 08:56:46 +0300 |
parents | |
children | a31eae25c0e6 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/treestore.c Fri Apr 11 08:56:46 2014 +0300 1.3 @@ -0,0 +1,245 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include "treestore.h" 1.8 + 1.9 +/* ---- ts_value implementation ---- */ 1.10 + 1.11 +int ts_init_value(struct ts_value *tsv) 1.12 +{ 1.13 + memset(tsv, 0, sizeof *tsv); 1.14 + return 0; 1.15 +} 1.16 + 1.17 +void ts_destroy_value(struct ts_value *tsv) 1.18 +{ 1.19 + int i; 1.20 + 1.21 + free(tsv->str); 1.22 + free(tsv->vec); 1.23 + 1.24 + for(i=0; i<tsv->array_size; i++) { 1.25 + ts_destroy_value(tsv->array + i); 1.26 + } 1.27 +} 1.28 + 1.29 + 1.30 +struct ts_value *ts_alloc_value(void) 1.31 +{ 1.32 + struct ts_value *v = malloc(sizeof *v); 1.33 + if(!v || ts_init_value(v) == -1) { 1.34 + free(v); 1.35 + return 0; 1.36 + } 1.37 + return v; 1.38 +} 1.39 + 1.40 +void ts_free_value(struct ts_value *tsv) 1.41 +{ 1.42 + ts_destroy_value(tsv); 1.43 + free(tsv); 1.44 +} 1.45 + 1.46 + 1.47 +int ts_copy_value(struct ts_value *dest, struct ts_value *src) 1.48 +{ 1.49 + int i; 1.50 + 1.51 + if(dest == src) return 0; 1.52 + 1.53 + *dest = *src; 1.54 + 1.55 + dest->str = 0; 1.56 + dest->vec = 0; 1.57 + dest->array = 0; 1.58 + 1.59 + if(src->str) { 1.60 + if(!(dest->str = malloc(strlen(src->str) + 1))) { 1.61 + goto fail; 1.62 + } 1.63 + strcpy(dest->str, src->str); 1.64 + } 1.65 + if(src->vec && src->vec_size > 0) { 1.66 + if(!(dest->vec = malloc(src->vec_size * sizeof *src->vec))) { 1.67 + goto fail; 1.68 + } 1.69 + memcpy(dest->vec, src->vec, src->vec_size * sizeof *src->vec); 1.70 + } 1.71 + if(src->array && src->array_size > 0) { 1.72 + if(!(dest->array = calloc(src->array_size, sizeof *src->array))) { 1.73 + goto fail; 1.74 + } 1.75 + for(i=0; i<src->array_size; i++) { 1.76 + if(ts_copy_value(dest->array + i, src->array + i) == -1) { 1.77 + goto fail; 1.78 + } 1.79 + } 1.80 + } 1.81 + return 0; 1.82 + 1.83 +fail: 1.84 + free(dest->str); 1.85 + free(dest->vec); 1.86 + if(dest->array) { 1.87 + for(i=0; i<dest->array_size; i++) { 1.88 + ts_destroy_value(dest->array + i); 1.89 + } 1.90 + free(dest->array); 1.91 + } 1.92 + return -1; 1.93 +} 1.94 + 1.95 + 1.96 +int ts_set_value(struct ts_value *tsv, const char *str) 1.97 +{ 1.98 + if(tsv->str) { 1.99 + ts_destroy_value(tsv); 1.100 + if(ts_init_value(tsv) == -1) { 1.101 + return -1; 1.102 + } 1.103 + } 1.104 + 1.105 + if(!(tsv->str = malloc(strlen(str) + 1))) { 1.106 + return -1; 1.107 + } 1.108 + strcpy(tsv->str, str); 1.109 + return 0; 1.110 +} 1.111 + 1.112 +int ts_set_valueiv(struct ts_value *tsv, int count, ...) 1.113 +{ 1.114 + int res; 1.115 + va_list ap; 1.116 + va_start(ap, count); 1.117 + res = ts_set_valueiv_va(tsv, count, ap); 1.118 + va_end(ap); 1.119 + return res; 1.120 +} 1.121 + 1.122 +#define MAKE_NUMSTR_FUNC(typestr, fmt) \ 1.123 + static char *make_##typestr##str(int x) \ 1.124 + { \ 1.125 + static char scrap[128]; \ 1.126 + char *str; \ 1.127 + int sz = snprintf(scrap, sizeof scrap, fmt, x); \ 1.128 + if(!(str = malloc(sz + 1))) return 0; \ 1.129 + sprintf(str, fmt, x); \ 1.130 + return str; \ 1.131 + } 1.132 + 1.133 +MAKE_NUMSTR_FUNC(int, "%d") 1.134 +MAKE_NUMSTR_FUNC(float, "%d") 1.135 + 1.136 +#define ARGS_ARE_INT ((enum ts_value_type)42) 1.137 + 1.138 +int ts_set_valueiv_va(struct ts_value *tsv, int count, va_list ap) 1.139 +{ 1.140 + if(count < 1) return -1; 1.141 + if(count == 1) { 1.142 + int num = va_arg(ap, int); 1.143 + if(!(tsv->str = make_intstr(tsv->inum))) { 1.144 + return -1; 1.145 + } 1.146 + 1.147 + tsv->type = TS_NUMBER; 1.148 + tsv->inum = num; 1.149 + tsv->fnum = (float)num; 1.150 + return 0; 1.151 + } 1.152 + 1.153 + /* otherwise it's an array, let ts_set_valuefv_va handle it */ 1.154 + /* XXX: va_arg will need to be called with int instead of float. set a special 1.155 + * value to the type field before calling this, to signify that. 1.156 + */ 1.157 + tsv->type = ARGS_ARE_INT; 1.158 + return ts_set_valuefv_va(tsv, count, ap); 1.159 +} 1.160 + 1.161 +int ts_set_valuei(struct ts_value *tsv, int inum) 1.162 +{ 1.163 + return ts_set_valueiv(tsv, 1, inum); 1.164 +} 1.165 + 1.166 + 1.167 +int ts_set_valuefv(struct ts_value *tsv, int count, ...) 1.168 +{ 1.169 + int res; 1.170 + va_list ap; 1.171 + va_start(ap, count); 1.172 + res = ts_set_valuefv_va(tsv, count, ap); 1.173 + va_end(ap); 1.174 + return res; 1.175 +} 1.176 + 1.177 +int ts_set_valuefv_va(struct ts_value *tsv, int count, va_list ap) 1.178 +{ 1.179 + int i; 1.180 + 1.181 + if(count < 1) return -1; 1.182 + if(count == 1) { 1.183 + int num = va_arg(ap, int); 1.184 + if(!(tsv->str = make_floatstr(tsv->inum))) { 1.185 + return -1; 1.186 + } 1.187 + 1.188 + tsv->type = TS_NUMBER; 1.189 + tsv->inum = num; 1.190 + tsv->fnum = (float)num; 1.191 + return 0; 1.192 + } 1.193 + 1.194 + /* otherwise it's an array, we need to create the ts_value array, and 1.195 + * the simplified vector 1.196 + */ 1.197 + if(!(tsv->vec = malloc(count * sizeof *tsv->vec))) { 1.198 + return -1; 1.199 + } 1.200 + tsv->vec_size = count; 1.201 + 1.202 + for(i=0; i<count; i++) { 1.203 + if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */ 1.204 + tsv->vec[i] = (float)va_arg(ap, int); 1.205 + } else { 1.206 + tsv->vec[i] = va_arg(ap, double); 1.207 + } 1.208 + } 1.209 + 1.210 + if(!(tsv->array = malloc(count * sizeof *tsv->array))) { 1.211 + free(tsv->vec); 1.212 + } 1.213 + tsv->array_size = count; 1.214 + 1.215 + for(i=0; i<count; i++) { 1.216 + ts_init_value(tsv->array + i); 1.217 + if(tsv->type == ARGS_ARE_INT) { /* only when called by ts_set_valueiv_va */ 1.218 + ts_set_valuei(tsv->array + i, (int)tsv->vec[i]); 1.219 + } else { 1.220 + ts_set_valuef(tsv->array + i, tsv->vec[i]); 1.221 + } 1.222 + } 1.223 + 1.224 + tsv->type = TS_VECTOR; 1.225 + return 0; 1.226 +} 1.227 + 1.228 +int ts_set_valuef(struct ts_value *tsv, int fnum) 1.229 +{ 1.230 + return ts_set_valuefv(tsv, 1, fnum); 1.231 +} 1.232 + 1.233 + 1.234 +int ts_set_valuev(struct ts_value *tsv, int count, ...) 1.235 +{ 1.236 + int res; 1.237 + va_list ap; 1.238 + va_start(ap, count); 1.239 + res = ts_set_valuev_va(tsv, count, ap); 1.240 + va_end(ap); 1.241 + return res; 1.242 +} 1.243 + 1.244 +int ts_set_valuev_va(struct ts_value *tsv, int count, va_list ap) 1.245 +{ 1.246 + if(count <= 1) return -1; 1.247 + return -1; /* TODO */ 1.248 +}