claw 1.9.0
 
Loading...
Searching...
No Matches
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@stuff-o-matic.com
24*/
31
32#include <claw/assert.hpp>
34
43
49 const std::string& value) const
50{
51 return comment + (' ' + value);
52}
53
60 const std::string& key, const std::string& value) const
61{
62 return key + ' ' + assignment + ' ' + value;
63}
64
70 const std::string& name) const
71{
72 return section_name.first + name + section_name.second;
73}
74
75// empty string
76const std::string claw::configuration_file::s_unknow_field_value;
77
85
92 const syntax_description& syntax)
93{
94 open(is, syntax);
95}
96
102bool claw::configuration_file::open(std::istream& is,
103 const syntax_description& syntax)
104{
105 std::string line;
106 bool ok = true;
107 section_content_ptr current_section = &m_noname_section;
108
109 while(get_line(is, syntax, line) && ok)
110 {
111 text::trim_right(line, " \t");
112
113 if(!line.empty())
114 ok = process_line(line, syntax, current_section);
115 }
116
117 return ok;
118}
119
125void claw::configuration_file::save(std::ostream& os,
126 const syntax_description& syntax)
127{
128 if(!m_noname_section.empty())
129 {
130 save_section_content(m_noname_section, os, syntax);
131 os << '\n';
132 }
133
134 file_content::const_iterator it;
135 for(it = m_sections.begin(); it != m_sections.end(); ++it)
136 {
137 os << syntax.make_section_name(it->first) << '\n';
138 save_section_content(it->second, os, syntax);
139 os << '\n';
140 }
141}
142
148const std::string&
149claw::configuration_file::operator()(const std::string& section,
150 const std::string& field) const
151{
152 file_content::const_iterator sect = m_sections.find(section);
153
154 if(sect == m_sections.end())
155 return s_unknow_field_value;
156 else
157 {
158 section_content::const_iterator fld = sect->second.find(field);
159
160 if(fld == sect->second.end())
161 return s_unknow_field_value;
162 else
163 return fld->second;
164 }
165}
166
173const std::string&
174claw::configuration_file::operator()(const std::string& field) const
175{
176 section_content::const_iterator fld = m_noname_section.find(field);
177
178 if(fld == m_noname_section.end())
179 return s_unknow_field_value;
180 else
181 return fld->second;
182}
183
189bool claw::configuration_file::has_field(const std::string& section,
190 const std::string& field) const
191{
192 return field_begin(section, field) != field_end(section, field);
193}
194
201bool claw::configuration_file::has_field(const std::string& field) const
202{
203 return field_begin(field) != field_end(field);
204}
205
214void claw::configuration_file::set_value(const std::string& section,
215 const std::string& field,
216 const std::string& val)
217{
218 file_content::iterator it = m_sections.find(section);
219
220 if(it != m_sections.end())
221 it->second.erase(field);
222
223 add_value(section, field, val);
224}
225
235void claw::configuration_file::set_value(const std::string& field,
236 const std::string& val)
237{
238 m_noname_section.erase(field);
239 add_value(field, val);
240}
241
250void claw::configuration_file::add_value(const std::string& section,
251 const std::string& field,
252 const std::string& val)
253{
254 m_sections[section].insert(section_content::value_type(field, val));
255}
256
264void claw::configuration_file::add_value(const std::string& field,
265 const std::string& val)
266{
267 m_noname_section.insert(section_content::value_type(field, val));
268}
269
274void claw::configuration_file::clear_section(const std::string& section)
275{
276 m_sections.erase(section);
277}
278
285claw::configuration_file::field_begin(const std::string& section,
286 const std::string& field) const
287{
288 file_content::const_iterator it = m_sections.find(section);
289
290 if(it == m_sections.end())
291 return const_field_iterator();
292 else
293 return const_field_iterator(it->second.lower_bound(field));
294}
295
302claw::configuration_file::field_end(const std::string& section,
303 const std::string& field) const
304{
305 file_content::const_iterator it = m_sections.find(section);
306
307 if(it == m_sections.end())
308 return const_field_iterator();
309 else
310 return const_field_iterator(it->second.upper_bound(field));
311}
312
320claw::configuration_file::field_begin(const std::string& field) const
321{
322 return const_field_iterator(m_noname_section.lower_bound(field));
323}
324
332claw::configuration_file::field_end(const std::string& field) const
333{
334 return const_field_iterator(m_noname_section.upper_bound(field));
335}
336
344{
345 return const_section_iterator(m_noname_section.begin());
346}
347
355{
356 return const_section_iterator(m_noname_section.end());
357}
358
364claw::configuration_file::section_begin(const std::string& section) const
365{
366 file_content::const_iterator it = m_sections.find(section);
367
368 if(it == m_sections.end())
369 return const_section_iterator();
370 else
371 return const_section_iterator(it->second.begin());
372}
373
379claw::configuration_file::section_end(const std::string& section) const
380{
381 file_content::const_iterator it = m_sections.find(section);
382
383 if(it == m_sections.end())
384 return const_section_iterator();
385 else
386 return const_section_iterator(it->second.end());
387}
388
394{
395 return const_file_iterator(m_sections.begin());
396}
397
403{
404 return const_file_iterator(m_sections.end());
405}
406
413bool claw::configuration_file::get_line(std::istream& is,
414 const syntax_description& syntax,
415 std::string& line) const
416{
417 const bool result(text::getline(is, line));
418
419 if(result)
420 {
421 text::trim_left(line, " \t");
422 escape_line(is, syntax, line);
423 }
424
425 return result;
426}
427
434bool claw::configuration_file::process_line(const std::string& line,
435 const syntax_description& syntax,
436 section_content_ptr& section)
437{
438 CLAW_PRECOND(!line.empty());
439
440 bool result = true;
441
442 if((line.size() >= 2) && (line[0] == syntax.section_name.first)
443 && (*(--line.end()) == syntax.section_name.second))
444 {
445 std::string section_name(line.substr(1, line.length() - 2));
446 text::trim(section_name, " \t");
447 section = &m_sections[section_name];
448 }
449 else
450 {
451 std::string::size_type pos = line.find_first_of(syntax.assignment);
452
453 if(pos != std::string::npos)
454 {
455 std::string field(line.substr(0, pos));
456 std::string value;
457
458 if((pos + 1) != line.length())
459 {
460 value = (line.substr(pos + 1));
461 text::trim(value, " \t");
462 }
463
464 text::trim(field, " \t");
465 section->insert(section_content::value_type(field, value));
466 }
467 else
468 result = false;
469 }
470
471 return result;
472}
473
480void claw::configuration_file::escape_line(std::istream& is,
481 const syntax_description& syntax,
482 std::string& line) const
483{
484 std::string input_line(line);
485 std::string::iterator it, last;
486 bool stop = false;
487
488 line.clear();
489 last = input_line.begin();
490
491 for(it = last; (it != input_line.end()) && !stop;)
492 if(*it == syntax.comment)
493 stop = true;
494 else if(*it == '\\')
495 {
496 line += std::string(last, it);
497 ++it;
498
499 if(it == input_line.end())
500 {
501 std::string remaining;
502 get_line(is, syntax, remaining);
503 line += remaining;
504 }
505 else
506 {
507 escape_char(*it, syntax, line);
508 ++it;
509 }
510
511 last = it;
512 }
513 else
514 ++it;
515
516 line += std::string(last, it);
517}
518
525void claw::configuration_file::escape_char(char escaped,
526 const syntax_description& syntax,
527 std::string& str) const
528{
529 switch(escaped)
530 {
531 case '\'':
532 str += "\'";
533 break;
534 case '\"':
535 str += "\"";
536 break;
537 case '\\':
538 str += "\\";
539 break;
540 case 'a':
541 str += "\a";
542 break;
543 case 'b':
544 str += "\b";
545 break;
546 case 'f':
547 str += "\f";
548 break;
549 case 'n':
550 str += "\n";
551 break;
552 case 'r':
553 str += "\r";
554 break;
555 case 't':
556 str += "\t";
557 break;
558 case 'v':
559 str += "\v";
560 break;
561 default:
562 if(escaped == syntax.comment)
563 str += syntax.comment;
564 else
565 (str += "\\") += escaped;
566 }
567}
568
575void claw::configuration_file::save_section_content(
576 const section_content& c, std::ostream& os,
577 const syntax_description& syntax) const
578{
579 section_content::const_iterator it;
580
581 for(it = c.begin(); it != c.end(); ++it)
582 os << syntax.make_assignment(it->first, it->second) << '\n';
583}
Some assert macros to strengthen you code.
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:94
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.
const_section_iterator section_end() const
Get an iterator past the last field name of a section.
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.
bool has_field(const std::string &section, const std::string &field) const
Tell if a field exists.
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.
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.
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.
paired_symbol section_name
Pair of symbols around a section name.
char comment
Symbol used to comment the rest of the line.
char assignment
Symbol used to assign a value to a field.