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 }