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);
55 for(int i = 0; i < total; i++)
70 void BC_Hash::reallocate_table(int new_total)
72 if(allocated < new_total)
74 int new_allocated = new_total * 2;
75 char **new_names = new char*[new_allocated];
76 char **new_values = new char*[new_allocated];
78 for(int i = 0; i < total; i++)
80 new_names[i] = names[i];
81 new_values[i] = values[i];
89 allocated = new_allocated;
93 int BC_Hash::load_file(FILE *fp)
96 int done = 0, ch = -1;
100 char *bp = line, *ep = bp + sizeof(line);
101 if( !fgets(bp, ep-bp, fp) ) break;
103 while( bp < ep && *bp == ' ' ) ++bp;
104 if( bp >= ep || !*bp || *bp == '\n' ) continue;
107 while( bp < ep && *bp && *bp != ' ' && *bp != '\n' ) ++bp;
108 if( bp >= ep || title == bp ) continue;
109 int title_len = bp - title;
110 // skip blank seperator
111 if( *bp++ != ' ' ) continue;
112 reallocate_table(total + 1);
113 char *tp = new char[title_len + 1];
115 while( --title_len >= 0 ) *tp++ = *title++;
117 // accumulate value (+ continued lines)
119 while( bp < ep && !done ) {
120 while( bp < ep && *bp && *bp != '\n' ) ++bp;
121 if( bp >= ep || !*bp ) break;
122 if( (ch=fgetc(fp)) < 0 ) break;
123 if( ch != '+' ) { ungetc(ch, fp); break; }
125 done = !fgets(bp, ep-bp, fp);
127 int value_len = bp - value;
128 char *vp = new char[value_len + 1];
130 while( --value_len >= 0 ) *vp++ = *value++;
139 FILE *fp = fopen(filename, "r");
141 int ret = load_file(fp);
146 int BC_Hash::save_file(FILE *fp)
148 for(int i = 0; i < total; i++) {
150 char *vp = values[i];
153 while( (vp=strchr(vp, '\n')) ) {
154 while( bp < vp ) fputc(*bp++,fp);
155 fputc('\n',fp); fputc('+',fp);
158 while( *bp ) fputc(*bp++,fp);
166 FILE *fp = fopen(filename,"w");
168 int ret = save_file(fp);
173 int BC_Hash::load_string(const char *bfr)
175 FILE *fp = fmemopen((void*)bfr, strlen(bfr), "r");
177 int ret = load_file(fp);
182 int BC_Hash::save_string(char *&bfr)
185 FILE *fp = open_memstream(&bfr, &bsz);
187 int ret = save_file(fp);
194 int32_t BC_Hash::get(const char *name, int32_t default_)
196 for(int i = 0; i < total; i++)
198 if(!strcmp(names[i], name))
200 return (int32_t)atol(values[i]);
203 return default_; // failed
206 int64_t BC_Hash::get(const char *name, int64_t default_)
208 int64_t result = default_;
209 for(int i = 0; i < total; i++)
211 if(!strcmp(names[i], name))
213 sscanf(values[i], _LD, &result);
220 double BC_Hash::get(const char *name, double default_)
222 for(int i = 0; i < total; i++)
224 if(!strcmp(names[i], name))
226 return atof(values[i]);
229 return default_; // failed
232 float BC_Hash::get(const char *name, float default_)
234 for(int i = 0; i < total; i++)
236 if(!strcmp(names[i], name))
238 return atof(values[i]);
241 return default_; // failed
244 char* BC_Hash::get(const char *name, char *default_)
246 for(int i = 0; i < total; i++)
248 if(!strcmp(names[i], name))
250 strcpy(default_, values[i]);
254 return default_; // failed
257 int BC_Hash::update(const char *name, double value) // update a value if it exists
259 char string[BCSTRLEN];
260 sprintf(string, "%.16e", value);
261 return update(name, string);
264 int BC_Hash::update(const char *name, float value) // update a value if it exists
266 char string[BCSTRLEN];
267 sprintf(string, "%.6e", value);
268 return update(name, string);
271 int BC_Hash::update(const char *name, int32_t value) // update a value if it exists
273 char string[BCSTRLEN];
274 sprintf(string, "%d", value);
275 return update(name, string);
278 int BC_Hash::update(const char *name, int64_t value) // update a value if it exists
280 char string[BCSTRLEN];
281 sprintf(string, _LD, value);
282 return update(name, string);
285 int BC_Hash::update(const char *name, const char *value)
287 for(int i = 0; i < total; i++)
289 if(!strcmp(names[i], name))
292 values[i] = new char[strlen(value) + 1];
293 strcpy(values[i], value);
298 // didn't find so create new entry
299 reallocate_table(total + 1);
300 names[total] = new char[strlen(name) + 1];
301 strcpy(names[total], name);
302 values[total] = new char[strlen(value) + 1];
303 strcpy(values[total], value);
308 #define varFn(rtyp, fn, typ) \
309 rtyp BC_Hash::fn##f(typ value, const char *fmt, ...) { \
310 char string[BCTEXTLEN]; va_list ap; va_start(ap, fmt); \
311 vsnprintf(string, BCTEXTLEN, fmt, ap); \
312 va_end(ap); return fn(string, value); \
315 varFn(int,update,double) varFn(double,get,double)
316 varFn(int,update,float) varFn(float,get,float)
317 varFn(int,update,int32_t) varFn(int32_t,get,int32_t)
318 varFn(int,update,int64_t) varFn(int64_t,get,int64_t)
319 varFn(int,update,const char *) varFn(char *,get,char *)
322 void BC_Hash::copy_from(BC_Hash *src)
324 // Can't delete because this is used by file decoders after plugins
325 // request data. use explicit destructor to clear/clean
329 reallocate_table(src->total);
330 // total = src->total;
332 for(int i = 0; i < src->total; i++)
334 update(src->names[i], src->values[i]);
335 // names[i] = new char[strlen(src->names[i]) + 1];
336 // values[i] = new char[strlen(src->values[i]) + 1];
337 // strcpy(names[i], src->names[i]);
338 // strcpy(values[i], src->values[i]);
343 int BC_Hash::equivalent(BC_Hash *src)
345 for(int i = 0; i < total && i < src->total; i++)
347 if(strcmp(names[i], src->names[i]) ||
348 strcmp(values[i], src->values[i])) return 0;
358 char* BC_Hash::get_key(int number)
360 return names[number];
363 char* BC_Hash::get_value(int number)
365 return values[number];
371 printf("BC_Hash::dump\n");
372 for(int i = 0; i < total; i++)
373 printf(" key=%s value=%s\n", names[i], values[i]);