]> git.stg.codes - stg.git/blob - stglibs/conffiles.lib/conffiles.cpp
В класс CONFIGFILE добавлена поддержка отказа от записи
[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
40 #include <fstream>
41
42 #include "conffiles.h"
43 #include "common.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, char * str, int * maxLen, const char * defaultVal) const
109 {
110 it = param_val.find(param);
111 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
112
113 if (it != param_val.end())
114     {
115     // þÔÏ-ÔÏ ÓÔÏÉÔ
116     strncpy(str, param_val[param].c_str(), *maxLen);
117     *maxLen = param_val[param].size();
118     return 0;
119     }
120
121 strncpy(str, defaultVal, *maxLen);
122 *maxLen = strlen(defaultVal);
123 return -1;
124 }*/
125 //---------------------------------------------------------------------------
126 int CONFIGFILE::ReadString(const string & param, string * val, const string & defaultVal) const
127 {
128 const map<string, string>::const_iterator it(param_val.find(param));
129 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
130
131 if (it != param_val.end())
132     {
133     // þÔÏ-ÔÏ ÓÔÏÉÔ
134     *val = it->second;
135     return 0;
136     }
137
138 *val = defaultVal;
139 return -1;
140 }
141 //---------------------------------------------------------------------------
142 void CONFIGFILE::WriteString(const string & param, const string &val)
143 {
144 param_val[param] = val;
145 changed = true;
146 }
147 //---------------------------------------------------------------------------
148 int CONFIGFILE::ReadTime(const string & param, time_t * val, time_t 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::ReadInt(const string & param, int * val, int defaultVal) const
169 {
170 const map<string, string>::const_iterator it(param_val.find(param));
171 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
172
173 if (it != param_val.end())
174     {
175     // þÔÏ-ÔÏ ÓÔÏÉÔ
176     char *res;
177     *val = strtol(it->second.c_str(), &res, 10);
178     if (*res != 0)
179         {
180         *val = defaultVal; //Error!
181         return EINVAL;
182         }
183     return 0;
184     }
185
186 *val = defaultVal;
187 return -1;
188 }
189 //---------------------------------------------------------------------------
190 int CONFIGFILE::ReadUInt(const string & param, unsigned int * val, unsigned int defaultVal) const
191 {
192 const map<string, string>::const_iterator it(param_val.find(param));
193 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
194
195 if (it != param_val.end())
196     {
197     // þÔÏ-ÔÏ ÓÔÏÉÔ
198     char *res;
199     *val = strtoul(it->second.c_str(), &res, 10);
200     if (*res != 0)
201         {
202         *val = defaultVal; //Error!
203         return EINVAL;
204         }
205     return 0;
206     }
207
208 *val = defaultVal;
209 return -1;
210 }
211 //---------------------------------------------------------------------------
212 int CONFIGFILE::ReadLongInt(const string & param, long int * val, long int defaultVal) const
213 {
214 const map<string, string>::const_iterator it(param_val.find(param));
215 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
216
217 if (it != param_val.end())
218     {
219     // þÔÏ-ÔÏ ÓÔÏÉÔ
220     char *res;
221     *val = strtol(it->second.c_str(), &res, 10);
222     if (*res != 0)
223         {
224         *val = defaultVal; //Error!
225         return EINVAL;
226         }
227     return 0;
228     }
229
230 *val = defaultVal;
231 return -1;
232 }
233 //---------------------------------------------------------------------------
234 int CONFIGFILE::ReadULongInt(const string & param, unsigned long int * val, unsigned long int defaultVal) const
235 {
236 const map<string, string>::const_iterator it(param_val.find(param));
237 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
238
239 if (it != param_val.end())
240     {
241     // þÔÏ-ÔÏ ÓÔÏÉÔ
242     char *res;
243     *val = strtoul(it->second.c_str(), &res, 10);
244     if (*res != 0)
245         {
246         *val = defaultVal; //Error!
247         return EINVAL;
248         }
249     return 0;
250     }
251
252 *val = defaultVal;
253 return -1;
254 }
255 //---------------------------------------------------------------------------
256 int CONFIGFILE::ReadLongLongInt(const string & param, int64_t * val, int64_t defaultVal) const
257 {
258 const map<string, string>::const_iterator it(param_val.find(param));
259 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
260
261 if (it != param_val.end())
262     {
263     // þÔÏ-ÔÏ ÓÔÏÉÔ
264     char *res;
265     *val = strtoll(it->second.c_str(), &res, 10);
266     if (*res != 0)
267         {
268         *val = defaultVal; //Error!
269         return EINVAL;
270         }
271     return 0;
272     }
273
274 *val = defaultVal;
275 return -1;
276 }
277 //---------------------------------------------------------------------------
278 int CONFIGFILE::ReadULongLongInt(const string & param, uint64_t * val, uint64_t defaultVal) const
279 {
280 const map<string, string>::const_iterator it(param_val.find(param));
281 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
282
283 if (it != param_val.end())
284     {
285     // þÔÏ-ÔÏ ÓÔÏÉÔ
286     char *res;
287     *val = strtoull(it->second.c_str(), &res, 10);
288     if (*res != 0)
289         {
290         *val = defaultVal; //Error!
291         return EINVAL;
292         }
293     return 0;
294     }
295
296 *val = defaultVal;
297 return -1;
298 }
299 //---------------------------------------------------------------------------
300 int CONFIGFILE::ReadShortInt(const string & param, short int * val, short int defaultVal) const
301 {
302 const map<string, string>::const_iterator it(param_val.find(param));
303 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
304
305 if (it != param_val.end())
306     {
307     // þÔÏ-ÔÏ ÓÔÏÉÔ
308     char *res;
309     *val = (short)strtol(it->second.c_str(), &res, 10);
310     if (*res != 0)
311         {
312         *val = defaultVal; //Error!
313         return EINVAL;
314         }
315     return 0;
316     }
317
318 *val = defaultVal;
319 return -1;
320 }
321 //---------------------------------------------------------------------------
322 int CONFIGFILE::ReadUShortInt(const string & param, unsigned short int * val, unsigned short int defaultVal) const
323 {
324 const map<string, string>::const_iterator it(param_val.find(param));
325 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
326
327 if (it != param_val.end())
328     {
329     // þÔÏ-ÔÏ ÓÔÏÉÔ
330     char *res;
331     *val = (short)strtoul(it->second.c_str(), &res, 10);
332     if (*res != 0)
333         {
334         *val = defaultVal; //Error!
335         return EINVAL;
336         }
337     return 0;
338     }
339
340 *val = defaultVal;
341 return -1;
342 }
343 //---------------------------------------------------------------------------
344 void CONFIGFILE::WriteInt(const string & param, int64_t val)
345 {
346 string s;
347 x2str(val, s);
348 param_val[param] = s;
349 changed = true;
350 }
351 //---------------------------------------------------------------------------
352 int CONFIGFILE::ReadDouble(const string & param, double * val, double defaultVal) const
353 {
354 const map<string, string>::const_iterator it(param_val.find(param));
355 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
356
357 if (it != param_val.end())
358     {
359     // þÔÏ-ÔÏ ÓÔÏÉÔ
360     char *res;
361     *val = strtod(it->second.c_str(), &res);
362     if (*res != 0)
363         {
364         *val = defaultVal; //Error!
365         return EINVAL;
366         }
367     return 0;
368     }
369
370 *val = defaultVal;
371 return -1;
372 }
373 //---------------------------------------------------------------------------
374 void CONFIGFILE::WriteDouble(const string & param, double val)
375 {
376 char s[30];
377 snprintf(s, 30, "%f", val);
378 param_val[param] = s;
379 changed = true;
380 }
381 //---------------------------------------------------------------------------
382 int CONFIGFILE::Flush(const std::string & path) const
383 {
384 ofstream f(path.c_str());
385 if (!f.is_open())
386     {
387     error = EIO;
388     return EIO;
389     }
390
391 map<string, string>::const_iterator it = param_val.begin();
392 while (it != param_val.end())
393     {
394     f << it->first << "=" << it->second << "\n";
395     ++it;
396     }
397
398 f.close();
399 return 0;
400 }
401 //---------------------------------------------------------------------------
402 int CONFIGFILE::Flush() const
403 {
404 if (!changed)
405     return 0;
406
407 std::string pid;
408 x2str(getpid(), pid);
409
410 if (Flush(fileName + "." + pid))
411     return -1;
412
413 if (rename((fileName + "." + pid).c_str(), fileName.c_str()))
414     return -1;
415
416 changed = false;
417
418 return 0;
419 }
420 //---------------------------------------------------------------------------