]> git.stg.codes - stg.git/blob - stglibs/conffiles.lib/conffiles.cpp
Split SETTINGS to interface and implementation
[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 "conffiles.h"
44 #include "common.h"
45
46 using namespace std;
47
48 //---------------------------------------------------------------------------
49 bool StringCaseCmp(const string & str1, const string & str2)
50 {
51 return (strcasecmp(str1.c_str(), str2.c_str()) < 0);
52 }
53 //---------------------------------------------------------------------------
54 CONFIGFILE::CONFIGFILE(const string & fn, bool nook)
55     : param_val(StringCaseCmp),
56       fileName(fn),
57       error(0),
58       changed(false)
59 {
60 ifstream f(fileName.c_str());
61
62 if (!f)
63     {
64     if (!nook)
65         error = -1;
66     return;
67     }
68
69 string line;
70 while (getline(f, line))
71     {
72     size_t pos = line.find('#');
73     if (pos != string::npos)
74         line.resize(pos);
75
76     if (line.find_first_not_of(" \t\r") == string::npos)
77         continue;
78
79     pos = line.find_first_of('=');
80     if (pos == string::npos)
81         {
82         error = -1;
83         return;
84         }
85
86     string parameter = line.substr(0, pos);
87     string value = line.substr(pos + 1);
88     param_val[parameter] = value;
89     }
90 }
91 //---------------------------------------------------------------------------
92 CONFIGFILE::~CONFIGFILE()
93 {
94 Flush();
95 }
96 //---------------------------------------------------------------------------
97 const string & CONFIGFILE::GetFileName() const
98 {
99 return fileName;
100 }
101 //---------------------------------------------------------------------------
102 int CONFIGFILE::Error() const
103 {
104 int e = error;
105 error = 0;
106 return e;
107 }
108 /*//---------------------------------------------------------------------------
109 int CONFIGFILE::ReadString(const string & param, char * str, int * maxLen, const char * defaultVal) const
110 {
111 it = param_val.find(param);
112 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
113
114 if (it != param_val.end())
115     {
116     // þÔÏ-ÔÏ ÓÔÏÉÔ
117     strncpy(str, param_val[param].c_str(), *maxLen);
118     *maxLen = param_val[param].size();
119     return 0;
120     }
121
122 strncpy(str, defaultVal, *maxLen);
123 *maxLen = strlen(defaultVal);
124 return -1;
125 }*/
126 //---------------------------------------------------------------------------
127 int CONFIGFILE::ReadString(const string & param, string * val, const string & defaultVal) const
128 {
129 const map<string, string>::const_iterator it(param_val.find(param));
130 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
131
132 if (it != param_val.end())
133     {
134     // þÔÏ-ÔÏ ÓÔÏÉÔ
135     *val = it->second;
136     return 0;
137     }
138
139 *val = defaultVal;
140 return -1;
141 }
142 //---------------------------------------------------------------------------
143 void CONFIGFILE::WriteString(const string & param, const string &val)
144 {
145 param_val[param] = val;
146 changed = true;
147 }
148 //---------------------------------------------------------------------------
149 int CONFIGFILE::ReadTime(const string & param, time_t * val, time_t defaultVal) const
150 {
151 const map<string, string>::const_iterator it(param_val.find(param));
152
153 if (it != param_val.end())
154     {
155     char *res;
156     *val = strtol(it->second.c_str(), &res, 10);
157     if (*res != 0)
158         {
159         *val = defaultVal; //Error!
160         return EINVAL;
161         }
162     return 0;
163     }
164
165 *val = defaultVal;
166 return -1;
167 }
168 //---------------------------------------------------------------------------
169 int CONFIGFILE::ReadInt(const string & param, int * val, int defaultVal) const
170 {
171 const map<string, string>::const_iterator it(param_val.find(param));
172 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
173
174 if (it != param_val.end())
175     {
176     // þÔÏ-ÔÏ ÓÔÏÉÔ
177     char *res;
178     *val = strtol(it->second.c_str(), &res, 10);
179     if (*res != 0)
180         {
181         *val = defaultVal; //Error!
182         return EINVAL;
183         }
184     return 0;
185     }
186
187 *val = defaultVal;
188 return -1;
189 }
190 //---------------------------------------------------------------------------
191 int CONFIGFILE::ReadUInt(const string & param, unsigned int * val, unsigned int defaultVal) const
192 {
193 const map<string, string>::const_iterator it(param_val.find(param));
194 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
195
196 if (it != param_val.end())
197     {
198     // þÔÏ-ÔÏ ÓÔÏÉÔ
199     char *res;
200     *val = strtoul(it->second.c_str(), &res, 10);
201     if (*res != 0)
202         {
203         *val = defaultVal; //Error!
204         return EINVAL;
205         }
206     return 0;
207     }
208
209 *val = defaultVal;
210 return -1;
211 }
212 //---------------------------------------------------------------------------
213 int CONFIGFILE::ReadLongInt(const string & param, long int * val, long int defaultVal) const
214 {
215 const map<string, string>::const_iterator it(param_val.find(param));
216 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
217
218 if (it != param_val.end())
219     {
220     // þÔÏ-ÔÏ ÓÔÏÉÔ
221     char *res;
222     *val = strtol(it->second.c_str(), &res, 10);
223     if (*res != 0)
224         {
225         *val = defaultVal; //Error!
226         return EINVAL;
227         }
228     return 0;
229     }
230
231 *val = defaultVal;
232 return -1;
233 }
234 //---------------------------------------------------------------------------
235 int CONFIGFILE::ReadULongInt(const string & param, unsigned long int * val, unsigned long int defaultVal) const
236 {
237 const map<string, string>::const_iterator it(param_val.find(param));
238 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
239
240 if (it != param_val.end())
241     {
242     // þÔÏ-ÔÏ ÓÔÏÉÔ
243     char *res;
244     *val = strtoul(it->second.c_str(), &res, 10);
245     if (*res != 0)
246         {
247         *val = defaultVal; //Error!
248         return EINVAL;
249         }
250     return 0;
251     }
252
253 *val = defaultVal;
254 return -1;
255 }
256 //---------------------------------------------------------------------------
257 int CONFIGFILE::ReadLongLongInt(const string & param, int64_t * val, int64_t defaultVal) const
258 {
259 const map<string, string>::const_iterator it(param_val.find(param));
260 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
261
262 if (it != param_val.end())
263     {
264     // þÔÏ-ÔÏ ÓÔÏÉÔ
265     char *res;
266     *val = strtoll(it->second.c_str(), &res, 10);
267     if (*res != 0)
268         {
269         *val = defaultVal; //Error!
270         return EINVAL;
271         }
272     return 0;
273     }
274
275 *val = defaultVal;
276 return -1;
277 }
278 //---------------------------------------------------------------------------
279 int CONFIGFILE::ReadULongLongInt(const string & param, uint64_t * val, uint64_t defaultVal) const
280 {
281 const map<string, string>::const_iterator it(param_val.find(param));
282 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
283
284 if (it != param_val.end())
285     {
286     // þÔÏ-ÔÏ ÓÔÏÉÔ
287     char *res;
288     *val = strtoull(it->second.c_str(), &res, 10);
289     if (*res != 0)
290         {
291         *val = defaultVal; //Error!
292         return EINVAL;
293         }
294     return 0;
295     }
296
297 *val = defaultVal;
298 return -1;
299 }
300 //---------------------------------------------------------------------------
301 int CONFIGFILE::ReadShortInt(const string & param, short int * val, short int defaultVal) const
302 {
303 const map<string, string>::const_iterator it(param_val.find(param));
304 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
305
306 if (it != param_val.end())
307     {
308     // þÔÏ-ÔÏ ÓÔÏÉÔ
309     char *res;
310     *val = (short)strtol(it->second.c_str(), &res, 10);
311     if (*res != 0)
312         {
313         *val = defaultVal; //Error!
314         return EINVAL;
315         }
316     return 0;
317     }
318
319 *val = defaultVal;
320 return -1;
321 }
322 //---------------------------------------------------------------------------
323 int CONFIGFILE::ReadUShortInt(const string & param, unsigned short int * val, unsigned short int defaultVal) const
324 {
325 const map<string, string>::const_iterator it(param_val.find(param));
326 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
327
328 if (it != param_val.end())
329     {
330     // þÔÏ-ÔÏ ÓÔÏÉÔ
331     char *res;
332     *val = (short)strtoul(it->second.c_str(), &res, 10);
333     if (*res != 0)
334         {
335         *val = defaultVal; //Error!
336         return EINVAL;
337         }
338     return 0;
339     }
340
341 *val = defaultVal;
342 return -1;
343 }
344 //---------------------------------------------------------------------------
345 void CONFIGFILE::WriteInt(const string & param, int64_t val)
346 {
347 string s;
348 x2str(val, s);
349 param_val[param] = s;
350 changed = true;
351 }
352 //---------------------------------------------------------------------------
353 int CONFIGFILE::ReadDouble(const string & param, double * val, double defaultVal) const
354 {
355 const map<string, string>::const_iterator it(param_val.find(param));
356 // îÁÛÌÉ ÎÕÖÎÕÀ ÐÅÒÅÍÅÎÎÕÀ
357
358 if (it != param_val.end())
359     {
360     // þÔÏ-ÔÏ ÓÔÏÉÔ
361     char *res;
362     *val = strtod(it->second.c_str(), &res);
363     if (*res != 0)
364         {
365         *val = defaultVal; //Error!
366         return EINVAL;
367         }
368     return 0;
369     }
370
371 *val = defaultVal;
372 return -1;
373 }
374 //---------------------------------------------------------------------------
375 void CONFIGFILE::WriteDouble(const string & param, double val)
376 {
377 char s[30];
378 snprintf(s, 30, "%f", val);
379 param_val[param] = s;
380 changed = true;
381 }
382 //---------------------------------------------------------------------------
383 int CONFIGFILE::Flush(const std::string & path) const
384 {
385 ofstream f(path.c_str());
386 if (!f.is_open())
387     {
388     error = EIO;
389     return EIO;
390     }
391
392 map<string, string>::const_iterator it = param_val.begin();
393 while (it != param_val.end())
394     {
395     f << it->first << "=" << it->second << "\n";
396     ++it;
397     }
398
399 f.close();
400 return 0;
401 }
402 //---------------------------------------------------------------------------
403 int CONFIGFILE::Flush() const
404 {
405 if (!changed)
406     return 0;
407
408 std::string pid;
409 x2str(getpid(), pid);
410
411 if (Flush(fileName + "." + pid))
412     return -1;
413
414 if (rename((fileName + "." + pid).c_str(), fileName.c_str()))
415     return -1;
416
417 changed = false;
418
419 return 0;
420 }
421 //---------------------------------------------------------------------------