4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "bcsignals.h"
28 #include "filesystem.h"
33 this->filename[0] = 0;
40 BC_Hash::BC_Hash(const char *filename)
42 strcpy(this->filename, filename);
50 directory.parse_tildas(this->filename);
56 for(int i = 0; i < total; i++)
65 void BC_Hash::reallocate_table(int new_total)
67 if(allocated < new_total)
69 int new_allocated = new_total * 2;
70 char **new_names = new char*[new_allocated];
71 char **new_values = new char*[new_allocated];
73 for(int i = 0; i < total; i++)
75 new_names[i] = names[i];
76 new_values[i] = values[i];
84 allocated = new_allocated;
88 int BC_Hash::load_file(FILE *fp)
91 int done = 0, ch = -1;
95 char *bp = line, *ep = bp + sizeof(line);
96 if( !fgets(bp, ep-bp, fp) ) break;
98 while( bp < ep && *bp == ' ' ) ++bp;
99 if( bp >= ep || !*bp || *bp == '\n' ) continue;
102 while( bp < ep && *bp && *bp != ' ' && *bp != '\n' ) ++bp;
103 if( bp >= ep || title == bp ) continue;
104 int title_len = bp - title;
105 // skip blank seperator
106 if( *bp++ != ' ' ) continue;
107 reallocate_table(total + 1);
108 char *tp = new char[title_len + 1];
110 while( --title_len >= 0 ) *tp++ = *title++;
112 // accumulate value (+ continued lines)
114 while( bp < ep && !done ) {
115 while( bp < ep && *bp && *bp != '\n' ) ++bp;
116 if( bp >= ep || !*bp ) break;
117 if( (ch=fgetc(fp)) < 0 ) break;
118 if( ch != '+' ) { ungetc(ch, fp); break; }
120 done = !fgets(bp, ep-bp, fp);
122 int value_len = bp - value;
123 char *vp = new char[value_len + 1];
125 while( --value_len >= 0 ) *vp++ = *value++;
134 FILE *fp = fopen(filename, "r");
136 int ret = load_file(fp);
141 int BC_Hash::save_file(FILE *fp)
143 for(int i = 0; i < total; i++) {
145 char *vp = values[i];
148 while( (vp=strchr(vp, '\n')) ) {
149 while( bp < vp ) fputc(*bp++,fp);
150 fputc('\n',fp); fputc('+',fp);
153 while( *bp ) fputc(*bp++,fp);
161 FILE *fp = fopen(filename,"w");
163 int ret = save_file(fp);
168 int BC_Hash::load_string(const char *bfr)
170 FILE *fp = fmemopen((void*)bfr, strlen(bfr), "r");
172 int ret = load_file(fp);
177 int BC_Hash::save_string(char *&bfr)
180 FILE *fp = open_memstream(&bfr, &bsz);
182 int ret = save_file(fp);
189 int32_t BC_Hash::get(const char *name, int32_t default_)
191 for(int i = 0; i < total; i++)
193 if(!strcmp(names[i], name))
195 return (int32_t)atol(values[i]);
198 return default_; // failed
201 int64_t BC_Hash::get(const char *name, int64_t default_)
203 int64_t result = default_;
204 for(int i = 0; i < total; i++)
206 if(!strcmp(names[i], name))
208 sscanf(values[i], _LD, &result);
215 double BC_Hash::get(const char *name, double default_)
217 for(int i = 0; i < total; i++)
219 if(!strcmp(names[i], name))
221 return atof(values[i]);
224 return default_; // failed
227 float BC_Hash::get(const char *name, float default_)
229 for(int i = 0; i < total; i++)
231 if(!strcmp(names[i], name))
233 return atof(values[i]);
236 return default_; // failed
239 char* BC_Hash::get(const char *name, char *default_)
241 for(int i = 0; i < total; i++)
243 if(!strcmp(names[i], name))
245 strcpy(default_, values[i]);
249 return default_; // failed
252 int BC_Hash::update(const char *name, double value) // update a value if it exists
254 char string[BCSTRLEN];
255 sprintf(string, "%.16e", value);
256 return update(name, string);
259 int BC_Hash::update(const char *name, float value) // update a value if it exists
261 char string[BCSTRLEN];
262 sprintf(string, "%.6e", value);
263 return update(name, string);
266 int BC_Hash::update(const char *name, int32_t value) // update a value if it exists
268 char string[BCSTRLEN];
269 sprintf(string, "%d", value);
270 return update(name, string);
273 int BC_Hash::update(const char *name, int64_t value) // update a value if it exists
275 char string[BCSTRLEN];
276 sprintf(string, _LD, value);
277 return update(name, string);
280 int BC_Hash::update(const char *name, const char *value)
282 for(int i = 0; i < total; i++)
284 if(!strcmp(names[i], name))
287 values[i] = new char[strlen(value) + 1];
288 strcpy(values[i], value);
293 // didn't find so create new entry
294 reallocate_table(total + 1);
295 names[total] = new char[strlen(name) + 1];
296 strcpy(names[total], name);
297 values[total] = new char[strlen(value) + 1];
298 strcpy(values[total], value);
303 #define varFn(rtyp, fn, typ) \
304 rtyp BC_Hash::fn##f(typ value, const char *fmt, ...) { \
305 char string[BCTEXTLEN]; va_list ap; va_start(ap, fmt); \
306 vsnprintf(string, BCTEXTLEN, fmt, ap); \
307 va_end(ap); return fn(string, value); \
310 varFn(int,update,double) varFn(double,get,double)
311 varFn(int,update,float) varFn(float,get,float)
312 varFn(int,update,int32_t) varFn(int32_t,get,int32_t)
313 varFn(int,update,int64_t) varFn(int64_t,get,int64_t)
314 varFn(int,update,const char *) varFn(char *,get,char *)
317 void BC_Hash::copy_from(BC_Hash *src)
319 // Can't delete because this is used by file decoders after plugins
321 // for(int i = 0; i < total; i++)
323 // delete [] names[i];
324 // delete [] values[i];
335 reallocate_table(src->total);
336 // total = src->total;
338 for(int i = 0; i < src->total; i++)
340 update(src->names[i], src->values[i]);
341 // names[i] = new char[strlen(src->names[i]) + 1];
342 // values[i] = new char[strlen(src->values[i]) + 1];
343 // strcpy(names[i], src->names[i]);
344 // strcpy(values[i], src->values[i]);
349 int BC_Hash::equivalent(BC_Hash *src)
351 for(int i = 0; i < total && i < src->total; i++)
353 if(strcmp(names[i], src->names[i]) ||
354 strcmp(values[i], src->values[i])) return 0;
364 char* BC_Hash::get_key(int number)
366 return names[number];
369 char* BC_Hash::get_value(int number)
371 return values[number];
377 printf("BC_Hash::dump\n");
378 for(int i = 0; i < total; i++)
379 printf(" key=%s value=%s\n", names[i], values[i]);