libassa  3.5.1
IniFile.cpp
Go to the documentation of this file.
1 // -*- c++ -*-
2 //------------------------------------------------------------------------------
3 // $Id: IniFile.cpp,v 1.7 2005/08/19 03:18:24 vlg Exp $
4 //------------------------------------------------------------------------------
5 // IniFile.cpp
6 //------------------------------------------------------------------------------
7 // Copyright (C) 2003,2004 Vladislav Grinchenko <vlg@users.sourceforge.net>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
13 //
14 // Date: Sat Sep 6 00:17:52 EDT 2003
15 //------------------------------------------------------------------------------
16 
17 #include <assa/Assure.h>
18 #include <assa/IniFile.h>
19 #include <assa/CommonUtils.h>
20 using namespace ASSA;
21 
23 IniFile (const string& fname_)
24  :
25  m_fname (fname_),
26  m_section_pttrn ("\\[[a-zA-Z0-9]+.*] *$"),
27  m_tuple_pttrn ("^[ \t]*[a-zA-Z0-9]+.* *= *.*"),
28  m_comment_pttrn ("^#.*$")
29 {
30  trace_with_mask ("IniFile::IniFile", INIFILE);
31 }
32 
33 IniFile::
34 ~IniFile ()
35 {
36  trace_with_mask ("IniFile::~IniFile", INIFILE);
37  m_config.clear ();
38 }
39 
40 int
42 load ()
43 {
44  trace_with_mask ("IniFile::load", INIFILE);
45 
46  const int size = 1024;
47  char inbuf [size];
48 
49  string line;
50  string name;
51  string value;
52  int ret = -1;
53 
54  m_stream.open (m_fname.c_str (), std::ios::in);
55  if (!m_stream) {
56  goto done;
57  }
58 
59  while (m_stream) {
60  m_stream.getline (inbuf, size, '\n');
61  DL((INIFILE,"Input: \"%s\"\n", inbuf));
62 
63  if (::strlen (inbuf) == 0 || m_comment_pttrn.match (inbuf) == 0) {
64  continue;
65  }
66  line = inbuf;
67  if (m_section_pttrn.match (inbuf) == 0) {
68  if (trim_section_name (line) < 0) {
69  goto done;
70  }
71  m_config.push_back (sect_type (line, std::list<tuple_type> ()));
72  }
73  else if (m_tuple_pttrn.match (inbuf) == 0) {
74  if (Utils::split_pair (line, '=', name, value) < 0) {
75  goto done;
76  }
77  Utils::trim_sides (name);
78  Utils::trim_sides (value);
79  m_config.back ().second.push_back (tuple_type (name, value));
80  }
81  else {
82  goto done;
83  }
84  }
97  ret = 0;
98 
99  done:
100  if (ret < 0) {
101  DL((INIFILE, "Parse error: illegal syntax!\n"));
102  }
103  m_stream.clear ();
104  m_stream.close ();
105  return ret;
106 }
107 
108 int
109 IniFile::
110 sync (const string& fname_)
111 {
112  trace_with_mask ("IniFile::sync(fname)", INIFILE);
113 
114  ::unlink (fname_.c_str ());
115  m_stream.open (fname_.c_str (), std::ios::app | std::ios::out);
116  if (!m_stream) {
117  EL((INIFILE,"Failed to open(\"%s\", app|out)\n", fname_.c_str ()));
118  return -1;
119  }
120  const_config_iterator i = m_config.begin ();
122 
123  while (i != m_config.end ()) {
124  m_stream << "[" << (*i).first << "]\n";
125  j = (*i).second.begin ();
126 
127  while (j != (*i).second.end ()) {
128  m_stream << (*j).first << "=" << (*j).second << "\n";
129  j++;
130  }
131  m_stream << "\n";
132  i++;
133  }
134  m_stream.clear ();
135  m_stream.close ();
136  return 0;
137 }
138 
139 void
140 IniFile::
141 dump () const
142 {
143  trace_with_mask ("IniFile::dump", INIFILE);
144 
145  const_config_iterator i = m_config.begin ();
147 
148  DL((INIFILE,"============= Start =================\n"));
149 
150  while (i != m_config.end ()) {
151  DL((INIFILE, "[%s]\n", (*i).first.c_str ()));
152  j = (*i).second.begin ();
153  while (j != (*i).second.end ()) {
154  DL((INIFILE, " %s=\%s\n",
155  (*j).first.c_str (), (*j).second.c_str ()));
156  j++;
157  }
158  i++;
159  }
160  DL((INIFILE,"============== End =================\n"));
161 }
162 
163 string
164 IniFile::
165 get_value (const string& section_, const string& name_) const
166 {
167  const_config_iterator i = m_config.begin ();
169  string ret ("");
170 
171  while (i != m_config.end ()) {
172  if ((*i).first == section_) {
173  j = (*i).second.begin ();
174  while (j != (*i).second.end ()) {
175  if ((*j).first == name_) {
176  ret = (*j).second;
177  break;
178  }
179  j++;
180  }
181  }
182  i++;
183  }
184  return ret;
185 }
186 
187 void
188 IniFile::
189 add_section (const string& section_)
190 {
191  const_config_iterator i = find_section (section_);
192  if (i == m_config.end ()) {
193  m_config.push_back (sect_type (section_, std::list<tuple_type> ()));
194  }
195 }
196 
198 IniFile::
199 find_section (const string& section_)
200 {
201  config_iterator i = m_config.begin ();
202 
203  while (i != m_config.end ()) {
204  if ((*i).first == section_) {
205  return (i);
206  }
207  i++;
208  }
209  return m_config.end ();
210 }
211 
213 IniFile::
214 find_section (const string& section_) const
215 {
216  const_config_iterator i = m_config.begin ();
217 
218  while (i != m_config.end ()) {
219  if ((*i).first == section_) {
220  return (i);
221  }
222  i++;
223  }
224  return m_config.end ();
225 }
226 
227 int
228 IniFile::
229 set_pair (const string& section_, const tuple_type& newkey_)
230 {
231  trace_with_mask ("IniFile::set_pair", INIFILE);
232 
233  config_iterator i = find_section (section_);
234  if (i == sect_end ()) {
235  DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ()));
236  return -1;
237  }
238  tuple_iterator j = (*i).second.begin ();
239  while (j != (*i).second.end ()) {
240  if ((*j).first == newkey_.first) {
241  (*j).second = newkey_.second;
242  return 0;
243  }
244  j++;
245  }
246  (*i).second.push_back (newkey_);
247  return 0;
248 }
249 
250 int
251 IniFile::
252 drop_section (const string& section_)
253 {
254  trace_with_mask ("IniFile::drop_section", INIFILE);
255 
256  config_iterator i = find_section (section_);
257  if (i == sect_end ()) {
258  DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ()));
259  return -1;
260  }
261  m_config.erase (i);
262  return 0;
263 }
264 
265 int
266 IniFile::
267 drop_pair (const string& section_, const string& name_)
268 {
269  trace_with_mask ("IniFile::drop_pair", INIFILE);
270 
271  config_iterator i = find_section (section_);
272  if (i == sect_end ()) {
273  DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ()));
274  return -1;
275  }
276 
277  tuple_iterator j = (*i).second.begin ();
278  while (j != (*i).second.end ()) {
279  if ((*j).first == name_) {
280  (*i).second.erase (j);
281  return 0;
282  }
283  j++;
284  }
285  return -1;
286 }
A collection of assert function wrappers.
A Windows-style INI configuration file management class.
#define EL(X)
A macro for writing error message to the Logger.
Definition: Logger.h:285
#define DL(X)
A macro for writing debug message to the Logger.
Definition: Logger.h:273
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition: Logger.h:437
Regexp m_tuple_pttrn
Name/value pair match.
Definition: IniFile.h:205
std::fstream m_stream
File stream.
Definition: IniFile.h:196
void add_section(const string &section_)
Add new section.
int trim_section_name(string &text_)
Remove square brakets around section name.
Definition: IniFile.h:212
pair< string, string > tuple_type
A tuple is a name/value pair.
Definition: IniFile.h:44
config_type m_config
Cache holds the entire INI file in memory.
Definition: IniFile.h:199
int load()
Load configuration data from the file.
config_type::iterator config_iterator
Mutable iterator over the list of configuration sections.
Definition: IniFile.h:56
int set_pair(const string &section_, const tuple_type &newkey_)
Add or change name/value pair in the section.
int drop_pair(const string &section_, const string &name_)
Remove name/value pair from the section in cache.
config_type::const_iterator const_config_iterator
Constant iterator over the list of configuration sections.
Definition: IniFile.h:59
config_iterator find_section(const string &section_)
Find section by its name.
IniFile(const string &fname_)
Do-nothing constructor.
int drop_section(const string &section_)
Remove section from cache.
Regexp m_comment_pttrn
Comment match.
Definition: IniFile.h:208
Regexp m_section_pttrn
Section header match.
Definition: IniFile.h:202
config_iterator sect_end()
Return iterator past the last section.
Definition: IniFile.h:174
int sync()
Write cached configuration to the file.
Definition: IniFile.h:219
list< tuple_type >::iterator tuple_iterator
Mutable iterator over name/value pairs in a section.
Definition: IniFile.h:62
void dump() const
Dump cache to the log file.
string get_value(const string &section_, const string &name_) const
Find and return a value of the name/value pair in the section section_.
unsigned int size() const
Return number of sections in the cache.
Definition: IniFile.h:178
list< tuple_type >::const_iterator const_tuple_iterator
Constant iterator over name/value pairs in a section.
Definition: IniFile.h:65
string m_fname
INI file name.
Definition: IniFile.h:193
pair< string, list< tuple_type > > sect_type
A section is a logical subcategory of related configuration information.
Definition: IniFile.h:49
int match(const char *text_)
Match an ASCII character string agains the pattern this class wraps.
Definition: Regexp.cpp:58
int split_pair(const string &text_, char sep_, string &lhs_, string &rhs_)
Split input string into two parts separated by the separator character.
Definition: CommonUtils.cpp:47
void trim_sides(std::string &text_)
Trim white spaces and tabs from the beginning and the end of the text string.
Definition: CommonUtils.cpp:93
Definition: Acceptor.h:40
@ INIFILE
Class IniFile messages
Definition: LogMask.h:52