Fawkes API  Fawkes Development Version
yaml.cpp
1 
2 /***************************************************************************
3  * yaml.cpp - Fawkes configuration stored in one or more YAML files
4  *
5  * Created: Wed Aug 01 16:46:13 2012
6  * Copyright 2006-2012 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <config/yaml.h>
25 
26 #include "yaml_node.h"
27 
28 #include <core/threading/mutex.h>
29 #include <core/threading/mutex_locker.h>
30 #include <core/exceptions/software.h>
31 #include <logging/liblogger.h>
32 #include <utils/system/fam_thread.h>
33 #include <utils/misc/string_split.h>
34 
35 #include <queue>
36 #include <fstream>
37 #include <cstring>
38 #include <cstdio>
39 #include <cstdlib>
40 #include <cerrno>
41 #include <dirent.h>
42 #include <sys/stat.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 
47 #include <yaml-cpp/exceptions.h>
48 
49 namespace fawkes {
50 #if 0 /* just to make Emacs auto-indent happy */
51 }
52 #endif
53 
54 #define PATH_REGEX "^[a-zA-Z0-9_-]+$"
55 #define YAML_REGEX "^[a-zA-Z0-9_-]+\\.yaml$"
56 // from https://www.ietf.org/rfc/rfc3986.txt
57 #define URL_REGEX "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"
58 #define FRAME_REGEX "^([a-zA-Z_][a-zA-Z0-9_/-]*)+$"
59 
60 
61 /** @class YamlConfiguration::YamlValueIterator <config/yaml.h>
62  * Iterator for YAML config trees.
63  * This iterator is used by YamlConfiguration as a result value
64  * for queries. Its use is opaque and knowledge of
65  * Configuration::ValueIterator will suffice for interaction.
66  * @author Tim Niemueller
67  */
68 
69 /** Constructor.
70  * Creates an iterator representing the invalid iterator.
71  */
73  : first_(true)
74 {
75  current_ = nodes_.end();
76 }
77 
78 
79 /** Initializing constructor.
80  * @param nodes nodes to iterate over
81  */
82 YamlConfiguration::YamlValueIterator::YamlValueIterator(std::map<std::string, YamlConfigurationNode *> &nodes)
83  : first_(true), nodes_(nodes)
84 {
85  current_ = nodes_.end();
86 }
87 
88 bool
90 {
91  if (first_) {
92  first_ = false;
93  current_ = nodes_.begin();
94  } else {
95  ++current_;
96  }
97  return (current_ != nodes_.end());
98 }
99 
100 bool
102 {
103  return (current_ != nodes_.end());
104 }
105 
106 const char *
108 {
109  if (current_ == nodes_.end()) {
110  throw Exception("YamlValueIterator: cannot get path of invalid iterator");
111  }
112  return current_->first.c_str();
113 }
114 
115 const char *
117 {
118  if (current_ == nodes_.end()) {
119  throw Exception("YamlValueIterator: cannot get type of invalid iterator");
120  }
121  return YamlConfigurationNode::Type::to_string(current_->second->get_type());
122 }
123 
124 bool
126 {
127  if (current_ == nodes_.end()) {
128  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
129  }
130  return (current_->second->is_type<float>());
131 }
132 
133 bool
135 {
136  if (current_ == nodes_.end()) {
137  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
138  }
139  return (current_->second->is_type<unsigned int>());
140 }
141 
142 bool
144 {
145  if (current_ == nodes_.end()) {
146  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
147  }
148  return (current_->second->is_type<int>());
149 }
150 
151 bool
153 {
154  if (current_ == nodes_.end()) {
155  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
156  }
157  return (current_->second->is_type<bool>());
158 }
159 
160 bool
162 {
163  if (current_ == nodes_.end()) {
164  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
165  }
166  return (current_->second->is_type<std::string>());
167 }
168 
169 bool
171 {
172  if (current_ == nodes_.end()) {
173  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
174  }
175  return current_->second->get_type() == YamlConfigurationNode::Type::SEQUENCE;
176 }
177 
178 
179 size_t
181 {
182  if (current_ == nodes_.end()) {
183  throw Exception("YamlValueIterator: cannot check type on invalid iterator");
184  }
185  if (current_->second->get_type() != YamlConfigurationNode::Type::SEQUENCE) {
186  throw Exception("YamlValueIterator: cannot get list size of non-list value");
187  }
188  return current_->second->get_list_size();
189 }
190 
191 float
193 {
194  if (current_ == nodes_.end()) {
195  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
196  }
197  return current_->second->get_value<float>();
198 }
199 
200 unsigned int
202 {
203  if (current_ == nodes_.end()) {
204  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
205  }
206  return current_->second->get_value<unsigned int>();
207 }
208 
209 int
211 {
212  if (current_ == nodes_.end()) {
213  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
214  }
215  return current_->second->get_value<int>();
216 }
217 
218 bool
220 {
221  if (current_ == nodes_.end()) {
222  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
223  }
224  return current_->second->get_value<bool>();
225 }
226 
227 std::string
229 {
230  if (current_ == nodes_.end()) {
231  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
232  }
233  return current_->second->get_value<std::string>();
234 }
235 
236 std::string
238 {
239  if (current_ == nodes_.end()) {
240  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
241  }
242  if (current_->second->get_type() == YamlConfigurationNode::Type::SEQUENCE) {
243  return current_->second->get_list_as_string();
244  } else {
245  return current_->second->get_value<std::string>();
246  }
247 }
248 
249 std::vector<float>
251 {
252  if (current_ == nodes_.end()) {
253  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
254  }
255  return current_->second->get_list<float>();
256 }
257 
258 std::vector<unsigned int>
260 {
261  if (current_ == nodes_.end()) {
262  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
263  }
264  return current_->second->get_list<unsigned int>();
265 }
266 
267 std::vector<int>
269 {
270  if (current_ == nodes_.end()) {
271  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
272  }
273  return current_->second->get_list<int>();
274 }
275 
276 std::vector<bool>
278 {
279  if (current_ == nodes_.end()) {
280  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
281  }
282  return current_->second->get_list<bool>();
283 }
284 
285 std::vector<std::string>
287 {
288  if (current_ == nodes_.end()) {
289  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
290  }
291  return current_->second->get_list<std::string>();
292 }
293 
294 
295 std::string
297 {
298  throw NotImplementedException("YamlConfig: comments are not available");
299 }
300 
301 bool
303 {
304  if (current_ == nodes_.end()) {
305  throw Exception("YamlValueIterator: cannot get value of invalid iterator");
306  }
307  return current_->second->is_default();
308 }
309 
310 
311 
312 /** @class YamlConfiguration <config/yaml.h>
313  * Configuration store using YAML documents.
314  * @author Tim Niemueller
315  */
316 
317 
318 /** Constructor. */
320 {
321  root_ = host_root_ = NULL;
322  fam_thread_ = NULL;
323  mutex = new Mutex();
324  write_pending_ = false;
325  write_pending_mutex_ = new Mutex();
326 
327  __sysconfdir = NULL;
328  __userconfdir = NULL;
329 
330 #ifdef USE_REGEX_CPP
331  __yaml_regex = std::regex(YAML_REGEX, std::regex_constants::extended);
332  __url_regex = std::regex(URL_REGEX, std::regex_constants::extended);
333  __frame_regex = std::regex(FRAME_REGEX, std::regex_constants::extended);
334 #else
335  if (regcomp(&__yaml_regex, YAML_REGEX, REG_EXTENDED) != 0) {
336  throw Exception("Failed to compile YAML regex");
337  }
338  if (regcomp(&__url_regex, URL_REGEX, REG_EXTENDED) != 0) {
339  throw Exception("Failed to compile URL regex");
340  }
341  if (regcomp(&__frame_regex, FRAME_REGEX, REG_EXTENDED) != 0) {
342  throw Exception("Failed to compile frame regex");
343  }
344 #endif
345 }
346 
347 /** Constructor.
348  * @param sysconfdir system configuration directory, will be searched for
349  * default configuration file, and system will try to create host-specific
350  * database if writable
351  * @param userconfdir user configuration directory, will be searched preferably
352  * for default configuration file, and will be used to create host-specific
353  * database if sysconfdir is not writable. This directory will be created
354  * if it does not exist during load().
355  */
357  const char *userconfdir)
358 {
359  root_ = host_root_ = NULL;
360  fam_thread_ = NULL;
361  mutex = new Mutex();
362  write_pending_ = false;
363  write_pending_mutex_ = new Mutex();
364 
365  __sysconfdir = strdup(sysconfdir);
366 
367 #ifdef USE_REGEX_CPP
368  __yaml_regex = std::regex(YAML_REGEX, std::regex_constants::extended);
369  __url_regex = std::regex(URL_REGEX, std::regex_constants::extended);
370  __frame_regex = std::regex(FRAME_REGEX, std::regex_constants::extended);
371 #else
372  if (regcomp(&__yaml_regex, YAML_REGEX, REG_EXTENDED) != 0) {
373  throw Exception("Failed to compile YAML regex");
374  }
375  if (regcomp(&__url_regex, URL_REGEX, REG_EXTENDED) != 0) {
376  throw Exception("Failed to compile URL regex");
377  }
378  if (regcomp(&__frame_regex, FRAME_REGEX, REG_EXTENDED) != 0) {
379  throw Exception("Failed to compile frame regex");
380  }
381 #endif
382 
383  if (userconfdir != NULL) {
384  __userconfdir = strdup(userconfdir);
385  } else {
386  const char *homedir = getenv("HOME");
387  if (homedir == NULL) {
388  __userconfdir = strdup(sysconfdir);
389  } else {
390  if (asprintf(&__userconfdir, "%s/%s", homedir, USERDIR) == -1) {
391  __userconfdir = strdup(sysconfdir);
392  }
393  }
394  }
395 }
396 
397 /** Destructor. */
399 {
400  if (write_pending_) {
401  write_host_file();
402  }
403 
404  delete root_;
405  delete host_root_;
406  root_ = host_root_ = NULL;
407 
408  if (fam_thread_) {
409  fam_thread_->cancel();
410  fam_thread_->join();
411  delete fam_thread_;
412  }
413 
414  if (__sysconfdir) free(__sysconfdir);
415  if (__userconfdir) free(__userconfdir);
416 #ifndef USE_REGEX_CPP
417  regfree(&__yaml_regex);
418  regfree(&__url_regex);
419  regfree(&__frame_regex);
420 #endif
421  delete mutex;
422  delete write_pending_mutex_;
423 }
424 
425 
426 void
427 YamlConfiguration::load(const char *file_path)
428 {
429 
430  if (file_path == NULL) {
431  file_path = "config.yaml";
432  }
433 
434  std::string filename;
435  if (file_path[0] == '/') {
436  filename = file_path;
437  } else {
438 
439  const char *try_paths[] = {__userconfdir, __sysconfdir};
440  int try_paths_len = 2;
441 
442 
443  for (int i = 0; i < try_paths_len; ++i) {
444  char *path;
445  if (asprintf(&path, "%s/%s", try_paths[i], file_path) != -1) {
446  if (access(path, R_OK) == 0) {
447  filename = path;
448  free(path);
449  break;
450  }
451  free(path);
452  }
453  }
454  if (filename == "") {
455  throw Exception("YamlConfig: cannot find configuration file %s/%s or %s/%s",
456  __userconfdir, file_path, __sysconfdir, file_path);
457  }
458  }
459 
460  config_file_ = filename;
461 
462  host_file_ = "";
463  std::list<std::string> files, dirs;
464  read_yaml_config(filename, host_file_, root_, host_root_, files, dirs);
465 
466 #ifdef HAVE_INOTIFY
467  fam_thread_ = new FamThread();
468  RefPtr<FileAlterationMonitor> fam = fam_thread_->get_fam();
469  fam->add_filter("^[^.].*\\.yaml$");
470  std::list<std::string>::iterator f;
471  for (f = files.begin(); f != files.end(); ++f) {
472  //LibLogger::log_info("YC", "Watching %s", f->c_str());
473  fam->watch_file(f->c_str());
474  }
475  for (f = dirs.begin(); f != dirs.end(); ++f) {
476  //LibLogger::log_info("YC", "Watching DIR %s", f->c_str());
477  fam->watch_dir(f->c_str());
478  }
479  fam->add_listener(this);
480  fam_thread_->start();
481 #endif
482 
483  //root_->print();
484 }
485 
486 
487 YamlConfigurationNode *
488 YamlConfiguration::read_yaml_file(std::string filename, bool ignore_missing,
489  std::queue<LoadQueueEntry> &load_queue,
490  std::string &host_file)
491 {
492  if (access(filename.c_str(), R_OK) == -1) {
493  if (ignore_missing) {
494  return NULL;
495  }
496  throw Exception(errno, "YamlConfig: cannot access file %s", filename.c_str());
497  }
498 
499 #ifdef HAVE_YAMLCPP_0_5
500  std::vector<YAML::Node> docs;
501 #else
502  std::ifstream fin(filename.c_str());
503  YAML::Parser parser;
504  YAML::Node doc1, doc2;
505 #endif
506  bool have_doc1 = false, have_doc2 = false;
507 
508  try {
509 #ifdef HAVE_YAMLCPP_0_5
510  docs = YAML::LoadAllFromFile(filename);
511  have_doc1 = docs.size() > 0;
512  have_doc2 = docs.size() > 1;
513 #else
514  parser.Load(fin);
515  have_doc1 = parser.GetNextDocument(doc1);
516  have_doc2 = parser.GetNextDocument(doc2);
517 #endif
518  } catch (YAML::ParserException &e) {
519  throw CouldNotOpenConfigException("Failed to parse %s line %i column %i: %s",
520  filename.c_str(), e.mark.line, e.mark.column,
521  e.msg.c_str());
522  }
523 
524  YamlConfigurationNode *sub_root = NULL;
525 
526  if (! have_doc1) {
527  //throw Exception("YamlConfig: file %s contains no document", filename.c_str());
528  // empty -> ignore
529  } else if (have_doc1 && have_doc2) {
530  // we have a meta info and a config document
531 #ifdef HAVE_YAMLCPP_0_5
532  read_meta_doc(docs[0], load_queue, host_file);
533  read_config_doc(docs[1], sub_root);
534 #else
535  read_meta_doc(doc1, load_queue, host_file);
536  read_config_doc(doc2, sub_root);
537 #endif
538 
539  } else {
540  // only one, assume this to be the config document
541 #ifdef HAVE_YAMLCPP_0_5
542  read_config_doc(docs[0], sub_root);
543 #else
544  read_config_doc(doc1, sub_root);
545 #endif
546  }
547 
548  return sub_root;
549 }
550 
551 
552 void
553 YamlConfiguration::read_yaml_config(std::string filename, std::string &host_file,
554  YamlConfigurationNode *& root, YamlConfigurationNode *& host_root,
555  std::list<std::string> &files, std::list<std::string> &dirs)
556 {
557  root = new YamlConfigurationNode();
558 
559  std::queue<LoadQueueEntry> load_queue;
560  load_queue.push(LoadQueueEntry(filename, false));
561 
562  while (! load_queue.empty()) {
563  LoadQueueEntry &qe = load_queue.front();
564 
565  if (qe.is_dir) {
566  dirs.push_back(qe.filename);
567  } else {
568  //LibLogger::log_debug("YamlConfiguration",
569  // "Reading YAML file '%s' (ignore missing: %s)",
570  // qe.filename.c_str(), qe.ignore_missing ? "yes" : "no");
571 
572  YamlConfigurationNode *sub_root = read_yaml_file(qe.filename, qe.ignore_missing, load_queue, host_file);
573 
574  if (sub_root) {
575  files.push_back(qe.filename);
576  *root += sub_root;
577  delete sub_root;
578  }
579  }
580 
581  load_queue.pop();
582  }
583 
584  if (host_file != "") {
585  //LibLogger::log_debug("YamlConfiguration",
586  // "Reading Host YAML file '%s'", host_file.c_str());
587  std::queue<LoadQueueEntry> host_load_queue;
588  host_root = read_yaml_file(host_file, true, host_load_queue, host_file);
589  if (! host_load_queue.empty()) {
590  throw CouldNotOpenConfigException("YamlConfig: includes are not allowed "
591  "in host document");
592  }
593  if (host_root) {
594  *root += host_root;
595  files.push_back(host_file);
596  } else host_root = new YamlConfigurationNode();
597  } else {
598  host_root = new YamlConfigurationNode();
599  }
600 }
601 
602 void
603 YamlConfiguration::fam_event(const char *filename, unsigned int mask)
604 {
605  MutexLocker lock(mutex);
606  try {
607  std::string host_file = "";
608  std::list<std::string> files, dirs;
609  YamlConfigurationNode *root, *host_root;
610  read_yaml_config(config_file_, host_file, root, host_root, files, dirs);
611 
612  std::list<std::string> changes = YamlConfigurationNode::diff(root_, root);
613 
614  if (! changes.empty()) {
615  YamlConfigurationNode *old_root = root_;
616  YamlConfigurationNode *old_host_root = host_root_;
617  root_ = root;
618  host_root_ = host_root;
619  host_file_ = host_file;
620  delete old_root;
621  delete old_host_root;
622 
623  std::list<std::string>::iterator c;
624  for (c = changes.begin(); c != changes.end(); ++c) {
625  notify_handlers(c->c_str());
626  }
627  }
628 
629  // includes might have changed to include a new empty file
630  // so even though no value changes were seen, we might very
631  // well have new files we need to watch (or files we do no
632  // longer have to watch, so always reset and re-add.
633  RefPtr<FileAlterationMonitor> fam = fam_thread_->get_fam();
634  fam->reset();
635  std::list<std::string>::iterator f;
636  for (f = files.begin(); f != files.end(); ++f) {
637  fam->watch_file(f->c_str());
638  }
639  for (f = dirs.begin(); f != dirs.end(); ++f) {
640  fam->watch_dir(f->c_str());
641  }
642 
643  } catch (Exception &e) {
644  LibLogger::log_warn("YamlConfiguration",
645  "Failed to reload changed config, exception follows");
646  LibLogger::log_warn("YamlConfiguration", e);
647  }
648 }
649 
650 /** Create absolute config path.
651  * If the @p path starts with / it is considered to be absolute. Otherwise
652  * it is prefixed with the config directory.
653  * @param path path
654  * @return absolute path
655  */
656 static std::string abs_cfg_path(const std::string &path)
657 {
658  if (path[0] == '/') {
659  return path;
660  } else {
661  return std::string(CONFDIR) + "/" + path;
662  }
663 }
664 
665 
666 void
667 YamlConfiguration::read_meta_doc(YAML::Node &doc, std::queue<LoadQueueEntry> &load_queue,
668  std::string &host_file)
669 {
670  try {
671  const YAML::Node &includes = doc["include"];
672 #ifdef HAVE_YAMLCPP_0_5
673  for (YAML::const_iterator it = includes.begin(); it != includes.end(); ++it) {
674  std::string include = it->as<std::string>();
675 #else
676  for (YAML::Iterator it = includes.begin(); it != includes.end(); ++it) {
677  std::string include;
678  *it >> include;
679 #endif
680  bool ignore_missing = false;
681  if (it->Tag() == "tag:fawkesrobotics.org,cfg/ignore-missing") {
682  ignore_missing = true;
683  }
684 
685  if (it->Tag() == "tag:fawkesrobotics.org,cfg/host-specific") {
686  if (host_file != "") {
687  throw Exception("YamlConfig: Only one host-specific file can be specified");
688  }
689 #ifdef HAVE_YAMLCPP_0_5
690  host_file = abs_cfg_path(it->Scalar());
691 #else
692  it->GetScalar(host_file);
693  host_file = abs_cfg_path(host_file);
694 #endif
695  continue;
696  }
697 
698  if (include.empty()) {
699  throw Exception("YamlConfig: invalid empty include");
700  }
701 
702  if (include[include.size() - 1] == '/') {
703  // this should be a directory
704  std::string dirname = abs_cfg_path(include);
705  struct stat dir_stat;
706  if ((stat(dirname.c_str(), &dir_stat) != 0)) {
707  if (ignore_missing) continue;
708  throw Exception(errno, "YamlConfig: Failed to stat directory %s", dirname.c_str());
709  }
710 
711  if (! S_ISDIR(dir_stat.st_mode)) {
712  throw Exception("YamlConfig: %s is not a directory", dirname.c_str());
713  }
714 
715  DIR *d = opendir(dirname.c_str());
716  if (! d) {
717  throw Exception(errno, "YamlConfig: failed to open directory %s",
718  dirname.c_str());
719  }
720 
721  load_queue.push(LoadQueueEntry(dirname, ignore_missing, true));
722 
723  std::list<std::string> files;
724 
725  struct dirent *dent;
726  while ((dent = readdir(d)) != NULL) {
727 #ifdef USE_REGEX_CPP
728  if (regex_search(dent->d_name, __yaml_regex)) {
729 # if 0
730  // just for emacs auto-indentation
731  }
732 # endif
733 #else
734  if (regexec(&__yaml_regex, dent->d_name, 0, NULL, 0) != REG_NOMATCH) {
735 #endif
736  std::string dn = dent->d_name;
737  files.push_back(dirname + dn);
738  }
739  }
740  closedir(d);
741 
742  files.sort();
743  for (std::list<std::string>::iterator f = files.begin(); f != files.end(); ++f) {
744  load_queue.push(LoadQueueEntry(*f, ignore_missing));
745  }
746 
747  } else {
748  load_queue.push(LoadQueueEntry(abs_cfg_path(include), ignore_missing));
749  }
750  }
751  } catch (YAML::KeyNotFound &e) {
752  //ignored, no includes
753  }
754 }
755 
756 
757 void
758 YamlConfiguration::read_config_doc(const YAML::Node &doc, YamlConfigurationNode *&node, std::string path)
759 {
760  if (! node) {
761  node = new YamlConfigurationNode("root");
762  }
763 
764  if (*path.rbegin() != '/')
765  path += '/';
766  if (node->name() != "root")
767  path += node->name();
768 
769  if (doc.Type() == YAML::NodeType::Map) {
770 #ifdef HAVE_YAMLCPP_0_5
771  for (YAML::const_iterator it = doc.begin(); it != doc.end(); ++it) {
772  std::string key = it->first.as<std::string>();
773 #else
774  for (YAML::Iterator it = doc.begin(); it != doc.end(); ++it) {
775  std::string key;
776  it.first() >> key;
777 #endif
778  YamlConfigurationNode *in = node;
779  if (key.find("/") != std::string::npos) {
780  // we need to split and find the proper insertion node
781  std::vector<std::string> pel = str_split(key);
782  for (size_t i = 0; i < pel.size() - 1; ++i) {
783  YamlConfigurationNode *n = (*in)[pel[i]];
784  if (! n) {
785  n = new YamlConfigurationNode(pel[i]);
786  in->add_child(pel[i], n);
787  }
788  in = n;
789  }
790 
791  key = pel.back();
792  }
793 
794  YamlConfigurationNode *tmp = (*in)[key];
795  if (tmp) {
796 #ifdef HAVE_YAMLCPP_0_5
797  if (tmp->is_scalar() && it->second.Type() != YAML::NodeType::Scalar)
798 #else
799  if (tmp->is_scalar() && it.second().Type() != YAML::NodeType::Scalar)
800 #endif
801  {
802  throw Exception("YamlConfig: %s: scalar %s cannot be overwritten by non-scalar",
803  path.c_str(), tmp->name().c_str());
804  }
805 #ifdef HAVE_YAMLCPP_0_5
806  tmp->set_scalar(it->second.Scalar());
807 #else
808  std::string s;
809  if (it.second().GetScalar(s)) {
810  tmp->set_scalar(s);
811  }
812 #endif
813  } else {
814 #ifdef HAVE_YAMLCPP_0_5
815  YamlConfigurationNode *tmp = new YamlConfigurationNode(key, it->second);
816  in->add_child(key, tmp);
817  read_config_doc(it->second, tmp, path);
818 #else
819  YamlConfigurationNode *tmp = new YamlConfigurationNode(key, it.second());
820  in->add_child(key, tmp);
821  read_config_doc(it.second(), tmp, path);
822 #endif
823  }
824  }
825 
826  } else if (doc.Type() == YAML::NodeType::Scalar) {
827  if (doc.Tag() == "tag:fawkesrobotics.org,cfg/ipv4" ||
828  doc.Tag() == "tag:fawkesrobotics.org,cfg/ipv6")
829  {
830  std::string addr_s;
831  try {
832  addr_s = node->get_string();
833  } catch (Exception &e) {
834  e.prepend("YamlConfig: %s: Invalid IPv4 or IPv6 address (not a string)", path.c_str());
835  throw;
836  }
837 
838  if (doc.Tag() == "tag:fawkesrobotics.org,cfg/ipv4") {
839  struct in_addr addr;
840  if (inet_pton(AF_INET, addr_s.c_str(), &addr) != 1) {
841  throw Exception("YamlConfig: %s is not a valid IPv4 address", addr_s.c_str());
842  }
843  }
844  if (doc.Tag() == "tag:fawkesrobotics.org,cfg/ipv6") {
845  struct in6_addr addr;
846  if (inet_pton(AF_INET6, addr_s.c_str(), &addr) != 1) {
847  throw Exception("YamlConfig: %s is not a valid IPv6 address", addr_s.c_str());
848  }
849  }
850 
851  } else if (doc.Tag() == "tag:fawkesrobotics.org,cfg/tcp-port" ||
852  doc.Tag() == "tag:fawkesrobotics.org,cfg/udp-port")
853  {
854  unsigned int p = 0;
855  try {
856  p = node->get_uint();
857  } catch (Exception &e) {
858  e.prepend("YamlConfig: %s: Invalid TCP/UDP port number (not an unsigned int)", path.c_str());
859  throw;
860  }
861  if (p <= 0 || p >= 65535) {
862  throw Exception("YamlConfig: Invalid TCP/UDP port number "
863  "(%u out of allowed range)", p);
864  }
865  } else if (doc.Tag() == "tag:fawkesrobotics.org,cfg/url") {
866 #ifdef HAVE_YAMLCPP_0_5
867  std::string scalar = doc.Scalar();
868 #else
869  std::string scalar;
870  doc.GetScalar(scalar);
871 #endif
872 #ifdef USE_REGEX_CPP
873  if (regex_search(scalar, __url_regex)) {
874 # if 0
875  // just for emacs auto-indentation
876  }
877 # endif
878 #else
879  if (regexec(&__url_regex, scalar.c_str(), 0, NULL, 0) == REG_NOMATCH) {
880  throw Exception("YamlConfig: %s: %s is not a valid URL", path.c_str(), scalar.c_str());
881  }
882 #endif
883  } else if (doc.Tag() == "tag:fawkesrobotics.org,cfg/frame") {
884 #ifdef HAVE_YAMLCPP_0_5
885  std::string scalar = doc.Scalar();
886 #else
887  std::string scalar;
888  doc.GetScalar(scalar);
889 #endif
890 #ifdef USE_REGEX_CPP
891  if (regex_search(scalar, __frame_regex)) {
892 # if 0
893  // just for emacs auto-indentation
894  }
895 # endif
896 #else
897  if (regexec(&__frame_regex, scalar.c_str(), 0, NULL, 0) == REG_NOMATCH) {
898  throw Exception("YamlConfig: %s: %s is not a valid frame ID", path.c_str(), scalar.c_str());
899  }
900 #endif
901  }
902 
903  }
904 }
905 
906 void
907 YamlConfiguration::write_host_file()
908 {
909  if (host_file_ == "") {
910  throw Exception("YamlConfig: no host config file specified");
911  }
912  if (mutex->try_lock()) {
913  try {
914  host_root_->emit(host_file_);
915  mutex->unlock();
916  } catch (...) {
917  write_pending_mutex_->unlock();
918  mutex->unlock();
919  throw;
920  }
921  } else {
922  write_pending_mutex_->lock();
923  write_pending_ = true;
924  write_pending_mutex_->unlock();
925  }
926 }
927 
928 
929 void
931 {
932  throw NotImplementedException("YamlConfig does not support copying of a configuration");
933 }
934 
935 bool
936 YamlConfiguration::exists(const char *path)
937 {
938  try {
939  YamlConfigurationNode *n = root_->find(path);
940  return ! n->has_children();
941  } catch (Exception &e) {
942  return false;
943  }
944 }
945 
946 
947 std::string
949 {
950  YamlConfigurationNode *n = root_->find(path);
951  if (n->has_children()) {
952  throw ConfigEntryNotFoundException(path);
953  }
954 
955  return YamlConfigurationNode::Type::to_string(n->get_type());
956 }
957 
958 std::string
960 {
961  return "";
962 }
963 
964 
965 /** Retrieve value casted to given type T.
966  * @param root root node of the tree to search
967  * @param path path to query
968  * @return value casted as desired
969  * @throw YAML::ScalarInvalid thrown if value does not exist or is of
970  * a different type.
971  */
972 template<typename T>
973 static inline T
974 get_value_as(YamlConfigurationNode *root, const char *path)
975 {
976  YamlConfigurationNode *n = root->find(path);
977  if (n->has_children()) {
978  throw ConfigEntryNotFoundException(path);
979  }
980  return n->get_value<T>();
981 }
982 
983 /** Retrieve value casted to given type T.
984  * @param root root node of the tree to search
985  * @param path path to query
986  * @return value casted as desired
987  * @throw YAML::ScalarInvalid thrown if value does not exist or is of
988  * a different type.
989  */
990 template<typename T>
991 static inline std::vector<T>
992 get_list(YamlConfigurationNode *root, const char *path)
993 {
994  YamlConfigurationNode *n = root->find(path);
995  if (n->has_children()) {
996  throw ConfigEntryNotFoundException(path);
997  }
998  return n->get_list<T>();
999 }
1000 
1001 
1002 float
1004 {
1005  return get_value_as<float>(root_, path);
1006 }
1007 
1008 unsigned int
1010 {
1011  return get_value_as<unsigned int>(root_, path);
1012 }
1013 
1014 int
1016 {
1017  return get_value_as<int>(root_, path);
1018 }
1019 
1020 bool
1022 {
1023  return get_value_as<bool>(root_, path);
1024 }
1025 
1026 std::string
1028 {
1029  return get_value_as<std::string>(root_, path);
1030 }
1031 
1032 
1033 std::vector<float>
1035 {
1036  return get_list<float>(root_, path);
1037 }
1038 
1039 
1040 std::vector<unsigned int>
1042 {
1043  return get_list<unsigned int>(root_, path);
1044 }
1045 
1046 
1047 std::vector<int>
1049 {
1050  return get_list<int>(root_, path);
1051 }
1052 
1053 std::vector<bool>
1055 {
1056  return get_list<bool>(root_, path);
1057 }
1058 
1059 std::vector<std::string>
1061 {
1062  return get_list<std::string>(root_, path);
1063 }
1064 
1065 
1066 /** Check if value is of given type T.
1067  * @param root root node of the tree to search
1068  * @param path path to query
1069  * @return true if value is of desired type, false otherwise
1070  */
1071 template<typename T>
1072 static inline bool
1073 is_type(YamlConfigurationNode *root, const char *path)
1074 {
1075  YamlConfigurationNode *n = root->find(path);
1076  if (n->has_children()) {
1077  throw ConfigEntryNotFoundException(path);
1078  }
1079  return n->is_type<T>();
1080 }
1081 
1082 
1083 bool
1085 {
1086  return is_type<float>(root_, path);
1087 }
1088 
1089 bool
1091 {
1092  YamlConfigurationNode *n = root_->find(path);
1093  if (n->has_children()) {
1094  throw ConfigEntryNotFoundException(path);
1095  }
1096 
1097  if (! n->is_type<unsigned int>()) return false;
1098 
1099  int v = n->get_value<int>();
1100  return (v >= 0);
1101 }
1102 
1103 bool
1104 YamlConfiguration::is_int(const char *path)
1105 {
1106  return is_type<int>(root_, path);
1107 }
1108 
1109 bool
1111 {
1112  return is_type<bool>(root_, path);
1113 }
1114 
1115 bool
1117 {
1118  return is_type<std::string>(root_, path);
1119 }
1120 
1121 
1122 bool
1124 {
1125  YamlConfigurationNode *n = root_->find(path);
1126  if (n->has_children()) {
1127  throw ConfigEntryNotFoundException(path);
1128  }
1129  return (n->get_type() == YamlConfigurationNode::Type::SEQUENCE);
1130 }
1131 
1132 
1133 std::string
1135 {
1136  return "";
1137 }
1138 
1139 bool
1141 {
1142  return false;
1143 }
1144 
1145 
1148 {
1149  try {
1150  YamlConfigurationNode *n = root_->find(path);
1151  if (n->has_children()) {
1152  return new YamlValueIterator();
1153  }
1154  std::map<std::string, YamlConfigurationNode *> nodes;
1155  nodes[path] = n;
1156  return new YamlValueIterator(nodes);
1157  } catch (ConfigEntryNotFoundException &e) {
1158  return new YamlValueIterator();
1159  }
1160 }
1161 
1162 
1163 void
1164 YamlConfiguration::set_float(const char *path, float f)
1165 {
1166  root_->set_value(path, f);
1167  host_root_->set_value(path, f);
1168  write_host_file();
1169 }
1170 
1171 void
1172 YamlConfiguration::set_uint(const char *path, unsigned int uint)
1173 {
1174  root_->set_value(path, uint);
1175  host_root_->set_value(path, uint);
1176  write_host_file();
1177 }
1178 
1179 void
1180 YamlConfiguration::set_int(const char *path, int i)
1181 {
1182  root_->set_value(path, i);
1183  host_root_->set_value(path, i);
1184  write_host_file();
1185 }
1186 
1187 void
1188 YamlConfiguration::set_bool(const char *path, bool b)
1189 {
1190  root_->set_value(path, b);
1191  host_root_->set_value(path, b);
1192  write_host_file();
1193 }
1194 
1195 void
1196 YamlConfiguration::set_string(const char *path, const char *s)
1197 {
1198  root_->set_value(path, std::string(s));
1199  host_root_->set_value(path, std::string(s));
1200  write_host_file();
1201 }
1202 
1203 
1204 void
1205 YamlConfiguration::set_string(const char *path, std::string &s)
1206 {
1207  set_string(path, s.c_str());
1208 }
1209 
1210 void
1211 YamlConfiguration::set_floats(const char *path, std::vector<float> &f)
1212 {
1213  root_->set_list(path, f);
1214  host_root_->set_list(path, f);
1215  write_host_file();
1216 }
1217 
1218 void
1219 YamlConfiguration::set_uints(const char *path, std::vector<unsigned int> &u)
1220 {
1221  root_->set_list(path, u);
1222  host_root_->set_list(path, u);
1223  write_host_file();
1224 }
1225 
1226 void
1227 YamlConfiguration::set_ints(const char *path, std::vector<int> &i)
1228 {
1229  root_->set_list(path, i);
1230  host_root_->set_list(path, i);
1231  write_host_file();
1232 }
1233 
1234 void
1235 YamlConfiguration::set_bools(const char *path, std::vector<bool> &b)
1236 {
1237  root_->set_list(path, b);
1238  host_root_->set_list(path, b);
1239  write_host_file();
1240 }
1241 
1242 void
1243 YamlConfiguration::set_strings(const char *path, std::vector<std::string> &s)
1244 {
1245  root_->set_list(path, s);
1246  host_root_->set_list(path, s);
1247  write_host_file();
1248 }
1249 
1250 void
1251 YamlConfiguration::set_strings(const char *path, std::vector<const char *> &s)
1252 {
1253  root_->set_list(path, s);
1254  host_root_->set_list(path, s);
1255  write_host_file();
1256 }
1257 
1258 void
1259 YamlConfiguration::set_comment(const char *path, const char *comment)
1260 {
1261 }
1262 
1263 void
1264 YamlConfiguration::set_comment(const char *path, std::string &comment)
1265 {
1266 }
1267 
1268 void
1269 YamlConfiguration::erase(const char *path)
1270 {
1271  host_root_->erase(path);
1272  root_->erase(path);
1273  write_host_file();
1274 }
1275 
1276 void
1277 YamlConfiguration::set_default_float(const char *path, float f)
1278 {
1279  throw NotImplementedException("YamlConfiguration does not support default values");
1280 }
1281 
1282 void
1283 YamlConfiguration::set_default_uint(const char *path, unsigned int uint)
1284 {
1285  throw NotImplementedException("YamlConfiguration does not support default values");
1286 }
1287 
1288 void
1289 YamlConfiguration::set_default_int(const char *path, int i)
1290 {
1291  throw NotImplementedException("YamlConfiguration does not support default values");
1292 }
1293 
1294 void
1295 YamlConfiguration::set_default_bool(const char *path, bool b)
1296 {
1297  throw NotImplementedException("YamlConfiguration does not support default values");
1298 }
1299 
1300 void
1302  const char *s)
1303 {
1304  throw NotImplementedException("YamlConfiguration does not support default values");
1305 }
1306 
1307 void
1308 YamlConfiguration::set_default_string(const char *path, std::string &s)
1309 {
1310  set_default_string(path, s.c_str());
1311 }
1312 
1313 void
1314 YamlConfiguration::set_default_comment(const char *path, const char *comment)
1315 {
1316  throw NotImplementedException("YamlConfiguration does not support default values");
1317 }
1318 
1319 void
1320 YamlConfiguration::set_default_comment(const char *path, std::string &comment)
1321 {
1322  set_default_comment(path, comment.c_str());
1323 }
1324 
1325 
1326 void
1328 {
1329  throw NotImplementedException("YamlConfiguration does not support default values");
1330 }
1331 
1332 /** Lock the config.
1333  * No further changes or queries can be executed on the configuration and will block until
1334  * the config is unlocked.
1335  */
1336 void
1338 {
1339  mutex->lock();
1340 }
1341 
1342 
1343 /** Try to lock the config.
1344  * @see Configuration::lock()
1345  * @return true, if the lock has been aquired, false otherwise
1346  */
1347 bool
1349 {
1350  return mutex->try_lock();
1351 }
1352 
1353 /** Unlock the config.
1354  * Modifications and queries are possible again.
1355  */
1356 void
1358 {
1359  write_pending_mutex_->lock();
1360  if (write_pending_) {
1361  host_root_->emit(host_file_);
1362  write_pending_ = false;
1363  }
1364  write_pending_mutex_->unlock();
1365  mutex->unlock();
1366 }
1367 
1368 
1369 void
1371 {
1372 }
1373 
1374 
1377 {
1378  std::map<std::string, YamlConfigurationNode *> nodes;
1379  root_->enum_leafs(nodes);
1380  return new YamlValueIterator(nodes);
1381 }
1382 
1384 YamlConfiguration::search(const char *path)
1385 {
1386  std::string tmp_path = path;
1387  std::string::size_type tl = tmp_path.length();
1388  if ((tl > 0) && (tmp_path[tl - 1] == '/')) {
1389  tmp_path.resize(tl - 1);
1390  }
1391  try {
1392  YamlConfigurationNode *n = root_->find(tmp_path.c_str());
1393  std::map<std::string, YamlConfigurationNode *> nodes;
1394  n->enum_leafs(nodes, tmp_path);
1395  return new YamlValueIterator(nodes);
1396  } catch (Exception &e) {
1397  return new YamlValueIterator();
1398  }
1399 }
1400 
1401 
1402 /** Query node for a specific path.
1403  * @param path path to retrieve node for
1404  * @return node representing requested path query result, if the path only
1405  * consists of collection and path name returns the whole document.
1406  */
1407 YamlConfigurationNode *
1408 YamlConfiguration::query(const char *path) const
1409 {
1410  std::queue<std::string> pel_q = str_split_to_queue(path);
1411  return root_->find(pel_q);
1412 }
1413 
1414 
1415 } // end namespace fawkes
virtual void set_int(const char *path, int i)
Set new value in configuration of type int.
Definition: yaml.cpp:1180
virtual std::vector< int > get_ints() const
Get list of values from configuration which is of type int.
Definition: yaml.cpp:268
virtual bool is_float() const
Check if current value is a float.
Definition: yaml.cpp:125
virtual bool is_list() const
Check if a value is a list.
Definition: yaml.cpp:170
virtual std::string get_string() const
Get string value.
Definition: yaml.cpp:228
ValueIterator * search(const char *path)
Iterator with search results.
Definition: yaml.cpp:1384
virtual bool is_uint(const char *path)
Check if a value is of type unsigned int.
Definition: yaml.cpp:1090
virtual int get_int() const
Get int value.
Definition: yaml.cpp:210
virtual float get_float() const
Get float value.
Definition: yaml.cpp:192
ValueIterator * iterator()
Iterator for all values.
Definition: yaml.cpp:1376
virtual void set_comment(const char *path, std::string &comment)
Set new comment for existing value.
Definition: yaml.cpp:1264
virtual std::vector< float > get_floats() const
Get list of values from configuration which is of type float.
Definition: yaml.cpp:250
YamlConfiguration()
Constructor.
Definition: yaml.cpp:319
virtual void erase_default(const char *path)
Erase the given default value from the configuration.
Definition: yaml.cpp:1327
virtual void set_uint(const char *path, unsigned int uint)
Set new value in configuration of type unsigned int.
Definition: yaml.cpp:1172
virtual bool is_list(const char *path)
Check if a value is a list.
Definition: yaml.cpp:1123
virtual std::vector< unsigned int > get_uints(const char *path)
Get list of values from configuration which is of type unsigned int.
Definition: yaml.cpp:1041
Fawkes library namespace.
virtual void set_strings(const char *path, std::vector< std::string > &s)
Set new value in configuration of type string.
Definition: yaml.cpp:1243
Called method has not been implemented.
Definition: software.h:107
Mutex locking helper.
Definition: mutex_locker.h:33
Thrown if config could not be opened.
Definition: config.h:61
Thrown if a config entry could not be found.
Definition: config.h:48
virtual bool valid() const
Check if the current element is valid.
Definition: yaml.cpp:101
virtual void set_string(const char *path, std::string &s)
Set new value in configuration of type string.
Definition: yaml.cpp:1205
void lock()
Lock the config.
Definition: yaml.cpp:1337
virtual bool is_bool(const char *path)
Check if a value is of type bool.
Definition: yaml.cpp:1110
virtual bool is_uint() const
Check if current value is a unsigned int.
Definition: yaml.cpp:134
virtual void set_default_comment(const char *path, const char *comment)
Set new default comment for existing default configuration value.
Definition: yaml.cpp:1314
virtual bool is_int(const char *path)
Check if a value is of type int.
Definition: yaml.cpp:1104
virtual std::vector< std::string > get_strings(const char *path)
Get list of values from configuration which is of type string.
Definition: yaml.cpp:1060
virtual bool is_default(const char *path)
Check if a value was read from the default config.
Definition: yaml.cpp:1140
virtual bool is_float(const char *path)
Check if a value is of type float.
Definition: yaml.cpp:1084
virtual bool is_bool() const
Check if current value is a bool.
Definition: yaml.cpp:152
virtual std::vector< unsigned int > get_uints() const
Get list of values from configuration which is of type unsigned int.
Definition: yaml.cpp:259
static std::queue< std::string > str_split_to_queue(const std::string &s, char delim='/')
Split string by delimiter.
Definition: string_split.h:193
virtual std::string get_comment() const
Get comment of value.
Definition: yaml.cpp:296
virtual ValueIterator * get_value(const char *path)
Get value from configuration.
Definition: yaml.cpp:1147
virtual int get_int(const char *path)
Get value from configuration which is of type int.
Definition: yaml.cpp:1015
virtual void load(const char *file_path)
Load configuration.
Definition: yaml.cpp:427
virtual std::vector< int > get_ints(const char *path)
Get list of values from configuration which is of type int.
Definition: yaml.cpp:1048
static std::string abs_cfg_path(const std::string &path)
Create absolute config path.
Definition: yaml.cpp:656
void reset()
Reset pointer.
Definition: refptr.h:464
virtual std::vector< bool > get_bools() const
Get list of values from configuration which is of type bool.
Definition: yaml.cpp:277
static std::vector< T > get_list(YamlConfigurationNode *root, const char *path)
Retrieve value casted to given type T.
Definition: memory.cpp:130
virtual std::string get_string(const char *path)
Get value from configuration which is of type string.
Definition: yaml.cpp:1027
virtual unsigned int get_uint(const char *path)
Get value from configuration which is of type unsigned int.
Definition: yaml.cpp:1009
virtual const char * path() const
Path of value.
Definition: yaml.cpp:107
virtual std::string get_type(const char *path)
Get type of value at given path.
Definition: yaml.cpp:948
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual std::string get_as_string() const
Get value as string.
Definition: yaml.cpp:237
virtual size_t get_list_size() const
Get number of elements in list value.
Definition: yaml.cpp:180
virtual void set_bool(const char *path, bool b)
Set new value in configuration of type bool.
Definition: yaml.cpp:1188
void prepend(const char *format,...)
Prepend messages to the message list.
Definition: exception.cpp:322
virtual void set_default_uint(const char *path, unsigned int uint)
Set new default value in configuration of type unsigned int.
Definition: yaml.cpp:1283
void unlock()
Unlock the config.
Definition: yaml.cpp:1357
virtual bool get_bool() const
Get bool value.
Definition: yaml.cpp:219
virtual void set_bools(const char *path, std::vector< bool > &b)
Set new value in configuration of type bool.
Definition: yaml.cpp:1235
virtual ~YamlConfiguration()
Destructor.
Definition: yaml.cpp:398
static void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: liblogger.cpp:162
virtual void set_float(const char *path, float f)
Set new value in configuration of type float.
Definition: yaml.cpp:1164
virtual unsigned int get_uint() const
Get unsigned int value.
Definition: yaml.cpp:201
virtual void try_dump()
Try to dump configuration.
Definition: yaml.cpp:1370
bool try_lock()
Try to lock the config.
Definition: yaml.cpp:1348
virtual void set_floats(const char *path, std::vector< float > &f)
Set new value in configuration of type float.
Definition: yaml.cpp:1211
virtual bool next()
Check if there is another element and advance to this if possible.
Definition: yaml.cpp:89
void notify_handlers(const char *path, bool comment_changed=false)
Notify handlers for given path.
Definition: config.cpp:615
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:49
virtual std::string get_comment(const char *path)
Get comment of value at given path.
Definition: yaml.cpp:959
virtual bool is_string(const char *path)
Check if a value is of type string.
Definition: yaml.cpp:1116
virtual bool is_default() const
Check if current value was read from the default config.
Definition: yaml.cpp:302
static T get_value_as(YamlConfigurationNode *root, const char *path)
Retrieve value casted to given type T.
Definition: memory.cpp:112
virtual bool exists(const char *path)
Check if a given value exists.
Definition: yaml.cpp:936
virtual void set_default_string(const char *path, std::string &s)
Set new default value in configuration of type string.
Definition: yaml.cpp:1308
virtual void set_ints(const char *path, std::vector< int > &i)
Set new value in configuration of type int.
Definition: yaml.cpp:1227
static std::vector< std::string > str_split(const std::string &s, char delim='/')
Split string by delimiter.
Definition: string_split.h:40
Iterator interface to iterate over config values.
Definition: config.h:72
virtual std::vector< std::string > get_strings() const
Get list of values from configuration which is of type string.
Definition: yaml.cpp:286
virtual bool get_bool(const char *path)
Get value from configuration which is of type bool.
Definition: yaml.cpp:1021
virtual void set_uints(const char *path, std::vector< unsigned int > &uint)
Set new value in configuration of type unsigned int.
Definition: yaml.cpp:1219
virtual void erase(const char *path)
Erase the given value from the configuration.
Definition: yaml.cpp:1269
virtual void set_default_bool(const char *path, bool b)
Set new default value in configuration of type bool.
Definition: yaml.cpp:1295
virtual void set_default_float(const char *path, float f)
Set new default value in configuration of type float.
Definition: yaml.cpp:1277
virtual void set_default_int(const char *path, int i)
Set new default value in configuration of type int.
Definition: yaml.cpp:1289
virtual std::string get_default_comment(const char *path)
Get comment of value at given path.
Definition: yaml.cpp:1134
virtual std::vector< float > get_floats(const char *path)
Get list of values from configuration which is of type float.
Definition: yaml.cpp:1034
FileAlterationMonitor thread wrapper.
Definition: fam_thread.h:35
virtual bool is_string() const
Check if current value is a string.
Definition: yaml.cpp:161
virtual void fam_event(const char *filename, unsigned int mask)
Event has been raised.
Definition: yaml.cpp:603
virtual float get_float(const char *path)
Get value from configuration which is of type float.
Definition: yaml.cpp:1003
virtual bool is_int() const
Check if current value is a int.
Definition: yaml.cpp:143
Mutex mutual exclusion lock.
Definition: mutex.h:32
virtual void copy(Configuration *copyconf)
Copies all values from the given configuration.
Definition: yaml.cpp:930
static bool is_type(YamlConfigurationNode *root, const char *path)
Check if value is of given type T.
Definition: memory.cpp:211
virtual std::vector< bool > get_bools(const char *path)
Get list of values from configuration which is of type bool.
Definition: yaml.cpp:1054
Interface for configuration handling.
Definition: config.h:67
virtual const char * type() const
Type of value.
Definition: yaml.cpp:116