gramods
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 
19 BEGIN_NAMESPACE_GMCORE;
20 
21 class Object;
22 
42 
43 public:
44 
48  Configuration();
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 
80  ~Configuration();
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 
205 private:
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 
254 template<class T>
255 std::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 
269 template<class T>
270 std::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 
288 template<class T>
289 bool 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 
305 template<class T>
306 bool 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 
317 template<class T>
318 bool 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 
335 template<class T>
336 void 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 
342 template<class T>
343 bool 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 
370 template <>
371 inline 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 
391 template<>
392 inline 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 
414 template<>
415 inline 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 
430 template<>
431 inline 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 
456 template<class T>
457 inline 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 
483 END_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.