rapidyaml  0.11.1
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 buffer of integers (see ievt::EventFlags) containing masks (to represent events) and offset+length (to represent strings in the source buffer). More...

#include <event_handler_ints.hpp>

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

Public Types

using pfn_relocate_arena = detail::pfn_relocate_arena
 
types
using value_type = ievt::DataType
 
using state = EventHandlerIntsState
 

Public Member Functions

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
 
void _mark_parent_with_children_ ()
 
void _send_flag_only_ (ievt::DataType flags)
 
void _send_key_scalar_ (csubstr scalar, ievt::DataType flags)
 
void _send_val_scalar_ (csubstr scalar, ievt::DataType flags)
 
void _send_str_ (csubstr scalar, ievt::DataType flags)
 
void _clear_tag_directives_ ()
 
id_type _num_tag_directives () const
 
csubstr _transform_directive (csubstr tag)
 
void check_trailing_doc_token () const
 Check whether the current parse tokens are trailing on the previous doc, and raise an error if they are. More...
 
construction and resetting
 EventHandlerInts (c4::yml::Callbacks const &cb)
 
 EventHandlerInts ()
 
void reset (csubstr 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 buffer successfully accomodated all the parse events. More...
 
void reserve_arena (int)
 
parse events
void start_parse (const char *filename, csubstr src, c4::yml::detail::pfn_relocate_arena relocate_arena, void *relocate_arena_data)
 
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 ()
 
csubstr _get_latest_empty_scalar () const
 
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)
 
void _set_tag (csubstr tag, ievt::DataType which)
 
YAML directive events
void add_directive (csubstr directive)
 
YAML arena events
substr arena_rem ()
 
substr alloc_arena (size_t len)
 this may fail, in which case a an empty string is returned More...
 
substr alloc_arena (size_t len, substr *relocated)
 this may fail, in which case an empty string is returned More...
 

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...
 
pfn_relocate_arena m_relocate_arena
 callback when the arena gets relocated More...
 
void * m_relocate_arena_data
 
csubstr m_src
 

Protected Member Functions

void _stack_start_parse (const char *filename, csubstr ymlsrc, pfn_relocate_arena relocate_arena, void *relocate_arena_data)
 
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
 
void _stack_relocate_to_new_arena (csubstr prev, substr curr)
 
substr _stack_relocate_to_new_arena (csubstr s, csubstr prev, substr curr)
 

Detailed Description

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).

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 435 of file event_handler_ints.hpp.

Member Typedef Documentation

◆ value_type

◆ state

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

Definition at line 442 of file event_handler_ints.hpp.

◆ pfn_relocate_arena

Definition at line 47 of file event_handler_stack.hpp.

Constructor & Destructor Documentation

◆ EventHandlerInts() [1/2]

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

Definition at line 470 of file event_handler_ints.hpp.

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

◆ EventHandlerInts() [2/2]

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

Definition at line 475 of file event_handler_ints.hpp.

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

Member Function Documentation

◆ reset()

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

Definition at line 480 of file event_handler_ints.hpp.

481  {
484  m_curr->evt_type = {};
485  m_curr->evt_id = 0;
486  m_arena = arena;
487  m_arena_pos = 0;
488  m_src = str;
489  m_evt = dst;
490  m_evt_size = dst_size;
491  m_evt_pos = 0;
492  m_evt_prev = 0;
493  m_has_docs = false;
494  m_has_yaml_directive = false;
495  for(TagDirective &td : m_tag_directives)
496  td = {};
497  }
@ 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::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 501 of file event_handler_ints.hpp.

502  {
503  return m_evt_pos;
504  }

◆ 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 508 of file event_handler_ints.hpp.

509  {
510  return m_arena_pos;
511  }

◆ fits_buffers()

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

Predicate to test if the event buffer successfully accomodated all the parse events.

Warning
this is valid only until the next parse

Definition at line 516 of file event_handler_ints.hpp.

517  {
518  return m_evt_pos <= m_evt_size && m_arena_pos <= m_arena.len;
519  }

◆ reserve_arena()

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

Definition at line 521 of file event_handler_ints.hpp.

522  {
523  // does not apply here
524  }

◆ start_parse()

void c4::yml::extra::EventHandlerInts::start_parse ( const char *  filename,
csubstr  src,
c4::yml::detail::pfn_relocate_arena  relocate_arena,
void *  relocate_arena_data 
)
inline

Definition at line 533 of file event_handler_ints.hpp.

534  {
535  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, src.str == m_src.str);
536  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, src.len == m_src.len);
537  this->_stack_start_parse(filename, src, relocate_arena, relocate_arena_data);
538  }
void _stack_start_parse(const char *filename, csubstr ymlsrc, pfn_relocate_arena relocate_arena, void *relocate_arena_data)

◆ finish_parse()

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

Definition at line 540 of file event_handler_ints.hpp.

541  {
542  if((_num_tag_directives() || m_has_yaml_directive) && !m_has_docs)
543  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "directives cannot be used without a document");
544  this->_stack_finish_parse();
545  }

◆ cancel_parse()

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

Definition at line 547 of file event_handler_ints.hpp.

548  {
549  while(m_stack.size() > 1)
550  _pop();
551  }
void _pop()
end the current scope

◆ begin_stream()

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

Definition at line 560 of file event_handler_ints.hpp.

561  {
563  }
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 565 of file event_handler_ints.hpp.

566  {
568  }

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

◆ begin_doc()

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

implicit doc start (without —)

Definition at line 578 of file event_handler_ints.hpp.

579  {
580  _c4dbgpf("{}/{}: begin_doc", m_evt_pos, m_evt_size);
583  {
584  _c4dbgp("push!");
585  _push();
586  _enable_(DOC);
587  }
588  m_has_docs = true;
589  }
@ DOC
a document
Definition: node_type.hpp:40
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 591 of file event_handler_ints.hpp.

592  {
593  _c4dbgpf("{}/{}: end_doc", m_evt_pos, m_evt_size);
596  {
597  _c4dbgp("pop!");
598  _pop();
599  }
600  }

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 603 of file event_handler_ints.hpp.

604  {
605  _c4dbgpf("{}/{}: begin_doc_expl", m_evt_pos, m_evt_size);
607  _c4dbgp("push!");
608  _push();
609  _enable_(DOC);
610  m_has_docs = true;
611  }
@ 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 613 of file event_handler_ints.hpp.

614  {
615  _c4dbgpf("{}/{}: end_doc_expl", m_evt_pos, m_evt_size);
618  {
619  _c4dbgp("pop!");
620  _pop();
621  }
622  m_has_yaml_directive = false;
623  }

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 632 of file event_handler_ints.hpp.

633  {
634  _c4dbgpf("{}/{}: bmap key flow", m_evt_pos, m_evt_size);
638  _push();
639  }
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
Definition: node_type.hpp:38
@ KEY
is member of a map
Definition: node_type.hpp:36
@ FLOW_SL
mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,...
Definition: node_type.hpp:59

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 640 of file event_handler_ints.hpp.

641  {
642  _c4dbgpf("{}/{}: bmap key block", m_evt_pos, m_evt_size);
646  _push();
647  }
@ BLOCK
mark container with block style (seqs as '- val ', maps as 'key: val')
Definition: node_type.hpp:61

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 649 of file event_handler_ints.hpp.

650  {
651  _c4dbgpf("{}/{}: bmap flow", m_evt_pos, m_evt_size);
654  _enable_(c4::yml::MAP|c4::yml::FLOW_SL);
655  _push();
656  }

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 657 of file event_handler_ints.hpp.

658  {
659  _c4dbgpf("{}/{}: bmap block", m_evt_pos, m_evt_size);
662  _enable_(c4::yml::MAP|c4::yml::BLOCK);
663  _push();
664  }

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 666 of file event_handler_ints.hpp.

667  {
668  _pop();
670  }

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

◆ end_map_flow()

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

Definition at line 672 of file event_handler_ints.hpp.

673  {
674  _pop();
676  }

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

◆ begin_seq_key_flow()

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

Definition at line 685 of file event_handler_ints.hpp.

686  {
687  _c4dbgpf("{}/{}: bseq key flow", m_evt_pos, m_evt_size);
691  _push();
692  }
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
Definition: node_type.hpp:39

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 693 of file event_handler_ints.hpp.

694  {
695  _c4dbgpf("{}/{}: bseq key block", m_evt_pos, m_evt_size);
699  _push();
700  }

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 702 of file event_handler_ints.hpp.

703  {
704  _c4dbgpf("{}/{}: bseq flow", m_evt_pos, m_evt_size);
707  _enable_(c4::yml::SEQ|c4::yml::FLOW_SL);
708  _push();
709  }

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 710 of file event_handler_ints.hpp.

711  {
712  _c4dbgpf("{}/{}: bseq block", m_evt_pos, m_evt_size);
715  _enable_(c4::yml::SEQ|c4::yml::BLOCK);
716  _push();
717  }

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 719 of file event_handler_ints.hpp.

720  {
721  _pop();
723  }

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

◆ end_seq_flow()

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

Definition at line 725 of file event_handler_ints.hpp.

726  {
727  _pop();
729  }

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

◆ add_sibling()

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

Definition at line 738 of file event_handler_ints.hpp.

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

◆ 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 749 of file event_handler_ints.hpp.

750  {
751  _c4dbgpf("{}/{}: prev={} actually_val_is_first_key_of_new_map_flow", m_evt_pos, m_evt_size, m_evt_prev);
752  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt_pos > 2);
753  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt_prev > 0);
754  // BEFORE
755  // ... flag start len (free)
756  // | |
757  // prev curr
758  // AFTER
759  // ... BMAP flag start len (free)
760  // | |
761  // prev curr
762  if(m_evt_prev + 1 < m_evt_size)
763  {
764  if(m_evt[m_evt_prev] & ievt::WSTR)
765  {
766  _c4dbgpf("{}/{}: WSTR", m_evt_pos, m_evt_size);
767  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt_prev > 0);
768  int32_t pos = _extend_left_to_include_tag_and_or_anchor(m_evt_prev);
769  if(m_evt_pos + 1 < m_evt_size)
770  {
771  for(int32_t i = pos; i <= m_evt_prev; i = _next(i))
772  {
773  m_evt[i] |= ievt::KEY_;
774  m_evt[i] &= ~ievt::VAL_;
775  }
776  int32_t num_move = m_evt_pos + 1 - pos;
777  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, num_move > 0);
778  memmove(m_evt + pos + 1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
779  }
780  m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_;
781  // move PSTR to prev
782  if(m_evt[pos + 1] & ievt::PSTR)
783  {
784  m_evt[pos ] |= ievt::PSTR;
785  m_evt[pos + 1] &= ~ievt::PSTR;
786  }
787  }
788  else
789  {
790  _c4dbgpf("{}/{}: container key", m_evt_pos, m_evt_size);
791  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[m_evt_prev] & (ievt::EMAP|ievt::ESEQ)));
792  int32_t pos;
793  _c4dbgpf("{}/{}: find matching open for {}", m_evt_pos, m_evt_size, m_evt_prev);
794  if((m_evt[m_evt_prev] & ievt::EMAP) == ievt::EMAP)
795  {
796  pos = _find_matching_open(ievt::BMAP, ievt::EMAP, m_evt_prev);
797  }
798  else
799  {
800  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[m_evt_prev] & ievt::ESEQ));
801  pos = _find_matching_open(ievt::BSEQ, ievt::ESEQ, m_evt_prev);
802  }
803  _c4dbgpf("{}/{}: matching open for {}={}", m_evt_pos, m_evt_size, m_evt_prev, pos);
804  _RYML_CHECK_BASIC_(m_stack.m_callbacks, pos >= 0); // internal error
805  _RYML_CHECK_BASIC_(m_stack.m_callbacks, pos < m_evt_prev); // internal error
806  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & ievt::ESEQ) == (m_evt[m_evt_prev] & ievt::BSEQ));
807  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & ievt::EMAP) == (m_evt[m_evt_prev] & ievt::BMAP));
808  // shift the array one position to the right, starting at pos
809  int32_t posp1 = pos + 1;
810  if(m_evt_pos + 1 < m_evt_size)
811  {
812  int32_t num_move = m_evt_pos + 1 - pos;
813  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, num_move > 0);
814  memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
815  }
816  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, posp1 < m_evt_pos);
817  // start the map
818  m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_;
819  // set next as key, not val
820  m_evt[posp1] |= ievt::KEY_;
821  m_evt[posp1] &= ~ievt::VAL_;
822  // move PSTR to pos
823  if(m_evt[posp1] & ievt::PSTR)
824  {
825  m_evt[pos] |= ievt::PSTR;
826  m_evt[posp1] &= ~ievt::PSTR;
827  }
828  }
829  }
830  m_curr->evt_id = m_evt_pos - 2;
831  ++m_evt_prev;
832  ++m_evt_pos;
833  _enable_(c4::yml::MAP|c4::yml::FLOW_SL);
834  _push();
835  }

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 843 of file event_handler_ints.hpp.

844  {
845  _c4dbgpf("{}/{}: prev={} actually_val_is_first_key_of_new_map_block", m_evt_pos, m_evt_size, m_evt_prev);
846  if(m_evt_prev < m_evt_size)
847  {
848  // interpolate BMAP|VAL|BLCK after the last BDOC
849  int32_t pos = _find_last_bdoc(m_evt_pos);
850  if(pos >= 0)
851  {
852  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_size);
853  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, pos < m_evt_pos);
854  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, (m_evt[pos] & ievt::BDOC) == ievt::BDOC);
855  if(m_evt_pos < m_evt_size)
856  {
857  ++pos; // add 1 to write after BDOC
858  int32_t num_move = m_evt_pos - pos;
859  int32_t posp1 = pos + 1;
860  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, ((m_evt[pos] & ievt::BSEQ) == ievt::BSEQ) || ((m_evt[pos] & ievt::BMAP) == ievt::BMAP));
861  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, num_move > 0);
862  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, 0 == (m_evt[posp1] & ievt::PSTR));
863  memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
864  m_evt[pos] = ievt::VAL_|ievt::BMAP|ievt::BLCK;
865  m_evt[posp1] &= ~ievt::VAL_;
866  m_evt[posp1] |= ievt::KEY_;
867  }
868  }
869  }
870  ++m_curr->evt_id;
871  ++m_evt_prev;
872  ++m_evt_pos;
873  _push();
874  }

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_.

◆ set_key_scalar_plain_empty()

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

Definition at line 953 of file event_handler_ints.hpp.

954  {
955  _c4dbgpf("{}/{}: set_key_scalar_plain_empty", m_evt_pos, m_evt_size);
958  }
@ KEY_PLAIN
mark key scalar as plain scalar (unquoted, even when multiline)
Definition: node_type.hpp:70
@ KEYNIL
the key is null (eg { : b} results in a null key)
Definition: node_type.hpp:48
void _send_key_scalar_(csubstr scalar, ievt::DataType flags)

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

◆ set_val_scalar_plain_empty()

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

Definition at line 959 of file event_handler_ints.hpp.

960  {
961  _c4dbgpf("{}/{}: set_val_scalar_plain_empty", m_evt_pos, m_evt_size);
964  }
@ VALNIL
the val is null (eg {a : } results in a null val)
Definition: node_type.hpp:49
@ 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:37
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
Definition: node_type.hpp:71
void _send_val_scalar_(csubstr scalar, ievt::DataType flags)

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

◆ _get_latest_empty_scalar()

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

Definition at line 965 of file event_handler_ints.hpp.

966  {
967  // ideally we should search back in the latest event that has
968  // a scalar, then select a zero-length scalar immediately
969  // after that scalar. But this also works for now:
970  return m_src.first(0);
971  }

◆ set_key_scalar_plain()

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

Definition at line 974 of file event_handler_ints.hpp.

975  {
976  _c4dbgpf("{}/{}: set_key_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
977  _send_key_scalar_(scalar, ievt::PLAI);
979  }

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

◆ set_val_scalar_plain()

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

Definition at line 980 of file event_handler_ints.hpp.

981  {
982  _c4dbgpf("{}/{}: set_val_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
983  _send_val_scalar_(scalar, ievt::PLAI);
985  }

References c4::yml::extra::ievt::PLAI, c4::yml::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 988 of file event_handler_ints.hpp.

989  {
990  _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{});
991  _send_key_scalar_(scalar, ievt::DQUO);
993  }
@ KEY_DQUO
mark key scalar as double quoted "
Definition: node_type.hpp:68
@ DQUO
scalar: double-quoted ("")

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

◆ set_val_scalar_dquoted()

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

Definition at line 994 of file event_handler_ints.hpp.

995  {
996  _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{});
997  _send_val_scalar_(scalar, ievt::DQUO);
999  }
@ VAL_DQUO
mark val scalar as double quoted "
Definition: node_type.hpp:69

References c4::yml::extra::ievt::DQUO, c4::yml::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 1002 of file event_handler_ints.hpp.

1003  {
1004  _c4dbgpf("{}/{}: set_key_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
1005  _send_key_scalar_(scalar, ievt::SQUO);
1006  _enable_(c4::yml::KEY|c4::yml::KEY_SQUO);
1007  }
@ KEY_SQUO
mark key scalar as single quoted '
Definition: node_type.hpp:66
@ SQUO
scalar: single-quoted (')

References c4::yml::KEY, c4::yml::KEY_SQUO, 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 1008 of file event_handler_ints.hpp.

1009  {
1010  _c4dbgpf("{}/{}: set_val_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_src.str, scalar.len, scalar);
1011  _send_val_scalar_(scalar, ievt::SQUO);
1012  _enable_(c4::yml::VAL|c4::yml::VAL_SQUO);
1013  }
@ VAL_SQUO
mark val scalar as single quoted '
Definition: node_type.hpp:67

References c4::yml::extra::ievt::SQUO, c4::yml::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 1016 of file event_handler_ints.hpp.

1017  {
1018  _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{});
1019  _send_key_scalar_(scalar, ievt::LITL);
1021  }
@ KEY_LITERAL
mark key scalar as multiline, block literal |
Definition: node_type.hpp:62
@ LITL
scalar: block literal (|)

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

◆ set_val_scalar_literal()

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

Definition at line 1022 of file event_handler_ints.hpp.

1023  {
1024  _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{});
1025  _send_val_scalar_(scalar, ievt::LITL);
1027  }
@ VAL_LITERAL
mark val scalar as multiline, block literal |
Definition: node_type.hpp:63

References c4::yml::extra::ievt::LITL, c4::yml::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 1030 of file event_handler_ints.hpp.

1031  {
1032  _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{});
1033  _send_key_scalar_(scalar, ievt::FOLD);
1035  }
@ KEY_FOLDED
mark key scalar as multiline, block folded >
Definition: node_type.hpp:64
@ FOLD
scalar: block folded (>)

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

◆ set_val_scalar_folded()

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

Definition at line 1036 of file event_handler_ints.hpp.

1037  {
1038  _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{});
1039  _send_val_scalar_(scalar, ievt::FOLD);
1041  }
@ VAL_FOLDED
mark val scalar as multiline, block folded >
Definition: node_type.hpp:65

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

◆ mark_key_scalar_unfiltered()

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

Definition at line 1044 of file event_handler_ints.hpp.

1045  {
1046  _c4dbgpf("{}/{}: mark_key_scalar_unfiltered", m_evt_pos, m_evt_size);
1047  if(m_evt_pos < m_evt_size)
1048  m_evt[m_evt_pos] |= ievt::UNFILT;
1049  }
@ 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 1050 of file event_handler_ints.hpp.

1051  {
1052  _c4dbgpf("{}/{}: mark_val_scalar_unfiltered", m_evt_pos, m_evt_size);
1053  if(m_evt_pos < m_evt_size)
1054  m_evt[m_evt_pos] |= ievt::UNFILT;
1055  }

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

◆ set_key_anchor()

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

Definition at line 1084 of file event_handler_ints.hpp.

1085  {
1086  _c4dbgpf("{}/{}: set_key_anchor", m_evt_pos, m_evt_size);
1087  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, !_has_any_(KEYREF));
1088  _enable_(c4::yml::KEYANCH);
1089  if(m_evt_pos + 3 < m_evt_size)
1090  {
1091  m_evt[m_evt_pos] |= ievt::KEY_|ievt::ANCH;
1092  _add_scalar_(m_evt_pos, anchor);
1093  }
1094  m_evt_prev = m_evt_pos;
1095  m_evt_pos += 3;
1096  }
#define _has_any_(bits)
@ KEYREF
a *reference: the key references an &anchor
Definition: node_type.hpp:42
@ KEYANCH
the key has an &anchor
Definition: node_type.hpp:44

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 1097 of file event_handler_ints.hpp.

1098  {
1099  _c4dbgpf("{}/{}: set_val_anchor", m_evt_pos, m_evt_size);
1100  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, !_has_any_(VALREF));
1101  _enable_(c4::yml::VALANCH);
1102  if(m_evt_pos + 3 < m_evt_size)
1103  {
1104  m_evt[m_evt_pos] |= ievt::VAL_|ievt::ANCH;
1105  _add_scalar_(m_evt_pos, anchor);
1106  }
1107  m_evt_prev = m_evt_pos;
1108  m_evt_pos += 3;
1109  }
@ VALANCH
the val has an &anchor
Definition: node_type.hpp:45
@ VALREF
a *reference: the val references an &anchor
Definition: node_type.hpp:43

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 1111 of file event_handler_ints.hpp.

1112  {
1113  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, ref.begins_with('*'));
1114  if(C4_UNLIKELY(_has_any_(KEYANCH)))
1115  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "key cannot have both anchor and ref");
1116  _enable_(c4::yml::KEY|c4::yml::KEYREF);
1117  _send_str_(ref.sub(1), ievt::KEY_|ievt::ALIA); // skip the leading *
1118  }
@ ALIA
*ref (reference)
void _send_str_(csubstr scalar, ievt::DataType flags)

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 1119 of file event_handler_ints.hpp.

1120  {
1121  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, ref.begins_with('*'));
1122  if(C4_UNLIKELY(_has_any_(VALANCH)))
1123  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "val cannot have both anchor and ref");
1124  _enable_(c4::yml::VAL|c4::yml::VALREF);
1125  _send_str_(ref.sub(1), ievt::VAL_|ievt::ALIA); // skip the leading *
1126  }

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 1135 of file event_handler_ints.hpp.

1136  {
1137  _c4dbgpf("{}/{}: set key tag ~~~{}~~~", m_evt_pos, m_evt_size, tag);
1138  _enable_(c4::yml::KEYTAG);
1139  _set_tag(tag, ievt::KEY_);
1140  }
@ KEYTAG
the key has a tag
Definition: node_type.hpp:46
void _set_tag(csubstr tag, ievt::DataType which)

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

◆ set_val_tag()

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

Definition at line 1141 of file event_handler_ints.hpp.

1142  {
1143  _c4dbgpf("{}/{}: set val tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, tag.len, tag);
1144  _enable_(c4::yml::VALTAG);
1145  _set_tag(tag, ievt::VAL_);
1146  }
@ VALTAG
the val has a tag
Definition: node_type.hpp:47

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

◆ _set_tag()

void c4::yml::extra::EventHandlerInts::_set_tag ( csubstr  tag,
ievt::DataType  which 
)
inline

Definition at line 1147 of file event_handler_ints.hpp.

1148  {
1149  csubstr ttag = _transform_directive(tag);
1150  _c4dbgpf("{}/{}: transformed_tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, ttag.len, ttag);
1151  if(m_evt_pos + 3 < m_evt_size)
1152  {
1153  m_evt[m_evt_pos] |= which|ievt::TAG_;
1154  _add_scalar_(m_evt_pos, ttag);
1155  }
1156  m_evt_prev = m_evt_pos;
1157  m_evt_pos += 3;
1158  }

References c4::yml::extra::ievt::TAG_.

◆ add_directive()

void c4::yml::extra::EventHandlerInts::add_directive ( csubstr  directive)
inline

Definition at line 1167 of file event_handler_ints.hpp.

1168  {
1169  _c4dbgpf("{}/{}: add directive ~~~{}~~~", m_evt_pos, m_evt_size, directive);
1170  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, directive.begins_with('%'));
1171  if(directive.begins_with("%TAG"))
1172  {
1173  const id_type pos = _num_tag_directives();
1174  if(C4_UNLIKELY(pos >= RYML_MAX_TAG_DIRECTIVES))
1175  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "too many directives");
1176  TagDirective &td = m_tag_directives[pos];
1177  if(C4_UNLIKELY(!td.create_from_str(directive)))
1178  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "failed to add directive");
1179  td.next_node_id = (id_type)m_evt_pos;
1180  _send_str_(td.handle, ievt::TAGD);
1181  _send_str_(td.prefix, ievt::TAGV);
1182  }
1183  else if(directive.begins_with("%YAML"))
1184  {
1185  _c4dbgpf("%YAML directive! ignoring...: {}", directive);
1186  if(C4_UNLIKELY(m_has_yaml_directive))
1187  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "multiple yaml directives");
1188  m_has_yaml_directive = true;
1189  csubstr rest = directive.sub(5).triml(' ');
1190  _send_str_(rest, ievt::YAML);
1191  }
1192  else
1193  {
1194  _c4dbgpf("unknown directive! ignoring... {}", directive);
1195  }
1196  }
#define RYML_MAX_TAG_DIRECTIVES
the maximum number of tag directives in a Tree
Definition: tag.hpp:19
@ TAGD
tag directive, name : \TAG <name> .......
@ TAGV
tag directive, value: \TAG ...... <value>
@ YAML
yaml directive: \YAML <version>
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
Definition: common.hpp:244

References c4::yml::TagDirective::create_from_str(), c4::yml::TagDirective::handle, c4::yml::TagDirective::next_node_id, c4::yml::TagDirective::prefix, RYML_MAX_TAG_DIRECTIVES, c4::yml::extra::ievt::TAGD, c4::yml::extra::ievt::TAGV, and c4::yml::extra::ievt::YAML.

◆ arena_rem()

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

Definition at line 1205 of file event_handler_ints.hpp.

1206  {
1207  return C4_LIKELY(m_arena_pos <= m_arena.len) ? m_arena.sub(m_arena_pos) : m_arena.last(0);
1208  }

◆ alloc_arena() [1/2]

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

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

Definition at line 1211 of file event_handler_ints.hpp.

1212  {
1213  substr s = arena_rem();
1214  if(C4_LIKELY(len <= s.len))
1215  s = s.first(len);
1216  else
1217  s.str = nullptr;
1218  m_arena_pos += len;
1219  return s;
1220  }

◆ alloc_arena() [2/2]

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

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

Definition at line 1223 of file event_handler_ints.hpp.

1224  {
1225  (void)relocated;
1226  return alloc_arena(len);
1227  }
substr alloc_arena(size_t len)
this may fail, in which case a an empty string is returned

◆ _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 1235 of file event_handler_ints.hpp.

1236  {
1237  _stack_push();
1238  m_curr->evt_type = {};
1239  }

◆ _pop()

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

end the current scope

Definition at line 1242 of file event_handler_ints.hpp.

◆ _enable__()

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

Definition at line 1247 of file event_handler_ints.hpp.

1248  {
1249  m_curr->evt_type |= bits;
1250  }

◆ _disable__()

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

Definition at line 1251 of file event_handler_ints.hpp.

1252  {
1253  m_curr->evt_type &= ~bits;
1254  }

◆ _has_any__()

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

Definition at line 1255 of file event_handler_ints.hpp.

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

◆ _mark_parent_with_children_()

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

Definition at line 1260 of file event_handler_ints.hpp.

1261  {
1262  if(m_parent)
1263  m_parent->has_children = true;
1264  }

◆ _send_flag_only_()

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

Definition at line 1266 of file event_handler_ints.hpp.

1267  {
1268  _c4dbgpf("{}/{}: flag only", m_evt_pos, m_evt_size);
1269  if(m_evt_pos < m_evt_size)
1270  m_evt[m_evt_pos] |= flags;
1271  m_curr->evt_id = m_evt_pos;
1272  m_evt_prev = m_evt_pos;
1273  ++m_evt_pos;
1274  if(m_evt_pos < m_evt_size)
1275  m_evt[m_evt_pos] = {};
1276  }

◆ _send_key_scalar_()

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

Definition at line 1278 of file event_handler_ints.hpp.

1279  {
1280  _c4dbgpf("{}/{}: key scalar", m_evt_pos, m_evt_size);
1281  if(m_evt_pos + 3 < m_evt_size)
1282  {
1283  m_evt[m_evt_pos] |= ievt::SCLR|ievt::KEY_|flags;
1284  _add_scalar_(m_evt_pos, scalar);
1285  }
1286  m_curr->evt_id = m_evt_pos;
1287  m_evt_prev = m_evt_pos;
1288  m_evt_pos += 3;
1289  }

References c4::yml::extra::ievt::KEY_, and c4::yml::extra::ievt::SCLR.

◆ _send_val_scalar_()

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

Definition at line 1291 of file event_handler_ints.hpp.

1292  {
1293  _c4dbgpf("{}/{}: val scalar", m_evt_pos, m_evt_size);
1294  if(m_evt_pos + 3 < m_evt_size)
1295  {
1296  m_evt[m_evt_pos] |= ievt::SCLR|ievt::VAL_|flags;
1297  _add_scalar_(m_evt_pos, scalar);
1298  }
1299  m_curr->evt_id = m_evt_pos;
1300  m_evt_prev = m_evt_pos;
1301  m_evt_pos += 3;
1302  }

References c4::yml::extra::ievt::SCLR, and c4::yml::extra::ievt::VAL_.

◆ _send_str_()

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

Definition at line 1304 of file event_handler_ints.hpp.

1305  {
1306  _c4dbgpf("{}/{}: send str", m_evt_pos, m_evt_size);
1307  if(m_evt_pos + 3 < m_evt_size)
1308  {
1309  m_evt[m_evt_pos] |= flags;
1310  _add_scalar_(m_evt_pos, scalar);
1311  }
1312  m_curr->evt_id = m_evt_pos;
1313  m_evt_prev = m_evt_pos;
1314  m_evt_pos += 3;
1315  }

◆ _clear_tag_directives_()

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

Definition at line 1317 of file event_handler_ints.hpp.

1318  {
1319  for(TagDirective &td : m_tag_directives)
1320  td = {};
1321  }

◆ _num_tag_directives()

id_type c4::yml::extra::EventHandlerInts::_num_tag_directives ( ) const
inline

Definition at line 1322 of file event_handler_ints.hpp.

1323  {
1324  // this assumes we have a very small number of tag directives
1325  id_type i = 0;
1326  for(; i < RYML_MAX_TAG_DIRECTIVES; ++i)
1327  if(m_tag_directives[i].handle.empty())
1328  break;
1329  return i;
1330  }

References RYML_MAX_TAG_DIRECTIVES.

◆ _transform_directive()

csubstr c4::yml::extra::EventHandlerInts::_transform_directive ( csubstr  tag)
inline

Definition at line 1331 of file event_handler_ints.hpp.

1332  {
1333  // lookup from the end. We want to find the first directive that
1334  // matches the tag and has a target node id leq than the given
1335  // node_id.
1336  for(id_type i = RYML_MAX_TAG_DIRECTIVES-1; i != NONE; --i)
1337  {
1338  TagDirective const& td = m_tag_directives[i];
1339  if(td.handle.empty())
1340  continue;
1341  if(tag.begins_with(td.handle) && (td.handle != td.prefix))
1342  {
1343  substr rem = arena_rem();
1344  size_t len = td.transform(tag, rem, m_stack.m_callbacks, /*with_brackets*/false);
1345  if(len == 0)
1346  return tag;
1347  alloc_arena(len);
1348  return rem.first(len <= rem.len ? len : 0);
1349  }
1350  }
1351  if(tag.begins_with('!'))
1352  {
1353  if(is_custom_tag(tag))
1354  {
1355  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "tag not found");
1356  }
1357  }
1358  return tag;
1359  }
bool is_custom_tag(csubstr tag)
Definition: tag.cpp:9
@ NONE
an index to none
Definition: common.hpp:251

References c4::yml::TagDirective::handle, c4::yml::is_custom_tag(), c4::yml::NONE, c4::yml::TagDirective::prefix, RYML_MAX_TAG_DIRECTIVES, and c4::yml::TagDirective::transform().

◆ _stack_start_parse()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_start_parse ( const char *  filename,
csubstr  ymlsrc,
pfn_relocate_arena  relocate_arena,
void *  relocate_arena_data 
)
inlineprotectedinherited

Definition at line 65 of file event_handler_stack.hpp.

66  {
67  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_curr != nullptr);
68  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, relocate_arena != nullptr);
69  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, relocate_arena_data != nullptr);
70  m_curr->start_parse(filename, m_curr->node_id);
71  m_relocate_arena = relocate_arena;
72  m_relocate_arena_data = relocate_arena_data;
73  m_src = ymlsrc;
74  }
pfn_relocate_arena m_relocate_arena
callback when the arena gets relocated

◆ _stack_finish_parse()

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

Definition at line 76 of file event_handler_stack.hpp.

77  {
78  m_src = {};
79  }

◆ _stack_reset_root()

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

Definition at line 83 of file event_handler_stack.hpp.

84  {
85  m_stack.clear();
86  m_stack.push({});
87  m_parent = nullptr;
88  m_curr = &m_stack.top();
89  }

◆ _stack_reset_non_root()

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

Definition at line 91 of file event_handler_stack.hpp.

92  {
93  m_stack.clear();
94  m_stack.push({}); // parent
95  m_stack.push({}); // node
96  m_parent = &m_stack.top(1);
97  m_curr = &m_stack.top();
98  }

◆ _stack_push()

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

Definition at line 100 of file event_handler_stack.hpp.

101  {
102  m_stack.push_top();
103  m_parent = &m_stack.top(1); // don't use m_curr. watch out for relocations inside the prev push
104  m_curr = &m_stack.top();
105  m_curr->reset_after_push();
106  }

◆ _stack_pop()

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

Definition at line 108 of file event_handler_stack.hpp.

109  {
110  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_parent);
111  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_stack.size() > 1);
112  m_parent->reset_before_pop(*m_curr);
113  m_stack.pop();
114  m_parent = m_stack.size() > 1 ? &m_stack.top(1) : nullptr;
115  m_curr = &m_stack.top();
116  #ifdef RYML_DBG
117  if(m_parent)
118  _c4dbgpf("popped! top is now node={} (parent={})", m_curr->node_id, m_parent->node_id);
119  else
120  _c4dbgpf("popped! top is now node={} @ ROOT", m_curr->node_id);
121  #endif
122  }

◆ _stack_should_push_on_begin_doc()

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

Definition at line 129 of file event_handler_stack.hpp.

130  {
131  const bool is_root = (m_stack.size() == 1u);
132  return is_root && (_has_any_(DOC|VAL|MAP|SEQ) || m_curr->has_children);
133  }

◆ _stack_should_pop_on_end_doc()

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

Definition at line 135 of file event_handler_stack.hpp.

136  {
137  const bool is_root = (m_stack.size() == 1u);
138  return !is_root && _has_any_(DOC);
139  }

◆ _stack_relocate_to_new_arena() [1/2]

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_relocate_to_new_arena ( csubstr  prev,
substr  curr 
)
inlineprotectedinherited

Definition at line 143 of file event_handler_stack.hpp.

144  {
145  for(state &st : m_stack)
146  {
147  if(st.line_contents.rem.is_sub(prev))
148  st.line_contents.rem = _stack_relocate_to_new_arena(st.line_contents.rem, prev, curr);
149  if(st.line_contents.full.is_sub(prev))
150  st.line_contents.full = _stack_relocate_to_new_arena(st.line_contents.full, prev, curr);
151  }
152  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_relocate_arena != nullptr);
153  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_relocate_arena_data != nullptr);
155  }

◆ _stack_relocate_to_new_arena() [2/2]

substr c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::_stack_relocate_to_new_arena ( csubstr  s,
csubstr  prev,
substr  curr 
)
inlineprotectedinherited

Definition at line 157 of file event_handler_stack.hpp.

158  {
159  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, prev.is_super(s));
160  auto pos = s.str - prev.str;
161  substr out = {curr.str + pos, s.len};
162  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, curr.is_super(out));
163  return out;
164  }

◆ check_trailing_doc_token()

void c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::check_trailing_doc_token ( ) const
inlineinherited

Check whether the current parse tokens are trailing on the previous doc, and raise an error if they are.

This function is called by the parse engine (not the event handler) before a doc is started.

Definition at line 172 of file event_handler_stack.hpp.

173  {
174  const bool is_root = (m_stack.size() == 1u);
175  const bool isndoc = (m_curr->flags & NDOC) != 0;
176  const bool suspicious = _has_any_(MAP|SEQ|VAL);
177  _c4dbgpf("target={} isroot={} suspicious={} ndoc={}", m_curr->node_id, is_root, suspicious, isndoc);
178  if((is_root || _has_any_(DOC)) && suspicious && !isndoc)
179  _RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "parse error");
180  }
@ NDOC
no document mode. a document has ended and another has not started yet.

Member Data Documentation

◆ m_stack

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

Definition at line 51 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 52 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 53 of file event_handler_stack.hpp.

◆ m_relocate_arena

pfn_relocate_arena c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::m_relocate_arena
inherited

callback when the arena gets relocated

Definition at line 54 of file event_handler_stack.hpp.

◆ m_relocate_arena_data

void* c4::yml::EventHandlerStack< EventHandlerInts , EventHandlerIntsState >::m_relocate_arena_data
inherited

Definition at line 55 of file event_handler_stack.hpp.

◆ m_src

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

Definition at line 56 of file event_handler_stack.hpp.


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