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

Last change on this file since 6824 was 3690, checked in by mies, 16 years ago

Merged 20090512-mies-connectors changes r3472:r3689 into trunk.

File size: 7.6 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
57class ConfigFile {
58// Data
59protected:
60 string myDelimiter; // separator between key and value
61 string myComment; // separator between value and comments
62 string mySentry; // optional string to signal end of file
63 std::map<string,string> myContents; // extracted keys and values
64
65 typedef std::map<string,string>::iterator mapi;
66 typedef std::map<string,string>::const_iterator mapci;
67
68// Methods
69public:
70 ConfigFile( string filename,
71 string delimiter = "=",
72 string comment = "#",
73 string sentry = "EndConfigFile" );
74 ConfigFile();
75
76 // Search for key and read value or optional default value
77 template<class T> T read( const string& key ) const; // call as read<T>
78 template<class T> T read( const string& key, const T& value ) const;
79 template<class T> bool readInto( T& var, const string& key ) const;
80 template<class T>
81 bool readInto( T& var, const string& key, const T& value ) const;
82
83 // Modify keys and values
84 template<class T> void add( string key, const T& value );
85 void remove( const string& key );
86
87 // Check whether key exists in configuration
88 bool keyExists( const string& key ) const;
89
90 // Check or change configuration syntax
91 string getDelimiter() const { return myDelimiter; }
92 string getComment() const { return myComment; }
93 string getSentry() const { return mySentry; }
94 string setDelimiter( const string& s )
95 { string old = myDelimiter; myDelimiter = s; return old; }
96 string setComment( const string& s )
97 { string old = myComment; myComment = s; return old; }
98
99 // Write or read configuration
100 friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf );
101 friend std::istream& operator>>( std::istream& is, ConfigFile& cf );
102
103protected:
104 template<class T> static string T_as_string( const T& t );
105 template<class T> static T string_as_T( const string& s );
106 static void trim( string& s );
107
108
109// Exception types
110public:
111 struct file_not_found {
112 string filename;
113 file_not_found( const string& filename_ = string() )
114 : filename(filename_) {} };
115 struct key_not_found { // thrown only by T read(key) variant of read()
116 string key;
117 key_not_found( const string& key_ = string() )
118 : key(key_) {} };
119};
120
121
122/* static */
123template<class T>
124string ConfigFile::T_as_string( const T& t )
125{
126 // Convert from a T to a string
127 // Type T must support << operator
128 std::ostringstream ost;
129 ost << t;
130 return ost.str();
131}
132
133
134/* static */
135template<class T>
136T ConfigFile::string_as_T( const string& s )
137{
138 // Convert from a string to a T
139 // Type T must support >> operator
140 T t;
141 std::istringstream ist(s);
142 ist >> t;
143 return t;
144}
145
146
147/* static */
148template<>
149inline string ConfigFile::string_as_T<string>( const string& s )
150{
151 // Convert from a string to a string
152 // In other words, do nothing
153 return s;
154}
155
156
157/* static */
158template<>
159inline bool ConfigFile::string_as_T<bool>( const string& s )
160{
161 // Convert from a string to a bool
162 // Interpret "false", "F", "no", "n", "0" as false
163 // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true
164 bool b = true;
165 string sup = s;
166 for( string::iterator p = sup.begin(); p != sup.end(); ++p )
167 *p = toupper(*p); // make string all caps
168 if( sup==string("FALSE") || sup==string("F") ||
169 sup==string("NO") || sup==string("N") ||
170 sup==string("0") || sup==string("NONE") )
171 b = false;
172 return b;
173}
174
175
176template<class T>
177T ConfigFile::read( const string& key ) const
178{
179 // Read the value corresponding to key
180 mapci p = myContents.find(key);
181 if( p == myContents.end() ) throw key_not_found(key);
182 return string_as_T<T>( p->second );
183}
184
185
186template<class T>
187T ConfigFile::read( const string& key, const T& value ) const
188{
189 // Return the value corresponding to key or given default value
190 // if key is not found
191 mapci p = myContents.find(key);
192 if( p == myContents.end() ) return value;
193 return string_as_T<T>( p->second );
194}
195
196
197template<class T>
198bool ConfigFile::readInto( T& var, const string& key ) const
199{
200 // Get the value corresponding to key and store in var
201 // Return true if key is found
202 // Otherwise leave var untouched
203 mapci p = myContents.find(key);
204 bool found = ( p != myContents.end() );
205 if( found ) var = string_as_T<T>( p->second );
206 return found;
207}
208
209
210template<class T>
211bool ConfigFile::readInto( T& var, const string& key, const T& value ) const
212{
213 // Get the value corresponding to key and store in var
214 // Return true if key is found
215 // Otherwise set var to given default
216 mapci p = myContents.find(key);
217 bool found = ( p != myContents.end() );
218 if( found )
219 var = string_as_T<T>( p->second );
220 else
221 var = value;
222 return found;
223}
224
225
226template<class T>
227void ConfigFile::add( string key, const T& value )
228{
229 // Add a key with given value
230 string v = T_as_string( value );
231 trim(key);
232 trim(v);
233 myContents[key] = v;
234 return;
235}
236
237#endif // CONFIGFILE_H
238
239// Release notes:
240// v1.0 21 May 1999
241// + First release
242// + Template read() access only through non-member readConfigFile()
243// + ConfigurationFileBool is only built-in helper class
244//
245// v2.0 3 May 2002
246// + Shortened name from ConfigurationFile to ConfigFile
247// + Implemented template member functions
248// + Changed default comment separator from % to #
249// + Enabled reading of multiple-line values
250//
251// v2.1 24 May 2004
252// + Made template specializations inline to avoid compiler-dependent linkage
253// + Allowed comments within multiple-line values
254// + Enabled blank line termination for multiple-line values
255// + Added optional sentry to detect end of configuration file
256// + Rewrote messy trimWhitespace() function as elegant trim()
Note: See TracBrowser for help on using the repository browser.