Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding dynamic keys (from short-living local strings) #500

Closed
rlalik opened this issue Feb 18, 2025 · 3 comments
Closed

Adding dynamic keys (from short-living local strings) #500

rlalik opened this issue Feb 18, 2025 · 3 comments

Comments

@rlalik
Copy link

rlalik commented Feb 18, 2025

Hi,

first time using the library, and I have an issue with making dynamic keys (the string is generated and has short life time).

I would like to have following structure:

- DynamicKey1:
  - 0:
    key1: val1
    key2: val2
  -1:
    key1: val1
    key2: val2
- DynamicKey2:
... and so on...

I start with some initial content:

auto tree = ryml::parse_in_arena(content.c_str());
auto treeroot = tree.rootref();
if (!treeroot.is_map()) {  // content may be empty
    treeroot |= ryml::MAP;
}

and now I want to add the key:

{ // brackets to limit scope for dynkey variable
    auto dynkey = fmt::format("DynamicKey{}", 1);
    // what to do here to add the key == dynkey, of which value is an another map: - DynamicKey1:
    auto dynnode = /* ... */;

    auto key0 = dynnode["0"];
    key0 |= ryml::MAP;
    key0["key1"] << fmt::format("val{}", 1).c_str();
}

// emit valid yaml
std::ofstream infile { "file_path" };
infile << tree;

Can you help me with this? The quickstart.cpp doesn't cover this I think. Perhaps you can include this?

@biojppm
Copy link
Owner

biojppm commented Feb 19, 2025

You need to keep all keys such that they outlive the tree, by serializing it to either the tree or any other place of your choice (that also outlives the tree).

To serialize to the tree, you can use node << ryml::key(to_csubstr(dynkey)).

This is indeed in the quickstart. For example:

//------------------------------------------------------------------
// Adding new nodes:

// adding a keyval node to a map:
CHECK(root.num_children() == 5);
wroot["newkeyval"] = "shiny and new"; // using these strings
wroot.append_child() << ryml::key("newkeyval (serialized)") << "shiny and new (serialized)"; // serializes and assigns the serialization
CHECK(root.num_children() == 7);
CHECK(root["newkeyval"].key() == "newkeyval");
CHECK(root["newkeyval"].val() == "shiny and new");
CHECK(root["newkeyval (serialized)"].key() == "newkeyval (serialized)");
CHECK(root["newkeyval (serialized)"].val() == "shiny and new (serialized)");

@rlalik
Copy link
Author

rlalik commented Feb 19, 2025

Not really, I tried it already. This:

{
    std::string aaa("aaa");
    treeroot << ryml::key(ryml::to_csubstr(aaa.c_str()));
}

gives

code.cpp: In function ?int main(int, char**)?:
code.cpp:1169:47: error: cannot bind non-const lvalue reference of type ?c4::basic_substring<const char>&? to an rvalue of type ?std::enable_if<true, c4::basic_substring<const char> >::type? {aka ?c4::basic_substring<const char>?}
 1169 |         treeroot << ryml::key(ryml::to_csubstr(aaa.c_str()));
      |                               ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
In file included from _deps/ryml-src/src/c4/yml/yml.hpp:6,
                 from _deps/ryml-src/src/ryml.hpp:4,
                 from code.cpp:25:
_deps/ryml-src/src/c4/yml/node.hpp:43:51: note:   initializing argument 1 of ?c4::yml::Key<K> c4::yml::key(K&) [with K = c4::basic_substring<const char>]?
   43 | template<class K> C4_ALWAYS_INLINE Key<K> key(K & k) { return Key<K>{k}; }

@biojppm
Copy link
Owner

biojppm commented Feb 19, 2025

The compile error is telling you cannot pass a temporary to ryml::key(). This works:

ryml::Tree t;
ryml::csubstr s = ryml::to_csubstr(std::string("key"));
t["test"] << ryml::key(s) << std::string("val");
CHECK(ryml::emitrs_yaml<std::string>(t) == "key: val\n");

I agree that the ergonomics of the key tag function could be improved.

@biojppm biojppm closed this as completed Feb 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants