gramods
Loading...
Searching...
No Matches
Configuration.hh
1
2#ifndef GRAMODS_CORE_CONFIGURATION
3#define GRAMODS_CORE_CONFIGURATION
4
5#include <gmCore/config.hh>
6#include <gmCore/Console.hh>
7
8#include <vector>
9#include <map>
10#include <string>
11#include <algorithm>
12#include <memory>
13#include <cctype>
14
15#ifdef gramods_ENABLE_TinyXML2
16
17#include <tinyxml2.h>
18
19BEGIN_NAMESPACE_GMCORE;
20
21class Object;
22
42
43public:
44
49
60 Configuration(int &argc, char *argv[],
61 std::vector<std::string> *error_list = nullptr);
62
67 Configuration(std::string config,
68 std::vector<std::string> *error_list = nullptr);
69
74 Configuration(tinyxml2::XMLNode *node,
75 std::vector<std::string> *error_list = nullptr);
76
81
85 bool hasParam(std::string name);
86
91 std::size_t getAllParamNames(std::vector<std::string> &name);
92
98 std::size_t getAllObjectKeys(std::vector<std::string> &name);
99
103 void addParam(std::string name, std::string value);
104
120 template<class T>
121 bool getParam(std::string name, T &value) const;
122
130 template<class T>
131 std::size_t getAllParams(std::string name, std::vector<T> &value) const;
132
145 template<class T>
146 bool getObjectByKey(std::string key, std::shared_ptr<T> &ptr) const;
147
158 template<class T>
159 bool getObjectByDef(std::string def, std::shared_ptr<T> &ptr) const;
160
171 template<class T>
172 bool getObject(std::shared_ptr<T> &ptr) const;
173
177 template<class T>
178 void addObject(std::shared_ptr<T> ptr, std::string key, std::string def);
179
189 template<class T>
190 std::size_t getAllObjects(std::vector<std::shared_ptr<T>> &value) const;
191
202 template<class T>
203 std::size_t getAllObjectsByKey(std::string key, std::vector<std::shared_ptr<T>> &ptr) const;
204
205private:
206
207 typedef std::map<std::string, std::shared_ptr<Object>> def_list;
208
209 void load(tinyxml2::XMLNode *node,
210 std::vector<std::string> *error_list = nullptr);
211
212 struct parameter_t {
213 parameter_t(std::string value = "")
214 : value(value), checked(false) {}
215 std::string value;
216 bool checked;
217 };
218
219 typedef std::vector<std::pair<std::string, parameter_t>> parameter_list;
220 typedef std::map<std::string, std::shared_ptr<parameter_t>> overrides_list;
221 struct child_t {
222 std::shared_ptr<Object> object;
223 std::string key;
224 std::string def;
225 };
226 typedef std::vector<child_t> child_object_list;
227
228 child_object_list child_objects;
229 parameter_list parameters;
230
231 std::shared_ptr<def_list> def_objects;
232 overrides_list parameter_overrides;
233 bool warn_unused_overrides;
234
235 bool parse_if(tinyxml2::XMLElement *element,
236 std::vector<std::string> *error_list);
237 void parse_param(tinyxml2::XMLElement *element,
238 std::vector<std::string> *error_list);
239
240 overrides_list propagateOverrides(const overrides_list &,
241 std::vector<std::string>);
242
247 Configuration(tinyxml2::XMLNode *node,
248 std::shared_ptr<def_list> defs,
249 overrides_list overrides,
250 std::vector<std::string> *error_list = nullptr);
251};
252
253
254template<class T>
255std::size_t Configuration::getAllObjects(std::vector<std::shared_ptr<T>> &value) const {
256
257 Configuration *_this = const_cast<Configuration*>(this);
258
259 auto original_size = value.size();
260
261 for (auto &child : _this->child_objects) {
262 std::shared_ptr<T> node = std::dynamic_pointer_cast<T>(child.object);
263 if (node) value.push_back(node);
264 }
265
266 return value.size() - original_size;
267}
268
269template<class T>
270std::size_t Configuration::getAllObjectsByKey(
271 std::string key, std::vector<std::shared_ptr<T>> &value) const {
272
273 Configuration *_this = const_cast<Configuration*>(this);
274
275 auto original_size = value.size();
276
277 for (auto &child : _this->child_objects) {
278
279 if (child.key != key) continue;
280
281 std::shared_ptr<T> node = std::dynamic_pointer_cast<T>(child.object);
282 if (node) value.push_back(node);
283 }
284
285 return value.size() - original_size;
286}
287
288template<class T>
289bool Configuration::getObjectByKey(std::string key, std::shared_ptr<T> &ptr) const {
290
291 auto it = std::find_if(child_objects.begin(),
292 child_objects.end(),
293 [key](const child_t &child) {
294 return key == child.key;
295 });
296 if (it == child_objects.end()) return false;
297
298 std::shared_ptr<T> _value = std::dynamic_pointer_cast<T>(it->object);
299 if (!_value) return false;
300
301 ptr = _value;
302 return true;
303}
304
305template<class T>
306bool Configuration::getObjectByDef(std::string def, std::shared_ptr<T> &ptr) const {
307
308 if (def_objects->count(def) == 0) return false;
309
310 std::shared_ptr<T> _value = std::dynamic_pointer_cast<T>((*def_objects)[def]);
311 if (!_value) return false;
312
313 ptr = _value;
314 return true;
315}
316
317template<class T>
318bool Configuration::getObject(std::shared_ptr<T> &ptr) const {
319
320 Configuration *_this = const_cast<Configuration*>(this);
321
322 for (auto &child : _this->child_objects) {
323
324 std::shared_ptr<T> _value = std::dynamic_pointer_cast<T>(child.object);
325
326 if (_value == nullptr) continue;
327
328 ptr = _value;
329 return true;
330 }
331
332 return false;
333}
334
335template<class T>
336void Configuration::addObject(std::shared_ptr<T> ptr,
337 std::string key,
338 std::string def) {
339 child_objects.push_back(child_t({ptr, key, def}));
340}
341
342template<class T>
343bool Configuration::getParam(std::string name, T &value) const {
344
345 std::string string_value;
346 if (!getParam(name, string_value))
347 return false;
348
349 try {
350
351 std::stringstream string_value_stream(string_value);
352
353 T _value;
354 string_value_stream >> _value;
355
356 if (!string_value_stream) {
357 GM_WRN("Configuration", "While getting '" << name << "', could not parse '" << string_value << "' as " << typeid(T).name() << "!");
358 return false;
359 }
360
361 value = _value;
362 return true;
363 }
364 catch (std::exception){
365 GM_WRN("Configuration", "While getting '" << name << "', could not parse '" << string_value << "' as " << typeid(T).name() << "!");
366 return false;
367 }
368}
369
370template <>
371inline bool Configuration::getParam(std::string name, std::string &value) const {
372
373 Configuration * _this = const_cast<Configuration*>(this);
374
375 auto it = std::find_if(_this->parameters.begin(),
376 _this->parameters.end(),
377 [name](std::pair<std::string, parameter_t> pair) {
378 return pair.first == name;
379 });
380 if (it == _this->parameters.end()) {
381 GM_DBG1("Configuration", "Could not find " << name);
382 return false;
383 }
384
385 value = it->second.value;
386 it->second.checked = true;
387 GM_DBG1("Configuration", "Read " << name << " = " << value);
388 return true;
389}
390
391template<>
392inline bool Configuration::getParam(std::string name, bool &value) const {
393
394 std::string string_value;
395
396 if (!getParam(name, string_value))
397 return false;
398
399 std::transform(string_value.begin(), string_value.end(), string_value.begin(),
400 [](unsigned char c){ return std::tolower(c); });
401
402 if (string_value == "true") { value = true; return true; }
403 if (string_value == "on") { value = true; return true; }
404 if (string_value == "1") { value = true; return true; }
405
406 if (string_value == "false") { value = false; return true; }
407 if (string_value == "off") { value = false; return true; }
408 if (string_value == "0") { value = false; return true; }
409
410 GM_WRN("Configuration", "Could not parse '" << string_value << "' as bool!");
411 return false;
412}
413
414template<>
415inline std::size_t Configuration::getAllParams(std::string name, std::vector<std::string> &value) const {
416
417 Configuration * _this = const_cast<Configuration*>(this);
418 std::size_t original_size = value.size();
419
420 for (auto &param : _this->parameters)
421 if (param.first == name) {
422 value.push_back(param.second.value);
423 param.second.checked = true;
424 GM_DBG1("Configuration", "Read " << name << " = " << param.second.value);
425 }
426
427 return value.size() - original_size;
428}
429
430template<>
431inline std::size_t Configuration::getAllParams(std::string name, std::vector<bool> &value) const {
432 std::vector<std::string> values;
433 getAllParams(name, values);
434
435 std::size_t original_size = value.size();
436 for (auto string_value : values)
437 try {
438 std::transform(string_value.begin(), string_value.end(), string_value.begin(),
439 [](unsigned char c){ return std::tolower(c); });
440
441 if (string_value == "true") { value.push_back(true); continue; }
442 if (string_value == "on") { value.push_back(true); continue; }
443 if (string_value == "1") { value.push_back(true); continue; }
444
445 if (string_value == "false") { value.push_back(false); continue; }
446 if (string_value == "off") { value.push_back(false); continue; }
447 if (string_value == "0") { value.push_back(false); continue; }
448
449 GM_WRN("Configuration", "Could not parse '" << string_value << "' as bool!");
450 } catch (std::exception &) {
451 GM_WRN("Configuration", "Could not parse '" << string_value << "' as bool!");
452 }
453 return value.size() - original_size;
454}
455
456template<class T>
457inline std::size_t Configuration::getAllParams(std::string name, std::vector<T> &value) const {
458 std::vector<std::string> values;
459 getAllParams(name, values);
460
461 std::size_t original_size = value.size();
462 for (auto string_value : values)
463 try {
464
465 std::stringstream string_value_stream(string_value);
466
467 T _value;
468 string_value_stream >> _value;
469
470 if (!string_value_stream) {
471 GM_WRN("Configuration", "While getting '" << name << "', could not parse '" << string_value << "' as " << typeid(T).name() << "!");
472 return false;
473 }
474
475 value.push_back(_value);
476 }
477 catch (std::exception){
478 GM_WRN("Configuration", "While getting '" << name << "', could not parse '" << string_value << "' as " << typeid(T).name() << "!");
479 }
480 return value.size() - original_size;
481}
482
483END_NAMESPACE_GMCORE;
484
485#endif
486
487#endif
488
A wrapper for the XML parser that also creates and configures the system objects and holds temporary ...
Definition Configuration.hh:41
Configuration(tinyxml2::XMLNode *node, std::vector< std::string > *error_list=nullptr)
Read the XML data, create objects as specified by the XML data and configure the objects.