Claw 1.7.3
configuration_file.cpp
Go to the documentation of this file.
1/*
2 CLAW - a C++ Library Absolutely Wonderful
3
4 CLAW is a free library without any particular aim but being useful to
5 anyone.
6
7 Copyright (C) 2005-2011 Julien Jorge
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23 contact: julien.jorge@gamned.org
24*/
31#include <claw/assert.hpp>
33
34/*----------------------------------------------------------------------------*/
39 : comment('#'), assignment('='), section_name('[', ']')
40{
41
42} // configuration_file::syntax_description::syntax_description()
43
44/*----------------------------------------------------------------------------*/
50( const std::string& value ) const
51{
52 return comment + (' ' + value);
53} // configuration_file::syntax_description::make_comment()
54
55/*----------------------------------------------------------------------------*/
62( const std::string& key, const std::string& value ) const
63{
64 return key + ' ' + assignment + ' ' + value;
65} // configuration_file::syntax_description::make_assignment()
66
67/*----------------------------------------------------------------------------*/
73( const std::string& name ) const
74{
75 return section_name.first + name + section_name.second;
76} // configuration_file::syntax_description::make_section_name()
77
78
79
80
81/*----------------------------------------------------------------------------*/
82// empty string
83const std::string claw::configuration_file::s_unknow_field_value;
84
85/*----------------------------------------------------------------------------*/
90{
91 // nothing to do
92} // configuration_file::configuration_file()
93
94/*----------------------------------------------------------------------------*/
101( std::istream& is, const syntax_description& syntax )
102{
103 open(is, syntax);
104} // configuration_file::configuration_file()
105
106/*----------------------------------------------------------------------------*/
113( std::istream& is, const syntax_description& syntax )
114{
115 std::string line;
116 bool ok = true;
117 section_content_ptr current_section = &m_noname_section;
118
119 while ( get_line(is, syntax, line) && ok )
120 {
121 text::trim_right(line, " \t");
122
123 if ( !line.empty() )
124 ok = process_line( line, syntax, current_section );
125 }
126
127 return ok;
128} // configuration_file::open()
129
130/*----------------------------------------------------------------------------*/
137( std::ostream& os, const syntax_description& syntax )
138{
139 if ( !m_noname_section.empty() )
140 {
141 save_section_content( m_noname_section, os, syntax );
142 os << '\n';
143 }
144
145 file_content::const_iterator it;
146 for ( it=m_sections.begin(); it!=m_sections.end(); ++it )
147 {
148 os << syntax.make_section_name(it->first) << '\n';
149 save_section_content( it->second, os, syntax );
150 os << '\n';
151 }
152} // configuration_file::save()
153
154/*----------------------------------------------------------------------------*/
160const std::string& claw::configuration_file::operator()
161 ( const std::string& section, const std::string& field ) const
162{
163 file_content::const_iterator sect = m_sections.find(section);
164
165 if ( sect == m_sections.end() )
166 return s_unknow_field_value;
167 else
168 {
169 section_content::const_iterator fld = sect->second.find(field);
170
171 if ( fld == sect->second.end() )
172 return s_unknow_field_value;
173 else
174 return fld->second;
175 }
176} // configuration_file::operator()()
177
178/*----------------------------------------------------------------------------*/
185const std::string&
186claw::configuration_file::operator()( const std::string& field ) const
187{
188 section_content::const_iterator fld = m_noname_section.find(field);
189
190 if ( fld == m_noname_section.end() )
191 return s_unknow_field_value;
192 else
193 return fld->second;
194} // configuration_file::operator()()
195
196/*----------------------------------------------------------------------------*/
203( const std::string& section, const std::string& field ) const
204{
205 return field_begin( section, field ) != field_end( section, field );
206} // configuration_file::has_field()
207
208/*----------------------------------------------------------------------------*/
215bool claw::configuration_file::has_field( const std::string& field ) const
216{
217 return field_begin( field ) != field_end( field );
218} // configuration_file::has_field()
219
220/*----------------------------------------------------------------------------*/
230( const std::string& section, const std::string& field, const std::string& val )
231{
232 file_content::iterator it = m_sections.find(section);
233
234 if ( it!=m_sections.end() )
235 it->second.erase(field);
236
237 add_value(section, field, val);
238} // configuration_file::set_value()
239
240/*----------------------------------------------------------------------------*/
251( const std::string& field, const std::string& val )
252{
253 m_noname_section.erase(field);
254 add_value(field, val);
255} // configuration_file::set_value()
256
257/*----------------------------------------------------------------------------*/
267( const std::string& section, const std::string& field, const std::string& val )
268{
269 m_sections[section].insert( section_content::value_type(field, val) );
270} // configuration_file::add_value()
271
272/*----------------------------------------------------------------------------*/
281( const std::string& field, const std::string& val )
282{
283 m_noname_section.insert( section_content::value_type(field, val) );
284} // configuration_file::add_value()
285
286/*----------------------------------------------------------------------------*/
291void claw::configuration_file::clear_section( const std::string& section )
292{
293 m_sections.erase(section);
294} // configuration_file::clear_section()
295
296/*----------------------------------------------------------------------------*/
304( const std::string& section, const std::string& field ) const
305{
306 file_content::const_iterator it = m_sections.find(section);
307
308 if (it == m_sections.end())
309 return const_field_iterator();
310 else
311 return const_field_iterator( it->second.lower_bound(field) );
312} // configuration_file::field_begin()
313
314/*----------------------------------------------------------------------------*/
322( const std::string& section, const std::string& field ) const
323{
324 file_content::const_iterator it = m_sections.find(section);
325
326 if (it == m_sections.end())
327 return const_field_iterator();
328 else
329 return const_field_iterator( it->second.upper_bound(field) );
330} // configuration_file::field_end()
331
332/*----------------------------------------------------------------------------*/
340claw::configuration_file::field_begin( const std::string& field ) const
341{
342 return const_field_iterator( m_noname_section.lower_bound(field) );
343} // configuration_file::field_begin()
344
345/*----------------------------------------------------------------------------*/
353claw::configuration_file::field_end( const std::string& field ) const
354{
355 return const_field_iterator( m_noname_section.upper_bound(field) );
356} // configuration_file::field_end()
357
358/*----------------------------------------------------------------------------*/
366{
367 return const_section_iterator( m_noname_section.begin() );
368} // configuration_file::section_begin()
369
370/*----------------------------------------------------------------------------*/
378{
379 return const_section_iterator( m_noname_section.end() );
380} // configuration_file::section_end()
381
382/*----------------------------------------------------------------------------*/
388claw::configuration_file::section_begin( const std::string& section ) const
389{
390 file_content::const_iterator it = m_sections.find(section);
391
392 if (it == m_sections.end())
393 return const_section_iterator();
394 else
395 return const_section_iterator( it->second.begin() );
396} // configuration_file::section_begin()
397
398/*----------------------------------------------------------------------------*/
404claw::configuration_file::section_end( const std::string& section ) const
405{
406 file_content::const_iterator it = m_sections.find(section);
407
408 if (it == m_sections.end())
409 return const_section_iterator();
410 else
411 return const_section_iterator( it->second.end() );
412} // configuration_file::section_end()
413
414/*----------------------------------------------------------------------------*/
420{
421 return const_file_iterator( m_sections.begin() );
422} // configuration_file::file_begin()
423
424/*----------------------------------------------------------------------------*/
430{
431 return const_file_iterator( m_sections.end() );
432} // configuration_file::file_end()
433
434/*----------------------------------------------------------------------------*/
441bool claw::configuration_file::get_line
442( std::istream& is, const syntax_description& syntax, std::string& line ) const
443{
444 bool result = static_cast<bool>(text::getline(is, line));
445
446 if ( result )
447 {
448 text::trim_left(line, " \t");
449 escape_line(is, syntax, line);
450 }
451
452 return result;
453} // configuration_file::get_line()
454
455/*----------------------------------------------------------------------------*/
462bool claw::configuration_file::process_line
463( const std::string& line, const syntax_description& syntax,
464 section_content_ptr& section )
465{
466 CLAW_PRECOND( !line.empty() );
467
468 bool result = true;
469
470 if ( (line.size() >= 2)
471 && (line[0] == syntax.section_name.first)
472 && ( *(--line.end()) == syntax.section_name.second) )
473 {
474 std::string section_name( line.substr(1, line.length()-2) );
475 text::trim( section_name, " \t" );
476 section = &m_sections[section_name];
477 }
478 else
479 {
480 std::string::size_type pos = line.find_first_of(syntax.assignment);
481
482 if (pos != std::string::npos)
483 {
484 std::string field( line.substr(0, pos) );
485 std::string value;
486
487 if ( (pos+1) != line.length() )
488 {
489 value = ( line.substr(pos+1) );
490 text::trim(value, " \t");
491 }
492
493 text::trim(field, " \t");
494 section->insert( section_content::value_type(field, value) );
495 }
496 else
497 result = false;
498 }
499
500 return result;
501} // configuration_file::process_line()
502
503/*----------------------------------------------------------------------------*/
510void claw::configuration_file::escape_line
511( std::istream& is, const syntax_description& syntax, std::string& line ) const
512{
513 std::string input_line(line);
514 std::string::iterator it, last;
515 bool stop = false;
516
517 line.clear();
518 last = input_line.begin();
519
520 for (it = last; (it!=input_line.end()) && !stop; )
521 if (*it == syntax.comment)
522 stop = true;
523 else if (*it == '\\')
524 {
525 line += std::string(last, it);
526 ++it;
527
528 if ( it == input_line.end() )
529 {
530 std::string remaining;
531 get_line(is, syntax, remaining);
532 line += remaining;
533 }
534 else
535 {
536 escape_char(*it, syntax, line);
537 ++it;
538 }
539
540 last = it;
541 }
542 else
543 ++it;
544
545 line += std::string(last, it);
546} // configuration_file::escape_line()
547
548/*----------------------------------------------------------------------------*/
555void claw::configuration_file::escape_char
556( char escaped, const syntax_description& syntax, std::string& str ) const
557{
558 switch (escaped)
559 {
560 case '\'' : str += "\'"; break;
561 case '\"' : str += "\""; break;
562 case '\\' : str += "\\"; break;
563 case 'a' : str += "\a"; break;
564 case 'b' : str += "\b"; break;
565 case 'f' : str += "\f"; break;
566 case 'n' : str += "\n"; break;
567 case 'r' : str += "\r"; break;
568 case 't' : str += "\t"; break;
569 case 'v' : str += "\v"; break;
570 default :
571 if ( escaped == syntax.comment )
572 str += syntax.comment;
573 else
574 (str += "\\") += escaped;
575 }
576} // configuration_file::escape_char()
577
578/*----------------------------------------------------------------------------*/
585void claw::configuration_file::save_section_content
586( const section_content& c, std::ostream& os,
587 const syntax_description& syntax ) const
588{
589 section_content::const_iterator it;
590
591 for (it=c.begin(); it!=c.end(); ++it)
592 os << syntax.make_assignment(it->first, it->second) << '\n';
593} // configuration_file::save_section_content()
Some assert macros to strengthen you code.
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:98
This class is an iterator on the values set for a same field name.
const_section_iterator section_begin() const
Get an iterator on the field names of a section.
void add_value(const std::string &section, const std::string &field, const std::string &val)
Add a value to a field.
const_file_iterator file_begin() const
Get an iterator on the first named section.
void set_value(const std::string &section, const std::string &field, const std::string &val)
Set the value of a field.
void clear_section(const std::string &section)
Remove a section and its fields.
const_field_iterator field_end(const std::string &section, const std::string &field) const
Get an iterator past the last value set for a field.
void save(std::ostream &os, const syntax_description &syntax=syntax_description())
Write the configuration in a stream.
claw::wrapped_iterator< constsection_content::key_type, section_content::const_iterator, const_pair_first< section_content::value_type > >::iterator_type const_section_iterator
Iterator on the fields of a section.
const_section_iterator section_end() const
Get an iterator past the last field name of a section.
bool has_field(const std::string &section, const std::string &field) const
Tell if a field exists.
claw::wrapped_iterator< constfile_content::key_type, file_content::const_iterator, const_pair_first< file_content::value_type > >::iterator_type const_file_iterator
Iterator on the name of the sections.
configuration_file()
Default constructor.
bool open(std::istream &is, const syntax_description &syntax=syntax_description())
Read the configuration from a stream.
const std::string & operator()(const std::string &section, const std::string &field) const
Get the value of a field.
const_field_iterator field_begin(const std::string &section, const std::string &field) const
Get an iterator on the first value set for a field.
const_file_iterator file_end() const
Get an iterator just past the last named section.
Base class for wrapped iterators.
Definition iterator.hpp:46
A class to get the content of a configuration file.
Generic algorithms on strings.
This class tells us how to parse the input file.
std::string make_comment(const std::string &value) const
Create a comment from a string.
std::string make_assignment(const std::string &key, const std::string &value) const
Make an assignment of a value to a key.
std::string make_section_name(const std::string &name) const
Create a section name from a string.