1//
2// AbstractConfiguration.cpp
3//
4// Library: Util
5// Package: Configuration
6// Module: AbstractConfiguration
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Util/AbstractConfiguration.h"
16#include "Poco/Util/ConfigurationView.h"
17#include "Poco/Exception.h"
18#include "Poco/NumberParser.h"
19#include "Poco/NumberFormatter.h"
20#include "Poco/String.h"
21
22
23using Poco::Mutex;
24using Poco::NotFoundException;
25using Poco::SyntaxException;
26using Poco::CircularReferenceException;
27using Poco::NumberParser;
28using Poco::NumberFormatter;
29using Poco::icompare;
30
31
32namespace Poco {
33namespace Util {
34
35
36AbstractConfiguration::AbstractConfiguration():
37 _depth(0),
38 _eventsEnabled(true)
39{
40}
41
42
43AbstractConfiguration::~AbstractConfiguration()
44{
45}
46
47
48bool AbstractConfiguration::hasProperty(const std::string& key) const
49{
50 Mutex::ScopedLock lock(_mutex);
51
52 std::string value;
53 return getRaw(key, value);
54}
55
56
57bool AbstractConfiguration::hasOption(const std::string& key) const
58{
59 return hasProperty(key);
60}
61
62
63bool AbstractConfiguration::has(const std::string& key) const
64{
65 return hasProperty(key);
66}
67
68
69std::string AbstractConfiguration::getString(const std::string& key) const
70{
71 Mutex::ScopedLock lock(_mutex);
72
73 std::string value;
74 if (getRaw(key, value))
75 return internalExpand(value);
76 else
77 throw NotFoundException(key);
78}
79
80
81std::string AbstractConfiguration::getString(const std::string& key, const std::string& defaultValue) const
82{
83 Mutex::ScopedLock lock(_mutex);
84
85 std::string value;
86 if (getRaw(key, value))
87 return internalExpand(value);
88 else
89 return defaultValue;
90}
91
92
93std::string AbstractConfiguration::getRawString(const std::string& key) const
94{
95 Mutex::ScopedLock lock(_mutex);
96
97 std::string value;
98 if (getRaw(key, value))
99 return value;
100 else
101 throw NotFoundException(key);
102}
103
104
105std::string AbstractConfiguration::getRawString(const std::string& key, const std::string& defaultValue) const
106{
107
108 Mutex::ScopedLock lock(_mutex);
109
110 std::string value;
111 if (getRaw(key, value))
112 return value;
113 else
114 return defaultValue;
115}
116
117
118int AbstractConfiguration::getInt(const std::string& key) const
119{
120 Mutex::ScopedLock lock(_mutex);
121
122 std::string value;
123 if (getRaw(key, value))
124 return parseInt(internalExpand(value));
125 else
126 throw NotFoundException(key);
127}
128
129
130int AbstractConfiguration::getInt(const std::string& key, int defaultValue) const
131{
132 Mutex::ScopedLock lock(_mutex);
133
134 std::string value;
135 if (getRaw(key, value))
136 return parseInt(internalExpand(value));
137 else
138 return defaultValue;
139}
140
141
142unsigned AbstractConfiguration::getUInt(const std::string& key) const
143{
144 Mutex::ScopedLock lock(_mutex);
145
146 std::string value;
147 if (getRaw(key, value))
148 return parseUInt(internalExpand(value));
149 else
150 throw NotFoundException(key);
151}
152
153
154unsigned AbstractConfiguration::getUInt(const std::string& key, unsigned defaultValue) const
155{
156 Mutex::ScopedLock lock(_mutex);
157
158 std::string value;
159 if (getRaw(key, value))
160 return parseUInt(internalExpand(value));
161 else
162 return defaultValue;
163}
164
165
166#if defined(POCO_HAVE_INT64)
167
168
169Int64 AbstractConfiguration::getInt64(const std::string& key) const
170{
171 Mutex::ScopedLock lock(_mutex);
172
173 std::string value;
174 if (getRaw(key, value))
175 return parseInt64(internalExpand(value));
176 else
177 throw NotFoundException(key);
178}
179
180
181Int64 AbstractConfiguration::getInt64(const std::string& key, Int64 defaultValue) const
182{
183 Mutex::ScopedLock lock(_mutex);
184
185 std::string value;
186 if (getRaw(key, value))
187 return parseInt64(internalExpand(value));
188 else
189 return defaultValue;
190}
191
192
193UInt64 AbstractConfiguration::getUInt64(const std::string& key) const
194{
195 Mutex::ScopedLock lock(_mutex);
196
197 std::string value;
198 if (getRaw(key, value))
199 return parseUInt64(internalExpand(value));
200 else
201 throw NotFoundException(key);
202}
203
204
205UInt64 AbstractConfiguration::getUInt64(const std::string& key, UInt64 defaultValue) const
206{
207 Mutex::ScopedLock lock(_mutex);
208
209 std::string value;
210 if (getRaw(key, value))
211 return parseUInt64(internalExpand(value));
212 else
213 return defaultValue;
214}
215
216
217#endif // defined(POCO_HAVE_INT64)
218
219
220double AbstractConfiguration::getDouble(const std::string& key) const
221{
222 Mutex::ScopedLock lock(_mutex);
223
224 std::string value;
225 if (getRaw(key, value))
226 return NumberParser::parseFloat(internalExpand(value));
227 else
228 throw NotFoundException(key);
229}
230
231
232double AbstractConfiguration::getDouble(const std::string& key, double defaultValue) const
233{
234 Mutex::ScopedLock lock(_mutex);
235
236 std::string value;
237 if (getRaw(key, value))
238 return NumberParser::parseFloat(internalExpand(value));
239 else
240 return defaultValue;
241}
242
243
244bool AbstractConfiguration::getBool(const std::string& key) const
245{
246 Mutex::ScopedLock lock(_mutex);
247
248 std::string value;
249 if (getRaw(key, value))
250 return parseBool(internalExpand(value));
251 else
252 throw NotFoundException(key);
253}
254
255
256bool AbstractConfiguration::getBool(const std::string& key, bool defaultValue) const
257{
258 Mutex::ScopedLock lock(_mutex);
259
260 std::string value;
261 if (getRaw(key, value))
262 return parseBool(internalExpand(value));
263 else
264 return defaultValue;
265}
266
267
268void AbstractConfiguration::setString(const std::string& key, const std::string& value)
269{
270 setRawWithEvent(key, value);
271}
272
273
274void AbstractConfiguration::setInt(const std::string& key, int value)
275{
276 setRawWithEvent(key, NumberFormatter::format(value));
277}
278
279
280void AbstractConfiguration::setUInt(const std::string& key, unsigned int value)
281{
282 setRawWithEvent(key, NumberFormatter::format(value));
283}
284
285
286#if defined(POCO_HAVE_INT64)
287
288
289void AbstractConfiguration::setInt64(const std::string& key, Int64 value)
290{
291 Mutex::ScopedLock lock(_mutex);
292
293 setRawWithEvent(key, NumberFormatter::format(value));
294}
295
296
297void AbstractConfiguration::setUInt64(const std::string& key, UInt64 value)
298{
299 Mutex::ScopedLock lock(_mutex);
300
301 setRawWithEvent(key, NumberFormatter::format(value));
302}
303
304
305#endif // defined(POCO_HAVE_INT64)
306
307
308void AbstractConfiguration::setDouble(const std::string& key, double value)
309{
310 setRawWithEvent(key, NumberFormatter::format(value));
311}
312
313
314void AbstractConfiguration::setBool(const std::string& key, bool value)
315{
316 setRawWithEvent(key, value ? "true" : "false");
317}
318
319
320void AbstractConfiguration::keys(Keys& range) const
321{
322 Mutex::ScopedLock lock(_mutex);
323
324 std::string key;
325 range.clear();
326 enumerate(key, range);
327}
328
329
330void AbstractConfiguration::keys(const std::string& key, Keys& range) const
331{
332 Mutex::ScopedLock lock(_mutex);
333
334 range.clear();
335 enumerate(key, range);
336}
337
338
339const AbstractConfiguration::Ptr AbstractConfiguration::createView(const std::string& prefix) const
340{
341 return new ConfigurationView(prefix, AbstractConfiguration::Ptr(const_cast<AbstractConfiguration*>(this), true));
342}
343
344
345AbstractConfiguration::Ptr AbstractConfiguration::createView(const std::string& prefix)
346{
347 return new ConfigurationView(prefix, AbstractConfiguration::Ptr(this, true));
348}
349
350
351namespace
352{
353 class AutoCounter
354 {
355 public:
356 AutoCounter(int& count): _count(count)
357 {
358 ++_count;
359 }
360
361 ~AutoCounter()
362 {
363 --_count;
364 }
365
366 private:
367 int& _count;
368 };
369}
370
371
372std::string AbstractConfiguration::expand(const std::string& value) const
373{
374 Mutex::ScopedLock lock(_mutex);
375
376 return internalExpand(value);
377}
378
379
380void AbstractConfiguration::remove(const std::string& key)
381{
382 if (_eventsEnabled)
383 {
384 propertyRemoving(this, key);
385 }
386 {
387
388 Mutex::ScopedLock lock(_mutex);
389 removeRaw(key);
390 }
391 if (_eventsEnabled)
392 {
393 propertyRemoved(this, key);
394 }
395}
396
397
398void AbstractConfiguration::enableEvents(bool enable)
399{
400 _eventsEnabled = enable;
401}
402
403
404bool AbstractConfiguration::eventsEnabled() const
405{
406 return _eventsEnabled;
407}
408
409
410void AbstractConfiguration::removeRaw(const std::string& /*key*/)
411{
412 throw Poco::NotImplementedException("removeRaw()");
413}
414
415
416std::string AbstractConfiguration::internalExpand(const std::string& value) const
417{
418 AutoCounter counter(_depth);
419 if (_depth > 10) throw CircularReferenceException("Too many property references encountered");
420 return uncheckedExpand(value);
421}
422
423
424std::string AbstractConfiguration::uncheckedExpand(const std::string& value) const
425{
426 std::string result;
427 std::string::const_iterator it = value.begin();
428 std::string::const_iterator end = value.end();
429 while (it != end)
430 {
431 if (*it == '$')
432 {
433 ++it;
434 if (it != end && *it == '{')
435 {
436 ++it;
437 std::string prop;
438 while (it != end && *it != '}') prop += *it++;
439 if (it != end) ++it;
440 std::string rawValue;
441 if (getRaw(prop, rawValue))
442 {
443 result.append(internalExpand(rawValue));
444 }
445 else
446 {
447 result.append("${");
448 result.append(prop);
449 result.append("}");
450 }
451 }
452 else result += '$';
453 }
454 else result += *it++;
455 }
456 return result;
457}
458
459
460int AbstractConfiguration::parseInt(const std::string& value)
461{
462 if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0))
463 return static_cast<int>(NumberParser::parseHex(value));
464 else
465 return NumberParser::parse(value);
466}
467
468
469unsigned AbstractConfiguration::parseUInt(const std::string& value)
470{
471 if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0))
472 return NumberParser::parseHex(value);
473 else
474 return NumberParser::parseUnsigned(value);
475}
476
477
478Int64 AbstractConfiguration::parseInt64(const std::string& value)
479{
480 if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0))
481 return static_cast<Int64>(NumberParser::parseHex64(value));
482 else
483 return NumberParser::parse64(value);
484}
485
486
487UInt64 AbstractConfiguration::parseUInt64(const std::string& value)
488{
489 if ((value.compare(0, 2, "0x") == 0) || (value.compare(0, 2, "0X") == 0))
490 return NumberParser::parseHex64(value);
491 else
492 return NumberParser::parseUnsigned64(value);
493}
494
495
496bool AbstractConfiguration::parseBool(const std::string& value)
497{
498 int n;
499 if (NumberParser::tryParse(value, n))
500 return n != 0;
501 else if (icompare(value, "true") == 0)
502 return true;
503 else if (icompare(value, "yes") == 0)
504 return true;
505 else if (icompare(value, "on") == 0)
506 return true;
507 else if (icompare(value, "false") == 0)
508 return false;
509 else if (icompare(value, "no") == 0)
510 return false;
511 else if (icompare(value, "off") == 0)
512 return false;
513 else
514 throw SyntaxException("Cannot convert to boolean", value);
515}
516
517
518void AbstractConfiguration::setRawWithEvent(const std::string& key, std::string value)
519{
520 KeyValue kv(key, value);
521 if (_eventsEnabled)
522 {
523 propertyChanging(this, kv);
524 }
525 {
526 Mutex::ScopedLock lock(_mutex);
527 setRaw(key, value);
528 }
529 if (_eventsEnabled)
530 {
531 propertyChanged(this, kv);
532 }
533}
534
535
536} } // namespace Poco::Util
537