]> git.stg.codes - stg.git/blob - stglibs/conffiles.lib/conffiles.cpp
Merge branch 'master' into full-month-stats
[stg.git] / stglibs / conffiles.lib / conffiles.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@ua.fm>
23  */
24
25  /*
26  $Revision: 1.5 $
27  $Date: 2009/10/22 11:40:22 $
28  */
29
30 //---------------------------------------------------------------------------
31
32 // getpid
33 #include <sys/types.h>
34 #include <unistd.h>
35
36 #include <cerrno> // E*
37 #include <cstring>
38 #include <cstdlib>
39 #include <cstdio>
40
41 #include <fstream>
42
43 #include "stg/conffiles.h"
44
45 using namespace std;
46
47 //---------------------------------------------------------------------------
48 bool StringCaseCmp(const string & str1, const string & str2)
49 {
50 return (strcasecmp(str1.c_str(), str2.c_str()) < 0);
51 }
52 //---------------------------------------------------------------------------
53 CONFIGFILE::CONFIGFILE(const string & fn, bool nook)
54     : param_val(StringCaseCmp),
55       fileName(fn),
56       error(0),
57       changed(false)
58 {
59 ifstream f(fileName.c_str());
60
61 if (!f)
62     {
63     if (!nook)
64         error = -1;
65     return;
66     }
67
68 string line;
69 while (getline(f, line))
70     {
71     size_t pos = line.find('#');
72     if (pos != string::npos)
73         line.resize(pos);
74
75     if (line.find_first_not_of(" \t\r") == string::npos)
76         continue;
77
78     pos = line.find_first_of('=');
79     if (pos == string::npos)
80         {
81         error = -1;
82         return;
83         }
84
85     string parameter = line.substr(0, pos);
86     string value = line.substr(pos + 1);
87     param_val[parameter] = value;
88     }
89 }
90 //---------------------------------------------------------------------------
91 CONFIGFILE::~CONFIGFILE()
92 {
93 Flush();
94 }
95 //---------------------------------------------------------------------------
96 const string & CONFIGFILE::GetFileName() const
97 {
98 return fileName;
99 }
100 //---------------------------------------------------------------------------
101 int CONFIGFILE::Error() const
102 {
103 int e = error;
104 error = 0;
105 return e;
106 }
107 //---------------------------------------------------------------------------
108 int CONFIGFILE::ReadString(const string & param, string * val, const string & defaultVal) const
109 {
110 const map<string, string>::const_iterator it(param_val.find(param));
111
112 if (it != param_val.end())
113     {
114     *val = it->second;
115     return 0;
116     }
117
118 *val = defaultVal;
119 return -1;
120 }
121 //---------------------------------------------------------------------------
122 void CONFIGFILE::WriteString(const string & param, const string &val)
123 {
124 param_val[param] = val;
125 changed = true;
126 }
127 //---------------------------------------------------------------------------
128 int CONFIGFILE::ReadTime(const string & param, time_t * val, time_t defaultVal) const
129 {
130 const map<string, string>::const_iterator it(param_val.find(param));
131
132 if (it != param_val.end())
133     {
134     char *res;
135     *val = strtol(it->second.c_str(), &res, 10);
136     if (*res != 0)
137         {
138         *val = defaultVal; //Error!
139         return EINVAL;
140         }
141     return 0;
142     }
143
144 *val = defaultVal;
145 return -1;
146 }
147 //---------------------------------------------------------------------------
148 int CONFIGFILE::ReadInt(const string & param, int * val, int defaultVal) const
149 {
150 const map<string, string>::const_iterator it(param_val.find(param));
151
152 if (it != param_val.end())
153     {
154     char *res;
155     *val = strtol(it->second.c_str(), &res, 10);
156     if (*res != 0)
157         {
158         *val = defaultVal; //Error!
159         return EINVAL;
160         }
161     return 0;
162     }
163
164 *val = defaultVal;
165 return -1;
166 }
167 //---------------------------------------------------------------------------
168 int CONFIGFILE::ReadUInt(const string & param, unsigned int * val, unsigned int defaultVal) const
169 {
170 const map<string, string>::const_iterator it(param_val.find(param));
171
172 if (it != param_val.end())
173     {
174     char *res;
175     *val = strtoul(it->second.c_str(), &res, 10);
176     if (*res != 0)
177         {
178         *val = defaultVal; //Error!
179         return EINVAL;
180         }
181     return 0;
182     }
183
184 *val = defaultVal;
185 return -1;
186 }
187 //---------------------------------------------------------------------------
188 int CONFIGFILE::ReadLongInt(const string & param, long int * val, long int defaultVal) const
189 {
190 const map<string, string>::const_iterator it(param_val.find(param));
191
192 if (it != param_val.end())
193     {
194     char *res;
195     *val = strtol(it->second.c_str(), &res, 10);
196     if (*res != 0)
197         {
198         *val = defaultVal; //Error!
199         return EINVAL;
200         }
201     return 0;
202     }
203
204 *val = defaultVal;
205 return -1;
206 }
207 //---------------------------------------------------------------------------
208 int CONFIGFILE::ReadULongInt(const string & param, unsigned long int * val, unsigned long int defaultVal) const
209 {
210 const map<string, string>::const_iterator it(param_val.find(param));
211
212 if (it != param_val.end())
213     {
214     char *res;
215     *val = strtoul(it->second.c_str(), &res, 10);
216     if (*res != 0)
217         {
218         *val = defaultVal; //Error!
219         return EINVAL;
220         }
221     return 0;
222     }
223
224 *val = defaultVal;
225 return -1;
226 }
227 //---------------------------------------------------------------------------
228 int CONFIGFILE::ReadLongLongInt(const string & param, int64_t * val, int64_t defaultVal) const
229 {
230 const map<string, string>::const_iterator it(param_val.find(param));
231
232 if (it != param_val.end())
233     {
234     char *res;
235     *val = strtoll(it->second.c_str(), &res, 10);
236     if (*res != 0)
237         {
238         *val = defaultVal; //Error!
239         return EINVAL;
240         }
241     return 0;
242     }
243
244 *val = defaultVal;
245 return -1;
246 }
247 //---------------------------------------------------------------------------
248 int CONFIGFILE::ReadULongLongInt(const string & param, uint64_t * val, uint64_t defaultVal) const
249 {
250 const map<string, string>::const_iterator it(param_val.find(param));
251
252 if (it != param_val.end())
253     {
254     char *res;
255     *val = strtoull(it->second.c_str(), &res, 10);
256     if (*res != 0)
257         {
258         *val = defaultVal; //Error!
259         return EINVAL;
260         }
261     return 0;
262     }
263
264 *val = defaultVal;
265 return -1;
266 }
267 //---------------------------------------------------------------------------
268 int CONFIGFILE::ReadShortInt(const string & param, short int * val, short int defaultVal) const
269 {
270 const map<string, string>::const_iterator it(param_val.find(param));
271
272 if (it != param_val.end())
273     {
274     char *res;
275     *val = (short)strtol(it->second.c_str(), &res, 10);
276     if (*res != 0)
277         {
278         *val = defaultVal; //Error!
279         return EINVAL;
280         }
281     return 0;
282     }
283
284 *val = defaultVal;
285 return -1;
286 }
287 //---------------------------------------------------------------------------
288 int CONFIGFILE::ReadUShortInt(const string & param, unsigned short int * val, unsigned short int defaultVal) const
289 {
290 const map<string, string>::const_iterator it(param_val.find(param));
291
292 if (it != param_val.end())
293     {
294     char *res;
295     *val = (short)strtoul(it->second.c_str(), &res, 10);
296     if (*res != 0)
297         {
298         *val = defaultVal; //Error!
299         return EINVAL;
300         }
301     return 0;
302     }
303
304 *val = defaultVal;
305 return -1;
306 }
307 //---------------------------------------------------------------------------
308 void CONFIGFILE::WriteInt(const string & param, int64_t val)
309 {
310 char buf[32];
311 snprintf(buf, sizeof(buf), "%lld", static_cast<long long int>(val));
312 param_val[param] = buf;
313 changed = true;
314 }
315 //---------------------------------------------------------------------------
316 int CONFIGFILE::ReadDouble(const string & param, double * val, double defaultVal) const
317 {
318 const map<string, string>::const_iterator it(param_val.find(param));
319
320 if (it != param_val.end())
321     {
322     char *res;
323     *val = strtod(it->second.c_str(), &res);
324     if (*res != 0)
325         {
326         *val = defaultVal; //Error!
327         return EINVAL;
328         }
329     return 0;
330     }
331
332 *val = defaultVal;
333 return -1;
334 }
335 //---------------------------------------------------------------------------
336 void CONFIGFILE::WriteDouble(const string & param, double val)
337 {
338 char s[30];
339 snprintf(s, 30, "%f", val);
340 param_val[param] = s;
341 changed = true;
342 }
343 //---------------------------------------------------------------------------
344 int CONFIGFILE::Flush(const std::string & path) const
345 {
346 ofstream f(path.c_str());
347 if (!f.is_open())
348     {
349     error = EIO;
350     return EIO;
351     }
352
353 map<string, string>::const_iterator it = param_val.begin();
354 while (it != param_val.end())
355     {
356     f << it->first << "=" << it->second << "\n";
357     ++it;
358     }
359
360 f.close();
361 return 0;
362 }
363 //---------------------------------------------------------------------------
364 int CONFIGFILE::Flush() const
365 {
366 if (!changed)
367     return 0;
368
369 char pid[6];
370 snprintf(pid, sizeof(pid), "%d", getpid());
371
372 if (Flush(fileName + "." + pid))
373     return -1;
374
375 if (rename((fileName + "." + pid).c_str(), fileName.c_str()))
376     return -1;
377
378 changed = false;
379
380 return 0;
381 }
382 //---------------------------------------------------------------------------