An Overlay-based
Virtual Network Substrate
SpoVNet

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

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