Traversing the ryml::Tree #245
-
Hi, struct keyData {
ryml::csubstr key;
ryml::csubstr parent;
ryml::csubstr data;
keyData() {}
keyData(ryml::csubstr k, ryml::csubstr p, ryml::csubstr d) : key(k), parent(p), data(d) {}
}; For example, if I have a tree like: ryml::Tree tree = ryml::parse_in_arena(R"(doe: "a deer, a female deer"
ray: "a drop of golden sun"
pi: 3.14159
xmas: true
french-hens: 3
calling-birds:
- huey
- dewey
- louie
- fred
xmas-fifth-day:
calling-birds: four
french-hens: 3
golden-rings: 5
partridges:
count: 1
location: a pear tree
turtle-doves: two
cars: GTO
)"); What I want as output is something like: <{"doe", "", "a deer, a female deer"}, {"pi", "", "3.14159"} ... {"calling-birds", "", "[huey, dewey, louie, fred]"},
{"xmas-fifth-day", "", "calling-birds: four
french-hens: 3
golden-rings: 5
partridges:
count: 1
location: a pear tree
turtle-doves: two"}, {"calling-birds", "xmas-fifth-day", "four"} ... {"count", "partridges", "1"} ... {"cars", "", "GTO"}> So, basically every key has a parent, which can be null, a data, which can be a map or a sequence. And I want to go through all the nodes recursively. I tried something like this, but it does not seem to be working properly, because for a map or a seq, I can not get their values or keys separately. This approach of mine may have other problems as well. void getstr(ryml::NodeRef node, ryml::csubstr parent, vector<keyData> &vec)
{
if (!node.has_children()) vec.push_back(keyData(node.has_key() ? node.key() : ryml::csubstr{}, parent, node.has_val() ? node.val() : ryml::csubstr{}));
else {
if (node.is_map())
{
std::string src = "";
for (ryml::NodeRef ch : node[0].siblings())
{
src = src + (ch.has_val() ? ch.val().str : "");
}
ryml::csubstr data = ryml::to_substr(src);
vec.push_back(keyData(node.has_key() ? node.key() : ryml::csubstr{}, parent, data));
}
else if (node.is_map())
{
std::string src = "";
for (ryml::NodeRef ch : node[0].siblings())
{
src = src + (ch.has_key() ? ch.key().str : "") + (ch.has_val() ? ch.val().str : "");
}
ryml::csubstr data = ryml::to_substr(src);
vec.push_back(keyData(node.has_key() ? node.key() : ryml::csubstr{}, parent, data));
}
for (ryml::NodeRef n : node.children())
{
getstr(n, node.has_key() ? node.key() : ryml::csubstr{}, vec);
}
} I would highly appreciate if you can tell me of way to get this required output from a ryml::Tree constructed out of Yaml file. Thanks a lot. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
@biojppm Should I assume its not possible to get the nested key-value pairs? |
Beta Was this translation helpful? Give feedback.
-
You can do anything, but the question is whether it is worth it. I'm not sure what you're trying to achieve by creating this vector, or if I can help you achieve it; the problem seems very specific. But I notice that for example, creating There are other problems in your code:
|
Beta Was this translation helpful? Give feedback.
-
Also I noticed that you're storing the Do something like this: struct keyData {
std::string key; // store as std::string!!!
std::string parent;
std::string data;
keyData() {}
keyData(ryml::csubstr k, ryml::csubstr p, ryml::csubstr d) : key(k.str, k.len), parent(p.str, p.len), data(d.str, d.len) {}
};
void getstr(ryml::NodeRef node, ryml::csubstr parent, vector<keyData> &vec)
{
auto getkey = [](NodeRef node){ return node.has_key() ? node.key() : ryml::csubstr{}; };
auto getval = [](NodeRef node){ return node.has_val() ? node.val() : ryml::csubstr{}; };
if (!node.has_children())
vec.push_back(keyData(getkey(node), parent, getval(node)));
else {
std::string src = ryml::emitrs<std::string>(node);
vec.push_back(keyData(getkey(node), parent, ryml::to_csubstr(src)));
for (ryml::NodeRef n : node.children())
{
getstr(n, getkey(n), vec);
}
} But maybe you will also have to do something about the key on the result of |
Beta Was this translation helpful? Give feedback.
Also I noticed that you're storing the
csubstr
view into a temporarystd::string
. That's sure to cause a read-after-free crash.Do something like this: