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"
32 this->filename[0] = 0;
39 BC_Hash::BC_Hash(const char *filename)
41 strcpy(this->filename, filename);
49 directory.parse_tildas(this->filename);
54 for(int i = 0; i < total; i++)
69 void BC_Hash::reallocate_table(int new_total)
71 if(allocated < new_total)
73 int new_allocated = new_total * 2;
74 char **new_names = new char*[new_allocated];
75 char **new_values = new char*[new_allocated];
77 for(int i = 0; i < total; i++)
79 new_names[i] = names[i];
80 new_values[i] = values[i];
88 allocated = new_allocated;
92 int BC_Hash::load_file(FILE *fp)
95 int done = 0, ch = -1;
99 char *bp = line, *ep = bp + sizeof(line);
100 if( !fgets(bp, ep-bp, fp) ) break;
102 while( bp < ep && *bp == ' ' ) ++bp;
103 if( bp >= ep || !*bp || *bp == '\n' ) continue;
106 while( bp < ep && *bp && *bp != ' ' && *bp != '\n' ) ++bp;
107 if( bp >= ep || title == bp ) continue;
108 int title_len = bp - title;
109 // skip blank seperator
110 if( *bp++ != ' ' ) continue;
111 reallocate_table(total + 1);
112 char *tp = new char[title_len + 1];
114 while( --title_len >= 0 ) *tp++ = *title++;
116 // accumulate value (+ continued lines)
118 while( bp < ep && !done ) {
119 while( bp < ep && *bp && *bp != '\n' ) ++bp;
120 if( bp >= ep || !*bp ) break;
121 if( (ch=fgetc(fp)) < 0 ) break;
122 if( ch != '+' ) { ungetc(ch, fp); break; }
124 done = !fgets(bp, ep-bp, fp);
126 int value_len = bp - value;
127 char *vp = new char[value_len + 1];
129 while( --value_len >= 0 ) *vp++ = *value++;
138 FILE *fp = fopen(filename, "r");
140 int ret = load_file(fp);
145 int BC_Hash::save_file(FILE *fp)
147 for(int i = 0; i < total; i++) {
149 char *vp = values[i];
152 while( (vp=strchr(vp, '\n')) ) {
153 while( bp < vp ) fputc(*bp++,fp);
154 fputc('\n',fp); fputc('+',fp);
157 while( *bp ) fputc(*bp++,fp);
165 FILE *fp = fopen(filename,"w");
167 int ret = save_file(fp);
172 int BC_Hash::load_string(const char *bfr)
174 FILE *fp = fmemopen((void*)bfr, strlen(bfr), "r");
176 int ret = load_file(fp);
181 int BC_Hash::save_string(char *&bfr)
184 FILE *fp = open_memstream(&bfr, &bsz);
186 int ret = save_file(fp);
193 int32_t BC_Hash::get(const char *name, int32_t default_)
195 for(int i = 0; i < total; i++)
197 if(!strcmp(names[i], name))
199 return (int32_t)atol(values[i]);
202 return default_; // failed
205 int64_t BC_Hash::get(const char *name, int64_t default_)
207 int64_t result = default_;
208 for(int i = 0; i < total; i++)
210 if(!strcmp(names[i], name))
212 sscanf(values[i], "%jd", &result);
219 double BC_Hash::get(const char *name, double default_)
221 for(int i = 0; i < total; i++)
223 if(!strcmp(names[i], name))
225 return atof(values[i]);
228 return default_; // failed
231 float BC_Hash::get(const char *name, float default_)
233 for(int i = 0; i < total; i++)
235 if(!strcmp(names[i], name))
237 return atof(values[i]);
240 return default_; // failed
243 char* BC_Hash::get(const char *name, char *default_)
245 for(int i = 0; i < total; i++)
247 if(!strcmp(names[i], name))
249 strcpy(default_, values[i]);
253 return default_; // failed
256 int BC_Hash::update(const char *name, double value) // update a value if it exists
258 char string[BCSTRLEN];
259 sprintf(string, "%.16e", value);
260 return update(name, string);
263 int BC_Hash::update(const char *name, float value) // update a value if it exists
265 char string[BCSTRLEN];
266 sprintf(string, "%.6e", value);
267 return update(name, string);
270 int BC_Hash::update(const char *name, int32_t value) // update a value if it exists
272 char string[BCSTRLEN];
273 sprintf(string, "%d", value);
274 return update(name, string);
277 int BC_Hash::update(const char *name, int64_t value) // update a value if it exists
279 char string[BCSTRLEN];
280 sprintf(string, "%jd", value);
281 return update(name, string);
284 int BC_Hash::update(const char *name, const char *value)
286 for(int i = 0; i < total; i++)
288 if(!strcmp(names[i], name))
291 values[i] = new char[strlen(value) + 1];
292 strcpy(values[i], value);
297 // didn't find so create new entry
298 reallocate_table(total + 1);
299 names[total] = new char[strlen(name) + 1];
300 strcpy(names[total], name);
301 values[total] = new char[strlen(value) + 1];
302 strcpy(values[total], value);
307 #define varFn(rtyp, fn, typ) \
308 rtyp BC_Hash::fn##f(typ value, const char *fmt, ...) { \
309 char string[BCTEXTLEN]; va_list ap; va_start(ap, fmt); \
310 vsnprintf(string, BCTEXTLEN, fmt, ap); \
311 va_end(ap); return fn(string, value); \
314 varFn(int,update,double) varFn(double,get,double)
315 varFn(int,update,float) varFn(float,get,float)
316 varFn(int,update,int32_t) varFn(int32_t,get,int32_t)
317 varFn(int,update,int64_t) varFn(int64_t,get,int64_t)
318 varFn(int,update,const char *) varFn(char *,get,char *)
321 void BC_Hash::copy_from(BC_Hash *src)
323 // Can't delete because this is used by file decoders after plugins
324 // request data. use explicit destructor to clear/clean
328 reallocate_table(src->total);
329 // total = src->total;
331 for(int i = 0; i < src->total; i++)
333 update(src->names[i], src->values[i]);
334 // names[i] = new char[strlen(src->names[i]) + 1];
335 // values[i] = new char[strlen(src->values[i]) + 1];
336 // strcpy(names[i], src->names[i]);
337 // strcpy(values[i], src->values[i]);
342 int BC_Hash::equivalent(BC_Hash *src)
344 for(int i = 0; i < total && i < src->total; i++)
346 if(strcmp(names[i], src->names[i]) ||
347 strcmp(values[i], src->values[i])) return 0;
357 char* BC_Hash::get_key(int number)
359 return names[number];
362 char* BC_Hash::get_value(int number)
364 return values[number];
370 printf("BC_Hash::dump\n");
371 for(int i = 0; i < total; i++)
372 printf(" key=%s value=%s\n", names[i], values[i]);