|
rapidyaml
0.11.1
parse and emit YAML, and do it fast
|
rapidyaml implements its parsing logic with a two-level model, where a ParseEngine object reads through the YAML source, and dispatches events to an EventHandler bound to the ParseEngine. More...
Classes | |
| struct | c4::yml::EventHandlerStack< HandlerImpl, HandlerState > |
| Use this class a base of implementations of event handler to simplify the stack logic. More... | |
| struct | c4::yml::EventHandlerTree |
| The event handler to create a ryml Tree. More... | |
| struct | c4::yml::extra::EventHandlerInts |
| A parser event handler that creates a compact representation of the YAML tree in a buffer of integers (see ievt::EventFlags) containing masks (to represent events) and offset+length (to represent strings in the source buffer). More... | |
| struct | c4::yml::extra::EventHandlerTestSuite |
| This event produces standard YAML events as used in the YAML test suite. More... | |
Functions | |
| int32_t | c4::yml::extra::estimate_events_ints_size (csubstr src) |
| Read YAML source and, without undergoing a full parse, estimate the size of the integer buffer required for EventHandlerInts. More... | |
| size_t | c4::yml::extra::events_ints_to_testsuite (csubstr parsed_yaml, csubstr arena, ievt::DataType const *evts_ints, ievt::DataType evts_ints_sz, substr evts_testsuite) |
| Create a testsuite event string from integer events. More... | |
| template<class Container > | |
| void | c4::yml::extra::events_ints_to_testsuite (csubstr parsed_yaml, csubstr arena, ievt::DataType const *evts_ints, ievt::DataType evts_ints_sz, Container *evts_testsuite) |
| Create a testsuite event string from integer events, writing into an output container. More... | |
| template<class Container > | |
| Container | c4::yml::extra::events_ints_to_testsuite (csubstr parsed_yaml, csubstr arena, ievt::DataType const *evts_ints, ievt::DataType evts_ints_sz) |
| Create a testsuite event string from integer events, returning a new container with the result. More... | |
| void | c4::yml::extra::events_ints_print (csubstr parsed_yaml, csubstr arena, ievt::DataType const *evts_ints, ievt::DataType evts_ints_sz) |
| Print integer events to stdout. More... | |
rapidyaml implements its parsing logic with a two-level model, where a ParseEngine object reads through the YAML source, and dispatches events to an EventHandler bound to the ParseEngine.
Because ParseEngine is templated on the event handler, the binding uses static polymorphism, without any virtual functions. The actual handler object can be changed at run time, (but of course needs to be the type of the template parameter). This is thus a very efficient architecture, and further enables the user to provide his own custom handler if he wishes to bypass the rapidyaml Tree.
There are two handlers implemented in this project:
The event model used by the parse engine and event handlers follows very closely the event model in the YAML test suite.
Consider for example this YAML,
which would produce these events in the test-suite parlance:
For reference, the ParseEngine object will produce this sequence of calls to its bound EventHandler:
For many other examples of all areas of YAML and how ryml's parse model corresponds to the YAML standard model, refer to the [unit tests for the parse engine](https://github.com/biojppm/rapidyaml/tree/master/test/test_parse_engine.cpp).
Most of the parsing events adopted by rapidyaml in its event model are fairly obvious, but there are two less-obvious events requiring some explanation.
These events exist to make it easier to parse some special YAML cases. They are called by the parser when a just-handled value/container is actually the first key of a new map:
actually_val_is_first_key_of_new_map_flow() (see implementation in EventHandlerTree / see implementation in EventHandlerTestSuite)actually_val_is_first_key_of_new_map_block() (see implementation in EventHandlerTree / see implementation in EventHandlerTestSuite)For example, consider an implicit map inside a seq: [a: b, c: d] which is parsed as [{a: b}, {c: d}]. The standard event sequence for this YAML would be the following:
The problem with this event sequence is that it forces the parser to delay setting the val scalar (in this case "a" and "c") until it knows whether the scalar is a key or a val. This would require the parser to store the scalar until this time. For instance, in the example above, the parser should delay setting "a" and "c", because they are in fact keys and not vals. Until then, the parser would have to store "a" and "c" in its internal state. The downside is that this complexity cost would apply even if there is no implicit map – every val in a seq would have to be delayed until one of the disambiguating subsequent tokens ,-]: is found. By calling this function, the parser can avoid this complexity, by preemptively setting the scalar as a val. Then a call to this function will create the map and rearrange the scalar as key. Now the cost applies only once: when a seqimap starts. So the following (easier and cheaper) event sequence below has the same effect as the event sequence above:
This also applies to container keys (although ryml's tree cannot accomodate these): the parser can preemptively set a container as a val, and call this event to turn that container into a key. For example, consider this yaml:
The standard event sequence for this YAML would be the following:
The problem with the sequence above is that, reading from left-to-right, the parser can only detect the proper calls at (1) and (2) once it reaches (1) in the YAML source. So, the parser would have to buffer the entire event sequence starting from the beginning until it reaches (1). Using this function, the parser can do instead:
| int32_t c4::yml::extra::estimate_events_ints_size | ( | csubstr | src | ) |
Read YAML source and, without undergoing a full parse, estimate the size of the integer buffer required for EventHandlerInts.
This estimation is meant to exceed the actual number of required events.
Definition at line 25 of file event_handler_ints.cpp.
| size_t c4::yml::extra::events_ints_to_testsuite | ( | csubstr | parsed_yaml, |
| csubstr | arena, | ||
| ievt::DataType const * | evts_ints, | ||
| ievt::DataType | evts_ints_sz, | ||
| substr | evts_testsuite | ||
| ) |
Create a testsuite event string from integer events.
This overload receives a buffer where the string should be written, and returns the size needed for the buffer. If that size is larger than the buffer's size, the user must resize the buffer and call again.
Definition at line 36 of file ints_to_testsuite.cpp.
References c4::yml::extra::ievt::ALIA, c4::yml::extra::ievt::ANCH, c4::yml::extra::ievt::AREN, c4::yml::extra::ievt::BDOC, c4::yml::extra::ievt::BMAP, c4::yml::extra::ievt::BSEQ, c4::yml::extra::ievt::BSTR, c4::yml::extra::ievt::DQUO, c4::yml::extra::ievt::EDOC, c4::yml::extra::ievt::EMAP, c4::yml::escape_scalar(), c4::yml::extra::ievt::ESEQ, c4::yml::extra::ievt::ESTR, c4::yml::extra::ievt::EXPL, c4::yml::extra::ievt::FLOW, c4::yml::extra::ievt::FOLD, c4::yml::extra::ievt::LITL, c4::yml::extra::ievt::SCLR, c4::yml::extra::ievt::SQUO, c4::yml::extra::ievt::TAG_, and c4::yml::extra::ievt::WSTR.
| void c4::yml::extra::events_ints_to_testsuite | ( | csubstr | parsed_yaml, |
| csubstr | arena, | ||
| ievt::DataType const * | evts_ints, | ||
| ievt::DataType | evts_ints_sz, | ||
| Container * | evts_testsuite | ||
| ) |
Create a testsuite event string from integer events, writing into an output container.
Definition at line 35 of file ints_to_testsuite.hpp.
References c4::yml::extra::events_ints_to_testsuite(), and c4::to_substr().
| Container c4::yml::extra::events_ints_to_testsuite | ( | csubstr | parsed_yaml, |
| csubstr | arena, | ||
| ievt::DataType const * | evts_ints, | ||
| ievt::DataType | evts_ints_sz | ||
| ) |
Create a testsuite event string from integer events, returning a new container with the result.
Definition at line 53 of file ints_to_testsuite.hpp.
References c4::yml::extra::events_ints_to_testsuite().
| void c4::yml::extra::events_ints_print | ( | csubstr | parsed_yaml, |
| csubstr | arena, | ||
| ievt::DataType const * | evts, | ||
| ievt::DataType | evts_sz | ||
| ) |
Print integer events to stdout.
Definition at line 94 of file ints_utils.cpp.
References c4::yml::extra::ievt::AREN, c4::yml::extra::ievt::to_chars_sub(), and c4::yml::extra::ievt::WSTR.