An Overlay-based
Virtual Network Substrate
SpoVNet

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

Last change on this file since 7471 was 7471, checked in by Christoph Mayer, 14 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.