1 /*
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is MPEG4IP.
13  *
14  * The Initial Developer of the Original Code is Cisco Systems Inc.
15  * Portions created by Cisco Systems Inc. are
16  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
17  *
18  * Contributor(s):
19  *		Dave Mackie		dmackie@cisco.com
20  *		Bill May 		wmay@cisco.com
21  */
22 
23 #ifndef __CONFIG_SET_H__
24 #define __CONFIG_SET_H__
25 
26 #include <mpeg4ip.h>
27 
28 
29 #ifndef CONFIG_SAFETY
30 #define CONFIG_SAFETY 1
31 #endif
32 
33 typedef u_int32_t config_integer_t;
34 
35 typedef u_int32_t config_index_t;
36 
37 
38 enum ConfigException {
39 	CONFIG_ERR_INAME,
40 	CONFIG_ERR_TYPE,
41 	CONFIG_ERR_MEMORY,
42 };
43 
44 // TBD type specific exception info and printing utility
45 class CConfigException {
46 public:
CConfigException(ConfigException e)47 	CConfigException(ConfigException e) {
48 		type = e;
49 	}
50 	ConfigException	type;
51 };
52 
53 #define CONFIG_MAX_STRLEN	255
54 
55 // TBD weld this in, and throw exception
56 
57 typedef enum ConfigType {
58 	CONFIG_TYPE_UNDEFINED,
59 	CONFIG_TYPE_INTEGER,
60 	CONFIG_TYPE_BOOL,
61 	CONFIG_TYPE_STRING,
62 	CONFIG_TYPE_FLOAT
63 } ConfigType;
64 
65 union UConfigValue {
UConfigValue(void)66 	UConfigValue(void) {
67 		m_svalue = NULL;
68 	}
UConfigValue(config_integer_t ivalue)69 	UConfigValue(config_integer_t ivalue) {
70 		m_ivalue = ivalue;
71 	}
UConfigValue(bool bvalue)72 	UConfigValue(bool bvalue) {
73 		m_bvalue = bvalue;
74 	}
UConfigValue(const char * svalue)75   UConfigValue(const char *svalue) {
76     m_svalue = svalue;
77   }
UConfigValue(char * svalue)78 	UConfigValue(char* svalue) {
79 		m_svalue = svalue;
80 	}
UConfigValue(float fvalue)81 	UConfigValue(float fvalue) {
82 		m_fvalue = fvalue;
83 	}
84 
85 	config_integer_t	m_ivalue;
86 	bool			m_bvalue;
87 	const char*		m_svalue;
88 	float				m_fvalue;
89 };
90 
91 typedef struct SConfigVariable {
92         config_index_t	               *m_iName;
93 	const char* 			m_sName;
94 	ConfigType			m_type;
95 	UConfigValue			m_defaultValue;
96 	const char*                     m_helpString;
97 	UConfigValue			m_value;
98 } SConfigVarible;
99 
100 
101 
102 struct SUnknownConfigVariable {
103   struct SUnknownConfigVariable *next;
104   SConfigVariable *value;
105 };
106 
107 class CConfigSet {
108 public:
CConfigSet(const SConfigVariable * variables,config_index_t numVariables,const char * defaultFileName)109 	CConfigSet(const SConfigVariable* variables,
110 	  config_index_t numVariables,
111 	  const char* defaultFileName) {
112 	  uint32_t size;
113 		m_debug = false;
114 		m_numVariables = numVariables;
115 		size = sizeof(SConfigVariable) * numVariables;
116 		m_variables =
117 		  (SConfigVariable*)malloc(size);
118 
119 		memcpy(m_variables, variables, size);
120 		m_fileName = defaultFileName == NULL ? NULL :
121 		  strdup(defaultFileName);
122 		SetToDefaults();
123 		m_unknown_head = NULL;
124 	};
125 
~CConfigSet()126 	~CConfigSet() {
127 		CHECK_AND_FREE(m_fileName);
128 		for (config_index_t i = 0; i < m_numVariables; i++) {
129 		  CleanUpConfig(&m_variables[i]);
130 		}
131 		free(m_variables);
132 		m_variables = NULL;
133 		SUnknownConfigVariable *ptr = m_unknown_head;
134 		while (ptr != NULL) {
135 		  m_unknown_head = ptr->next;
136 		  CHECK_AND_FREE(ptr->value->m_sName);
137 		  CHECK_AND_FREE(ptr->value->m_value.m_svalue);
138 		  free(ptr->value);
139 		  free(ptr);
140 		  ptr = m_unknown_head;
141 		}
142 	}
143 
InitializeIndexes(void)144 	void InitializeIndexes(void) {
145 	  for (config_index_t ix = 0; ix < m_numVariables; ix++) {
146 	      *m_variables[ix].m_iName = ix;
147 	    }
148 	}
149 
AddConfigVariables(const SConfigVariable * vars,config_index_t numVariables)150 	void AddConfigVariables (const SConfigVariable* vars,
151 				 config_index_t numVariables) {
152 	  config_index_t start = m_numVariables;
153 	  uint32_t size = sizeof(SConfigVariable) *
154 	    (m_numVariables + numVariables);
155 	  m_variables = (SConfigVariable*)realloc(m_variables, size);
156 	  memcpy(&m_variables[m_numVariables], vars,
157 		 numVariables * sizeof(SConfigVariable));
158 	  m_numVariables += numVariables;
159 	  SetToDefaults(start);
160 	}
161 
GetFileName()162 	const char* GetFileName() {
163 		return m_fileName;
164 	}
165 
SetFileName(const char * name)166 	void SetFileName(const char *name) {
167 	  CHECK_AND_FREE(m_fileName);
168 	  m_fileName = strdup(name);
169 	};
170 
CheckIName(config_index_t iName)171 	inline void CheckIName(config_index_t iName) {
172 		if (iName >= m_numVariables) {
173 		  fprintf(stderr,
174 			  "config variable index failure - try %u max %u\n",
175 			  iName, m_numVariables);
176 		  fflush(stderr);
177 		  throw new CConfigException(CONFIG_ERR_INAME);
178 		}
179 		if (*m_variables[iName].m_iName != iName) {
180 		  fprintf(stderr,
181 			   "config variable index mismatch %u should %u\n",
182 			   iName, *m_variables[iName].m_iName);
183 		  fflush(stderr);
184 		  throw new CConfigException(CONFIG_ERR_INAME);
185 		}
186 	}
187 
188 
CheckIntegerType(config_index_t iName)189 	inline void CheckIntegerType(config_index_t iName) {
190 		if (m_variables[iName].m_type != CONFIG_TYPE_INTEGER) {
191 		  fprintf(stderr,
192 			  "config type mismatch on %s - shouldn't be integer\n",
193 			  m_variables[iName].m_sName);
194 		  fflush(stderr);
195 		  throw new CConfigException(CONFIG_ERR_TYPE);
196 		}
197 	}
198 
CheckBoolType(config_index_t iName)199 	inline void CheckBoolType(config_index_t iName) {
200 		if (m_variables[iName].m_type != CONFIG_TYPE_BOOL) {
201 		  fprintf(stderr,
202 			  "config type mismatch on %s - shouldn't be bool\n",
203 			  m_variables[iName].m_sName);
204 		  fflush(stderr);
205 		  throw new CConfigException(CONFIG_ERR_TYPE);
206 		}
207 	}
208 
CheckStringType(config_index_t iName)209 	inline void CheckStringType(config_index_t iName) {
210 		if (m_variables[iName].m_type != CONFIG_TYPE_STRING) {
211 		  fprintf(stderr,
212 			  "config type mismatch on %s - shouldn't be string\n",
213 			  m_variables[iName].m_sName);
214 		  fflush(stderr);
215 			throw new CConfigException(CONFIG_ERR_TYPE);
216 		}
217 	}
218 
CheckFloatType(config_index_t iName)219 	inline void CheckFloatType(config_index_t iName) {
220 		if (m_variables[iName].m_type != CONFIG_TYPE_FLOAT) {
221 		  fprintf(stderr,
222 			  "config type mismatch on %s - shouldn't be float\n",
223 			  m_variables[iName].m_sName);
224 		  fflush(stderr);
225 			throw new CConfigException(CONFIG_ERR_TYPE);
226 		}
227 	}
228 
IsDefault(const config_index_t iName)229 	inline bool IsDefault (const config_index_t iName) {
230 #if CONFIG_SAFETY
231 	  CheckIName(iName);
232 #endif
233 	  return IsValueDefault(&m_variables[iName]);
234 	};
235 
GetIntegerValue(const config_index_t iName)236 	inline config_integer_t GetIntegerValue(const config_index_t iName) {
237 #if CONFIG_SAFETY
238 		CheckIName(iName);
239 		CheckIntegerType(iName);
240 #endif
241 		return m_variables[iName].m_value.m_ivalue;
242 	}
243 
SetIntegerValue(const config_index_t iName,config_integer_t ivalue)244 	inline void SetIntegerValue(const config_index_t iName,
245 	  config_integer_t ivalue) {
246 #if CONFIG_SAFETY
247 		CheckIName(iName);
248 		CheckIntegerType(iName);
249 #endif
250 		m_variables[iName].m_value.m_ivalue = ivalue;
251 	}
252 
GetBoolValue(const config_index_t iName)253 	inline bool GetBoolValue(const config_index_t iName) {
254 #if CONFIG_SAFETY
255 		CheckIName(iName);
256 		CheckBoolType(iName);
257 #endif
258 		return m_variables[iName].m_value.m_bvalue;;
259 	}
260 
SetBoolValue(const config_index_t iName,bool bvalue)261 	inline void SetBoolValue(const config_index_t iName, bool bvalue) {
262 #if CONFIG_SAFETY
263 		CheckIName(iName);
264 		CheckBoolType(iName);
265 #endif
266 		m_variables[iName].m_value.m_bvalue = bvalue;
267 	}
268 
GetStringValue(const config_index_t iName)269 	inline const char* GetStringValue(const config_index_t iName) {
270 #if CONFIG_SAFETY
271 		CheckIName(iName);
272 		CheckStringType(iName);
273 #endif
274 		return m_variables[iName].m_value.m_svalue;
275 	}
276 
GetHelpValue(const config_index_t iName)277 	inline const char* GetHelpValue(const config_index_t iName) {
278 #if CONFIG_SAFETY
279 	  CheckIName(iName);
280 #endif
281 	  return m_variables[iName].m_helpString;
282 	};
283 
SetStringValue(const config_index_t iName,const char * svalue)284 	inline void SetStringValue(const config_index_t iName, const char* svalue) {
285 #if CONFIG_SAFETY
286 		CheckIName(iName);
287 		CheckStringType(iName);
288 #endif
289 		if (svalue == m_variables[iName].m_value.m_svalue) {
290 			return;
291 		}
292 		CHECK_AND_FREE(m_variables[iName].m_value.m_svalue);
293 		if (svalue == NULL) {
294 		  m_variables[iName].m_value.m_svalue = NULL;
295 		} else {
296 		  m_variables[iName].m_value.m_svalue = strdup(svalue);
297 		  if (m_variables[iName].m_value.m_svalue == NULL) {
298 		    throw new CConfigException(CONFIG_ERR_MEMORY);
299 		  }
300 		}
301 	}
302 
GetFloatValue(const config_index_t iName)303 	inline float GetFloatValue(const config_index_t iName) {
304 #if CONFIG_SAFETY
305 		CheckIName(iName);
306 		CheckFloatType(iName);
307 #endif
308 		return m_variables[iName].m_value.m_fvalue;
309 	}
310 
SetFloatValue(const config_index_t iName,float fvalue)311 	inline void SetFloatValue(const config_index_t iName, float fvalue) {
312 #if CONFIG_SAFETY
313 		CheckIName(iName);
314 		CheckFloatType(iName);
315 #endif
316 		m_variables[iName].m_value.m_fvalue = fvalue;
317 	}
318 
319 	void SetToDefaults(int start = 0) {
320 		for (config_index_t i = start; i < m_numVariables; i++) {
321 			SetToDefault(&m_variables[i]);
322 		}
323 	}
324 
SetToDefault(const config_index_t iName)325 	void SetToDefault(const config_index_t iName) {
326 	  SetToDefault(&m_variables[iName]);
327 	}
328 
ProcessLine(char * line)329 	void ProcessLine (char *line) {
330 	// comment
331 	  SConfigVariable* var;
332 	  if (line[0] == '#') {
333 	    return;
334 	  }
335 	  char* s = line, *name;
336 	  while (*s != '\0') s++;
337 	  s--;
338 	  while (isspace(*s)) {
339 	    *s = '\0';
340 	    s--;
341 	  }
342 	  s = name = line;
343 
344 	  var = FindByName(strsep(&s, "="));
345 	  if (var == NULL || s == NULL) {
346 	    if (s != NULL) {
347 	      SConfigVariable *svar;
348 	      svar = MALLOC_STRUCTURE(SConfigVariable);
349 	      memset(svar, 0, sizeof(*svar));
350 	      svar->m_sName = strdup(name);
351 	      svar->m_type = CONFIG_TYPE_STRING;
352 	      if (!FromAscii(svar, s)) {
353 		fprintf(stderr, "bad config value in line %s\n", s);
354 	      }
355 	      SUnknownConfigVariable *ptr;
356 	      ptr = MALLOC_STRUCTURE(SUnknownConfigVariable);
357 	      ptr->next = m_unknown_head;
358 	      ptr->value = svar;
359 	      m_unknown_head = ptr;
360 	    }
361 	    if (m_debug) {
362 	      fprintf(stderr, "bad config line %s\n", s);
363 	    }
364 	    return;
365 	  }
366 	  if (!FromAscii(var, s)) {
367 	    if (m_debug) {
368 	      fprintf(stderr, "bad config value in line %s\n", s);
369 	    }
370 	  }
371 	}
372 
SetVariableFromAscii(config_index_t ix,char * arg)373 	void SetVariableFromAscii(config_index_t ix, char *arg) {
374 	  FromAscii(&m_variables[ix], arg);
375 	};
376 
377 	bool ReadFile(const char* fileName = NULL) {
378 	  if (fileName == NULL && m_fileName == NULL)
379 	    return false;
380 
381 	  if (fileName != NULL) {
382 		CHECK_AND_FREE(m_fileName);
383 		m_fileName = strdup(fileName);
384 	  }
385 		FILE* pFile = fopen(m_fileName, "r");
386 		if (pFile == NULL) {
387 			if (m_debug) {
388 				fprintf(stderr, "couldn't open file %s\n", fileName);
389 			}
390 			return false;
391 		}
392 		char line[256];
393 		while (fgets(line, sizeof(line), pFile)) {
394 		  ProcessLine(line);
395 		}
396 		fclose(pFile);
397 		return true;
398 	}
399 
400 	bool WriteToFile(const char* fileName = NULL, bool allValues = false) {
401 		FILE* pFile;
402 		config_index_t i;
403 		SConfigVariable *var;
404 		SUnknownConfigVariable *ptr;
405 		if (fileName == NULL && m_fileName == NULL) {
406 		  return false;
407 		}
408 		if (fileName == NULL) {
409 		  fileName = m_fileName;
410 		}
411 		pFile = fopen(fileName, "w");
412 		if (pFile == NULL) {
413 			if (m_debug) {
414 				fprintf(stderr, "couldn't open file %s\n", fileName);
415 			}
416 			return false;
417 		}
418 		for (i = 0; i < m_numVariables; i++) {
419 			var = &m_variables[i];
420 			if (allValues || !IsValueDefault(var)) {
421 				fprintf(pFile, "%s=%s\n", var->m_sName,
422 					ToAscii(var));
423 			}
424 		}
425 		ptr = m_unknown_head;
426 		while (ptr != NULL) {
427 		  fprintf(pFile, "%s=%s\n", ptr->value->m_sName,
428 			  ToAscii(ptr->value));
429 		  ptr = ptr->next;
430 		}
431 		fclose(pFile);
432 		return true;
433 	}
434 
435 
436 	void SetDebug(bool debug = true) {
437 		m_debug = debug;
438 	}
439 #ifdef _WIN32
440 	int ReadVariablesFromRegistry(const char *reg_name,
441 				      const char *config_section);
442 	void WriteVariablesToRegistry(const char *reg_name,
443 				      const char *config_section);
444 #endif
445  public:
FindIndexByName(const char * sName)446 	config_index_t FindIndexByName(const char *sName) {
447 		for (config_index_t i = 0; i < m_numVariables; i++) {
448 			if (!strcasecmp(sName, m_variables[i].m_sName)) {
449 			  return i;
450 			}
451 		}
452 		return UINT32_MAX;
453 	}
GetTypeFromIndex(config_index_t index)454 	ConfigType GetTypeFromIndex (config_index_t index) {
455 	  if (index < m_numVariables) {
456 	    return m_variables[index].m_type;
457 	  }
458 	  return CONFIG_TYPE_UNDEFINED;
459 	};
GetNameFromIndex(config_index_t index)460 	const char *GetNameFromIndex (config_index_t index) {
461 	  if (index < m_numVariables) {
462 	    return m_variables[index].m_sName;
463 	  }
464 	  return NULL;
465 	};
GetNumVariables(void)466 	config_index_t GetNumVariables (void) {
467 	  return m_numVariables;
468 	};
469 	void DisplayHelp(bool onlyHelp = false) {
470 	  config_index_t ix;
471 	  for (ix = 0; ix < m_numVariables; ix++) {
472 	    if (m_variables[ix].m_helpString) {
473 	      fprintf(stdout, "%s - %s\n", m_variables[ix].m_sName,
474 		      m_variables[ix].m_helpString);
475 	    } else if (onlyHelp == false) {
476 	      fprintf(stdout, "%s\n", m_variables[ix].m_sName);
477 	    }
478 	  }
479 	};
Dump(void)480 	void Dump (void) {
481 	  fprintf(stdout, "File - %s\n", GetFileName());
482 	  config_index_t ix;
483 	  for (ix = 0; ix < m_numVariables; ix++) {
484 	    fprintf(stdout, "%s:\t%s\n",
485 		    m_variables[ix].m_sName,
486 		    ToAscii(&m_variables[ix]));
487 	  }
488 	};
GetUnknownStringValue(const char * var_name)489 	const char* GetUnknownStringValue (const char *var_name) {
490 	  SUnknownConfigVariable *svar = m_unknown_head;
491 	  while (svar != NULL) {
492 	    if (strcasecmp(var_name, svar->value->m_sName) == 0) {
493 	      return svar->value->m_value.m_svalue;
494 	    }
495 	    svar = svar->next;
496 	  }
497 	  config_index_t ix = FindIndexByName(var_name);
498 	  if (ix == UINT32_MAX) return NULL;
499 	  return m_variables[ix].m_value.m_svalue;
500 	};
501 
502 protected:
FindByName(const char * sName)503 	SConfigVariable* FindByName(const char* sName) {
504 	  config_index_t ix = FindIndexByName(sName);
505 	  if (ix == UINT32_MAX) return NULL;
506 	  return &m_variables[ix];
507 	};
508 
509 protected:
510 	SConfigVariable*	m_variables;
511 	config_index_t		m_numVariables;
512 	bool 			m_debug;
513 	const char*		m_fileName;
514 	SUnknownConfigVariable *m_unknown_head;
ToAscii(SConfigVariable * v)515 	const char* ToAscii(SConfigVariable *v) {
516 	  static char sBuf[CONFIG_MAX_STRLEN+3];
517 	  switch (v->m_type) {
518 	  case CONFIG_TYPE_INTEGER:
519 	    sprintf(sBuf, "%d", v->m_value.m_ivalue);
520 	    return sBuf;
521 	  case CONFIG_TYPE_BOOL:
522 	    sprintf(sBuf, "%d", v->m_value.m_bvalue);
523 	    return sBuf;
524 	  case CONFIG_TYPE_STRING:
525 	    if (v->m_value.m_svalue == NULL) {
526 	      sprintf(sBuf, "\"\"");
527 	      return sBuf;
528 	    }
529 	    if (strchr(v->m_value.m_svalue, ' ')) {
530 	      sBuf[0] = '"';
531 	      strncpy(&sBuf[1], v->m_value.m_svalue, CONFIG_MAX_STRLEN);
532 	      strcpy(&sBuf[MIN(strlen(v->m_value.m_svalue),
533 			       CONFIG_MAX_STRLEN)+1], "\"");
534 	    }
535 	    return v->m_value.m_svalue;
536 	  case CONFIG_TYPE_FLOAT:
537 	    sprintf(sBuf, "%f", v->m_value.m_fvalue);
538 	    return sBuf;
539 	  case CONFIG_TYPE_UNDEFINED:
540 	  default:
541 	    return "";
542 	  }
543 	};
544 
FromAscii(SConfigVarible * v,const char * s)545 	bool FromAscii(SConfigVarible *v, const char* s) {
546 	  switch (v->m_type) {
547 	  case CONFIG_TYPE_INTEGER:
548 	    return (sscanf(s, " %i ", &v->m_value.m_ivalue) == 1);
549 	  case CONFIG_TYPE_BOOL:
550 	    // OPTION could add "yes/no", "true/false"
551 	    if (sscanf(s, " %u ", &v->m_value.m_ivalue) != 1) {
552 	      return false;
553 	    }
554 	    v->m_value.m_bvalue = v->m_value.m_ivalue ? true : false;
555 	    return true;
556 	  case CONFIG_TYPE_STRING:
557 	    // N.B. assuming m_svalue has been alloc'ed
558 	    {
559 	      size_t len = strlen(s);
560 	      CHECK_AND_FREE(v->m_value.m_svalue);
561 	      if (*s == '"' && s[len] == '"') {
562 		char *newvalue = strdup(s + 1);
563 		newvalue[len - 1] = '\0';
564 
565 		v->m_value.m_svalue = newvalue;
566 	      } else {
567 		v->m_value.m_svalue = strdup(s);
568 	      }
569 	      if (v->m_value.m_svalue == NULL) {
570 		throw new CConfigException(CONFIG_ERR_MEMORY);
571 	      }
572 	      return true;
573 	    }
574 	  case CONFIG_TYPE_FLOAT:
575 	    return (sscanf(s, " %f ", &v->m_value.m_fvalue) == 1);
576 	  case CONFIG_TYPE_UNDEFINED:
577 	  default:
578 	    return false;
579 	  }
580 	};
581 
SetToDefault(SConfigVariable * v)582 	void SetToDefault(SConfigVariable *v) {
583 	  switch (v->m_type) {
584 	  case CONFIG_TYPE_INTEGER:
585 	    v->m_value.m_ivalue = v->m_defaultValue.m_ivalue;
586 	    break;
587 	  case CONFIG_TYPE_BOOL:
588 	    v->m_value.m_bvalue = v->m_defaultValue.m_bvalue;
589 	    break;
590 	  case CONFIG_TYPE_STRING:
591 	    CHECK_AND_FREE(v->m_value.m_svalue);
592 	    if (v->m_defaultValue.m_svalue == NULL) {
593 	      v->m_value.m_svalue = NULL;
594 	    } else {
595 	      v->m_value.m_svalue = strdup(v->m_defaultValue.m_svalue);
596 	      if (v->m_value.m_svalue == NULL) {
597 		throw new CConfigException(CONFIG_ERR_MEMORY);
598 	      }
599 	    }
600 	    break;
601 	  case CONFIG_TYPE_FLOAT:
602 	    v->m_value.m_fvalue = v->m_defaultValue.m_fvalue;
603 	    break;
604 	  case CONFIG_TYPE_UNDEFINED:
605 	  default:
606 	    break;
607 	  }
608 	};
609 
IsValueDefault(SConfigVarible * v)610 	bool IsValueDefault(SConfigVarible *v) {
611 	  switch (v->m_type) {
612 	  case CONFIG_TYPE_INTEGER:
613 	    return v->m_value.m_ivalue == v->m_defaultValue.m_ivalue;
614 	  case CONFIG_TYPE_BOOL:
615 	    return v->m_value.m_bvalue == v->m_defaultValue.m_bvalue;
616 	  case CONFIG_TYPE_STRING:
617 	    if (v->m_defaultValue.m_svalue == NULL &&
618 		v->m_value.m_svalue == NULL)
619 	      return true;
620 	    if (v->m_defaultValue.m_svalue == NULL) return false;
621 	    if (v->m_value.m_svalue == NULL) return false;
622 	    return (strcmp(v->m_value.m_svalue,
623 			   v->m_defaultValue.m_svalue) == 0);
624 	  case CONFIG_TYPE_FLOAT:
625 	    return v->m_value.m_fvalue == v->m_defaultValue.m_fvalue;
626 	  case CONFIG_TYPE_UNDEFINED:
627 	  default:
628 	    return false;
629 	  }
630 	};
CleanUpConfig(SConfigVariable * v)631         void CleanUpConfig(SConfigVariable *v) {
632 	  if (v->m_type == CONFIG_TYPE_STRING) {
633 	    CHECK_AND_FREE(v->m_value.m_svalue);
634 	  }
635 	};
636 };
637 
638 // To define configuration variables - first DECLARE_CONFIG in a
639 // .h file.  Then in either a C++ or h file, define a static array
640 // of configuration variables using CONFIG_BOOL, CONFIG_FLOAT, CONFIG_INT
641 // or CONFIG_STRING.  You can include the .h anywhere you use the variable -
642 // in a .cpp, you must include the .h file with DECLARE_CONFIG_VARIABLES
643 // defined before the .h file.  Note - if you're already including mp4live.h,
644 // you need to #define the DECLARE_CONFIG_VARIABLES after the include.
645 //
646 // Note - you want to add the config variables BEFORE the ReadFile
647 // call
648 
649 #define CONFIG_BOOL(var, name, defval) \
650  { &(var), (name), CONFIG_TYPE_BOOL, (defval), }
651 #define CONFIG_FLOAT(var, name, defval) \
652  { &(var), (name), CONFIG_TYPE_FLOAT,(float) (defval), }
653 #define CONFIG_INT(var, name, defval) \
654  { &(var), (name), CONFIG_TYPE_INTEGER,(config_integer_t) (defval), }
655 #define CONFIG_STRING(var, name, defval) \
656  { &(var), (name), CONFIG_TYPE_STRING, (const char *)(defval), (const char *)NULL }
657 #define CONFIG_BOOL_HELP(var, name, defval, help) \
658  { &(var), (name), CONFIG_TYPE_BOOL, (defval), (help), }
659 #define CONFIG_FLOAT_HELP(var, name, defval, help) \
660  { &(var), (name), CONFIG_TYPE_FLOAT,(float) (defval), (help), }
661 #define CONFIG_INT_HELP(var, name, defval, help) \
662  { &(var), (name), CONFIG_TYPE_INTEGER,(config_integer_t) (defval), (help), }
663 #define CONFIG_STRING_HELP(var, name, defval, help) \
664  { &(var), (name), CONFIG_TYPE_STRING, (const char *)(defval), (help), (const char *)NULL,  }
665 
666 
667 #endif /* __CONFIG_SET_H__ */
668 
669 #undef DECLARE_CONFIG
670 #ifdef DECLARE_CONFIG_VARIABLES
671 #define DECLARE_CONFIG(a) config_index_t (a);
672 #else
673 #define DECLARE_CONFIG(a) extern config_index_t (a);
674 #endif
675