configuration_file.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include <claw/configuration_file.hpp>
00031 #include <claw/assert.hpp>
00032 #include <claw/string_algorithm.hpp>
00033
00034
00038 claw::configuration_file::syntax_description::syntax_description()
00039 : comment('#'), assignment('='), section_name('[', ']')
00040 {
00041
00042 }
00043
00044
00045
00046
00047
00048 const std::string claw::configuration_file::s_unknow_field_value;
00049
00050
00054 claw::configuration_file::configuration_file()
00055 {
00056
00057 }
00058
00059
00065 claw::configuration_file::configuration_file
00066 ( std::istream& is, const syntax_description& syntax )
00067 {
00068 open(is, syntax);
00069 }
00070
00071
00077 bool claw::configuration_file::open
00078 ( std::istream& is, const syntax_description& syntax )
00079 {
00080 std::string line;
00081 bool ok = true;
00082 section_content_ptr current_section = &m_noname_section;
00083
00084 while ( get_line(is, syntax, line) && ok )
00085 {
00086 text::trim_right(line, " \t");
00087
00088 if ( !line.empty() )
00089 ok = process_line( line, syntax, current_section );
00090 }
00091
00092 return ok;
00093 }
00094
00095
00101 const std::string& claw::configuration_file::operator()
00102 ( const std::string& section, const std::string& field ) const
00103 {
00104 file_content::const_iterator sect = m_sections.find(section);
00105
00106 if ( sect == m_sections.end() )
00107 return s_unknow_field_value;
00108 else
00109 {
00110 section_content::const_iterator fld = sect->second.find(field);
00111
00112 if ( fld == sect->second.end() )
00113 return s_unknow_field_value;
00114 else
00115 return fld->second;
00116 }
00117 }
00118
00119
00126 const std::string&
00127 claw::configuration_file::operator()( const std::string& field ) const
00128 {
00129 section_content::const_iterator fld = m_noname_section.find(field);
00130
00131 if ( fld == m_noname_section.end() )
00132 return s_unknow_field_value;
00133 else
00134 return fld->second;
00135 }
00136
00137
00143 claw::configuration_file::const_field_iterator
00144 claw::configuration_file::field_begin
00145 ( const std::string& section, const std::string& field ) const
00146 {
00147 file_content::const_iterator it = m_sections.find(section);
00148
00149 if (it == m_sections.end())
00150 return const_field_iterator();
00151 else
00152 return const_field_iterator( it->second.lower_bound(field) );
00153 }
00154
00155
00161 claw::configuration_file::const_field_iterator
00162 claw::configuration_file::field_end
00163 ( const std::string& section, const std::string& field ) const
00164 {
00165 file_content::const_iterator it = m_sections.find(section);
00166
00167 if (it == m_sections.end())
00168 return const_field_iterator();
00169 else
00170 return const_field_iterator( it->second.upper_bound(field) );
00171 }
00172
00173
00180 claw::configuration_file::const_field_iterator
00181 claw::configuration_file::field_begin( const std::string& field ) const
00182 {
00183 return const_field_iterator( m_noname_section.lower_bound(field) );
00184 }
00185
00186
00193 claw::configuration_file::const_field_iterator
00194 claw::configuration_file::field_end( const std::string& field ) const
00195 {
00196 return const_field_iterator( m_noname_section.upper_bound(field) );
00197 }
00198
00199
00206 bool claw::configuration_file::get_line
00207 ( std::istream& is, const syntax_description& syntax, std::string& line ) const
00208 {
00209 bool result = text::getline(is, line);
00210
00211 if ( result )
00212 {
00213 text::trim_left(line, " \t");
00214 escape_line(is, syntax, line);
00215 }
00216
00217 return result;
00218 }
00219
00220
00227 bool claw::configuration_file::process_line
00228 ( const std::string& line, const syntax_description& syntax,
00229 section_content_ptr& section )
00230 {
00231 CLAW_PRECOND( !line.empty() );
00232
00233 bool result = true;
00234
00235 if ( (line.size() >= 2)
00236 && (line[0] == syntax.section_name.first)
00237 && ( *(--line.end()) == syntax.section_name.second) )
00238 {
00239 std::string section_name( line.substr(1, line.length()-2) );
00240 text::trim( section_name, " \t" );
00241 section = &m_sections[section_name];
00242 }
00243 else
00244 {
00245 std::string::size_type pos = line.find_first_of(syntax.assignment);
00246
00247 if (pos != std::string::npos)
00248 {
00249 std::string field( line.substr(0, pos) );
00250 std::string value;
00251
00252 if ( (pos+1) != line.length() )
00253 {
00254 value = ( line.substr(pos+1) );
00255 text::trim(value, " \t");
00256 }
00257
00258 text::trim(field, " \t");
00259 section->insert( section_content::value_type(field, value) );
00260 }
00261 else
00262 result = false;
00263 }
00264
00265 return result;
00266 }
00267
00268
00275 void claw::configuration_file::escape_line
00276 ( std::istream& is, const syntax_description& syntax, std::string& line ) const
00277 {
00278 std::string input_line(line);
00279 std::string::iterator it, last;
00280 bool stop = false;
00281
00282 line = "";
00283 last = input_line.begin();
00284
00285 for (it = last; (it!=input_line.end()) && !stop; )
00286 if (*it == syntax.comment)
00287 stop = true;
00288 else if (*it == '\\')
00289 {
00290 line += std::string(last, it);
00291 ++it;
00292
00293 if ( it == input_line.end() )
00294 {
00295 std::string remaining;
00296 get_line(is, syntax, remaining);
00297 line += remaining;
00298 }
00299 else
00300 {
00301 escape_char(*it, syntax, line);
00302 ++it;
00303 }
00304
00305 last = it;
00306 }
00307 else
00308 ++it;
00309
00310 line += std::string(last, it);
00311 }
00312
00313
00320 void claw::configuration_file::escape_char
00321 ( char escaped, const syntax_description& syntax, std::string& str ) const
00322 {
00323 switch (escaped)
00324 {
00325 case '\'' : str += "\'"; break;
00326 case '\"' : str += "\""; break;
00327 case '\\' : str += "\\"; break;
00328 case 'a' : str += "\a"; break;
00329 case 'b' : str += "\b"; break;
00330 case 'f' : str += "\f"; break;
00331 case 'n' : str += "\n"; break;
00332 case 'r' : str += "\r"; break;
00333 case 't' : str += "\t"; break;
00334 case 'v' : str += "\v"; break;
00335 default :
00336 if ( escaped == syntax.comment )
00337 str += syntax.comment;
00338 else
00339 (str += "\\") += escaped;
00340 }
00341 }