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
83 const 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 /*----------------------------------------------------------------------------*/
160 const 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 /*----------------------------------------------------------------------------*/
185 const std::string&
186 claw::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 /*----------------------------------------------------------------------------*/
215 bool 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 /*----------------------------------------------------------------------------*/
291 void 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 /*----------------------------------------------------------------------------*/
340 claw::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 /*----------------------------------------------------------------------------*/
353 claw::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 /*----------------------------------------------------------------------------*/
388 claw::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 /*----------------------------------------------------------------------------*/
404 claw::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 /*----------------------------------------------------------------------------*/
441 bool claw::configuration_file::get_line
442 ( std::istream& is, const syntax_description& syntax, std::string& line ) const
443 {
444  bool result = 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 /*----------------------------------------------------------------------------*/
462 bool 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 /*----------------------------------------------------------------------------*/
510 void 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 /*----------------------------------------------------------------------------*/
555 void 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 /*----------------------------------------------------------------------------*/
585 void 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()