]> git.stg.codes - stg.git/blob - stglibs/conffiles.lib/conffiles.cpp
4fb72f618ddc6e5f60abab6dff8d754280008446
[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 namespace
46 {
47 //---------------------------------------------------------------------------
48 std::string TrimL(std::string val)
49 {
50 size_t pos = val.find_first_not_of(" \t");
51 if (pos == std::string::npos)
52     {
53     val.erase(val.begin(), val.end());
54     }
55 else
56     {
57     val.erase(0, pos);
58     }
59 return val;
60 }
61 //---------------------------------------------------------------------------
62 std::string TrimR(std::string val)
63 {
64 size_t pos = val.find_last_not_of(" \t");
65 if (pos != std::string::npos)
66     {
67     val.erase(pos + 1);
68     }
69 return val;
70 }
71 //---------------------------------------------------------------------------
72 std::string Trim(std::string val)
73 {
74 return TrimR(TrimL(val));
75 }
76 }
77 //---------------------------------------------------------------------------
78 } // namespace anonymous
79
80 //---------------------------------------------------------------------------
81 bool StringCaseCmp(const std::string & str1, const std::string & str2)
82 {
83 return (strcasecmp(str1.c_str(), str2.c_str()) < 0);
84 }
85 //---------------------------------------------------------------------------
86 CONFIGFILE::CONFIGFILE(const std::string & fn, bool nook)
87     : param_val(StringCaseCmp),
88       fileName(fn),
89       error(0),
90       changed(false)
91 {
92 std::ifstream f(fileName.c_str());
93
94 if (!f)
95     {
96     if (!nook)
97         error = -1;
98     return;
99     }
100
101 std::string line;
102 while (getline(f, line))
103     {
104     size_t pos = line.find('#');
105     if (pos != std::string::npos)
106         line.resize(pos);
107
108     if (line.find_first_not_of(" \t\r") == std::string::npos)
109         continue;
110
111     pos = line.find_first_of('=');
112     if (pos == std::string::npos)
113         {
114         error = -1;
115         return;
116         }
117
118 <<<<<<< Updated upstream
119     std::string parameter = Trim(line.substr(0, pos));
120     std::string value = Trim(line.substr(pos + 1));
121 =======
122     std::string parameter = line.substr(0, pos);
123     std::string value = line.substr(pos + 1);
124 >>>>>>> Stashed changes
125     param_val[parameter] = value;
126     }
127 }
128 //---------------------------------------------------------------------------
129 CONFIGFILE::~CONFIGFILE()
130 {
131 Flush();
132 }
133 //---------------------------------------------------------------------------
134 const std::string & CONFIGFILE::GetFileName() const
135 {
136 return fileName;
137 }
138 //---------------------------------------------------------------------------
139 int CONFIGFILE::Error() const
140 {
141 int e = error;
142 error = 0;
143 return e;
144 }
145 //---------------------------------------------------------------------------
146 int CONFIGFILE::ReadString(const std::string & param, std::string * val, const std::string & defaultVal) const
147 {
148 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
149
150 if (it != param_val.end())
151     {
152     *val = it->second;
153     return 0;
154     }
155
156 *val = defaultVal;
157 return -1;
158 }
159 //---------------------------------------------------------------------------
160 void CONFIGFILE::WriteString(const std::string & param, const std::string &val)
161 {
162 param_val[param] = val;
163 changed = true;
164 }
165 //---------------------------------------------------------------------------
166 int CONFIGFILE::ReadTime(const std::string & param, time_t * val, time_t defaultVal) const
167 {
168 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
169
170 if (it != param_val.end())
171     {
172     char *res;
173     *val = strtol(it->second.c_str(), &res, 10);
174     if (*res != 0)
175         {
176         *val = defaultVal; //Error!
177         return EINVAL;
178         }
179     return 0;
180     }
181
182 *val = defaultVal;
183 return -1;
184 }
185 //---------------------------------------------------------------------------
186 int CONFIGFILE::ReadInt(const std::string & param, int * val, int defaultVal) const
187 {
188 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
189
190 if (it != param_val.end())
191     {
192     char *res;
193     *val = static_cast<int>(strtol(it->second.c_str(), &res, 10));
194     if (*res != 0)
195         {
196         *val = defaultVal; //Error!
197         return EINVAL;
198         }
199     return 0;
200     }
201
202 *val = defaultVal;
203 return -1;
204 }
205 //---------------------------------------------------------------------------
206 int CONFIGFILE::ReadUInt(const std::string & param, unsigned int * val, unsigned int defaultVal) const
207 {
208 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
209
210 if (it != param_val.end())
211     {
212     char *res;
213     *val = static_cast<unsigned int>(strtoul(it->second.c_str(), &res, 10));
214     if (*res != 0)
215         {
216         *val = defaultVal; //Error!
217         return EINVAL;
218         }
219     return 0;
220     }
221
222 *val = defaultVal;
223 return -1;
224 }
225 //---------------------------------------------------------------------------
226 int CONFIGFILE::ReadLongInt(const std::string & param, long int * val, long int defaultVal) const
227 {
228 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
229
230 if (it != param_val.end())
231     {
232     char *res;
233     *val = strtol(it->second.c_str(), &res, 10);
234     if (*res != 0)
235         {
236         *val = defaultVal; //Error!
237         return EINVAL;
238         }
239     return 0;
240     }
241
242 *val = defaultVal;
243 return -1;
244 }
245 //---------------------------------------------------------------------------
246 int CONFIGFILE::ReadULongInt(const std::string & param, unsigned long int * val, unsigned long int defaultVal) const
247 {
248 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
249
250 if (it != param_val.end())
251     {
252     char *res;
253     *val = strtoul(it->second.c_str(), &res, 10);
254     if (*res != 0)
255         {
256         *val = defaultVal; //Error!
257         return EINVAL;
258         }
259     return 0;
260     }
261
262 *val = defaultVal;
263 return -1;
264 }
265 //---------------------------------------------------------------------------
266 int CONFIGFILE::ReadLongLongInt(const std::string & param, int64_t * val, int64_t defaultVal) const
267 {
268 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
269
270 if (it != param_val.end())
271     {
272     char *res;
273     *val = strtoll(it->second.c_str(), &res, 10);
274     if (*res != 0)
275         {
276         *val = defaultVal; //Error!
277         return EINVAL;
278         }
279     return 0;
280     }
281
282 *val = defaultVal;
283 return -1;
284 }
285 //---------------------------------------------------------------------------
286 int CONFIGFILE::ReadULongLongInt(const std::string & param, uint64_t * val, uint64_t defaultVal) const
287 {
288 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
289
290 if (it != param_val.end())
291     {
292     char *res;
293     *val = strtoull(it->second.c_str(), &res, 10);
294     if (*res != 0)
295         {
296         *val = defaultVal; //Error!
297         return EINVAL;
298         }
299     return 0;
300     }
301
302 *val = defaultVal;
303 return -1;
304 }
305 //---------------------------------------------------------------------------
306 int CONFIGFILE::ReadShortInt(const std::string & param, short int * val, short int defaultVal) const
307 {
308 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
309
310 if (it != param_val.end())
311     {
312     char *res;
313     *val = (short)strtol(it->second.c_str(), &res, 10);
314     if (*res != 0)
315         {
316         *val = defaultVal; //Error!
317         return EINVAL;
318         }
319     return 0;
320     }
321
322 *val = defaultVal;
323 return -1;
324 }
325 //---------------------------------------------------------------------------
326 int CONFIGFILE::ReadUShortInt(const std::string & param, unsigned short int * val, unsigned short int defaultVal) const
327 {
328 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
329
330 if (it != param_val.end())
331     {
332     char *res;
333     *val = (short)strtoul(it->second.c_str(), &res, 10);
334     if (*res != 0)
335         {
336         *val = defaultVal; //Error!
337         return EINVAL;
338         }
339     return 0;
340     }
341
342 *val = defaultVal;
343 return -1;
344 }
345 //---------------------------------------------------------------------------
346 void CONFIGFILE::WriteInt(const std::string & param, int64_t val)
347 {
348 char buf[32];
349 snprintf(buf, sizeof(buf), "%lld", static_cast<long long int>(val));
350 param_val[param] = buf;
351 changed = true;
352 }
353 //---------------------------------------------------------------------------
354 int CONFIGFILE::ReadDouble(const std::string & param, double * val, double defaultVal) const
355 {
356 const std::map<std::string, std::string>::const_iterator it(param_val.find(param));
357
358 if (it != param_val.end())
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 std::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 std::ofstream f(path.c_str());
385 if (!f.is_open())
386     {
387     error = EIO;
388     return EIO;
389     }
390
391 std::map<std::string, std::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 char pid[6];
408 snprintf(pid, sizeof(pid), "%d", getpid());
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 //---------------------------------------------------------------------------