1 /*--------------------------------------------------------------------------*\
2  * ConfigFile class
3  *
4  * Input file consists of lines of text of the form
5  *   name = value
6  * where 'name' is the look up key and 'value' is the resultant value
7  *
8  * '\' is the escape character and allows values to contain embedded '"' and
9  *   '#' characters, as well as to do line continuation.
10  * To put '"' in a value use '\"'.  To put '\' in a value use '\\'.
11  *
12  * Anything in double quotes is copied literally (except escape sequences).
13  * Outside of double quotes:
14  *   '#' starts a comment; the rest of the line is ignored
15  *   White space is ignored
16  *
17  *--------------------------------------------------------------------------
18  *
19  * Created by Mark Huss <mark@mhuss.com>
20  *
21  * Developed and built using the mingw32 gcc compiler 2.95.2
22  *
23  * THIS SOFTWARE IS NOT COPYRIGHTED
24  *
25  * This source code is offered for use in the public domain. You may
26  * use, modify or distribute it freely.
27  *
28  * This code is distributed in the hope that it will be useful but
29  * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
30  * DISCLAMED. This includes but is not limited to warranties of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
32  *
33 \*--------------------------------------------------------------------------*/
34 
35 #if !defined(CONFIG_FILE__H)
36 #define CONFIG_FILE__H
37 
38 #include <stdio.h>  // for FILE*
39 
40 //----------------------------------------------------------------------------
41 // CFList : a simple linked list class
42 //
43 class CFList {
44 public:
CFList(const char * name,const char * value)45   CFList(const char* name, const char* value): m_next(0) {
46     m_name = strDup(name);
47     m_value = strDup(value);
48   }
49 
~CFList()50   ~CFList() {
51     delete [] m_name; m_name=0;
52     delete [] m_value; m_value=0;
53 
54     // recursive delete
55     delete m_next;
56     m_next = 0;
57   }
58 
59   void add(const char* name, const char* value);
60   void update(const char* name, const char* value);
61 
62   const char* value(const char* name) const;
63   bool boolValue(const char* name) const;
64   int intValue(const char* name) const;
65   double dblValue(const char* name) const;
66 
67   void dump( FILE* fp = stdout ) const;
68 
69 private:
CFList()70   CFList() {}  // default c'tor not allowed
71 
72   static char* strDup( const char* p );
73 
74   const char* m_name;
75   const char* m_value;
76   CFList* m_next;
77 };  // end class CFList
78 
79 //----------------------------------------------------------------------------
80 // the main class
81 
82 class ConfigFile {
83 
84 public:
85   // cheap way to define integer constants
86   enum {
87     NV_SEP_CHAR = '=',
88     COMMENT_CHAR = '#',
89     QUOTE_CHAR = '"',
90     ESC_CHAR = '\\',
91     BUFSIZE = 5120
92   };
93 
94   enum {
95     OK = 0,
96     INVALID_FILE_NAME,
97     FILE_NOT_FOUND,
98     NO_ENTRIES
99   };
100 
101   static bool debug;
102 
103   // constructors
ConfigFile()104   ConfigFile() : m_status( NO_ENTRIES ), m_items( "ConfigFile", "init" ) {}
105 
ConfigFile(const char * fname)106   ConfigFile( const char* fname ) : m_items( "ConfigFile", "init" ) {
107      readAndParseFile( fname );
108   }
109 
110   // specify a new config file
filename(const char * fname)111   int filename( const char* fname ) { return readAndParseFile( fname ); }
112 
113   // retrieve a string value --return NULL if not found
value(const char * name)114   const char* value( const char* name ) const  {
115     return m_items.value( name );
116   }
117 
118   // retrieve a boolean value -- returns false if not found or name is not '[Tt]rue'
boolValue(const char * name)119   int boolValue( const char* name ) const {
120     return m_items.boolValue( name );
121   }
122 
123   // retrieve an int value -- returns 0 if not found or name is not an int
intValue(const char * name)124   int intValue( const char* name ) const {
125     return m_items.intValue( name );
126   }
127 
128   // retrieve a double value -- returns 0. if not found or name is not a double
dblValue(const char * name)129   double dblValue( const char* name ) const {
130     return m_items.dblValue( name );
131   }
132 
133   // output all keys and values
dump(FILE * fp)134   void dump( FILE* fp ) const { m_items.dump( fp ); }
135 
status()136   int status() const { return m_status; }
137 
138 private:
139   int m_status;
140   CFList m_items;
141 
142   // config file path & name
143   const char* m_filename;
144 
145   // load m_values
146   int readAndParseFile( const char* fname );
147 
148   bool compactBuffer(char* buf);
149 
150 }; // end class ConfigFile
151 
152 #endif  /* #if !defined(CONFIG_FILE__H) */
153