rapidyaml  0.12.0
parse and emit YAML, and do it fast
c4::yml::extra::EventHandlerInts Struct Reference

A parser event handler that creates a compact representation of the YAML tree in a contiguous buffer of integers. More...

#include <event_handler_ints.hpp>

Inheritance diagram for c4::yml::extra::EventHandlerInts:
c4::yml::EventHandlerStack< EventHandlerInts, EventHandlerIntsState >

Public Types

types
enum  { requires_strings_on_buffers = true }
 
using value_type = ievt::DataType
 
using state = EventHandlerIntsState
 

Public Member Functions

construction and resetting
 EventHandlerInts (c4::yml::Callbacks const &cb)
 
 EventHandlerInts ()
 
void reset (substr str, substr arena, ievt::DataType *dst, int32_t dst_size)
 
int required_size_events () const
 get the size needed for the event buffer from the previous parse More...
 
size_t required_size_arena () const
 get the size needed for the arena from the previous parse More...
 
bool fits_buffers () const
 Predicate to test if the event and arena buffers successfully accomodated all the parse events. More...
 
void reserve_arena (int)
 
TagDirectivestag_directives ()
 
TagCachetag_cache ()
 
parse events
void start_parse (const char *filename, substr src)
 
void finish_parse ()
 
void cancel_parse ()
 
YAML stream events
void begin_stream ()
 
void end_stream ()
 
YAML document events
void begin_doc ()
 implicit doc start (without —) More...
 
void end_doc ()
 implicit doc end (without ...) More...
 
void begin_doc_expl ()
 explicit doc start, with — More...
 
void end_doc_expl ()
 explicit doc end, with ... More...
 
YAML map functions
void begin_map_key_flow ()
 
void begin_map_key_block ()
 
void begin_map_val_flow ()
 
void begin_map_val_block ()
 
void end_map_block ()
 
void end_map_flow (bool)
 
YAML seq events
void begin_seq_key_flow ()
 
void begin_seq_key_block ()
 
void begin_seq_val_flow ()
 
void begin_seq_val_block ()
 
void end_seq_block ()
 
void end_seq_flow (bool)
 
YAML structure events
void add_sibling ()
 
void actually_val_is_first_key_of_new_map_flow ()
 set the previous val as the first key of a new map, with flow style. More...
 
void actually_val_is_first_key_of_new_map_block ()
 like its flow counterpart, but this function can only be called after the end of a flow-val at root or doc level. More...
 
YAML scalar events
void set_key_scalar_plain_empty ()
 
void set_val_scalar_plain_empty ()
 
void set_key_scalar_plain (csubstr scalar)
 
void set_val_scalar_plain (csubstr scalar)
 
void set_key_scalar_dquoted (csubstr scalar)
 
void set_val_scalar_dquoted (csubstr scalar)
 
void set_key_scalar_squoted (csubstr scalar)
 
void set_val_scalar_squoted (csubstr scalar)
 
void set_key_scalar_literal (csubstr scalar)
 
void set_val_scalar_literal (csubstr scalar)
 
void set_key_scalar_folded (csubstr scalar)
 
void set_val_scalar_folded (csubstr scalar)
 
void mark_key_scalar_unfiltered ()
 
void mark_val_scalar_unfiltered ()
 
YAML anchor/reference events
void set_key_anchor (csubstr anchor)
 
void set_val_anchor (csubstr anchor)
 
void set_key_ref (csubstr ref)
 
void set_val_ref (csubstr ref)
 
YAML tag events
void set_key_tag (csubstr tag)
 
void set_val_tag (csubstr tag)
 
YAML directive events
void add_directive_yaml (csubstr yaml_version)
 
void add_directive_tag (csubstr handle, csubstr prefix)
 
arena events
substr arena ()
 
substr arena_rem ()
 
substr alloc_arena (size_t len)
 this may fail, in which case an empty string is returned More...
 
implementation helpers
void _push ()
 push a new parent, add a child to the new parent, and set the child as the current node More...
 
void _pop ()
 end the current scope More...
 
template<c4::yml::type_bits bits>
void _enable__ () noexcept
 
template<c4::yml::type_bits bits>
void _disable__ () noexcept
 
template<c4::yml::type_bits bits>
bool _has_any__ () const noexcept
 
int32_t _next (int32_t pos) const noexcept
 
int32_t _prev (int32_t pos) const noexcept
 
bool _is_sub_ (csubstr str) const noexcept
 
void _send_flag_only_ (ievt::DataType flags)
 
void _send_str_ (csubstr scalar, ievt::DataType flags)
 
void _mark_parent_with_children_ ()
 
csubstr _get_latest_empty_scalar () const
 
int32_t _find_last_bdoc (int32_t pos) const
 
int32_t _find_matching_open (ievt::DataType open, ievt::DataType close, int32_t pos) const
 
int32_t _extend_left_to_include_tag_and_or_anchor (int32_t pos) const
 

Public Attributes

detail::stack< statem_stack
 
statem_curr
 current stack level: top of the stack. cached here for easier access. More...
 
statem_parent
 parent of the current stack level. More...
 
substr m_src
 

Protected Member Functions

void _stack_start_parse (const char *filename, substr ymlsrc)
 
void _stack_finish_parse ()
 
void _stack_reset_root ()
 
void _stack_reset_non_root ()
 
void _stack_push ()
 
void _stack_pop ()
 
bool _stack_should_push_on_begin_doc () const
 
bool _stack_should_pop_on_end_doc () const
 

Detailed Description

A parser event handler that creates a compact representation of the YAML tree in a contiguous buffer of integers.

The integers are ievt::EventFlags containing masks (to represent events), interleaved with offset+length (to represent strings in the source buffer).

This is meant for use by other programming languages, and supports container keys (unlike the ryml tree). It parses faster than the ryml tree parser, because the resulting data structure is much simpler.

The resulting integer buffer is a linear array of integers containing events (as a mask of ievt::EventFlags), which in some cases (see ievt::WSTR) are followed by an encoded string (encoded as an offset and length to the parsed source buffer).

For example, parsing [a, bb, ccc] results in the following event buffer (grouped to highlight the event sequence structure):

{c++}
using namespace c4::yml::extra::ievt;
const DataType arr[] = { // result of parsing: [a, bb, ccc]
BSTR, // begin stream
BDOC, // begin doc
VAL_|BSEQ|FLOW, // begin seq as val, flow
VAL_|SCLR|PLAI, 1, 1, // val scalar, plain style: "a" starts at offset 1 and has length 1
VAL_|SCLR|PLAI|PSTR, 4, 2, // val scalar, plain style: "bb" starts at offset 4 and has length 2; preceded by a string event (PSTR)
VAL_|SCLR|PLAI|PSTR, 8, 3, // val scalar, plain style: "ccc" starts at offset 8 and has length 3; preceded by a string event (PSTR)
ESEQ|PSTR, // end seq; preceded by a string event (PSTR)
EDOC, // end doc
ESTR, // end stream
};
@ SCLR
scalar (=VAL in test suite events)
@ ESTR
end stream (-STR in test suite events)
@ BSTR
begin stream (+STR in test suite events)
@ BSEQ
begin seq (+SEQ in test suite events)
@ ESEQ
end seq (-SEQ in test suite events)
@ FLOW
container: flow: [] for seqs or {} for maps
@ VAL_
as value special flag to enable look-back in the event array. it signifies that the previous event ha...
@ BDOC
begin doc (+DOC in test suite events)
@ EDOC
end doc (-DOC in test suite events)
int32_t DataType
data type for integer events.

Here is a sketch clarifying the meaning of this event sequence:

source : [a, bb, ccc]
has a string........
| offset "a"
| | length "a"
| | |
event0 event1 event2 [ event3 "a"......|..|
| | | | | |
(start) +--------+-------+------------------+---------------+--+-----> (continued)
arr[i] : BSTR BDOC VAL_|BSEQ|FLOW VAL_|SCLR|PLAI..1..1
i : 0 1 2 3 4 5
has a string............. has a string.............
| offset "bb" | offset "ccc"
| | length "bb" | | length "ccc"
| | | | | |
event4 "bb"..........|..| event5 "ccc".........|..|
| | | | | |
(cont)--> -----+--------------------+--+--------------+--------------------+--+-----> (continued)
arr[i] : VAL_|SCLR|PLAI|PSTR..4..2 VAL_|SCLR|PLAI|PSTR..8..3
i : 6 | 7 8 9 | 10 11
| |
prev event has string prev event has string
(to get to prev, jump (to get to prev, jump
back 3 slots: ie 6->3) back 3 slots: ie 9->6)
event6 ] event7 event8
| | |
(cont)--> -----+-------------+--------+-----| (end)
arr[i] : ESEQ|PSTR EDOC ESTR
i : 12 | 13 14
|
prev event has string
(to get to it, jump
back 3 slots: ie 12->9)

Note that the buffer contains both events and strings encoded as integer pairs. That is, events that have an associated string are immediately followed by two integers providing the offset and length of that string in the source buffer. (In the example above, this happens in the events for the strings a, bb, and ccc at positions 3, 6 and 9, respectively).

The flag ievt::PSTR and the mask ievt::WSTR are provided to enable easier iteration over the array: you can use them to test for presence of a string when iterating over the array.

The flag ievt::PSTR announces that an event is preceded by a string. That is, the previous event has a string, so that when this flag is found while iterating right-to-left, a jump of -3 should be used to get at the bitmask of the previous event. (In the example above, this flag is present for the events for bb and ccc, but not a because it is not preceded by a string).

Likewise, to signify that the current event is followed by a string, there is the mask ievt::WSTR, which is a mask of all the flags of events that have a string: ievt::SCLR, ievt::ALIA, ievt::ANCH and ievt::TAG_. While iterating left-to-right in the array, presence of any of the bits in the mask ievt::WSTR means that a jump of +3 should be employed to get at the bitmask of the next event.

Here's another example with the result of parsing a: bb

{c++}
const DataType arr[] = { // result of parsing: `a: bb`
BSTR, // begin stream
BDOC, // begin doc
VAL_|BMAP|BLCK, // begin map as val, block
KEY_|SCLR|PLAI, 0, 1, // key scalar, plain style: "a" starts at offset 0 and has length 1
VAL_|SCLR|PLAI|PSTR, 3, 2, // val scalar, plain style: "bb" starts at offset 3 and has length 2
EMAP|PSTR, // end map
EDOC, // end doc
ESTR, // end stream
};
@ EMAP
end map (-MAP in test suite events)
@ BMAP
begin map (+MAP in test suite events)
@ BLCK
container: block

Typical code to iterate left-to-right over the array will look like this:

{c++}
// source buffer, modified in place during parsing (IMPORTANT!)
substr src = ...;
substr arena = ...; // arena used for scalars/tags that are extended during filtering
// events resulting from parsing
const int events[] = {...};
int events_size = ...;
for(int i = 0; i < events_size; ++i)
{
if(events[i] & ievt::WSTR) // this event has a string following it
{
size_t offset = (size_t)events[i+1];
size_t length = (size_t)events[i+2];
csubstr region = (events[i] & ievt::AREN) ? arena : src; // is the string in the arena?
csubstr str = region.sub(offset, length); // get the string
...
i += 2; // skip the two ints of the string
// (the jump is three places; the loop adds the other place)
}
else // this is a single-int event
{
...
}
}
@ WSTR
WithSTRing: mask of all the events that encode a string following the event. For such events,...
@ AREN
IMPORTANT. Marks events whose string was placed in the arena. This happens when the filtered string i...

This handler must be initialized with the input source buffer, the output arena, and the output event buffer. This handler will not take ownership nor attempt to resize the output buffer. If the size required for the output buffer or arena are larger than their actual size, parsing goes all way to the end, determining the required buffer sizes without writing anything past the end of the respective buffer. After parsing is finished, the user must ensure that the buffer size was enough to accomodate all the data that needs to be written into it, or react accordingly (eg, throw an error, or resize the buffer then retry the parse).

A couple of functions will be helpful to do this. After parsing, EventHandlerInts::fits_buffers() must be used to verify that the output buffers were enough to accomodate the results. Then, EventHandlerInts::required_size_events() and EventHandlerInts::required_size_arena() can be used to retrieve to necessary information. To get an estimation of the number of events before parsing, see estimate_events_ints_size().

Typical code to parse YAML with this handler will look like this:

{c++}
csubstr filename = ...;
substr src = ...;
// estimate the size required for the events buffer,
// overpredicting it to be safe.
int estimated_size = extra::estimate_events_ints_size(src);
extra::EventHandlerInts handler;
ParseEngine<extra::EventHandlerInts> parser(&handler);
// example with a vector
std::vector<int> evts;
// ensure we have a fighting chance to acommodate the events
evts.resize((size_t)estimated_size);
// arena to place scalars/tags that may have been extended after filtering
std::vector<char> arena;
arena.resize(src.len); // this is generally enough
// initialize the handler
handler.reset(src, arena, evts.data(), (int)evts.size());
// parse the YAML
parser.parse_in_place_ev(filename, src);
if(handler.fits_buffers()) // were the buffer sizes enough?
{
evts.resize((size_t)handler.required_size_events()); // trim the vector
...
}
else
{
// event size estimation underpredicted, or arena is too small!
// for the first case, open an issue at
// https://github.com/biojppm/rapidyaml/issues
error("buffer could not accomodate all the events");
// NOTE: see below for notes on doing a parse retry.
}
int32_t estimate_events_ints_size(csubstr src)
Read YAML source and, without undergoing a full parse, estimate the size of the integer buffer requir...

The result of estimate_events_ints_size() (click to see more info) must be an overprediction: it overpredicts for every single case among the many hundreds covered in the unit tests. This is deliberate, and aims at ensuring that a retry parse is not needed. But conceivably, it may underpredict in some instances not found in the out tests. What to do then?

First, open an issue to allow the estimation to be improved! Second, there are two ways to handle this situation in code:

1) throw an error (as sketched above)

2) grow the buffer to the required size (see EventHandlerInts::required_size_events()), and then parse again

If your code must be able to handle any case including where the prediction undershoots before the estimate function is fixed (after you open the issue), that is, if you are considering a parse retry, there is something important that needs attention. The YAML source buffer is mutated in-place during the parse, and cannot be used to parse again. So if you want to retry, you need to keep a pristine copy of the source, and use it for the retry:

{c++}
const std::string src = ...; // the YAML code to be parsed
std::string parsed_src = src; // this is where we will parse (filter during parsing)
std::vector<int> evts((size_t)estimated_size); // ensure we have a fighting change to acommodate the events
std::vector<char> arena(src.size()); // ensure we have a fighting change to acommodate the events
ParseEngine<extra::EventHandlerInts> parser(&handler);
handler.reset(to_substr(parsed_src), to_substr(arena), evts.data(), (int)evts.size());
parser.parse_in_place_ev(filename, to_substr(parsed_src));
if(handler.fits_buffers()) // were the buffer sizes enough?
{
evts.resize((size_t)handler.required_size()); // trim the vector
...
}
else
{
evts.resize((size_t)handler.required_size_events()); // buffer size was not enough.
arena.resize(handler.required_size_arena()); // buffer size was not enough.
// copy again
parsed_src = src;
// retry parse
handler.reset(to_substr(parsed_src), to_substr(arena), evts.data(), (int)evts.size());
parser.parse_in_place_ev(filename, to_substr(parsed_src));
assert((size_t)handler.fits_buffers()); // must always be true
}
substr to_substr(substr s) noexcept
neutral version for use in generic code
Definition: substr.hpp:2208

When bringing this to other programming languages, the semantics will be very similar to this.

Definition at line 436 of file event_handler_ints.hpp.

Member Typedef Documentation

◆ value_type

◆ state

using c4::yml::extra::EventHandlerInts::state = EventHandlerIntsState

Definition at line 443 of file event_handler_ints.hpp.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
requires_strings_on_buffers 

Definition at line 444 of file event_handler_ints.hpp.

Constructor & Destructor Documentation

◆ EventHandlerInts() [1/2]

c4::yml::extra::EventHandlerInts::EventHandlerInts ( c4::yml::Callbacks const &  cb)
inline

Definition at line 472 of file event_handler_ints.hpp.

473  : EventHandlerStack(cb)
474  {
475  reset(substr{}, substr{}, nullptr, 0);
476  }
void reset(substr str, substr arena, ievt::DataType *dst, int32_t dst_size)

◆ EventHandlerInts() [2/2]

c4::yml::extra::EventHandlerInts::EventHandlerInts ( )
inline

Definition at line 477 of file event_handler_ints.hpp.

479  {
480  }
Callbacks const & get_callbacks()
get the global callbacks
Definition: common.cpp:94

Member Function Documentation

◆ reset()

void c4::yml::extra::EventHandlerInts::reset ( substr  str,
substr  arena,
ievt::DataType dst,
int32_t  dst_size 
)
inline

Definition at line 482 of file event_handler_ints.hpp.

483  {
486  m_curr->evt_type = {};
487  m_curr->evt_id = 0;
488  m_arena = arena;
489  m_arena_pos = 0;
490  m_src = str;
491  m_evt = dst;
492  m_evt_size = dst_size;
493  m_evt_pos = 0;
494  m_evt_prev = 0;
495  m_curr_doc = 0;
496  m_tag_directives.clear();
497  m_tag_cache.clear();
498  }
@ RTOP
reading at top level
@ RUNK
reading unknown state (when starting): must determine whether scalar, map or seq
state * m_curr
current stack level: top of the stack. cached here for easier access.

References c4::yml::TagCache::clear(), c4::yml::TagDirectives::clear(), c4::yml::RTOP, and c4::yml::RUNK.

◆ required_size_events()

int c4::yml::extra::EventHandlerInts::required_size_events ( ) const
inline

get the size needed for the event buffer from the previous parse

Warning
this is valid only until the next parse

Definition at line 502 of file event_handler_ints.hpp.

503  {
504  return m_evt_pos;
505  }

◆ required_size_arena()

size_t c4::yml::extra::EventHandlerInts::required_size_arena ( ) const
inline

get the size needed for the arena from the previous parse

Warning
this is valid only until the next parse

Definition at line 509 of file event_handler_ints.hpp.

510  {
511  return m_arena_pos;
512  }

◆ fits_buffers()

bool c4::yml::extra::EventHandlerInts::fits_buffers ( ) const
inline

Predicate to test if the event and arena buffers successfully accomodated all the parse events.

Warning
this is valid only until the next parse

Definition at line 518 of file event_handler_ints.hpp.

519  {
520  return m_evt_pos <= m_evt_size && m_arena_pos <= m_arena.len;
521  }

◆ reserve_arena()

void c4::yml::extra::EventHandlerInts::reserve_arena ( int  )
inline

Definition at line 523 of file event_handler_ints.hpp.

524  {
525  // does not apply here
526  }

◆ tag_directives()

TagDirectives& c4::yml::extra::EventHandlerInts::tag_directives ( )
inline

Definition at line 528 of file event_handler_ints.hpp.

528 { return m_tag_directives; }

◆ tag_cache()

TagCache& c4::yml::extra::EventHandlerInts::tag_cache ( )
inline

Definition at line 529 of file event_handler_ints.hpp.

529 { return m_tag_cache; }

◆ start_parse()

void c4::yml::extra::EventHandlerInts::start_parse ( const char *  filename,
substr  src 
)
inline

Definition at line 538 of file event_handler_ints.hpp.

539  {
540  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, src.str == m_src.str);
541  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, src.len == m_src.len);
542  this->_stack_start_parse(filename, src);
543  }

◆ finish_parse()

void c4::yml::extra::EventHandlerInts::finish_parse ( )
inline

◆ cancel_parse()

void c4::yml::extra::EventHandlerInts::cancel_parse ( )
inline

Definition at line 550 of file event_handler_ints.hpp.

551  {
552  while(m_stack.size() > 1)
553  _pop();
554  }
void _pop()
end the current scope

◆ begin_stream()

void c4::yml::extra::EventHandlerInts::begin_stream ( )
inline

Definition at line 563 of file event_handler_ints.hpp.

564  {
566  }
void _send_flag_only_(ievt::DataType flags)

References c4::yml::extra::ievt::BSTR.

◆ end_stream()

void c4::yml::extra::EventHandlerInts::end_stream ( )
inline

Definition at line 568 of file event_handler_ints.hpp.

569  {
571  }

References c4::yml::extra::ievt::ESTR.

◆ begin_doc()

void c4::yml::extra::EventHandlerInts::begin_doc ( )
inline

implicit doc start (without —)

Definition at line 581 of file event_handler_ints.hpp.

582  {
583  _c4dbgpf("{}/{}: begin_doc", m_evt_pos, m_evt_size);
586  {
587  _c4dbgp("push!");
588  _push();
589  _enable_(DOC);
590  }
591  }
@ DOC
a document
Definition: node_type.hpp:41
void _push()
push a new parent, add a child to the new parent, and set the child as the current node

References c4::yml::extra::ievt::BDOC, and c4::yml::DOC.

◆ end_doc()

void c4::yml::extra::EventHandlerInts::end_doc ( )
inline

implicit doc end (without ...)

Definition at line 593 of file event_handler_ints.hpp.

594  {
595  _c4dbgpf("{}/{}: end_doc", m_evt_pos, m_evt_size);
598  {
599  _c4dbgp("pop!");
600  _pop();
601  }
602  ++m_curr_doc;
603  }

References c4::yml::extra::ievt::EDOC.

◆ begin_doc_expl()

void c4::yml::extra::EventHandlerInts::begin_doc_expl ( )
inline

explicit doc start, with —

Definition at line 606 of file event_handler_ints.hpp.

607  {
608  _c4dbgpf("{}/{}: begin_doc_expl", m_evt_pos, m_evt_size);
610  _c4dbgp("push!");
611  _push();
612  _enable_(DOC);
613  }
@ EXPL
--- (with BDOC) or ... (with EDOC)

References c4::yml::extra::ievt::BDOC, c4::yml::DOC, and c4::yml::extra::ievt::EXPL.

◆ end_doc_expl()

void c4::yml::extra::EventHandlerInts::end_doc_expl ( )
inline

explicit doc end, with ...

Definition at line 615 of file event_handler_ints.hpp.

616  {
617  _c4dbgpf("{}/{}: end_doc_expl", m_evt_pos, m_evt_size);
620  {
621  _c4dbgp("pop!");
622  _pop();
623  }
624  ++m_curr_doc;
625  }

References c4::yml::extra::ievt::EDOC, and c4::yml::extra::ievt::EXPL.

◆ begin_map_key_flow()

void c4::yml::extra::EventHandlerInts::begin_map_key_flow ( )
inline

Definition at line 634 of file event_handler_ints.hpp.

635  {
636  _c4dbgpf("{}/{}: bmap key flow", m_evt_pos, m_evt_size);
640  _push();
641  }
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
Definition: node_type.hpp:39
@ KEY
is member of a map
Definition: node_type.hpp:37
@ FLOW_SL
mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,...
Definition: node_type.hpp:60

References c4::yml::extra::ievt::BMAP, c4::yml::extra::ievt::FLOW, c4::yml::FLOW_SL, c4::yml::KEY, c4::yml::extra::ievt::KEY_, and c4::yml::MAP.

◆ begin_map_key_block()

void c4::yml::extra::EventHandlerInts::begin_map_key_block ( )
inline

Definition at line 642 of file event_handler_ints.hpp.

643  {
644  _c4dbgpf("{}/{}: bmap key block", m_evt_pos, m_evt_size);
648  _push();
649  }
@ BLOCK
mark container with block style (seqs as '- val ', maps as 'key: val')
Definition: node_type.hpp:62

References c4::yml::extra::ievt::BLCK, c4::yml::BLOCK, c4::yml::extra::ievt::BMAP, c4::yml::KEY, c4::yml::extra::ievt::KEY_, and c4::yml::MAP.

◆ begin_map_val_flow()

void c4::yml::extra::EventHandlerInts::begin_map_val_flow ( )
inline

Definition at line 651 of file event_handler_ints.hpp.

652  {
653  _c4dbgpf("{}/{}: bmap flow", m_evt_pos, m_evt_size);
656  _enable_(c4::yml::MAP|c4::yml::FLOW_SL);
657  _push();
658  }

References c4::yml::extra::ievt::BMAP, c4::yml::extra::ievt::FLOW, c4::yml::FLOW_SL, c4::yml::MAP, and c4::yml::extra::ievt::VAL_.

◆ begin_map_val_block()

void c4::yml::extra::EventHandlerInts::begin_map_val_block ( )
inline

Definition at line 659 of file event_handler_ints.hpp.

660  {
661  _c4dbgpf("{}/{}: bmap block", m_evt_pos, m_evt_size);
664  _enable_(c4::yml::MAP|c4::yml::BLOCK);
665  _push();
666  }

References c4::yml::extra::ievt::BLCK, c4::yml::BLOCK, c4::yml::extra::ievt::BMAP, c4::yml::MAP, and c4::yml::extra::ievt::VAL_.

◆ end_map_block()

void c4::yml::extra::EventHandlerInts::end_map_block ( )
inline

Definition at line 668 of file event_handler_ints.hpp.

669  {
670  _pop();
672  }

References c4::yml::extra::ievt::EMAP.

◆ end_map_flow()

void c4::yml::extra::EventHandlerInts::end_map_flow ( bool  )
inline

Definition at line 674 of file event_handler_ints.hpp.

675  {
676  _pop();
678  }

References c4::yml::extra::ievt::EMAP.

◆ begin_seq_key_flow()

void c4::yml::extra::EventHandlerInts::begin_seq_key_flow ( )
inline

Definition at line 687 of file event_handler_ints.hpp.

688  {
689  _c4dbgpf("{}/{}: bseq key flow", m_evt_pos, m_evt_size);
693  _push();
694  }
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
Definition: node_type.hpp:40

References c4::yml::extra::ievt::BSEQ, c4::yml::extra::ievt::FLOW, c4::yml::FLOW_SL, c4::yml::KEY, c4::yml::extra::ievt::KEY_, and c4::yml::SEQ.

◆ begin_seq_key_block()

void c4::yml::extra::EventHandlerInts::begin_seq_key_block ( )
inline

Definition at line 695 of file event_handler_ints.hpp.

696  {
697  _c4dbgpf("{}/{}: bseq key block", m_evt_pos, m_evt_size);
701  _push();
702  }

References c4::yml::extra::ievt::BLCK, c4::yml::BLOCK, c4::yml::extra::ievt::BSEQ, c4::yml::KEY, c4::yml::extra::ievt::KEY_, and c4::yml::SEQ.

◆ begin_seq_val_flow()

void c4::yml::extra::EventHandlerInts::begin_seq_val_flow ( )
inline

Definition at line 704 of file event_handler_ints.hpp.

705  {
706  _c4dbgpf("{}/{}: bseq flow", m_evt_pos, m_evt_size);
709  _enable_(c4::yml::SEQ|c4::yml::FLOW_SL);
710  _push();
711  }

References c4::yml::extra::ievt::BSEQ, c4::yml::extra::ievt::FLOW, c4::yml::FLOW_SL, c4::yml::SEQ, and c4::yml::extra::ievt::VAL_.

◆ begin_seq_val_block()

void c4::yml::extra::EventHandlerInts::begin_seq_val_block ( )
inline

Definition at line 712 of file event_handler_ints.hpp.

713  {
714  _c4dbgpf("{}/{}: bseq block", m_evt_pos, m_evt_size);
717  _enable_(c4::yml::SEQ|c4::yml::BLOCK);
718  _push();
719  }

References c4::yml::extra::ievt::BLCK, c4::yml::BLOCK, c4::yml::extra::ievt::BSEQ, c4::yml::SEQ, and c4::yml::extra::ievt::VAL_.

◆ end_seq_block()

void c4::yml::extra::EventHandlerInts::end_seq_block ( )
inline

Definition at line 721 of file event_handler_ints.hpp.

722  {
723  _pop();
725  }

References c4::yml::extra::ievt::ESEQ.

◆ end_seq_flow()

void c4::yml::extra::EventHandlerInts::end_seq_flow ( bool  )
inline

Definition at line 727 of file event_handler_ints.hpp.

728  {
729  _pop();
731  }

References c4::yml::extra::ievt::ESEQ.

◆ add_sibling()

void c4::yml::extra::EventHandlerInts::add_sibling ( )
inline

Definition at line 740 of file event_handler_ints.hpp.

741  {
742  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_parent);
743  m_curr->evt_type = {};
744  }

◆ set_key_scalar_plain_empty()

void c4::yml::extra::EventHandlerInts::set_key_scalar_plain_empty ( )
inline

Definition at line 754 of file event_handler_ints.hpp.

755  {
756  _c4dbgpf("{}/{}: set_key_scalar_plain_empty", m_evt_pos, m_evt_size);
759  }
@ KEY_PLAIN
mark key scalar as plain scalar (unquoted, even when multiline)
Definition: node_type.hpp:71
@ KEYNIL
the key is null (eg { : b} results in a null key)
Definition: node_type.hpp:49
void _send_str_(csubstr scalar, ievt::DataType flags)

References c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEY_PLAIN, c4::yml::KEYNIL, c4::yml::extra::ievt::PLAI, and c4::yml::extra::ievt::SCLR.

◆ set_val_scalar_plain_empty()

void c4::yml::extra::EventHandlerInts::set_val_scalar_plain_empty ( )
inline

Definition at line 760 of file event_handler_ints.hpp.

761  {
762  _c4dbgpf("{}/{}: set_val_scalar_plain_empty", m_evt_pos, m_evt_size);
765  }
@ VALNIL
the val is null (eg {a : } results in a null val)
Definition: node_type.hpp:50
@ VAL
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
Definition: node_type.hpp:38
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
Definition: node_type.hpp:72

References c4::yml::extra::ievt::PLAI, c4::yml::extra::ievt::SCLR, c4::yml::VAL, c4::yml::extra::ievt::VAL_, c4::yml::VAL_PLAIN, and c4::yml::VALNIL.

◆ set_key_scalar_plain()

void c4::yml::extra::EventHandlerInts::set_key_scalar_plain ( csubstr  scalar)
inline

Definition at line 768 of file event_handler_ints.hpp.

769  {
770  _c4dbgpf("{}/{}: set_key_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
773  }

References c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEY_PLAIN, c4::yml::extra::ievt::PLAI, and c4::yml::extra::ievt::SCLR.

◆ set_val_scalar_plain()

void c4::yml::extra::EventHandlerInts::set_val_scalar_plain ( csubstr  scalar)
inline

Definition at line 774 of file event_handler_ints.hpp.

775  {
776  _c4dbgpf("{}/{}: set_val_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
779  }

References c4::yml::extra::ievt::PLAI, c4::yml::extra::ievt::SCLR, c4::yml::VAL, c4::yml::extra::ievt::VAL_, and c4::yml::VAL_PLAIN.

◆ set_key_scalar_dquoted()

void c4::yml::extra::EventHandlerInts::set_key_scalar_dquoted ( csubstr  scalar)
inline

Definition at line 782 of file event_handler_ints.hpp.

783  {
784  _c4dbgpf("{}/{}: set_key_scalar_dquo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str?size_t(scalar.str-m_src.str):m_src.len, scalar.len, scalar.str?scalar:csubstr{});
787  }
@ KEY_DQUO
mark key scalar as double quoted "
Definition: node_type.hpp:69
@ DQUO
scalar: double-quoted ("")

References c4::yml::extra::ievt::DQUO, c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEY_DQUO, and c4::yml::extra::ievt::SCLR.

◆ set_val_scalar_dquoted()

void c4::yml::extra::EventHandlerInts::set_val_scalar_dquoted ( csubstr  scalar)
inline

Definition at line 788 of file event_handler_ints.hpp.

789  {
790  _c4dbgpf("{}/{}: set_val_scalar_dquo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str?size_t(scalar.str-m_src.str):m_src.len, scalar.len, scalar.str?scalar:csubstr{});
793  }
@ VAL_DQUO
mark val scalar as double quoted "
Definition: node_type.hpp:70

References c4::yml::extra::ievt::DQUO, c4::yml::extra::ievt::SCLR, c4::yml::VAL, c4::yml::extra::ievt::VAL_, and c4::yml::VAL_DQUO.

◆ set_key_scalar_squoted()

void c4::yml::extra::EventHandlerInts::set_key_scalar_squoted ( csubstr  scalar)
inline

Definition at line 796 of file event_handler_ints.hpp.

797  {
798  _c4dbgpf("{}/{}: set_key_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
801  }
@ KEY_SQUO
mark key scalar as single quoted '
Definition: node_type.hpp:67
@ SQUO
scalar: single-quoted (')

References c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEY_SQUO, c4::yml::extra::ievt::SCLR, and c4::yml::extra::ievt::SQUO.

◆ set_val_scalar_squoted()

void c4::yml::extra::EventHandlerInts::set_val_scalar_squoted ( csubstr  scalar)
inline

Definition at line 802 of file event_handler_ints.hpp.

803  {
804  _c4dbgpf("{}/{}: set_val_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
807  }
@ VAL_SQUO
mark val scalar as single quoted '
Definition: node_type.hpp:68

References c4::yml::extra::ievt::SCLR, c4::yml::extra::ievt::SQUO, c4::yml::VAL, c4::yml::extra::ievt::VAL_, and c4::yml::VAL_SQUO.

◆ set_key_scalar_literal()

void c4::yml::extra::EventHandlerInts::set_key_scalar_literal ( csubstr  scalar)
inline

Definition at line 810 of file event_handler_ints.hpp.

811  {
812  _c4dbgpf("{}/{}: set_key_scalar_literal: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str?size_t(scalar.str-m_src.str):m_src.len, scalar.len, scalar.str?scalar:csubstr{});
815  }
@ KEY_LITERAL
mark key scalar as multiline, block literal |
Definition: node_type.hpp:63
@ LITL
scalar: block literal (|)

References c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEY_LITERAL, c4::yml::extra::ievt::LITL, and c4::yml::extra::ievt::SCLR.

◆ set_val_scalar_literal()

void c4::yml::extra::EventHandlerInts::set_val_scalar_literal ( csubstr  scalar)
inline

Definition at line 816 of file event_handler_ints.hpp.

817  {
818  _c4dbgpf("{}/{}: set_val_scalar_literal: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str?size_t(scalar.str-m_src.str):m_src.len, scalar.len, scalar.str?scalar:csubstr{});
821  }
@ VAL_LITERAL
mark val scalar as multiline, block literal |
Definition: node_type.hpp:64

References c4::yml::extra::ievt::LITL, c4::yml::extra::ievt::SCLR, c4::yml::VAL, c4::yml::extra::ievt::VAL_, and c4::yml::VAL_LITERAL.

◆ set_key_scalar_folded()

void c4::yml::extra::EventHandlerInts::set_key_scalar_folded ( csubstr  scalar)
inline

Definition at line 824 of file event_handler_ints.hpp.

825  {
826  _c4dbgpf("{}/{}: set_key_scalar_folded: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str?size_t(scalar.str-m_src.str):m_src.len, scalar.len, scalar.str?scalar:csubstr{});
829  }
@ KEY_FOLDED
mark key scalar as multiline, block folded >
Definition: node_type.hpp:65
@ FOLD
scalar: block folded (>)

References c4::yml::extra::ievt::FOLD, c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEY_FOLDED, and c4::yml::extra::ievt::SCLR.

◆ set_val_scalar_folded()

void c4::yml::extra::EventHandlerInts::set_val_scalar_folded ( csubstr  scalar)
inline

Definition at line 830 of file event_handler_ints.hpp.

831  {
832  _c4dbgpf("{}/{}: set_val_scalar_folded: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str?size_t(scalar.str-m_src.str):m_src.len, scalar.len, scalar.str?scalar:csubstr{});
835  }
@ VAL_FOLDED
mark val scalar as multiline, block folded >
Definition: node_type.hpp:66

References c4::yml::extra::ievt::FOLD, c4::yml::extra::ievt::SCLR, c4::yml::VAL, c4::yml::extra::ievt::VAL_, and c4::yml::VAL_FOLDED.

◆ mark_key_scalar_unfiltered()

void c4::yml::extra::EventHandlerInts::mark_key_scalar_unfiltered ( )
inline

Definition at line 838 of file event_handler_ints.hpp.

839  {
840  _c4dbgpf("{}/{}: mark_key_scalar_unfiltered", m_evt_pos, m_evt_size);
841  if(m_evt_pos < m_evt_size)
842  m_evt[m_evt_pos] |= ievt::UNFILT;
843  }
@ UNFILT
special flag to mark a scalar as unfiltered (when the parser is set not to filter).

References c4::yml::extra::ievt::UNFILT.

◆ mark_val_scalar_unfiltered()

void c4::yml::extra::EventHandlerInts::mark_val_scalar_unfiltered ( )
inline

Definition at line 844 of file event_handler_ints.hpp.

845  {
846  _c4dbgpf("{}/{}: mark_val_scalar_unfiltered", m_evt_pos, m_evt_size);
847  if(m_evt_pos < m_evt_size)
848  m_evt[m_evt_pos] |= ievt::UNFILT;
849  }

References c4::yml::extra::ievt::UNFILT.

◆ set_key_anchor()

void c4::yml::extra::EventHandlerInts::set_key_anchor ( csubstr  anchor)
inline

Definition at line 880 of file event_handler_ints.hpp.

881  {
882  _c4dbgpf("{}/{}: set_key_anchor: {}", m_evt_pos, m_evt_size, anchor);
883  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, !_has_any_(KEYREF));
884  _enable_(c4::yml::KEYANCH);
885  if(m_evt_pos + 3 < m_evt_size)
886  {
887  m_evt[m_evt_pos] |= ievt::KEY_|ievt::ANCH;
888  _add_scalar_(m_evt_pos, anchor);
889  }
890  m_evt_prev = m_evt_pos;
891  m_evt_pos += 3;
892  }
#define _has_any_(bits)
@ KEYREF
a *reference: the key references an &anchor
Definition: node_type.hpp:43
@ KEYANCH
the key has an &anchor
Definition: node_type.hpp:45

References _has_any_, c4::yml::extra::ievt::ANCH, c4::yml::extra::ievt::KEY_, c4::yml::KEYANCH, and c4::yml::KEYREF.

◆ set_val_anchor()

void c4::yml::extra::EventHandlerInts::set_val_anchor ( csubstr  anchor)
inline

Definition at line 893 of file event_handler_ints.hpp.

894  {
895  _c4dbgpf("{}/{}: set_val_anchor: {}", m_evt_pos, m_evt_size, anchor);
896  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, !_has_any_(VALREF));
897  _enable_(c4::yml::VALANCH);
898  if(m_evt_pos + 3 < m_evt_size)
899  {
900  m_evt[m_evt_pos] |= ievt::VAL_|ievt::ANCH;
901  _add_scalar_(m_evt_pos, anchor);
902  }
903  m_evt_prev = m_evt_pos;
904  m_evt_pos += 3;
905  }
@ VALANCH
the val has an &anchor
Definition: node_type.hpp:46
@ VALREF
a *reference: the val references an &anchor
Definition: node_type.hpp:44

References _has_any_, c4::yml::extra::ievt::ANCH, c4::yml::extra::ievt::VAL_, c4::yml::VALANCH, and c4::yml::VALREF.

◆ set_key_ref()

void c4::yml::extra::EventHandlerInts::set_key_ref ( csubstr  ref)
inline

Definition at line 907 of file event_handler_ints.hpp.

908  {
909  _c4dbgpf("{}/{}: set_key_ref: {}", m_evt_pos, m_evt_size, ref);
910  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, ref.begins_with('*'));
911  if(C4_UNLIKELY(_has_any_(KEYANCH)))
912  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "key cannot have both anchor and ref");
913  _enable_(c4::yml::KEY|c4::yml::KEYREF);
914  _send_str_(ref.sub(1), ievt::KEY_|ievt::ALIA); // skip the leading *
915  }
@ ALIA
*ref (reference)

References _has_any_, c4::yml::extra::ievt::ALIA, c4::yml::KEY, c4::yml::extra::ievt::KEY_, c4::yml::KEYANCH, and c4::yml::KEYREF.

◆ set_val_ref()

void c4::yml::extra::EventHandlerInts::set_val_ref ( csubstr  ref)
inline

Definition at line 916 of file event_handler_ints.hpp.

917  {
918  _c4dbgpf("{}/{}: set_val_ref: {}", m_evt_pos, m_evt_size, ref);
919  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, ref.begins_with('*'));
920  if(C4_UNLIKELY(_has_any_(VALANCH)))
921  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "val cannot have both anchor and ref");
922  _enable_(c4::yml::VAL|c4::yml::VALREF);
923  _send_str_(ref.sub(1), ievt::VAL_|ievt::ALIA); // skip the leading *
924  }

References _has_any_, c4::yml::extra::ievt::ALIA, c4::yml::VAL, c4::yml::extra::ievt::VAL_, c4::yml::VALANCH, and c4::yml::VALREF.

◆ set_key_tag()

void c4::yml::extra::EventHandlerInts::set_key_tag ( csubstr  tag)
inline

Definition at line 933 of file event_handler_ints.hpp.

934  {
935  _c4dbgpf("{}/{}: set key tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, tag.len, tag.str ? tag : csubstr("(arena full)"));
936  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, _is_sub_(tag));
937  _enable_(c4::yml::KEYTAG);
939  }
@ KEYTAG
the key has a tag
Definition: node_type.hpp:47
bool _is_sub_(csubstr str) const noexcept

References c4::yml::extra::ievt::KEY_, c4::yml::KEYTAG, and c4::yml::extra::ievt::TAG_.

◆ set_val_tag()

void c4::yml::extra::EventHandlerInts::set_val_tag ( csubstr  tag)
inline

Definition at line 940 of file event_handler_ints.hpp.

941  {
942  _c4dbgpf("{}/{}: set val tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, tag.len, tag.str ? tag : csubstr("(arena full)"));
943  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, _is_sub_(tag));
944  _enable_(c4::yml::VALTAG);
946  }
@ VALTAG
the val has a tag
Definition: node_type.hpp:48

References c4::yml::extra::ievt::TAG_, c4::yml::extra::ievt::VAL_, and c4::yml::VALTAG.

◆ add_directive_yaml()

void c4::yml::extra::EventHandlerInts::add_directive_yaml ( csubstr  yaml_version)
inline

Definition at line 955 of file event_handler_ints.hpp.

956  {
957  _c4dbgpf("{}/{}: %YAML directive! version={}", m_evt_pos, m_evt_size, yaml_version);
958  _send_str_(yaml_version, ievt::YAML);
959  }
@ YAML
yaml directive: \YAML <version>

References c4::yml::extra::ievt::YAML.

◆ add_directive_tag()

void c4::yml::extra::EventHandlerInts::add_directive_tag ( csubstr  handle,
csubstr  prefix 
)
inline

Definition at line 961 of file event_handler_ints.hpp.

962  {
963  _c4dbgpf("{}/{}: %TAG directive! handle={} prefix={} doc_id={}", m_evt_pos, m_evt_size, handle, prefix, m_curr_doc);
964  if(C4_UNLIKELY(!m_tag_directives.add(handle, prefix, m_curr_doc)))
965  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "too many %TAG directives");
966  _send_str_(handle, ievt::TAGH);
967  _send_str_(prefix, ievt::TAGP);
968  }
@ TAGH
tag directive, handle: \TAG <handle> ........
@ TAGP
tag directive, prefix: \TAG ........ <prefix>

References c4::yml::TagDirectives::add(), c4::yml::extra::ievt::TAGH, and c4::yml::extra::ievt::TAGP.

◆ actually_val_is_first_key_of_new_map_flow()

void c4::yml::extra::EventHandlerInts::actually_val_is_first_key_of_new_map_flow ( )
inline

set the previous val as the first key of a new map, with flow style.

See the documentation for Event Handlers, which has important notes about this event.

Definition at line 982 of file event_handler_ints.hpp.

983  {
984  _c4dbgpf("{}/{}: prev={} actually_val_is_first_key_of_new_map_flow", m_evt_pos, m_evt_size, m_evt_prev);
985  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt_pos > 2);
986  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt_prev > 0);
987  // BEFORE
988  // ... flag start len (free)
989  // | |
990  // prev curr
991  // AFTER
992  // ... BMAP flag start len (free)
993  // | |
994  // prev curr
995  if(m_evt_pos < m_evt_size)
996  {
997  if(m_evt[m_evt_prev] & ievt::WSTR)
998  {
999  _c4dbgpf("{}/{}: WSTR", m_evt_pos, m_evt_size);
1000  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt_prev > 0);
1001  int32_t pos = _extend_left_to_include_tag_and_or_anchor(m_evt_prev);
1002  if(m_evt_pos + 1 < m_evt_size)
1003  {
1004  for(int32_t i = pos; i <= m_evt_prev; i = _next(i))
1005  {
1006  m_evt[i] |= ievt::KEY_;
1007  m_evt[i] &= ~ievt::VAL_;
1008  }
1009  int32_t num_move = m_evt_pos + 1 - pos;
1010  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, num_move > 0);
1011  memmove(m_evt + pos + 1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
1012  }
1013  m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_;
1014  // move PSTR to prev
1015  if(m_evt[pos + 1] & ievt::PSTR)
1016  {
1017  m_evt[pos ] |= ievt::PSTR;
1018  m_evt[pos + 1] &= ~ievt::PSTR;
1019  }
1020  }
1021  else
1022  {
1023  _c4dbgpf("{}/{}: container key", m_evt_pos, m_evt_size);
1024  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[m_evt_prev] & (ievt::EMAP|ievt::ESEQ)));
1025  int32_t pos;
1026  _c4dbgpf("{}/{}: find matching open for {}", m_evt_pos, m_evt_size, m_evt_prev);
1027  if((m_evt[m_evt_prev] & ievt::EMAP) == ievt::EMAP)
1028  {
1029  pos = _find_matching_open(ievt::BMAP, ievt::EMAP, m_evt_prev);
1030  }
1031  else
1032  {
1033  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[m_evt_prev] & ievt::ESEQ));
1034  pos = _find_matching_open(ievt::BSEQ, ievt::ESEQ, m_evt_prev);
1035  }
1036  _c4dbgpf("{}/{}: matching open for {}={}", m_evt_pos, m_evt_size, m_evt_prev, pos);
1037  _RYML_CHECK_BASIC_(m_stack.m_callbacks, pos >= 0); // internal error
1038  _RYML_CHECK_BASIC_(m_stack.m_callbacks, pos < m_evt_prev); // internal error
1039  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & ievt::ESEQ) == (m_evt[m_evt_prev] & ievt::BSEQ));
1040  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & ievt::EMAP) == (m_evt[m_evt_prev] & ievt::BMAP));
1041  // shift the array one position to the right, starting at pos
1042  int32_t posp1 = pos + 1;
1043  if(m_evt_pos + 1 < m_evt_size)
1044  {
1045  int32_t num_move = m_evt_pos + 1 - pos;
1046  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, num_move > 0);
1047  memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
1048  }
1049  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, posp1 < m_evt_pos);
1050  // start the map
1051  m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_;
1052  // set next as key, not val
1053  m_evt[posp1] |= ievt::KEY_;
1054  m_evt[posp1] &= ~ievt::VAL_;
1055  // move PSTR to pos
1056  if(m_evt[posp1] & ievt::PSTR)
1057  {
1058  m_evt[pos] |= ievt::PSTR;
1059  m_evt[posp1] &= ~ievt::PSTR;
1060  }
1061  }
1062  }
1063  m_curr->evt_id = m_evt_pos - 2;
1064  ++m_evt_prev;
1065  ++m_evt_pos;
1066  _enable_(c4::yml::MAP|c4::yml::FLOW_SL);
1067  _push();
1068  }
int32_t _next(int32_t pos) const noexcept
int32_t _find_matching_open(ievt::DataType open, ievt::DataType close, int32_t pos) const
int32_t _extend_left_to_include_tag_and_or_anchor(int32_t pos) const

References c4::yml::extra::ievt::BMAP, c4::yml::extra::ievt::BSEQ, c4::yml::extra::ievt::EMAP, c4::yml::extra::ievt::ESEQ, c4::yml::extra::ievt::FLOW, c4::yml::FLOW_SL, c4::yml::extra::ievt::KEY_, c4::yml::MAP, c4::yml::extra::ievt::PSTR, c4::yml::extra::ievt::VAL_, and c4::yml::extra::ievt::WSTR.

◆ actually_val_is_first_key_of_new_map_block()

void c4::yml::extra::EventHandlerInts::actually_val_is_first_key_of_new_map_block ( )
inline

like its flow counterpart, but this function can only be called after the end of a flow-val at root or doc level.

See the documentation for Event Handlers, which has important notes about this event.

Definition at line 1076 of file event_handler_ints.hpp.

1077  {
1078  _c4dbgpf("{}/{}: prev={} actually_val_is_first_key_of_new_map_block", m_evt_pos, m_evt_size, m_evt_prev);
1079  if(m_evt_pos < m_evt_size)
1080  {
1081  // interpolate BMAP|VAL|BLCK after the last BDOC
1082  int32_t pos = _find_last_bdoc(m_evt_pos);
1083  if(pos >= 0)
1084  {
1085  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size);
1086  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_pos);
1087  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & ievt::BDOC) == ievt::BDOC);
1088  if(m_evt_pos < m_evt_size)
1089  {
1090  ++pos; // add 1 to write after BDOC
1091  int32_t num_move = m_evt_pos - pos;
1092  int32_t posp1 = pos + 1;
1093  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, ((m_evt[pos] & ievt::BSEQ) == ievt::BSEQ) || ((m_evt[pos] & ievt::BMAP) == ievt::BMAP));
1094  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, num_move > 0);
1095  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, 0 == (m_evt[posp1] & ievt::PSTR));
1096  memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
1097  m_evt[pos] = ievt::VAL_|ievt::BMAP|ievt::BLCK;
1098  m_evt[posp1] &= ~ievt::VAL_;
1099  m_evt[posp1] |= ievt::KEY_;
1100  }
1101  }
1102  }
1103  ++m_curr->evt_id;
1104  ++m_evt_prev;
1105  ++m_evt_pos;
1106  _push();
1107  }
int32_t _find_last_bdoc(int32_t pos) const

References c4::yml::extra::ievt::BDOC, c4::yml::extra::ievt::BLCK, c4::yml::extra::ievt::BMAP, c4::yml::extra::ievt::BSEQ, c4::yml::extra::ievt::KEY_, c4::yml::extra::ievt::PSTR, and c4::yml::extra::ievt::VAL_.

◆ arena()

substr c4::yml::extra::EventHandlerInts::arena ( )
inline

Definition at line 1116 of file event_handler_ints.hpp.

1117  {
1118  return m_arena.first(m_arena_pos < m_arena.len ? m_arena_pos : m_arena.len);
1119  }

◆ arena_rem()

substr c4::yml::extra::EventHandlerInts::arena_rem ( )
inline

Definition at line 1120 of file event_handler_ints.hpp.

1121  {
1122  return C4_LIKELY(m_arena_pos <= m_arena.len) ? m_arena.sub(m_arena_pos) : m_arena.last(0);
1123  }

◆ alloc_arena()

substr c4::yml::extra::EventHandlerInts::alloc_arena ( size_t  len)
inline

this may fail, in which case an empty string is returned

Definition at line 1125 of file event_handler_ints.hpp.

1126  {
1127  substr s = arena_rem();
1128  if(C4_LIKELY(len <= s.len))
1129  s.len = len;
1130  else
1131  s.str = nullptr;
1132  m_arena_pos += len;
1133  return s;
1134  }

◆ _push()

void c4::yml::extra::EventHandlerInts::_push ( )
inline

push a new parent, add a child to the new parent, and set the child as the current node

Definition at line 1145 of file event_handler_ints.hpp.

1146  {
1147  _stack_push();
1148  m_curr->evt_type = {};
1149  }

◆ _pop()

void c4::yml::extra::EventHandlerInts::_pop ( )
inline

end the current scope

Definition at line 1152 of file event_handler_ints.hpp.

◆ _enable__()

template<c4::yml::type_bits bits>
void c4::yml::extra::EventHandlerInts::_enable__ ( )
inlinenoexcept

Definition at line 1157 of file event_handler_ints.hpp.

1158  {
1159  m_curr->evt_type |= bits;
1160  }

◆ _disable__()

template<c4::yml::type_bits bits>
void c4::yml::extra::EventHandlerInts::_disable__ ( )
inlinenoexcept

Definition at line 1161 of file event_handler_ints.hpp.

1162  {
1163  m_curr->evt_type &= ~bits;
1164  }

◆ _has_any__()

template<c4::yml::type_bits bits>
bool c4::yml::extra::EventHandlerInts::_has_any__ ( ) const
inlinenoexcept

Definition at line 1165 of file event_handler_ints.hpp.

1166  {
1167  return (m_curr->evt_type & bits) != c4::yml::type_bits(0);
1168  }
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
Definition: node_type.hpp:30

◆ _next()

int32_t c4::yml::extra::EventHandlerInts::_next ( int32_t  pos) const
inlinenoexcept

Definition at line 1170 of file event_handler_ints.hpp.

1171  {
1172  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size);
1173  return pos + ((m_evt[pos] & ievt::WSTR) ? 3 : 1);
1174  }

References c4::yml::extra::ievt::WSTR.

◆ _prev()

int32_t c4::yml::extra::EventHandlerInts::_prev ( int32_t  pos) const
inlinenoexcept

Definition at line 1176 of file event_handler_ints.hpp.

1177  {
1178  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size);
1179  return pos - ((m_evt[pos] & ievt::PSTR) ? 3 : 1);
1180  }

References c4::yml::extra::ievt::PSTR.

◆ _is_sub_()

bool c4::yml::extra::EventHandlerInts::_is_sub_ ( csubstr  str) const
inlinenoexcept

Definition at line 1182 of file event_handler_ints.hpp.

1183  {
1184  return (!str.str || str.is_sub(m_src) || str.is_sub(m_arena));
1185  }

◆ _send_flag_only_()

void c4::yml::extra::EventHandlerInts::_send_flag_only_ ( ievt::DataType  flags)
inline

Definition at line 1187 of file event_handler_ints.hpp.

1188  {
1189  _c4dbgpf("{}/{}: flag only", m_evt_pos, m_evt_size);
1190  if(m_evt_pos < m_evt_size)
1191  m_evt[m_evt_pos] |= flags;
1192  m_curr->evt_id = m_evt_pos;
1193  m_evt_prev = m_evt_pos;
1194  ++m_evt_pos;
1195  if(m_evt_pos < m_evt_size)
1196  m_evt[m_evt_pos] = {};
1197  }

◆ _send_str_()

void c4::yml::extra::EventHandlerInts::_send_str_ ( csubstr  scalar,
ievt::DataType  flags 
)
inline

Definition at line 1199 of file event_handler_ints.hpp.

1200  {
1201  _c4dbgpf("{}/{}: send str", m_evt_pos, m_evt_size);
1202  if(m_evt_pos + 3 < m_evt_size)
1203  {
1204  m_evt[m_evt_pos] |= flags;
1205  _add_scalar_(m_evt_pos, scalar);
1206  }
1207  m_curr->evt_id = m_evt_pos;
1208  m_evt_prev = m_evt_pos;
1209  m_evt_pos += 3;
1210  }

◆ _mark_parent_with_children_()

void c4::yml::extra::EventHandlerInts::_mark_parent_with_children_ ( )
inline

Definition at line 1212 of file event_handler_ints.hpp.

1213  {
1214  if(m_parent)
1215  m_parent->has_children = true;
1216  }

◆ _get_latest_empty_scalar()

csubstr c4::yml::extra::EventHandlerInts::_get_latest_empty_scalar ( ) const
inline

Definition at line 1218 of file event_handler_ints.hpp.

1219  {
1220  // ideally we should search back in the latest event that has
1221  // a scalar, then select a zero-length scalar immediately
1222  // after that scalar. But this also works for now:
1223  return m_src.first(0);
1224  }

◆ _find_last_bdoc()

int32_t c4::yml::extra::EventHandlerInts::_find_last_bdoc ( int32_t  pos) const
inline

Definition at line 1226 of file event_handler_ints.hpp.

1227  {
1228  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size); // it's safe to read from the array
1229  while(pos >= 0)
1230  {
1231  ievt::DataType e = m_evt[pos];
1232  if((e & ievt::BDOC) == ievt::BDOC)
1233  return pos;
1234  pos -= (e & ievt::PSTR) ? 3 : 1;
1235  }
1236  return -1; // LCOV_EXCL_LINE
1237  }

References c4::yml::extra::ievt::BDOC, and c4::yml::extra::ievt::PSTR.

◆ _find_matching_open()

int32_t c4::yml::extra::EventHandlerInts::_find_matching_open ( ievt::DataType  open,
ievt::DataType  close,
int32_t  pos 
) const
inline

Definition at line 1239 of file event_handler_ints.hpp.

1240  {
1241  _c4dbgpf("find_matching: start at {}", pos);
1242  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size);
1243  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & close) == close);
1244  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & open) == (close & ~ievt::END_));
1245  pos = _prev(pos); // don't count the starting close token
1246  uint32_t count = 0;
1247  while(pos >= 0)
1248  {
1249  ievt::DataType e = m_evt[pos];
1250  _c4dbgpf("find_matching: pos={} count={} e={}", pos, count, m_evt[pos]);
1251  if((e & close) == close)
1252  {
1253  _c4dbgpf(".............: pos={} close! count={} e={}", pos, count, m_evt[pos]);
1254  ++count;
1255  }
1256  else if((e & open) == open)
1257  {
1258  _c4dbgpf(".............: pos={} open! count={} e={}", pos, count, m_evt[pos]);
1259  if(!count)
1260  return pos;
1261  else
1262  --count;
1263  }
1264  pos = _prev(pos);
1265  }
1266  _c4dbgpf("find_matching: not found!", 0); // LCOV_EXCL_LINE
1267  return -1; // LCOV_EXCL_LINE
1268  }
int32_t _prev(int32_t pos) const noexcept

References c4::yml::extra::ievt::END_.

◆ _extend_left_to_include_tag_and_or_anchor()

int32_t c4::yml::extra::EventHandlerInts::_extend_left_to_include_tag_and_or_anchor ( int32_t  pos) const
inline

Definition at line 1270 of file event_handler_ints.hpp.

1271  {
1272  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size);
1273  int32_t prev = _prev(pos);
1274  while((prev > 0) && (m_evt[prev] & (ievt::TAG_|ievt::ANCH)))
1275  {
1276  _c4dbgpf("{}/{}: {} is anchor/tag. extend to {}", m_evt_pos, m_evt_size, prev, prev);
1277  pos = prev;
1278  prev = _prev(prev);
1279  }
1280  return pos;
1281  }

References c4::yml::extra::ievt::ANCH, and c4::yml::extra::ievt::TAG_.

◆ _stack_start_parse()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_start_parse ( const char *  filename,
substr  ymlsrc 
)
inlineprotectedinherited

Definition at line 58 of file event_handler_stack.hpp.

59  {
60  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_curr != nullptr);
61  m_curr->start_parse(filename, m_curr->node_id);
62  m_src = ymlsrc;
63  }

◆ _stack_finish_parse()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_finish_parse ( )
inlineprotectedinherited

Definition at line 65 of file event_handler_stack.hpp.

66  {
67  }

◆ _stack_reset_root()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_reset_root ( )
inlineprotectedinherited

Definition at line 71 of file event_handler_stack.hpp.

72  {
73  m_stack.clear();
74  m_stack.push({});
75  m_parent = nullptr;
76  m_curr = &m_stack.top();
77  }

◆ _stack_reset_non_root()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_reset_non_root ( )
inlineprotectedinherited

Definition at line 79 of file event_handler_stack.hpp.

80  {
81  m_stack.clear();
82  m_stack.push({}); // parent
83  m_stack.push({}); // node
84  m_parent = &m_stack.top(1);
85  m_curr = &m_stack.top();
86  }

◆ _stack_push()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_push ( )
inlineprotectedinherited

Definition at line 88 of file event_handler_stack.hpp.

89  {
90  m_stack.push_top();
91  m_parent = &m_stack.top(1); // don't use m_curr. watch out for relocations inside the prev push
92  m_curr = &m_stack.top();
93  m_curr->reset_after_push();
94  }

◆ _stack_pop()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_pop ( )
inlineprotectedinherited

Definition at line 96 of file event_handler_stack.hpp.

97  {
98  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_parent);
99  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_stack.size() > 1);
100  m_parent->reset_before_pop(*m_curr);
101  m_stack.pop();
102  m_parent = m_stack.size() > 1 ? &m_stack.top(1) : nullptr;
103  m_curr = &m_stack.top();
104  #ifdef RYML_DBG
105  if(m_parent)
106  _c4dbgpf("popped! top is now node={} (parent={})", m_curr->node_id, m_parent->node_id);
107  else
108  _c4dbgpf("popped! top is now node={} @ ROOT", m_curr->node_id);
109  #endif
110  }

◆ _stack_should_push_on_begin_doc()

bool c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_should_push_on_begin_doc ( ) const
inlineprotectedinherited

Definition at line 121 of file event_handler_stack.hpp.

122  {
123  const bool is_root = (m_stack.size() == 1u);
124  return is_root && (m_curr->has_children || _has_any_(DOC|VAL|MAP|SEQ));
125  }

◆ _stack_should_pop_on_end_doc()

bool c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_should_pop_on_end_doc ( ) const
inlineprotectedinherited

Definition at line 127 of file event_handler_stack.hpp.

128  {
129  const bool is_root = (m_stack.size() == 1u);
130  return !is_root && _has_any_(DOC);
131  }

Member Data Documentation

◆ m_stack

detail::stack<state> c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::m_stack
inherited

Definition at line 46 of file event_handler_stack.hpp.

◆ m_curr

state* c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::m_curr
inherited

current stack level: top of the stack. cached here for easier access.

Definition at line 47 of file event_handler_stack.hpp.

◆ m_parent

state* c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::m_parent
inherited

parent of the current stack level.

Definition at line 48 of file event_handler_stack.hpp.

◆ m_src

substr c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::m_src
inherited

Definition at line 49 of file event_handler_stack.hpp.


The documentation for this struct was generated from the following file: