source: source/ariba/utility/configuration/ConfigFile.h@ 12062

Last change on this file since 12062 was 7471, checked in by Christoph Mayer, 15 years ago
File size: 7.7 KB
Line 
1// [License]
2// ConfigFile.h
3// Class for reading named values from configuration files
4// Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu
5
6// Copyright (c) 2004 Richard J. Wagner
7//
8// Permission is hereby granted, free of charge, to any person obtaining a copy
9// of this software and associated documentation files (the "Software"), to
10// deal in the Software without restriction, including without limitation the
11// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12// sell copies of the Software, and to permit persons to whom the Software is
13// furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in
16// all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24// IN THE SOFTWARE.
25// [License]
26
27
28// Typical usage
29// -------------
30//
31// Given a configuration file "settings.inp":
32// atoms = 25
33// length = 8.0 # nanometers
34// name = Reece Surcher
35//
36// Named values are read in various ways, with or without default values:
37// ConfigFile config( "settings.inp" );
38// int atoms = config.read<int>( "atoms" );
39// double length = config.read( "length", 10.0 );
40// string author, title;
41// config.readInto( author, "name" );
42// config.readInto( title, "title", string("Untitled") );
43//
44// See file example.cpp for more examples.
45
46#ifndef CONFIGFILE_H
47#define CONFIGFILE_H
48
49#include <string>
50#include <map>
51#include <iostream>
52#include <fstream>
53#include <sstream>
54
55using std::string;
56
57namespace ariba {
58namespace utility {
59
60class ConfigFile {
61// Data
62protected:
63 string myDelimiter; // separator between key and value
64 string myComment; // separator between value and comments
65 string mySentry; // optional string to signal end of file
66 std::map<string,string> myContents; // extracted keys and values
67
68 typedef std::map<string,string>::iterator mapi;
69 typedef std::map<string,string>::const_iterator mapci;
70
71// Methods
72public:
73 ConfigFile( string filename,
74 string delimiter = "=",
75 string comment = "#",
76 string sentry = "EndConfigFile" );
77 ConfigFile();
78
79 // Search for key and read value or optional default value
80 template<class T> T read( const string& key ) const; // call as read<T>
81 template<class T> T read( const string& key, const T& value ) const;
82 template<class T> bool readInto( T& var, const string& key ) const;
83 template<class T>
84 bool readInto( T& var, const string& key, const T& value ) const;
85
86 // Modify keys and values
87 template<class T> void add( string key, const T& value );
88 void remove( const string& key );
89
90 // Check whether key exists in configuration
91 bool keyExists( const string& key ) const;
92
93 // Check or change configuration syntax
94 string getDelimiter() const { return myDelimiter; }
95 string getComment() const { return myComment; }
96 string getSentry() const { return mySentry; }
97 string setDelimiter( const string& s )
98 { string old = myDelimiter; myDelimiter = s; return old; }
99 string setComment( const string& s )
100 { string old = myComment; myComment = s; return old; }
101
102 // Write or read configuration
103 friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf );
104 friend std::istream& operator>>( std::istream& is, ConfigFile& cf );
105
106protected:
107 template<class T> static string T_as_string( const T& t );
108 template<class T> static T string_as_T( const string& s );
109 static void trim( string& s );
110
111
112// Exception types
113public:
114 struct file_not_found {
115 string filename;
116 file_not_found( const string& filename_ = string() )
117 : filename(filename_) {} };
118 struct key_not_found { // thrown only by T read(key) variant of read()
119 string key;
120 key_not_found( const string& key_ = string() )
121 : key(key_) {} };
122};
123
124
125/* static */
126template<class T>
127string ConfigFile::T_as_string( const T& t )
128{
129 // Convert from a T to a string
130 // Type T must support << operator
131 std::ostringstream ost;
132 ost << t;
133 return ost.str();
134}
135
136
137/* static */
138template<class T>
139T ConfigFile::string_as_T( const string& s )
140{
141 // Convert from a string to a T
142 // Type T must support >> operator
143 T t;
144 std::istringstream ist(s);
145 ist >> t;
146 return t;
147}
148
149
150/* static */
151template<>
152inline string ConfigFile::string_as_T<string>( const string& s )
153{
154 // Convert from a string to a string
155 // In other words, do nothing
156 return s;
157}
158
159
160/* static */
161template<>
162inline bool ConfigFile::string_as_T<bool>( const string& s )
163{
164 // Convert from a string to a bool
165 // Interpret "false", "F", "no", "n", "0" as false
166 // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true
167 bool b = true;
168 string sup = s;
169 for( string::iterator p = sup.begin(); p != sup.end(); ++p )
170 *p = toupper(*p); // make string all caps
171 if( sup==string("FALSE") || sup==string("F") ||
172 sup==string("NO") || sup==string("N") ||
173 sup==string("0") || sup==string("NONE") )
174 b = false;
175 return b;
176}
177
178
179template<class T>
180T ConfigFile::read( const string& key ) const
181{
182 // Read the value corresponding to key
183 mapci p = myContents.find(key);
184 if( p == myContents.end() ) throw key_not_found(key);
185 return string_as_T<T>( p->second );
186}
187
188
189template<class T>
190T ConfigFile::read( const string& key, const T& value ) const
191{
192 // Return the value corresponding to key or given default value
193 // if key is not found
194 mapci p = myContents.find(key);
195 if( p == myContents.end() ) return value;
196 return string_as_T<T>( p->second );
197}
198
199
200template<class T>
201bool ConfigFile::readInto( T& var, const string& key ) const
202{
203 // Get the value corresponding to key and store in var
204 // Return true if key is found
205 // Otherwise leave var untouched
206 mapci p = myContents.find(key);
207 bool found = ( p != myContents.end() );
208 if( found ) var = string_as_T<T>( p->second );
209 return found;
210}
211
212
213template<class T>
214bool ConfigFile::readInto( T& var, const string& key, const T& value ) const
215{
216 // Get the value corresponding to key and store in var
217 // Return true if key is found
218 // Otherwise set var to given default
219 mapci p = myContents.find(key);
220 bool found = ( p != myContents.end() );
221 if( found )
222 var = string_as_T<T>( p->second );
223 else
224 var = value;
225 return found;
226}
227
228
229template<class T>
230void ConfigFile::add( string key, const T& value )
231{
232 // Add a key with given value
233 string v = T_as_string( value );
234 trim(key);
235 trim(v);
236 myContents[key] = v;
237 return;
238}
239
240}}
241
242#endif // CONFIGFILE_H
243
244// Release notes:
245// v1.0 21 May 1999
246// + First release
247// + Template read() access only through non-member readConfigFile()
248// + ConfigurationFileBool is only built-in helper class
249//
250// v2.0 3 May 2002
251// + Shortened name from ConfigurationFile to ConfigFile
252// + Implemented template member functions
253// + Changed default comment separator from % to #
254// + Enabled reading of multiple-line values
255//
256// v2.1 24 May 2004
257// + Made template specializations inline to avoid compiler-dependent linkage
258// + Allowed comments within multiple-line values
259// + Enabled blank line termination for multiple-line values
260// + Added optional sentry to detect end of configuration file
261// + Rewrote messy trimWhitespace() function as elegant trim()
Note: See TracBrowser for help on using the repository browser.