Claw 1.7.0
|
00001 /* 00002 CLAW - a C++ Library Absolutely Wonderful 00003 00004 CLAW is a free library without any particular aim but being useful to 00005 anyone. 00006 00007 Copyright (C) 2005-2011 Julien Jorge 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with this library; if not, write to the Free Software 00021 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00022 00023 contact: julien.jorge@gamned.org 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 } // configuration_file::syntax_description::syntax_description() 00043 00044 /*----------------------------------------------------------------------------*/ 00049 std::string claw::configuration_file::syntax_description::make_comment 00050 ( const std::string& value ) const 00051 { 00052 return comment + (' ' + value); 00053 } // configuration_file::syntax_description::make_comment() 00054 00055 /*----------------------------------------------------------------------------*/ 00061 std::string claw::configuration_file::syntax_description::make_assignment 00062 ( const std::string& key, const std::string& value ) const 00063 { 00064 return key + ' ' + assignment + ' ' + value; 00065 } // configuration_file::syntax_description::make_assignment() 00066 00067 /*----------------------------------------------------------------------------*/ 00072 std::string claw::configuration_file::syntax_description::make_section_name 00073 ( const std::string& name ) const 00074 { 00075 return section_name.first + name + section_name.second; 00076 } // configuration_file::syntax_description::make_section_name() 00077 00078 00079 00080 00081 /*----------------------------------------------------------------------------*/ 00082 // empty string 00083 const std::string claw::configuration_file::s_unknow_field_value; 00084 00085 /*----------------------------------------------------------------------------*/ 00089 claw::configuration_file::configuration_file() 00090 { 00091 // nothing to do 00092 } // configuration_file::configuration_file() 00093 00094 /*----------------------------------------------------------------------------*/ 00100 claw::configuration_file::configuration_file 00101 ( std::istream& is, const syntax_description& syntax ) 00102 { 00103 open(is, syntax); 00104 } // configuration_file::configuration_file() 00105 00106 /*----------------------------------------------------------------------------*/ 00112 bool claw::configuration_file::open 00113 ( std::istream& is, const syntax_description& syntax ) 00114 { 00115 std::string line; 00116 bool ok = true; 00117 section_content_ptr current_section = &m_noname_section; 00118 00119 while ( get_line(is, syntax, line) && ok ) 00120 { 00121 text::trim_right(line, " \t"); 00122 00123 if ( !line.empty() ) 00124 ok = process_line( line, syntax, current_section ); 00125 } 00126 00127 return ok; 00128 } // configuration_file::open() 00129 00130 /*----------------------------------------------------------------------------*/ 00136 void claw::configuration_file::save 00137 ( std::ostream& os, const syntax_description& syntax ) 00138 { 00139 if ( !m_noname_section.empty() ) 00140 { 00141 save_section_content( m_noname_section, os, syntax ); 00142 os << '\n'; 00143 } 00144 00145 file_content::const_iterator it; 00146 for ( it=m_sections.begin(); it!=m_sections.end(); ++it ) 00147 { 00148 os << syntax.make_section_name(it->first) << '\n'; 00149 save_section_content( it->second, os, syntax ); 00150 os << '\n'; 00151 } 00152 } // configuration_file::save() 00153 00154 /*----------------------------------------------------------------------------*/ 00160 const std::string& claw::configuration_file::operator() 00161 ( const std::string& section, const std::string& field ) const 00162 { 00163 file_content::const_iterator sect = m_sections.find(section); 00164 00165 if ( sect == m_sections.end() ) 00166 return s_unknow_field_value; 00167 else 00168 { 00169 section_content::const_iterator fld = sect->second.find(field); 00170 00171 if ( fld == sect->second.end() ) 00172 return s_unknow_field_value; 00173 else 00174 return fld->second; 00175 } 00176 } // configuration_file::operator()() 00177 00178 /*----------------------------------------------------------------------------*/ 00185 const std::string& 00186 claw::configuration_file::operator()( const std::string& field ) const 00187 { 00188 section_content::const_iterator fld = m_noname_section.find(field); 00189 00190 if ( fld == m_noname_section.end() ) 00191 return s_unknow_field_value; 00192 else 00193 return fld->second; 00194 } // configuration_file::operator()() 00195 00196 /*----------------------------------------------------------------------------*/ 00202 bool claw::configuration_file::has_field 00203 ( const std::string& section, const std::string& field ) const 00204 { 00205 return field_begin( section, field ) != field_end( section, field ); 00206 } // configuration_file::has_field() 00207 00208 /*----------------------------------------------------------------------------*/ 00215 bool claw::configuration_file::has_field( const std::string& field ) const 00216 { 00217 return field_begin( field ) != field_end( field ); 00218 } // configuration_file::has_field() 00219 00220 /*----------------------------------------------------------------------------*/ 00229 void claw::configuration_file::set_value 00230 ( const std::string& section, const std::string& field, const std::string& val ) 00231 { 00232 file_content::iterator it = m_sections.find(section); 00233 00234 if ( it!=m_sections.end() ) 00235 it->second.erase(field); 00236 00237 add_value(section, field, val); 00238 } // configuration_file::set_value() 00239 00240 /*----------------------------------------------------------------------------*/ 00250 void claw::configuration_file::set_value 00251 ( const std::string& field, const std::string& val ) 00252 { 00253 m_noname_section.erase(field); 00254 add_value(field, val); 00255 } // configuration_file::set_value() 00256 00257 /*----------------------------------------------------------------------------*/ 00266 void claw::configuration_file::add_value 00267 ( const std::string& section, const std::string& field, const std::string& val ) 00268 { 00269 m_sections[section].insert( section_content::value_type(field, val) ); 00270 } // configuration_file::add_value() 00271 00272 /*----------------------------------------------------------------------------*/ 00280 void claw::configuration_file::add_value 00281 ( const std::string& field, const std::string& val ) 00282 { 00283 m_noname_section.insert( section_content::value_type(field, val) ); 00284 } // configuration_file::add_value() 00285 00286 /*----------------------------------------------------------------------------*/ 00291 void claw::configuration_file::clear_section( const std::string& section ) 00292 { 00293 m_sections.erase(section); 00294 } // configuration_file::clear_section() 00295 00296 /*----------------------------------------------------------------------------*/ 00302 claw::configuration_file::const_field_iterator 00303 claw::configuration_file::field_begin 00304 ( const std::string& section, const std::string& field ) const 00305 { 00306 file_content::const_iterator it = m_sections.find(section); 00307 00308 if (it == m_sections.end()) 00309 return const_field_iterator(); 00310 else 00311 return const_field_iterator( it->second.lower_bound(field) ); 00312 } // configuration_file::field_begin() 00313 00314 /*----------------------------------------------------------------------------*/ 00320 claw::configuration_file::const_field_iterator 00321 claw::configuration_file::field_end 00322 ( const std::string& section, const std::string& field ) const 00323 { 00324 file_content::const_iterator it = m_sections.find(section); 00325 00326 if (it == m_sections.end()) 00327 return const_field_iterator(); 00328 else 00329 return const_field_iterator( it->second.upper_bound(field) ); 00330 } // configuration_file::field_end() 00331 00332 /*----------------------------------------------------------------------------*/ 00339 claw::configuration_file::const_field_iterator 00340 claw::configuration_file::field_begin( const std::string& field ) const 00341 { 00342 return const_field_iterator( m_noname_section.lower_bound(field) ); 00343 } // configuration_file::field_begin() 00344 00345 /*----------------------------------------------------------------------------*/ 00352 claw::configuration_file::const_field_iterator 00353 claw::configuration_file::field_end( const std::string& field ) const 00354 { 00355 return const_field_iterator( m_noname_section.upper_bound(field) ); 00356 } // configuration_file::field_end() 00357 00358 /*----------------------------------------------------------------------------*/ 00364 claw::configuration_file::const_section_iterator 00365 claw::configuration_file::section_begin() const 00366 { 00367 return const_section_iterator( m_noname_section.begin() ); 00368 } // configuration_file::section_begin() 00369 00370 /*----------------------------------------------------------------------------*/ 00376 claw::configuration_file::const_section_iterator 00377 claw::configuration_file::section_end() const 00378 { 00379 return const_section_iterator( m_noname_section.end() ); 00380 } // configuration_file::section_end() 00381 00382 /*----------------------------------------------------------------------------*/ 00387 claw::configuration_file::const_section_iterator 00388 claw::configuration_file::section_begin( const std::string& section ) const 00389 { 00390 file_content::const_iterator it = m_sections.find(section); 00391 00392 if (it == m_sections.end()) 00393 return const_section_iterator(); 00394 else 00395 return const_section_iterator( it->second.begin() ); 00396 } // configuration_file::section_begin() 00397 00398 /*----------------------------------------------------------------------------*/ 00403 claw::configuration_file::const_section_iterator 00404 claw::configuration_file::section_end( const std::string& section ) const 00405 { 00406 file_content::const_iterator it = m_sections.find(section); 00407 00408 if (it == m_sections.end()) 00409 return const_section_iterator(); 00410 else 00411 return const_section_iterator( it->second.end() ); 00412 } // configuration_file::section_end() 00413 00414 /*----------------------------------------------------------------------------*/ 00418 claw::configuration_file::const_file_iterator 00419 claw::configuration_file::file_begin() const 00420 { 00421 return const_file_iterator( m_sections.begin() ); 00422 } // configuration_file::file_begin() 00423 00424 /*----------------------------------------------------------------------------*/ 00428 claw::configuration_file::const_file_iterator 00429 claw::configuration_file::file_end() const 00430 { 00431 return const_file_iterator( m_sections.end() ); 00432 } // configuration_file::file_end() 00433 00434 /*----------------------------------------------------------------------------*/ 00441 bool claw::configuration_file::get_line 00442 ( std::istream& is, const syntax_description& syntax, std::string& line ) const 00443 { 00444 bool result = text::getline(is, line); 00445 00446 if ( result ) 00447 { 00448 text::trim_left(line, " \t"); 00449 escape_line(is, syntax, line); 00450 } 00451 00452 return result; 00453 } // configuration_file::get_line() 00454 00455 /*----------------------------------------------------------------------------*/ 00462 bool claw::configuration_file::process_line 00463 ( const std::string& line, const syntax_description& syntax, 00464 section_content_ptr& section ) 00465 { 00466 CLAW_PRECOND( !line.empty() ); 00467 00468 bool result = true; 00469 00470 if ( (line.size() >= 2) 00471 && (line[0] == syntax.section_name.first) 00472 && ( *(--line.end()) == syntax.section_name.second) ) 00473 { 00474 std::string section_name( line.substr(1, line.length()-2) ); 00475 text::trim( section_name, " \t" ); 00476 section = &m_sections[section_name]; 00477 } 00478 else 00479 { 00480 std::string::size_type pos = line.find_first_of(syntax.assignment); 00481 00482 if (pos != std::string::npos) 00483 { 00484 std::string field( line.substr(0, pos) ); 00485 std::string value; 00486 00487 if ( (pos+1) != line.length() ) 00488 { 00489 value = ( line.substr(pos+1) ); 00490 text::trim(value, " \t"); 00491 } 00492 00493 text::trim(field, " \t"); 00494 section->insert( section_content::value_type(field, value) ); 00495 } 00496 else 00497 result = false; 00498 } 00499 00500 return result; 00501 } // configuration_file::process_line() 00502 00503 /*----------------------------------------------------------------------------*/ 00510 void claw::configuration_file::escape_line 00511 ( std::istream& is, const syntax_description& syntax, std::string& line ) const 00512 { 00513 std::string input_line(line); 00514 std::string::iterator it, last; 00515 bool stop = false; 00516 00517 line.clear(); 00518 last = input_line.begin(); 00519 00520 for (it = last; (it!=input_line.end()) && !stop; ) 00521 if (*it == syntax.comment) 00522 stop = true; 00523 else if (*it == '\\') 00524 { 00525 line += std::string(last, it); 00526 ++it; 00527 00528 if ( it == input_line.end() ) 00529 { 00530 std::string remaining; 00531 get_line(is, syntax, remaining); 00532 line += remaining; 00533 } 00534 else 00535 { 00536 escape_char(*it, syntax, line); 00537 ++it; 00538 } 00539 00540 last = it; 00541 } 00542 else 00543 ++it; 00544 00545 line += std::string(last, it); 00546 } // configuration_file::escape_line() 00547 00548 /*----------------------------------------------------------------------------*/ 00555 void claw::configuration_file::escape_char 00556 ( char escaped, const syntax_description& syntax, std::string& str ) const 00557 { 00558 switch (escaped) 00559 { 00560 case '\'' : str += "\'"; break; 00561 case '\"' : str += "\""; break; 00562 case '\\' : str += "\\"; break; 00563 case 'a' : str += "\a"; break; 00564 case 'b' : str += "\b"; break; 00565 case 'f' : str += "\f"; break; 00566 case 'n' : str += "\n"; break; 00567 case 'r' : str += "\r"; break; 00568 case 't' : str += "\t"; break; 00569 case 'v' : str += "\v"; break; 00570 default : 00571 if ( escaped == syntax.comment ) 00572 str += syntax.comment; 00573 else 00574 (str += "\\") += escaped; 00575 } 00576 } // configuration_file::escape_char() 00577 00578 /*----------------------------------------------------------------------------*/ 00585 void claw::configuration_file::save_section_content 00586 ( const section_content& c, std::ostream& os, 00587 const syntax_description& syntax ) const 00588 { 00589 section_content::const_iterator it; 00590 00591 for (it=c.begin(); it!=c.end(); ++it) 00592 os << syntax.make_assignment(it->first, it->second) << '\n'; 00593 } // configuration_file::save_section_content()