allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / guicast / bchash.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25
26 #include "bchash.h"
27 #include "bcsignals.h"
28 #include "filesystem.h"
29 #include "format.inc"
30
31 BC_Hash::BC_Hash()
32 {
33         this->filename[0] = 0;
34         total = 0;
35         allocated = 0;
36         names = 0;
37         values = 0;
38 }
39
40 BC_Hash::BC_Hash(const char *filename)
41 {
42         strcpy(this->filename, filename);
43         total = 0;
44         allocated = 0;
45         names = 0;
46         values = 0;
47
48         FileSystem directory;
49
50         directory.parse_tildas(this->filename);
51         total = 0;
52 }
53
54 BC_Hash::~BC_Hash()
55 {
56         for(int i = 0; i < total; i++)
57         {
58                 delete [] names[i];
59                 delete [] values[i];
60         }
61         delete [] names;
62         delete [] values;
63 }
64
65 void BC_Hash::reallocate_table(int new_total)
66 {
67         if(allocated < new_total)
68         {
69                 int new_allocated = new_total * 2;
70                 char **new_names = new char*[new_allocated];
71                 char **new_values = new char*[new_allocated];
72
73                 for(int i = 0; i < total; i++)
74                 {
75                         new_names[i] = names[i];
76                         new_values[i] = values[i];
77                 }
78
79                 delete [] names;
80                 delete [] values;
81
82                 names = new_names;
83                 values = new_values;
84                 allocated = new_allocated;
85         }
86 }
87
88 int BC_Hash::load_file(FILE *fp)
89 {
90         char line[4096];
91         int done = 0, ch = -1;
92         total = 0;
93
94         while( !done ) {
95                 char *bp = line, *ep = bp + sizeof(line);
96                 if( !fgets(bp, ep-bp, fp) ) break;
97                 // skip ws (indent)
98                 while( bp < ep && *bp == ' ' ) ++bp;
99                 if( bp >= ep || !*bp || *bp == '\n' ) continue;
100                 char *title = bp;
101                 // span to ws
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];
109                 names[total] = tp;
110                 while( --title_len >= 0 ) *tp++ = *title++;
111                 *tp = 0;
112                 // accumulate value (+ continued lines)
113                 char *value = bp;
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; }
119                         *bp++ = '\n';
120                         done = !fgets(bp, ep-bp, fp);
121                 }
122                 int value_len = bp - value;
123                 char *vp = new char[value_len + 1];
124                 values[total] = vp;
125                 while( --value_len >= 0 ) *vp++ = *value++;
126                 *vp = 0;
127                 total++;
128         }
129         return 0;
130 }
131
132 int BC_Hash::load()
133 {
134         FILE *fp = fopen(filename, "r");
135         if( !fp ) return 1;
136         int ret = load_file(fp);
137         fclose(fp);
138         return ret;
139 }
140
141 int BC_Hash::save_file(FILE *fp)
142 {
143         for(int i = 0; i < total; i++) {
144                 fputs(names[i], fp);
145                 char *vp = values[i];
146                 char *bp = vp;
147                 fputc(' ',fp);
148                 while( (vp=strchr(vp, '\n')) ) {
149                         while( bp < vp ) fputc(*bp++,fp);
150                         fputc('\n',fp);  fputc('+',fp);
151                         ++bp;  ++vp;
152                 }
153                 while( *bp ) fputc(*bp++,fp);
154                 fputc('\n', fp);
155         }
156         return 0;
157 }
158
159 int BC_Hash::save()
160 {
161         FILE *fp = fopen(filename,"w");
162         if( !fp ) return 1;
163         int ret = save_file(fp);
164         fclose(fp);
165         return ret;
166 }
167
168 int BC_Hash::load_string(const char *bfr)
169 {
170         FILE *fp = fmemopen((void*)bfr, strlen(bfr), "r");
171         if( !fp ) return 1;
172         int ret = load_file(fp);
173         fclose(fp);
174         return ret;
175 }
176
177 int BC_Hash::save_string(char *&bfr)
178 {
179         size_t bsz = 0;
180         FILE *fp = open_memstream(&bfr, &bsz);
181         if( !fp ) return 1;
182         int ret = save_file(fp);
183         fclose(fp);
184         return ret;
185 }
186
187
188
189 int32_t BC_Hash::get(const char *name, int32_t default_)
190 {
191         for(int i = 0; i < total; i++)
192         {
193                 if(!strcmp(names[i], name))
194                 {
195                         return (int32_t)atol(values[i]);
196                 }
197         }
198         return default_;  // failed
199 }
200
201 int64_t BC_Hash::get(const char *name, int64_t default_)
202 {
203         int64_t result = default_;
204         for(int i = 0; i < total; i++)
205         {
206                 if(!strcmp(names[i], name))
207                 {
208                         sscanf(values[i], _LD, &result);
209                         return result;
210                 }
211         }
212         return result;
213 }
214
215 double BC_Hash::get(const char *name, double default_)
216 {
217         for(int i = 0; i < total; i++)
218         {
219                 if(!strcmp(names[i], name))
220                 {
221                         return atof(values[i]);
222                 }
223         }
224         return default_;  // failed
225 }
226
227 float BC_Hash::get(const char *name, float default_)
228 {
229         for(int i = 0; i < total; i++)
230         {
231                 if(!strcmp(names[i], name))
232                 {
233                         return atof(values[i]);
234                 }
235         }
236         return default_;  // failed
237 }
238
239 char* BC_Hash::get(const char *name, char *default_)
240 {
241         for(int i = 0; i < total; i++)
242         {
243                 if(!strcmp(names[i], name))
244                 {
245                         strcpy(default_, values[i]);
246                         return values[i];
247                 }
248         }
249         return default_;  // failed
250 }
251
252 int BC_Hash::update(const char *name, double value) // update a value if it exists
253 {
254         char string[BCSTRLEN];
255         sprintf(string, "%.16e", value);
256         return update(name, string);
257 }
258
259 int BC_Hash::update(const char *name, float value) // update a value if it exists
260 {
261         char string[BCSTRLEN];
262         sprintf(string, "%.6e", value);
263         return update(name, string);
264 }
265
266 int BC_Hash::update(const char *name, int32_t value) // update a value if it exists
267 {
268         char string[BCSTRLEN];
269         sprintf(string, "%d", value);
270         return update(name, string);
271 }
272
273 int BC_Hash::update(const char *name, int64_t value) // update a value if it exists
274 {
275         char string[BCSTRLEN];
276         sprintf(string, _LD, value);
277         return update(name, string);
278 }
279
280 int BC_Hash::update(const char *name, const char *value)
281 {
282         for(int i = 0; i < total; i++)
283         {
284                 if(!strcmp(names[i], name))
285                 {
286                         delete [] values[i];
287                         values[i] = new char[strlen(value) + 1];
288                         strcpy(values[i], value);
289                         return 0;
290                 }
291         }
292
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);
299         total++;
300         return 1;
301 }
302
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); \
308 }
309
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 *)
315
316
317 void BC_Hash::copy_from(BC_Hash *src)
318 {
319 // Can't delete because this is used by file decoders after plugins
320 // request data.
321 //      for(int i = 0; i < total; i++)
322 //      {
323 //              delete [] names[i];
324 //              delete [] values[i];
325 //      }
326 //      delete [] names;
327 //      delete [] values;
328 //
329 //      allocated = 0;
330 //      names = 0;
331 //      values = 0;
332 //      total = 0;
333
334 SET_TRACE
335         reallocate_table(src->total);
336 //      total = src->total;
337 SET_TRACE
338         for(int i = 0; i < src->total; i++)
339         {
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]);
345         }
346 SET_TRACE
347 }
348
349 int BC_Hash::equivalent(BC_Hash *src)
350 {
351         for(int i = 0; i < total && i < src->total; i++)
352         {
353                 if(strcmp(names[i], src->names[i]) ||
354                         strcmp(values[i], src->values[i])) return 0;
355         }
356         return 1;
357 }
358
359 int BC_Hash::size()
360 {
361         return total;
362 }
363
364 char* BC_Hash::get_key(int number)
365 {
366         return names[number];
367 }
368
369 char* BC_Hash::get_value(int number)
370 {
371         return values[number];
372 }
373
374
375 void BC_Hash::dump()
376 {
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]);
380 }