24 #include <boost/property_tree/ptree.hpp>
25 #include <boost/xpressive/xpressive.hpp>
35 const string ARRAY_SUFFIX =
"_array";
45 list<pair<string, string>> FlattenArray(
const ptree& pt,
const string& elementsKey,
const string& path)
48 return list<pair<string, string>>({make_pair(path, pt.data().c_str())});
50 list<pair<string, string>> entries;
52 for (ptree::const_iterator it = pt.begin(); it != pt.end(); it++) {
53 const string& key = it->first;
55 if (key == elementsKey) {
56 newPath = path +
"[" + to_string(index++) +
"]";
58 newPath = path ==
"" ? key : path +
"." + key;
60 entries.splice(entries.end(), PTreeUtils::Flatten(it->second,
true, newPath));
68 void PTreeUtils::CopyNonExistingChildren(ptree
const& from, ptree& into, set<string>
const& ignore)
70 for (ptree::value_type
const& v : from) {
71 if (ignore.find(v.first) != ignore.end()) {
76 ptree & child = into.get_child(v.first);
78 CopyNonExistingChildren(v.second, child, ignore);
80 catch (ptree_bad_path&) {
82 into.put_child(v.first, v.second);
87 void PTreeUtils::CopyStructure(ptree
const& from, ptree& into,
string const& fill_value, set<string>
const& ignore)
89 for (ptree::value_type
const& v : from) {
90 if (ignore.find(v.first) != ignore.end()) {
94 ptree & child = into.get_child(v.first);
96 CopyStructure(v.second, child, fill_value, ignore);
98 catch (ptree_bad_path&) {
99 if (v.second.empty()) {
101 into.put_child(v.first, ptree(fill_value));
104 auto& inserted = into.put_child(v.first, ptree());
105 CopyStructure(v.second, inserted, fill_value, ignore);
111 void PTreeUtils::FillPTree(ptree& pt1,
const ptree& pt2)
113 assert(pt1.size() == pt2.size() &&
"The ptrees don't have the same structure.");
114 if (pt1.size() == 0) {
115 if (pt1.data() ==
"") {
116 pt1.data() = pt2.data();
119 ptree::iterator it1 = pt1.begin();
120 ptree::const_iterator it2 = pt2.begin();
121 while (it1 != pt1.end()) {
122 assert(it1->first == it2->first &&
"The ptrees don't have the same structure.");
123 FillPTree(it1->second, it2->second);
130 list<pair<string, string>> PTreeUtils::Flatten(
const ptree& pt,
bool indexedArray,
const string& path)
132 if (pt.size() == 0) {
133 return list<pair<string, string>>({make_pair(path, pt.data().c_str())});
135 list<pair<string, string>> entries;
136 for (ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) {
137 const string& key = it->first;
138 string newPath = (path ==
"" ? key : path +
"." + key);
139 if (indexedArray && key.length() > ARRAY_SUFFIX.length()
140 && key.compare(key.length() - ARRAY_SUFFIX.length(),
141 ARRAY_SUFFIX.length(), ARRAY_SUFFIX) == 0) {
142 entries.splice(entries.end(), FlattenArray(it->second,
143 key.substr(0, key.length() - ARRAY_SUFFIX.length()), newPath));
145 entries.splice(entries.end(), Flatten(it->second, indexedArray, newPath));
152 const ptree& PTreeUtils::GetIndexedChild(
const ptree& pt,
const string& path)
157 string pathElement = path;
160 size_t separatorIndex = path.find(
'.');
161 if (separatorIndex != string::npos) {
162 pathElement = path.substr(0, separatorIndex);
163 newPath = path.substr(separatorIndex + 1);
165 assert(pathElement !=
"" &&
"There's no element after the separator.");
169 const boost::xpressive::sregex match_indexed
170 = boost::xpressive::sregex::compile(
"(.+)_array\\[(\\d+)\\]");
171 boost::xpressive::smatch match;
172 if (boost::xpressive::regex_match(pathElement, match, match_indexed)) {
173 string arrayElementKey = match[1];
174 const ptree& subPtree = pt.get_child(arrayElementKey + ARRAY_SUFFIX);
175 unsigned int index = FromString<unsigned int>(match[2]);
176 for (
const auto& entry : subPtree) {
177 if (entry.first == arrayElementKey) {
179 return GetIndexedChild(entry.second, newPath);
186 throw ptree_bad_path(
"No such node", boost::property_tree::path(pathElement));
188 return GetIndexedChild(pt.get_child(pathElement), newPath);
193 void PTreeUtils::PutIndexedChild(ptree& pt,
const string& path,
const ptree& child)
198 string pathElement = path;
201 size_t separatorIndex = path.find(
'.');
202 if (separatorIndex != string::npos) {
203 pathElement = path.substr(0, separatorIndex);
204 newPath = path.substr(separatorIndex + 1);
206 assert(pathElement !=
"" &&
"There's no element after the separator.");
209 const boost::xpressive::sregex match_indexed
210 = boost::xpressive::sregex::compile(
"(.+)_array\\[(\\d+)\\]");
211 boost::xpressive::smatch match;
212 if (boost::xpressive::regex_match(pathElement, match, match_indexed)) {
213 string arrayElementKey = match[1];
214 ptree& subPtree = pt.get_child(arrayElementKey + ARRAY_SUFFIX);
215 unsigned int index = FromString<unsigned int>(match[2]);
217 for (
auto& entry : subPtree) {
218 if (entry.first == arrayElementKey) {
220 PutIndexedChild(entry.second, newPath, child);
228 throw ptree_bad_path(
"No such node", boost::property_tree::path(pathElement));
230 PutIndexedChild(pt.get_child(pathElement), newPath, child);
235 void PTreeUtils::RemoveNonExistingChildren(
const ptree& src, ptree& dst,
const set<string>& ignore)
237 for (
auto dst_it = dst.begin(); dst_it != dst.end(); ++dst_it) {
238 if (ignore.find(dst_it->first) != ignore.end()) {
243 const ptree& child = src.get_child(dst_it->first);
245 RemoveNonExistingChildren(child, dst_it->second, ignore);
247 catch (ptree_bad_path&) {
249 dst_it = dst.erase(dst_it);
Namespace for the core simulator.
String manipulation utilities.