@@ -55,7 +55,7 @@ void PropertyTree::mergeConfig(const YAML::Node& config, bool allow_extra_proper
5555 const auto & key = it->first .as <std::string>();
5656 if (children_.count (key) == 0 )
5757 {
58- auto & extra_node = children_[ key] ;
58+ auto & extra_node = get ( key) ;
5959 extra_node.setAttribute (EXTRA_KEY, YAML::Node (true ));
6060 extra_node.mergeConfig (it->second , allow_extra_properties);
6161 }
@@ -71,10 +71,12 @@ void PropertyTree::mergeConfig(const YAML::Node& config, bool allow_extra_proper
7171 elem_schema = w->second ;
7272
7373 children_.clear ();
74+ keys_.clear ();
7475 int idx = 0 ;
7576 for (const auto & elt : config)
7677 {
7778 std::string key = std::to_string (idx++);
79+ keys_.push_back (key);
7880 children_[key] = elem_schema;
7981 children_[key].mergeConfig (elt, allow_extra_properties);
8082 }
@@ -110,10 +112,22 @@ void PropertyTree::validate(bool allow_extra_properties) const
110112 vfn (*this );
111113}
112114
113- // / Add a custom validator for this node
114115void PropertyTree::addValidator (ValidatorFn fn) { validators_.push_back (std::move (fn)); }
115116
116- PropertyTree& PropertyTree::get (std::string_view key) { return children_[std::string (key)]; }
117+ PropertyTree& PropertyTree::get (std::string_view key)
118+ {
119+ auto k = std::string (key);
120+ auto it = children_.find (k);
121+ if (it == children_.end ())
122+ {
123+ // first time insertion
124+ keys_.push_back (k);
125+ // default-construct in map
126+ it = children_.emplace (k, PropertyTree{}).first ;
127+ }
128+ return it->second ;
129+ }
130+
117131const PropertyTree& PropertyTree::get (std::string_view key) const { return children_.at (std::string (key)); }
118132
119133const PropertyTree* PropertyTree::find (std::string_view key) const
@@ -129,14 +143,7 @@ bool PropertyTree::isNull() const { return value_.IsNull(); }
129143
130144bool PropertyTree::isContainer () const { return !children_.empty (); }
131145
132- std::vector<std::string> PropertyTree::keys () const
133- {
134- std::vector<std::string> res;
135- res.reserve (children_.size ());
136- for (const auto & pair : children_)
137- res.push_back (pair.first );
138- return res;
139- }
146+ std::vector<std::string> PropertyTree::keys () const { return keys_; }
140147
141148void PropertyTree::setAttribute (std::string_view name, const YAML::Node& attr)
142149{
@@ -318,14 +325,19 @@ YAML::Node PropertyTree::toYAML(bool exclude_attributes) const
318325
319326 node[ATTRIBUTES_KEY] = attr_node;
320327 }
328+
329+ if (keys_.size () != children_.size ())
330+ throw std::runtime_error (" PropertyTree, keys_ and children_ are not the same size" );
331+
321332 // emit children
322- for (const auto & pair : children_ )
333+ for (const auto & key : keys_ )
323334 {
335+ const PropertyTree& child = children_.at (key);
324336 // If the property is not required and is null then skip when excluding attributes
325- if (exclude_attributes && !pair. second . isRequired () && pair. second .isNull ())
337+ if (exclude_attributes && !child. isRequired () && child .isNull ())
326338 continue ;
327339
328- node[pair. first ] = pair. second .toYAML (exclude_attributes);
340+ node[key ] = child .toYAML (exclude_attributes);
329341 }
330342
331343 // if leaf (no children) but value present, emit under 'value'
0 commit comments