source: source/ariba/utility/configuration/ConfigFile.cpp@ 9992

Last change on this file since 9992 was 7471, checked in by Christoph Mayer, 14 years ago
File size: 4.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#include "ConfigFile.h"
28
29using std::string;
30
31namespace ariba {
32namespace utility {
33
34
35ConfigFile::ConfigFile( string filename, string delimiter,
36 string comment, string sentry )
37 : myDelimiter(delimiter), myComment(comment), mySentry(sentry)
38{
39 // Construct a ConfigFile, getting keys and values from given file
40
41 std::ifstream in( filename.c_str() );
42
43 if( !in ) throw file_not_found( filename );
44
45 in >> (*this);
46}
47
48
49ConfigFile::ConfigFile()
50 : myDelimiter( string(1,'=') ), myComment( string(1,'#') )
51{
52 // Construct a ConfigFile without a file; empty
53}
54
55
56void ConfigFile::remove( const string& key )
57{
58 // Remove key and its value
59 myContents.erase( myContents.find( key ) );
60 return;
61}
62
63
64bool ConfigFile::keyExists( const string& key ) const
65{
66 // Indicate whether key is found
67 mapci p = myContents.find( key );
68 return ( p != myContents.end() );
69}
70
71
72/* static */
73void ConfigFile::trim( string& s )
74{
75 // Remove leading and trailing whitespace
76 static const char whitespace[] = " \n\t\v\r\f";
77 s.erase( 0, s.find_first_not_of(whitespace) );
78 s.erase( s.find_last_not_of(whitespace) + 1U );
79}
80
81
82std::ostream& operator<<( std::ostream& os, const ConfigFile& cf )
83{
84 // Save a ConfigFile to os
85 for( ConfigFile::mapci p = cf.myContents.begin();
86 p != cf.myContents.end();
87 ++p )
88 {
89 os << p->first << " " << cf.myDelimiter << " ";
90 os << p->second << std::endl;
91 }
92 return os;
93}
94
95
96std::istream& operator>>( std::istream& is, ConfigFile& cf )
97{
98 // Load a ConfigFile from is
99 // Read in keys and values, keeping internal whitespace
100 typedef string::size_type pos;
101 const string& delim = cf.myDelimiter; // separator
102 const string& comm = cf.myComment; // comment
103 const string& sentry = cf.mySentry; // end of file sentry
104 const pos skip = delim.length(); // length of separator
105
106 string nextline = ""; // might need to read ahead to see where value ends
107
108 while( is || nextline.length() > 0 )
109 {
110 // Read an entire line at a time
111 string line;
112 if( nextline.length() > 0 )
113 {
114 line = nextline; // we read ahead; use it now
115 nextline = "";
116 }
117 else
118 {
119 std::getline( is, line );
120 }
121
122 // Ignore comments
123 line = line.substr( 0, line.find(comm) );
124
125 // Check for end of file sentry
126 if( sentry != "" && line.find(sentry) != string::npos ) return is;
127
128 // Parse the line if it contains a delimiter
129 pos delimPos = line.find( delim );
130 if( delimPos < string::npos )
131 {
132 // Extract the key
133 string key = line.substr( 0, delimPos );
134 line.replace( 0, delimPos+skip, "" );
135
136 // See if value continues on the next line
137 // Stop at blank line, next line with a key, end of stream,
138 // or end of file sentry
139 bool terminate = false;
140 while( !terminate && is )
141 {
142 std::getline( is, nextline );
143 terminate = true;
144
145 string nlcopy = nextline;
146 ConfigFile::trim(nlcopy);
147 if( nlcopy == "" ) continue;
148
149 nextline = nextline.substr( 0, nextline.find(comm) );
150 if( nextline.find(delim) != string::npos )
151 continue;
152 if( sentry != "" && nextline.find(sentry) != string::npos )
153 continue;
154
155 nlcopy = nextline;
156 ConfigFile::trim(nlcopy);
157 if( nlcopy != "" ) line += "\n";
158 line += nextline;
159 terminate = false;
160 }
161
162 // Store key and value
163 ConfigFile::trim(key);
164 ConfigFile::trim(line);
165 cf.myContents[key] = line; // overwrites if key is repeated
166 }
167 }
168
169 return is;
170}
171
172}}
Note: See TracBrowser for help on using the repository browser.