Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • 21:42
    biojppm commented #164
  • 21:10
    biojppm labeled #164
  • 16:24
    codecov[bot] commented #161
  • 16:22
    codecov[bot] commented #161
  • 16:20
    codecov[bot] commented #161
  • 16:18
    codecov[bot] commented #161
  • 16:16
    codecov[bot] commented #161
  • 16:14
    codecov[bot] commented #161
  • 16:04
    codecov[bot] commented #161
  • 16:02
    biojppm synchronize #161
  • 16:02

    biojppm on test_suite

    [fix] fix vs compile errors [impl] Tree: add doc() getter [fix] block scalars at 0 indent… (compare)

  • 15:20
    Lemongrass3110 opened #164
  • 05:53
    Tanimodori commented #87
  • Oct 26 19:50
    codecov[bot] commented #161
  • Oct 26 19:46
    codecov[bot] commented #161
  • Oct 26 19:44
    codecov[bot] commented #161
  • Oct 26 19:43
    codecov[bot] commented #161
  • Oct 26 19:43
    codecov[bot] commented #161
  • Oct 26 19:42
    codecov[bot] commented #161
  • Oct 26 19:40
    codecov[bot] commented #161
overage-waif-cocoon
@overage-waif-cocoon
@biojppm, trying to use your library, moving from yaml-cpp and getting a compiler error. The Quick Start seems to indicate that you can call Tree::operator[] with a const char*: ryml::NodeRef node = tree["foo"];, but that function doesn't seem to exist. There is an overload that takes a c4::csubstr, but I'd rather not have to wrap all the literals. Am I doing something wrong here?
jpmag
@biojppm
@overage-waif-cocoon when you call tree["foo"] the argument type is actually an array, template<size_t N> csubstr(const char (&arr)[N]), which is then converted to a temporary c4::csubstr using the N size from the templated constructor. This is O(1) (when you have a const char*, constructing a c4::csubstr is O(N) by necessity, as the length is unknown). Unfortunately, csubstr has no overload for constructing from const char*. Although this seems peculiar, and is undesirable indeed, there's an annoying reason for this : if you provide an overload both for const char* and const char (&arr)[N]`, the compiler will always pick the first, and never the second -- even if you pass an in-scope array instead of the decayed pointer. That's why I've gone with the utility function to_csubstr() to make it easier.
jpmag
@biojppm
However, since the tree/node_ref scope is not the csubstr, maybe an overload for const char * can be provided, but only if this does not prevent arrays to go to the O(1) csubstr overload.
I'm not sure, but I can investigate.
overage-waif-cocoon
@overage-waif-cocoon
@biojppm , thanks for the explanation. Don't spend too much time on it. Just though it was odd that accessing with a literal wasn't working for me. Compiler was trying to call Tree::operator[](size_t i) with the string literal (and failing, obviously). It seems like there should be an implicit conversion to csubstr, but that wasn't happening for me.
jpmag
@biojppm
So you are using a literal? Wow, then it's strange indeed - it should not happen at all. Can you submit a bug with a Minimum Verifiable Example? And which compiler is it?
To be clear, with a literal the compiler must pick the overload Tree::operator[](csubstr) --- and if it doesn't that's something that should be looked at. With a plain c-string things change however; there you are required to
* sorry, there you are required to use to_csubstr()
overage-waif-cocoon
@overage-waif-cocoon
Actually, I'm probably mistaken. I think the literal was getting converted to a const char* before it made it into the Tree::operator[] call. I can fix that. I'll let you know if it's still an issue. Thanks for your help.
Caldfir
@aitken.tim_gitlab
@biojppm Howdy - was looking around at the library and noticed some of the emit() prototypes use FILE*, but there doesn't seem to be an equivalent on the parse() side, and the c4::fs::file_get_contents used in the tests doesn't seem to be part of c4core. Is there a convenient way for reading from a file source? Right now I'm just throwing the whole file in a char* myself but it feels like I'm missing something obvious.
jpmag
@biojppm

@aitken.tim_gitlab - Thanks for asking. You are correct. Indeed, the reasoning here is different for parse() and emit(). The former always requires an existing YAML string which is indexed into in the tree, whereas emitting is a bit more abstract in that regard, because we're just dumping characters into a sink. So that's why the API reflects this distinction. Maybe it would make sense to create some wrappers like receiving FILE* and doing something like file_get_contents()to pass the buffer to parse(), but then this would beg the question of also providing wrappers for iostreams, and that is something I'd rather not do - #including streams and std::string in parse is absolutely out of question here. Another reason is that the parse()overloads would grow in number even further. Yet another reason is that I also do not want to force the c4fs library on users, and getting the file contents is actually a minor task.

So that's why things are the way they are. But I'm open to opposing view or enabling ideas, as I admit the situation is not ideal.

Caldfir
@aitken.tim_gitlab
Alrighty, thanks for answering. I guess I would advocate for symmetry between parse/emit in this case because seeing the one prototype sent me on a bit of a goose-chase looking for the other, and I suspect this is going to be common. Alternately, showing a file-based input example in the documentation could help guide people in the right direction.
zcmimi
@zcmimi
How to convert ryml::Tree to std::map?
map<string,string>
zcmimi
@zcmimi
map<std::any,std::any>
jpmag
@biojppm
@zcmimi sorry for the late reply. Does the main README not help you do it?
@aitken.tim_gitlab your point on the documentation is a good; I'll take that up.
Erez Oxman
@erez-o

Hi, I created a documentation with api references at https://rapidyaml.docsforge.com/
Tell me if it's helpful, It's basically a modern version of doxygen.
Disclaimer, I'm the creator of docsforge.

BTW, you're using doxygen groups for preprocess_json & preprocess_rxmap. Is that intended?

14 replies
Riddle
@riddlepl

Hello, I've a problem with the ryml library. Maybe I'm missing something but let me elaborate:
Lets have this simple yaml:

  some_entry: 3
  other_entry_list:
    - first element
    - second element
    - third_element:
       - something_else

What I need to do is to validate such yml. So I wrote code that goes by all children of root, validates its names, then go inside all that has children.. When I approach to "third_element" on the list "other_entry_list" ryml gets weird.. third_element is_map() is true, however is_key() return false

has_children() is true, i can go deeper, but I cant figure out how to get node name of "third_element"
Riddle
@riddlepl
btw why "- third_element" is a map, not a seq?
Riddle
@riddlepl
hmm unexpected.. in sequence.. there is a map with a child of the name -third element
Riddle
@riddlepl
can I somehow print out whole Tree with some debug information about nodes?
1 reply
too see how its actually built
Riddle
@riddlepl

to better show the problem:

some_entry: 3
other_entry_list:
  - first element
  - second element
  - third_element:
     - something_else

and

some_entry: 3
other_entry_list:
  - third_element:
    - something_else

in the second case there is that strange node that is a map but has no key

and in its children there is one child.. and it is "third_element"
but if you change it to the previous example (where it is not alone on the outer list) it looks different
jpmag
@biojppm
This should help clarify:

TEST(seq_of_map, general)
{
    auto tree = parse(R"(
some_entry: 3
other_entry_list:
  - first_element
  - second_element
  - third_element:
    - something_else
)");
    auto r = tree.rootref();
    EXPECT_EQ(r["some_entry"].val(), "3");
    auto other = r["other_entry_list"];
    EXPECT_EQ(other.is_seq(), true);
    EXPECT_EQ(other[0].val(), "first_element");
    EXPECT_EQ(other[1].val(), "second_element");
    EXPECT_EQ(other[2].is_map(), true);
    EXPECT_EQ(other[2]["third_element"].has_key(), true);
    EXPECT_EQ(other[2]["third_element"].has_children(), true);
    EXPECT_EQ(other[2]["third_element"][0].val(), "something_else");
}

The element that is a map is a sequence member. The colon turns it into a map, which has a value that is a sequence.

Welcome to YAMLS's complex simplicity :-)

HTH
And again, there is an unsupported debug header which you can use, in the detail folder
You can also simply emit to stdout, which may clarify what is going on.
Riddle
@riddlepl
well im pretty sure that if you change that yml from example you tested to have only one element in the list, and the element is a map, that map has_key() is false
Riddle
@riddlepl
nevermind i guess i get it now, thank you