13#include <boost/algorithm/string.hpp>
15#include "sparta/utils/Utils.hpp"
72 Node* parent_ =
nullptr;
79 uint32_t write_count_;
80 mutable uint32_t read_count_ = 0;
81 std::map<std::string, std::any> user_data_;
84 class UserDataPrinterBase
87 virtual ~UserDataPrinterBase() =
default;
88 virtual void print(
const std::string& name, std::any user_data, std::ostream& o, uint32_t indent)
const = 0;
93 class UserDataPrinter :
public UserDataPrinterBase
96 void print(
const std::string& name, std::any user_data, std::ostream& o, uint32_t indent)
const override
98 const T& ud = std::any_cast<const T&>(user_data);
99 for (uint32_t i = 0; i < indent; ++i) {
103 print_(o, ud, indent);
108 template <
typename Value>
109 typename std::enable_if<MetaStruct::is_any_pointer<Value>::value,
void>::type
110 print_(std::ostream& o,
const Value& val, uint32_t indent)
const {
115 print_(o, *val, indent);
119 template <
typename Value>
120 typename std::enable_if<!MetaStruct::is_any_pointer<Value>::value,
void>::type
121 print_(std::ostream& o,
const Value& val, uint32_t indent)
const {
122 if constexpr (std::is_same_v<Value, TreeNode::ExtensionsBase>) {
123 if (
auto ps = val.getParameters()) {
124 o << val.getClassName() <<
" extension with parameters:\n";
125 const std::string s = ps->dumpList();
126 std::vector<std::string> lines;
127 boost::split(lines, s, boost::is_any_of(
"\n"));
128 for (
auto & line : lines) {
129 for (uint32_t i = 0; i < indent+2; ++i) {
135 o <<
"extension without parameters";
144 std::unordered_map<std::string, std::unique_ptr<UserDataPrinterBase>> user_data_printers_;
150 uint32_t required_ = 0;
159 Node(
Node* parent,
const std::string& name,
160 const std::string& value,
const std::string& origin) :
203 has_value_(n.has_value_),
204 write_count_(n.write_count_),
205 read_count_(n.read_count_)
207 for(
auto& x : n.children_){
208 children_.emplace_back(new Node(this, *x.get()));
223 has_value_ = n.has_value_;
224 write_count_ =
static_cast<decltype(write_count_)
>(has_value_);
226 for(
auto& x : n.children_){
227 children_.emplace_back(new Node(this, *x.get()));
237 void dump(std::ostream& o)
const {
238 o <<
"<VPT Node: \"" << name_ <<
"\" children:" << children_.size()
239 <<
" writes:" << write_count_ <<
" reads:" << read_count_ <<
" required:" << required_ <<
">";
245 const std::string&
getName()
const {
return name_; }
273 Node const * p =
this;
299 std::stack<const std::string*> names;
300 Node const * n =
this;
301 while(n && n->
getName().size() > 0){
306 std::stringstream ss;
307 if(names.size() > 0){
310 while(names.size() > 0){
311 ss <<
'.' << *names.top();
322 return name_.size() == 0;
389 template <typename T, typename=typename std::enable_if<!std::is_convertible<T, std::string>::value>::type>
397 template <typename T, typename=typename std::enable_if<std::is_convertible<T, std::string>::value>::type>
405 operator std::string ()
const {
413 template <
typename T>
414 operator T ()
const {
422 template <
typename T>
436 static bool matches(
const std::string& pattern,
const std::string& other) {
439 return std::regex_match(other, what, expr);
451 throw SpartaException(
"Cannot call ParameterTree::Node::getChild with a name that is a search pattern: \"")
452 << name <<
"\". addChild must be used instead";
456 auto itr = children_.rbegin();
457 for(; itr != children_.rend(); ++itr){
458 if(
matches((*itr)->getName(), name)){
477 if(path.size() == 0){
482 std::string immediate_child_name;
484 if(immediate_child_name.size() == 0){
498 child =
addChild(immediate_child_name, required);
501 if(name_pos == std::string::npos){
505 const std::string remainder = path.substr(name_pos);
506 return child->
create(remainder, required);
518 if(children_.size() == 0){
539 auto itr = children_.rbegin();
540 for(; itr != children_.rend(); ++itr){
541 if((*itr)->getName() == name){
547 if(name_has_wildcard){
553 }
else if(
matches(name, (*itr)->getName())){
564 }
else if(
matches((*itr)->getName(), name)){
580 "Cannot add a child to a virtual parameter tree node \"" << name_
581 <<
"\" since it already has a value: \"" << value_ <<
"\"");
582 children_.emplace_back(
new Node(
this, name));
584 children_.back()->incRequired();
586 return (children_.back().get());
599 "Node \"" << name_ <<
"\" has no child named \"" << name <<
"\"");
625 void setValue(
const std::string& val,
bool required=
true,
const std::string& origin=
"") {
652 for(
auto & n : children_){
663 return parent_->release_(
this);
679 bool set(
const std::string& path,
const std::string& val,
bool required,
const std::string& origin=
"") {
685 std::string full_path =
getPath();
686 if(full_path.size() > 0 && path.size() > 0){
690 return getOwner()->
set(full_path, val, required, origin);
731 std::vector<Node*> children;
732 for(
auto & n : children_){
733 children.push_back(n.get());
742 std::vector<const Node*> children;
743 for(
auto & n : children_){
744 children.push_back(n.get());
753 const std::string & name,
754 std::vector<Node*> & matching_nodes)
757 matching_nodes.emplace_back(
this);
763 child->recursFindPTreeNodesNamed(name, matching_nodes);
771 const std::string & name,
772 std::vector<const Node*> & matching_nodes)
const
775 matching_nodes.emplace_back(
this);
781 child->recursFindPTreeNodesNamed(name, matching_nodes);
789 if (children_.empty()) {
792 for (
const auto & child : children_) {
793 child->recurseVisitLeaves(callback);
800 void recursePrint(std::ostream& o, uint32_t indent=0,
bool print_user_data=
true)
const {
801 for(uint32_t i=0; i<indent; ++i){
806 o <<
" = \"" << value_ <<
"\" (read " << read_count_ <<
", written " << write_count_
807 <<
", required " << required_ <<
", origin '" <<
getOrigin() <<
"')";
813 for(
auto & n : children_){
814 n->recursePrint(o, indent+2, print_user_data);
822 if (user_data_.empty()) {
826 for(uint32_t i=0; i<indent; ++i){
830 o <<
"User data (" <<
getPath() <<
"):\n";
831 for (
const auto & [ud_name, ud_printer] : user_data_printers_) {
832 std::any ud = user_data_.at(ud_name);
833 ud_printer->print(ud_name, ud, o, indent+2);
850 sparta_assert(ot,
"Cannot append a null virtual parameter tree");
853 const bool required =
false;
855 child->recursAppendTree_(ot);
858 recursAppendTree_(ot);
866 template <
typename T>
868 static_assert(std::is_copy_constructible<T>::value,
"std::any only works with copyable types");
869 user_data_[name] = user_data;
870 user_data_printers_[name] = std::make_unique<UserDataPrinter<T>>();
877 template <
typename T>
879 static_assert(std::is_copy_constructible<T>::value,
"std::any only works with copyable types");
880 user_data_[name] = std::move(user_data);
881 user_data_printers_[name] = std::make_unique<UserDataPrinter<T>>();
887 template <
typename T>
889 constexpr bool must_exist =
true;
896 template <
typename T>
898 constexpr bool must_exist =
true;
905 template <
typename T>
906 const T *
tryGetUserData(
const std::string & name,
bool must_exist =
false)
const {
907 auto it = user_data_.find(name);
908 if (it == user_data_.end()) {
910 throw SpartaException(
"User data '") << name <<
"' does not exist for node '"
915 return &std::any_cast<const T&>(it->second);
921 template <
typename T>
923 auto it = user_data_.find(name);
924 if (it == user_data_.end()) {
926 throw SpartaException(
"User data '") << name <<
"' does not exist for node '"
931 return &std::any_cast<T&>(it->second);
938 std::map<
const Node*, std::map<std::string, const TreeNode::ExtensionsBase*>> & map)
const
941 if (
auto ext =
tryGetUserData<std::shared_ptr<TreeNode::ExtensionsBase>>(key)) {
942 map[
this][key] = ext->get();
947 child->recurseGetAllNodeExtensions(map);
955 std::set<std::string> keys;
956 for (
const auto & [key, _] : user_data_) {
966 user_data_printers_.erase(name);
967 if (user_data_.count(name)) {
968 user_data_.erase(name);
978 user_data_printers_.clear();
979 auto sz = user_data_.size();
989 ChildVector::const_reverse_iterator itr_;
1000 return itr_ == rhp.itr_;
1004 return itr_ != rhp.itr_;
1007 void operator++(
int) {++itr_;}
1009 void operator++() {++itr_;}
1011 bool matches(
const std::string& other)
const {
1015 const Node* get()
const {
1023 const Node* operator->()
const {
1046 void recursAppendTree_(
const Node* ot) {
1053 for(
const auto & [ud_name, ud_value] : ot->user_data_){
1054 user_data_[ud_name] = ud_value;
1059 Node* c =
create(child->getName(), child->getRequiredCount() > 0);
1060 c->recursAppendTree_(child);
1064 std::unique_ptr<Node> release_(
Node *node) {
1065 std::unique_ptr<Node> rtn;
1066 auto it = std::find_if(children_.begin(), children_.end(),
1067 [node] (
const auto & child) ->
bool {
1068 return (child.get() == node);
1070 if (it != children_.end()) {
1071 rtn = std::move(*it);
1072 children_.erase(it);
1082 root_(new
Node(nullptr, this))
1086 root_(new Node(nullptr, this))
1088 root_->appendTree(rhp.getRoot());
1109 root_.reset(
new Node(
nullptr,
this));
1126 bool set(
const std::string& path,
const std::string& value,
bool required,
const std::string& origin=
"") {
1131 n->
setValue(value, required, origin);
1151 if(path.size() == 0){
1155 return getRoot()->
create(path, required);
1172 throw SpartaException(
"Unable to find parameter in tree: \"") << path <<
"\"";
1191 bool hasValue(
const std::string& path,
const bool must_be_leaf =
true)
const {
1192 const Node* n = tryGet_(path, must_be_leaf);
1193 return n !=
nullptr && n->
hasValue();
1202 bool exists(
const std::string& path,
const bool must_be_leaf =
true)
const {
1203 return tryGet_(path, must_be_leaf) !=
nullptr;
1218 return recursCountUnreadValueNodes_<const Node>(root_.get(), nodes);
1233 return recursCountUnreadValueNodes_<Node>(root_.get(), nodes);
1241 const Node*
tryGet(
const std::string& path,
const bool must_be_leaf =
true)
const {
1242 return tryGet_(path, must_be_leaf);
1250 Node*
tryGet(
const std::string& path,
const bool must_be_leaf =
true) {
1251 return tryGet_(path, must_be_leaf);
1261 if(path.size() == 0){
1262 return root_->getRequiredCount() > 0;
1265 std::string immediate_child_name;
1266 size_t name_pos = 0;
1269 if(immediate_child_name.size() == 0){
1272 <<
" is invalid because it contains an empty name (between two '.' "
1273 "characters). Parents cannot currently be refrenced in the parameter tree";
1276 bool match_found =
false;
1277 const bool required = recursGetIsRequired_(root_.get(), path, immediate_child_name, name_pos, match_found);
1279 "Asked ParameterTree if path \"" << path <<
"\" is required but no "
1280 "matching node was found in the ParameterTree");
1290 Node * node = tryGet_(path,
false);
1291 if(
nullptr != node) {
1307 if(path.size() == 0){
1308 return root_->hasValue() && root_->getReadCount() > 0;
1311 std::string immediate_child_name;
1312 size_t name_pos = 0;
1315 if(immediate_child_name.size() == 0){
1318 <<
" is invalid because it contains an empty name (between two '.' "
1319 "characters). Parents cannot currently be refrenced in the parameter tree";
1322 return recursIsRead_(root_.get(), path, immediate_child_name, name_pos);
1325 Node
const * getRoot()
const {
return root_.get(); }
1327 Node * getRoot() {
return root_.get(); }
1337 root_->appendTree(rhp.getRoot());
1344 root_->recurseVisitLeaves(callback);
1351 root_->recursePrint(o, 0, print_user_data);
1357 std::map<const Node*, std::map<std::string, const TreeNode::ExtensionsBase*>>
1360 std::map<const Node*, std::map<std::string, const TreeNode::ExtensionsBase*>> all_ext_map;
1361 root_->recurseGetAllNodeExtensions(all_ext_map);
1371 const Node* tryGet_(
const std::string& path,
const bool must_be_leaf =
true)
const {
1372 if(path.size() == 0){
1376 std::string immediate_child_name;
1377 size_t name_pos = 0;
1380 if(immediate_child_name.size() == 0){
1382 throw SpartaException(
"Parameter ") << path
1383 <<
" is invalid because it contains an empty name (between two '.' "
1384 "characters). Parents cannot currently be refrenced in the parameter tree";
1387 return recursTryGet_<const Node>(
static_cast<const Node*
>(root_.get()), path,
1388 immediate_child_name, name_pos, must_be_leaf);
1395 Node* tryGet_(
const std::string& path,
const bool must_be_leaf =
true) {
1396 if(path.size() == 0){
1400 std::string immediate_child_name;
1401 size_t name_pos = 0;
1404 if(immediate_child_name.size() == 0){
1406 throw SpartaException(
"Parameter ") << path
1407 <<
" is invalid because it contains an empty name (between two '.' "
1408 "characters). Parents cannot currently be refrenced in the parameter tree";
1411 return recursTryGet_(root_.get(), path,
1412 immediate_child_name, name_pos, must_be_leaf);
1415 template<
typename NodeT>
1416 static NodeT* recursTryGet_(NodeT* node,
const std::string& path,
1417 const std::string& match_name,
1418 size_t name_pos,
const bool must_be_leaf)
1421 "Cannot attempt to read a node with a path containing wildcard "
1422 "characters. A specific node path must be used. Error in \""
1423 << match_name <<
"\" from \"" << path <<
"\"");
1425 if(name_pos == std::string::npos){
1427 NodeT* result =
nullptr;
1428 NodeT* backup =
nullptr;
1429 auto itr = node->getMatcherBegin();
1430 for(; itr != node->getMatcherEnd(); ++itr){
1431 if(itr.matches(match_name)){
1432 if(itr.get()->hasValue() || !must_be_leaf){
1433 itr.get()->incrementReadCount();
1449 std::string immediate_child_name;
1452 if(immediate_child_name.size() == 0){
1454 throw SpartaException(
"Parameter ") << path
1455 <<
" is invalid because it contains an empty name (between two '.' "
1456 "characters). Parents cannot currently be refrenced in the parameter tree";
1459 NodeT* result =
nullptr;
1460 auto itr = node->getMatcherBegin();
1461 for(; itr != node->getMatcherEnd(); ++itr){
1462 if(itr.matches(match_name)){
1463 NodeT* match = recursTryGet_(itr.get(), path, immediate_child_name, name_pos, must_be_leaf);
1464 if(match && (match->hasValue() || !must_be_leaf)) {
1465 match->incrementReadCount();
1466 if(result ==
nullptr){
1479 bool recursGetIsRequired_(
const Node* node,
1480 const std::string& path,
1481 const std::string& match_name,
1483 bool& found_match)
const
1485 found_match =
false;
1487 if(name_pos == std::string::npos){
1489 auto itr = node->getMatcherBegin();
1490 for(; itr != node->getMatcherEnd(); ++itr){
1492 ? itr->getName() == match_name
1493 : itr.matches(match_name))
1496 return itr.get()->getRequiredCount() > 0;
1504 std::string immediate_child_name;
1507 if(immediate_child_name.size() == 0){
1509 throw SpartaException(
"Parameter ") << path
1510 <<
" is invalid because it contains an empty name (between two '.' "
1511 "characters). Parents cannot currently be refrenced in the parameter tree";
1514 auto itr = node->getMatcherBegin();
1515 for(; itr != node->getMatcherEnd(); ++itr){
1516 if(itr.matches(match_name)){
1517 const bool required = recursGetIsRequired_(itr.get(), path, immediate_child_name, name_pos, found_match);
1532 template<
class NodeT>
1533 static uint32_t recursCountUnreadValueNodes_(NodeT* n, std::vector<NodeT*> * nodes) {
1535 if(n->hasValue() && (n->getReadCount() == 0)){
1538 nodes->push_back(n);
1541 auto itr = n->getMatcherBegin();
1542 for(; itr != n->getMatcherEnd(); ++itr){
1543 count += recursCountUnreadValueNodes_<NodeT>(itr.get(), nodes);
1551 bool recursIsRead_(
const Node* node,
1552 const std::string& path,
1553 const std::string& match_name,
1554 size_t name_pos)
const
1557 "Cannot attempt to read a node with a path containing wildcard "
1558 "characters. A specific node path must be used. Error in \""
1559 << match_name <<
"\" from \"" << path <<
"\"");
1561 if(name_pos == std::string::npos){
1562 auto itr = node->getMatcherBegin();
1563 for(; itr != node->getMatcherEnd(); ++itr){
1564 if(itr.matches(match_name)){
1565 if(itr.get()->hasValue() && itr.get()->getReadCount() > 0){
1574 std::string immediate_child_name;
1576 if(immediate_child_name.size() == 0){
1578 throw SpartaException(
"Parameter ") << path
1579 <<
" is invalid because it contains an empty name (between two '.' "
1580 "characters). Parents cannot currently be refrenced in the parameter tree";
1583 auto itr = node->getMatcherBegin();
1584 for(; itr != node->getMatcherEnd(); ++itr){
1585 if(itr.matches(match_name)){
1586 bool read = recursIsRead_(itr.get(), path, immediate_child_name, name_pos);
1598 std::unique_ptr<Node> root_;
1602 inline std::ostream&
operator<<(std::ostream& o,
const ParameterTree::Node& n) {
1607 inline std::ostream&
operator<<(std::ostream& o,
const ParameterTree::Node* n) {
1609 o <<
"<null ParameterTree::Node>";
String-to-value helpers and string formatting helpers.
Individual Parameter interface base class, container class, and global helpers methods.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Basic Node framework in sparta device tree composite pattern.
Node containing a Parameter and value to apply. Can be used to describes a value extracted from the t...
const std::string & peekValue() const
Gets the value of this object as a string.
Node(Node *parent, const std::string &name)
Value-less constructor.
uint32_t getReadCount() const
Gets the number of times this node has been accessed to be read (i.e. with get/tryGet)
const std::string & getValue() const
Gets the value of this object as a string.
std::unique_ptr< Node > release()
Release this node and its children from the tree.
T getAs() const
Gets the value in this object.
Node * getPriorityChildMatch(const std::string &name) const
Attempts to get an immediate child with an exact match for a given name or pattern string....
std::string getPath() const
Gets the path to this node including the root node.
Node(Node *parent, ParameterTree *tree)
Root node constructor. Constructs node pointing to a new tree having no name. Normal nodes to not hav...
void setUserData(const std::string &name, const T &user_data)
Set any named user data (std::any)
MatchIterator getMatcherBegin() const
Get most recent child added.
static bool matches(const std::string &pattern, const std::string &other)
Does a string, name, interpreted as a sparta TreeNode pattern, match another string interpreted as a ...
std::set< std::string > getUserDataKeys() const
Get all user data keys (names).
Node()=delete
Not default-constructable.
Node * getRoot()
Gets the parent of this node.
void recursFindPTreeNodesNamed(const std::string &name, std::vector< const Node * > &matching_nodes) const
Recursively find all nodes that have a given name.
void recurseVisitLeaves(std::function< void(const Node *)> callback) const
Apply the given callback to all leaf nodes.
Node * addChild(const std::string &name, bool required)
void incrementReadCount() const
Increment the read count of this node.
bool operator==(const T &rhp) const
Equality test. Attempts to lexically cast underlying string to requested data-type.
T & getUserData(const std::string &name)
Get any named user data (std::any_cast)
bool isRoot() const
Is this a root node.
size_t clearUserData()
Clear all user data. Returns the number of elements removed.
void resetReadCount() const
Reset the read count back to zero.
Node * create(const std::string &path, bool required)
Get a child for setting a parameter, creating it if needed.
Node & operator[](const std::string &name) const
Gets a child of this node by its name.
Node * getChild(const std::string &name) const
Gets the most recently created child of this node by a concrete child name.
const std::string & getAs() const
getAs template instance for string types (e.g. char[], const char*, std::string)
bool hasValue() const
Does this node have a value written to it which can be accessed through:
const std::string & getName() const
Gets the name of this node.
std::vector< const Node * > getChildren() const
Gets vector of pointers to children of this node.
void dump(std::ostream &o) const
Dumps the content of this node to an ostream on a single line. Does not recurs into children.
ParameterTree * getOwner()
Gets the ParameterTree object that owns this node.
const T * tryGetUserData(const std::string &name, bool must_exist=false) const
Try to get any named user data (std::any_cast)
Node const * getParent() const
Gets the parent of this node.
void recursePrint(std::ostream &o, uint32_t indent=0, bool print_user_data=true) const
Recursively print.
void incRequired()
Increment the required count.
T * tryGetUserData(const std::string &name, bool must_exist=false)
Try to get any named user data (std::any_cast)
bool isRequired() const
Return true if this parameter node is required to exist by the client by 1 or more "set"-ers using th...
std::vector< std::unique_ptr< Node > > ChildVector
Vector of children owned by this node.
std::vector< Node * > getChildren()
Gets vector of pointers to children of this node.
bool set(const std::string &path, const std::string &val, bool required, const std::string &origin="")
Set the string value of a child of this node. Note that this may not affect this node directly becaus...
void appendTree(const Node *ot)
Appends a tree as a child of this node.
const std::string & getOrigin() const
Gets the origin associated with the value at this node.
void setUserData(const std::string &name, T &&user_data)
Set any named user data (std::any)
void setValue(const std::string &val, bool required=true, const std::string &origin="")
Set a value on this node directly.
Node * getParent()
Gets the parent of this node.
uint32_t getRequiredCount() const
Returns the number of times this node has been flagged as required.
void recurseGetAllNodeExtensions(std::map< const Node *, std::map< std::string, const TreeNode::ExtensionsBase * > > &map) const
Get a mapping from Nodes to their extensions recursively.
void printUserData(std::ostream &o, uint32_t indent=0) const
Pretty-print all user data for this node, if any.
Node const * getRoot() const
Gets the parent of this node.
MatchIterator getMatcherEnd() const
Get end of child match iterator (past oldest child added)
bool clearUserData(const std::string &name)
Clear named user data. Returns true if removed, false if not found.
Node & operator=(const Node &n)
Parent-preserving deep-copy assignment operator.
const T & getUserData(const std::string &name) const
Get any named user data (std::any_cast)
void unrequire()
Clear the required count. This is necessary if a parameter is flagged as deprecated or removed in a c...
void recursFindPTreeNodesNamed(const std::string &name, std::vector< Node * > &matching_nodes)
Recursively find all nodes that have a given name.
Node(Node *parent, const Node &n)
Deep-Copy constructor.
const ParameterTree * getOwner() const
Gets the ParameterTree object that owns this node.
Virtual Parameter Tree. This represents a tree of parameters read from some source but does not neces...
Node * create(const std::string &path, bool required=false)
Add a node to the tree, with proper priority.
bool set(const std::string &path, const std::string &value, bool required, const std::string &origin="")
Add a parameter to the tree, replacing any existing parameter.
const Node * tryGet(const std::string &path, const bool must_be_leaf=true) const
Try to get a node if it exists. Returns nullptr it it does not.
bool exists(const std::string &path, const bool must_be_leaf=true) const
Try to check if a node exists.
Node * tryGet(const std::string &path, const bool must_be_leaf=true)
tryGet non-const version
bool unrequire(const std::string &path)
Unrequire a node in the tree.
bool hasValue(const std::string &path, const bool must_be_leaf=true) const
Try to check if a node has value.
uint32_t getUnreadValueNodes(std::vector< Node * > *nodes)
Counts the number of values attached to the parameter tree which have values but have not been read....
virtual ~ParameterTree()
Destructor.
void visitLeaves(std::function< void(const Node *)> callback) const
Apply the given callback to all leaf nodes.
void recursePrint(std::ostream &o, bool print_user_data=true) const
Recursively print.
bool isRequired(const std::string &path) const
Recursively find first leaf node matching this pattern and decide if any node matching that node's pa...
ParameterTree()
Default Constructor.
void clear()
Clear all content from this tree.
uint32_t getUnreadValueNodes(std::vector< const Node * > *nodes) const
Counts the number of values attached to the parameter tree which have values but have not been read....
bool isRead(const std::string &path) const
Has a node with a given path been read.
const Node & operator[](const std::string &name) const
Gets a node form the parameter tree.
const Node & get(const std::string &path) const
Gets a node from the parameter tree while respecting parameter application order. In other words,...
void merge(const ParameterTree &rhp)
Merge this tree with another by applying all of its parameters to this tree. Parameters in the right ...
std::map< const Node *, std::map< std::string, const TreeNode::ExtensionsBase * > > getAllNodeExtensions() const
Get a mapping from Nodes to their extensions.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
static std::string getNextName(const std::string &name, size_t &pos)
Gets the next name between two '.' chars in a string starting at pos.
static bool hasWildcardCharacters(const std::string &name)
Determines if a given node name has any wildcard characters which will be substituted in createSearch...
static std::string createSearchRegexPattern(const std::string &pat)
Compute a regex pattern for a node child path containing any number of wildcard characters (not a dot...
Macros for handling exponential backoff.
T lexicalCast(const std::string &str, uint32_t base=10)
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo