rapidyaml  0.10.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 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, 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 ()
 
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 ()
 
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
 

Protected Member Functions

void _stack_start_parse (const char *filename, 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:

{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
VAL_|SCLR|PLAI|PSTR, 8, 3, // val scalar, plain style: "ccc" starts at offset 8 and has length 3
ESEQ|PSTR, // end seq
EDOC, // end doc
ESTR, // end stream
};
@ PSTR
special flag to enable look-back in the event array. it signifies that the previous event has a strin...
@ BSTR
+STR begin stream
int32_t DataType
data type for integer events.
@ FLOW
reading is inside explicit flow chars: [] or {}

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

source : [a, bb, ccc]
string offset "a" string offset "bb" string offset "ccc"
| string length "a" | string length "bb" | string length "ccc"
| | | | | |
event event event [ event "a".......|..| event "bb"...........|..| event "ccc"..........|..| event ] event event
| | | | | | | | | | | | | | |
+--------+-------+------------------+---------------+--+------+--------------------+--+------+--------------------+--+------+-------------+--------+-----|
event # : 0 1 2 3 . . 4 | . . 5 | . . 6 7 8 (event #)
index/pos: 0 1 2 3 4 5 6 | 7 8 9 | 10 11 12 13 14 (index/pos)
\ | | \ | | | \ | | |
has a string--+--+ has a string-+-----+--+ has a string-+-----+--+
| |
prev event has string prev event has string
(jump back 3 to get to it) (jump back 3 to get to it)

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.

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
{
...
}
}
@ 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...
void error(Callbacks const &cb, const char *msg, size_t msg_len, Location loc)
Definition: common.cpp:130

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 of cases 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 parsring)
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:2184

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

Definition at line 389 of file event_handler_ints.hpp.

Member Typedef Documentation

◆ value_type

◆ state

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

Definition at line 396 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 425 of file event_handler_ints.hpp.

426  : EventHandlerStack(cb)
427  {
428  reset(csubstr{}, substr{}, nullptr, 0);
429  }
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 430 of file event_handler_ints.hpp.

432  {
433  }
Callbacks const & get_callbacks()
get the global callbacks
Definition: common.cpp:118

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

436  {
439  m_curr->evt_type = {};
440  m_curr->evt_id = 0;
441  m_arena = arena;
442  m_arena_pos = 0;
443  m_str = str;
444  m_evt = dst;
445  m_evt_size = dst_size;
446  m_evt_pos = 0;
447  m_evt_prev = 0;
448  m_has_docs = false;
449  m_has_yaml_directive = false;
450  for(TagDirective &td : m_tag_directives)
451  td = {};
452  }
@ 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 456 of file event_handler_ints.hpp.

457  {
458  return m_evt_pos;
459  }

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

464  {
465  return m_arena_pos;
466  }

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

472  {
473  return m_evt_pos <= m_evt_size && m_arena_pos <= m_arena.len;
474  }

◆ reserve_arena()

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

Definition at line 476 of file event_handler_ints.hpp.

477  {
478  // does not apply here
479  }

◆ start_parse()

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

Definition at line 488 of file event_handler_ints.hpp.

489  {
490  this->_stack_start_parse(filename, relocate_arena, relocate_arena_data);
491  }
void _stack_start_parse(const char *filename, pfn_relocate_arena relocate_arena, void *relocate_arena_data)

◆ finish_parse()

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

Definition at line 493 of file event_handler_ints.hpp.

494  {
495  if((_num_tag_directives() || m_has_yaml_directive) && !m_has_docs)
496  _RYML_CB_ERR_(m_stack.m_callbacks, "directives cannot be used without a document", {});
497  this->_stack_finish_parse();
498  }

◆ cancel_parse()

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

Definition at line 500 of file event_handler_ints.hpp.

501  {
502  while(m_stack.size() > 1)
503  _pop();
504  }
void _pop()
end the current scope

◆ begin_stream()

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

Definition at line 513 of file event_handler_ints.hpp.

514  {
516  }
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 518 of file event_handler_ints.hpp.

519  {
521  }

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

◆ begin_doc()

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

implicit doc start (without —)

Definition at line 531 of file event_handler_ints.hpp.

532  {
533  _c4dbgpf("{}/{}: begin_doc", m_evt_pos, m_evt_size);
536  {
537  _c4dbgp("push!");
538  _push();
539  _enable_(DOC);
540  }
541  m_has_docs = true;
542  }
@ 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 544 of file event_handler_ints.hpp.

545  {
546  _c4dbgpf("{}/{}: end_doc", m_evt_pos, m_evt_size);
549  {
550  _c4dbgp("pop!");
551  _pop();
552  }
553  }

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

557  {
558  _c4dbgpf("{}/{}: begin_doc_expl", m_evt_pos, m_evt_size);
560  _c4dbgp("push!");
561  _push();
562  _enable_(DOC);
563  m_has_docs = true;
564  }
@ 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 566 of file event_handler_ints.hpp.

567  {
568  _c4dbgpf("{}/{}: end_doc_expl", m_evt_pos, m_evt_size);
571  {
572  _c4dbgp("pop!");
573  _pop();
574  }
575  m_has_yaml_directive = false;
576  }

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

586  {
587  _c4dbgpf("{}/{}: bmap key flow", m_evt_pos, m_evt_size);
591  _push();
592  }
@ 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
@ FLOW
flow container: [] for seqs or {} for maps

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

594  {
595  _c4dbgpf("{}/{}: bmap key block", m_evt_pos, m_evt_size);
599  _push();
600  }
@ 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 602 of file event_handler_ints.hpp.

603  {
604  _c4dbgpf("{}/{}: bmap flow", m_evt_pos, m_evt_size);
607  _enable_(c4::yml::MAP|c4::yml::FLOW_SL);
608  _push();
609  }

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

611  {
612  _c4dbgpf("{}/{}: bmap block", m_evt_pos, m_evt_size);
615  _enable_(c4::yml::MAP|c4::yml::BLOCK);
616  _push();
617  }

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

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

Definition at line 619 of file event_handler_ints.hpp.

620  {
621  _pop();
623  }

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

◆ begin_seq_key_flow()

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

Definition at line 632 of file event_handler_ints.hpp.

633  {
634  _c4dbgpf("{}/{}: bseq key flow", m_evt_pos, m_evt_size);
638  _push();
639  }
@ 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 640 of file event_handler_ints.hpp.

641  {
642  _c4dbgpf("{}/{}: bseq key block", m_evt_pos, m_evt_size);
646  _push();
647  }

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

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

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

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

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

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

Definition at line 666 of file event_handler_ints.hpp.

667  {
668  _pop();
670  }

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

◆ add_sibling()

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

Definition at line 679 of file event_handler_ints.hpp.

680  {
681  _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
682  m_curr->evt_type = {};
683  }

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

691  {
692  _c4dbgpf("{}/{}: prev={} actually_val_is_first_key_of_new_map_flow", m_evt_pos, m_evt_size, m_evt_prev);
693  _RYML_CB_ASSERT(m_stack.m_callbacks, m_evt_pos > 2);
694  _RYML_CB_ASSERT(m_stack.m_callbacks, m_evt_prev > 0);
695  // BEFORE
696  // ... flag start len (free)
697  // | |
698  // prev curr
699  // AFTER
700  // ... BMAP flag start len (free)
701  // | |
702  // prev curr
703  if(m_evt_prev + 1 < m_evt_size)
704  {
705  if(m_evt[m_evt_prev] & ievt::WSTR)
706  {
707  _c4dbgpf("{}/{}: WSTR", m_evt_pos, m_evt_size);
708  _RYML_CB_ASSERT(m_stack.m_callbacks, m_evt_prev > 0);
709  int32_t pos = _extend_left_to_include_tag_and_or_anchor(m_evt_prev);
710  if(m_evt_pos + 1 < m_evt_size)
711  {
712  for(int32_t i = pos; i <= m_evt_prev; i = _next(i))
713  {
714  m_evt[i] |= ievt::KEY_;
715  m_evt[i] &= ~ievt::VAL_;
716  }
717  int32_t num_move = m_evt_pos + 1 - pos;
718  _RYML_CB_ASSERT(m_stack.m_callbacks, num_move > 0);
719  memmove(m_evt + pos + 1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
720  }
721  m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_;
722  // move PSTR to prev
723  if(m_evt[pos + 1] & ievt::PSTR)
724  {
725  m_evt[pos ] |= ievt::PSTR;
726  m_evt[pos + 1] &= ~ievt::PSTR;
727  }
728  }
729  else
730  {
731  _c4dbgpf("{}/{}: container key", m_evt_pos, m_evt_size);
732  _RYML_CB_ASSERT(m_stack.m_callbacks, (m_evt[m_evt_prev] & (ievt::EMAP|ievt::ESEQ)));
733  int32_t pos;
734  _c4dbgpf("{}/{}: find matching open for {}", m_evt_pos, m_evt_size, m_evt_prev);
735  if(m_evt[m_evt_prev] & ievt::EMAP)
736  {
737  pos = _find_matching_open(ievt::BMAP, ievt::EMAP, m_evt_prev);
738  }
739  else
740  {
741  _RYML_CB_ASSERT(m_stack.m_callbacks, (m_evt[m_evt_prev] & ievt::ESEQ));
742  pos = _find_matching_open(ievt::BSEQ, ievt::ESEQ, m_evt_prev);
743  }
744  _c4dbgpf("{}/{}: matching open for {}={}", m_evt_pos, m_evt_size, m_evt_prev, pos);
745  _RYML_CB_CHECK(m_stack.m_callbacks, pos >= 0); // internal error
746  _RYML_CB_CHECK(m_stack.m_callbacks, pos < m_evt_prev); // internal error
747  _RYML_CB_ASSERT(m_stack.m_callbacks, (m_evt[pos] & ievt::ESEQ) == (m_evt[m_evt_prev] & ievt::BSEQ));
748  _RYML_CB_ASSERT(m_stack.m_callbacks, (m_evt[pos] & ievt::EMAP) == (m_evt[m_evt_prev] & ievt::BMAP));
749  // shift the array one position to the right, starting at pos
750  int32_t posp1 = pos + 1;
751  if(m_evt_pos + 1 < m_evt_size)
752  {
753  int32_t num_move = m_evt_pos + 1 - pos;
754  _RYML_CB_ASSERT(m_stack.m_callbacks, num_move > 0);
755  memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
756  }
757  _RYML_CB_ASSERT(m_stack.m_callbacks, posp1 < m_evt_pos);
758  // start the map
759  m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_;
760  // set next as key, not val
761  m_evt[posp1] |= ievt::KEY_;
762  m_evt[posp1] &= ~ievt::VAL_;
763  // move PSTR to pos
764  if(m_evt[posp1] & ievt::PSTR)
765  {
766  m_evt[pos] |= ievt::PSTR;
767  m_evt[posp1] &= ~ievt::PSTR;
768  }
769  }
770  }
771  m_curr->evt_id = m_evt_pos - 2;
772  ++m_evt_prev;
773  ++m_evt_pos;
774  _enable_(c4::yml::MAP|c4::yml::FLOW_SL);
775  _push();
776  }

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

785  {
786  if(m_evt_prev < m_evt_size)
787  {
788  // interpolate BMAP|VAL|BLCK after the last BDOC
789  int32_t pos = _find_last_bdoc(m_evt_pos);
790  if(pos >= 0)
791  {
792  _RYML_CB_ASSERT(m_stack.m_callbacks, pos < m_evt_size);
793  _RYML_CB_ASSERT(m_stack.m_callbacks, pos < m_evt_pos);
794  _RYML_CB_ASSERT(m_stack.m_callbacks, (m_evt[pos] & ievt::BDOC));
795  if(m_evt_pos < m_evt_size)
796  {
797  ++pos; // add 1 to write after BDOC
798  int32_t num_move = m_evt_pos - pos;
799  int32_t posp1 = pos + 1;
800  _RYML_CB_ASSERT(m_stack.m_callbacks, (m_evt[pos] & (ievt::BSEQ|ievt::BMAP)));
801  _RYML_CB_ASSERT(m_stack.m_callbacks, num_move > 0);
802  _RYML_CB_ASSERT(m_stack.m_callbacks, 0 == (m_evt[posp1] & ievt::PSTR));
803  memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::DataType));
804  m_evt[pos] = ievt::VAL_|ievt::BMAP|ievt::BLCK;
805  m_evt[posp1] &= ~ievt::VAL_;
806  m_evt[posp1] |= ievt::KEY_;
807  }
808  }
809  }
810  ++m_curr->evt_id;
811  ++m_evt_prev;
812  ++m_evt_pos;
813  _push();
814  }

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

892  {
893  _c4dbgpf("{}/{}: set_key_scalar_plain_empty", m_evt_pos, m_evt_size);
896  }
@ 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 897 of file event_handler_ints.hpp.

898  {
899  _c4dbgpf("{}/{}: set_val_scalar_plain_empty", m_evt_pos, m_evt_size);
902  }
@ 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 903 of file event_handler_ints.hpp.

904  {
905  // ideally we should search back in the latest event that has
906  // a scalar, then select a zero-length scalar immediately
907  // after that scalar. But this also works for now:
908  return m_str.first(0);
909  }

◆ set_key_scalar_plain()

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

Definition at line 912 of file event_handler_ints.hpp.

913  {
914  _c4dbgpf("{}/{}: set_key_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
915  _send_key_scalar_(scalar, ievt::PLAI);
917  }

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

919  {
920  _c4dbgpf("{}/{}: set_val_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
921  _send_val_scalar_(scalar, ievt::PLAI);
923  }

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

927  {
928  _c4dbgpf("{}/{}: set_key_scalar_dquo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
929  _send_key_scalar_(scalar, ievt::DQUO);
931  }
@ KEY_DQUO
mark key scalar as double quoted "
Definition: node_type.hpp:68
@ DQUO
double-quoted scalar ("")

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

933  {
934  _c4dbgpf("{}/{}: set_val_scalar_dquo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
935  _send_val_scalar_(scalar, ievt::DQUO);
937  }
@ 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 940 of file event_handler_ints.hpp.

941  {
942  _c4dbgpf("{}/{}: set_key_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
943  _send_key_scalar_(scalar, ievt::SQUO);
945  }
@ KEY_SQUO
mark key scalar as single quoted '
Definition: node_type.hpp:66
@ SQUO
single-quoted scalar (')

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

947  {
948  _c4dbgpf("{}/{}: set_val_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
949  _send_val_scalar_(scalar, ievt::SQUO);
951  }
@ 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 954 of file event_handler_ints.hpp.

955  {
956  _c4dbgpf("{}/{}: set_key_scalar_literal: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
957  _send_key_scalar_(scalar, ievt::LITL);
959  }
@ KEY_LITERAL
mark key scalar as multiline, block literal |
Definition: node_type.hpp:62
@ LITL
block literal scalar (|)

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

961  {
962  _c4dbgpf("{}/{}: set_val_scalar_literal: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
963  _send_val_scalar_(scalar, ievt::LITL);
965  }
@ 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 968 of file event_handler_ints.hpp.

969  {
970  _c4dbgpf("{}/{}: set_key_scalar_folded: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
971  _send_key_scalar_(scalar, ievt::FOLD);
973  }
@ KEY_FOLDED
mark key scalar as multiline, block folded >
Definition: node_type.hpp:64
@ FOLD
block folded scalar (>)

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

975  {
976  _c4dbgpf("{}/{}: set_val_scalar_folded: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.str-m_str.str, scalar.len, scalar);
977  _send_val_scalar_(scalar, ievt::FOLD);
979  }
@ 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 982 of file event_handler_ints.hpp.

983  {
984  _c4dbgpf("{}/{}: mark_key_scalar_unfiltered", m_evt_pos, m_evt_size);
985  if(m_evt_pos < m_evt_size)
986  m_evt[m_evt_pos] |= ievt::UNFILT;
987  }
@ 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 988 of file event_handler_ints.hpp.

989  {
990  _c4dbgpf("{}/{}: mark_val_scalar_unfiltered", m_evt_pos, m_evt_size);
991  if(m_evt_pos < m_evt_size)
992  m_evt[m_evt_pos] |= ievt::UNFILT;
993  }

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

◆ set_key_anchor()

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

Definition at line 1022 of file event_handler_ints.hpp.

1023  {
1024  _c4dbgpf("{}/{}: set_key_anchor", m_evt_pos, m_evt_size);
1025  _RYML_CB_ASSERT(m_stack.m_callbacks, !_has_any_(KEYREF));
1026  _enable_(c4::yml::KEYANCH);
1027  if(m_evt_pos + 3 < m_evt_size)
1028  {
1029  m_evt[m_evt_pos] |= ievt::KEY_|ievt::ANCH;
1030  _add_scalar_(m_evt_pos, anchor);
1031  }
1032  m_evt_prev = m_evt_pos;
1033  m_evt_pos += 3;
1034  }
#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 1035 of file event_handler_ints.hpp.

1036  {
1037  _c4dbgpf("{}/{}: set_val_anchor", m_evt_pos, m_evt_size);
1038  _RYML_CB_ASSERT(m_stack.m_callbacks, !_has_any_(VALREF));
1039  _enable_(c4::yml::VALANCH);
1040  if(m_evt_pos + 3 < m_evt_size)
1041  {
1042  m_evt[m_evt_pos] |= ievt::VAL_|ievt::ANCH;
1043  _add_scalar_(m_evt_pos, anchor);
1044  }
1045  m_evt_prev = m_evt_pos;
1046  m_evt_pos += 3;
1047  }
@ 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 1049 of file event_handler_ints.hpp.

1050  {
1051  _RYML_CB_ASSERT(m_stack.m_callbacks, ref.begins_with('*'));
1052  if(C4_UNLIKELY(_has_any_(KEYANCH)))
1053  _RYML_CB_ERR_(m_stack.m_callbacks, "key cannot have both anchor and ref", m_curr->pos);
1054  _enable_(c4::yml::KEY|c4::yml::KEYREF);
1055  _send_str_(ref.sub(1), ievt::KEY_|ievt::ALIA); // skip the leading *
1056  }
@ ALIA
*ref =ALI alias (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 1057 of file event_handler_ints.hpp.

1058  {
1059  _RYML_CB_ASSERT(m_stack.m_callbacks, ref.begins_with('*'));
1060  if(C4_UNLIKELY(_has_any_(VALANCH)))
1061  _RYML_CB_ERR_(m_stack.m_callbacks, "val cannot have both anchor and ref", m_curr->pos);
1062  _enable_(c4::yml::VAL|c4::yml::VALREF);
1063  _send_str_(ref.sub(1), ievt::VAL_|ievt::ALIA); // skip the leading *
1064  }

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

1074  {
1075  _c4dbgpf("{}/{}: set key tag ~~~{}~~~", m_evt_pos, m_evt_size, tag);
1076  _enable_(c4::yml::KEYTAG);
1077  _set_tag(tag, ievt::KEY_);
1078  }
@ 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 1079 of file event_handler_ints.hpp.

1080  {
1081  _c4dbgpf("{}/{}: set val tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, tag.len, tag);
1082  _enable_(c4::yml::VALTAG);
1083  _set_tag(tag, ievt::VAL_);
1084  }
@ 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 1085 of file event_handler_ints.hpp.

1086  {
1087  csubstr ttag = _transform_directive(tag);
1088  _c4dbgpf("{}/{}: transformed_tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, ttag.len, ttag);
1089  if(m_evt_pos + 3 < m_evt_size)
1090  {
1091  m_evt[m_evt_pos] |= which|ievt::TAG_;
1092  _add_scalar_(m_evt_pos, ttag);
1093  }
1094  m_evt_prev = m_evt_pos;
1095  m_evt_pos += 3;
1096  }

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

◆ add_directive()

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

Definition at line 1105 of file event_handler_ints.hpp.

1106  {
1107  _c4dbgpf("{}/{}: add directive ~~~{}~~~", m_evt_pos, m_evt_size, directive);
1108  _RYML_CB_ASSERT(m_stack.m_callbacks, directive.begins_with('%'));
1109  if(directive.begins_with("%TAG"))
1110  {
1111  const id_type pos = _num_tag_directives();
1112  if(C4_UNLIKELY(pos >= RYML_MAX_TAG_DIRECTIVES))
1113  _RYML_CB_ERR_(m_stack.m_callbacks, "too many directives", m_curr->pos);
1114  TagDirective &td = m_tag_directives[pos];
1115  if(C4_UNLIKELY(!td.create_from_str(directive)))
1116  _RYML_CB_ERR_(m_stack.m_callbacks, "failed to add directive", m_curr->pos);
1117  td.next_node_id = (id_type)m_evt_pos;
1118  _send_str_(td.handle, ievt::TAGD);
1119  _send_str_(td.prefix, ievt::TAGV);
1120  }
1121  else if(directive.begins_with("%YAML"))
1122  {
1123  _c4dbgpf("%YAML directive! ignoring...: {}", directive);
1124  if(C4_UNLIKELY(m_has_yaml_directive))
1125  _RYML_CB_ERR_(m_stack.m_callbacks, "multiple yaml directives", m_curr->pos);
1126  m_has_yaml_directive = true;
1127  csubstr rest = directive.sub(5).triml(' ');
1128  _send_str_(rest, ievt::YAML);
1129  }
1130  else
1131  {
1132  _c4dbgpf("unknown directive! ignoring... {}", directive);
1133  }
1134  }
#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>
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:253

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

1144  {
1145  return C4_LIKELY(m_arena_pos <= m_arena.len) ? m_arena.sub(m_arena_pos) : m_arena.last(0);
1146  }

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

1150  {
1151  substr s = arena_rem();
1152  if(C4_LIKELY(len <= s.len))
1153  s = s.first(len);
1154  else
1155  s.str = nullptr;
1156  m_arena_pos += len;
1157  return s;
1158  }

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

1162  {
1163  (void)relocated;
1164  return alloc_arena(len);
1165  }
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 1173 of file event_handler_ints.hpp.

1174  {
1175  _stack_push();
1176  m_curr->evt_type = {};
1177  }

◆ _pop()

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

end the current scope

Definition at line 1180 of file event_handler_ints.hpp.

◆ _enable__()

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

Definition at line 1185 of file event_handler_ints.hpp.

1186  {
1187  m_curr->evt_type |= bits;
1188  }

◆ _disable__()

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

Definition at line 1189 of file event_handler_ints.hpp.

1190  {
1191  m_curr->evt_type &= ~bits;
1192  }

◆ _has_any__()

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

Definition at line 1193 of file event_handler_ints.hpp.

1194  {
1195  return (m_curr->evt_type & bits) != c4::yml::type_bits(0);
1196  }
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 1198 of file event_handler_ints.hpp.

1199  {
1200  if(m_parent)
1201  m_parent->has_children = true;
1202  }

◆ _send_flag_only_()

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

Definition at line 1204 of file event_handler_ints.hpp.

1205  {
1206  _c4dbgpf("{}/{}: flag only", m_evt_pos, m_evt_size);
1207  if(m_evt_pos < m_evt_size)
1208  m_evt[m_evt_pos] |= flags;
1209  m_curr->evt_id = m_evt_pos;
1210  m_evt_prev = m_evt_pos;
1211  ++m_evt_pos;
1212  if(m_evt_pos < m_evt_size)
1213  m_evt[m_evt_pos] = {};
1214  }

◆ _send_key_scalar_()

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

Definition at line 1216 of file event_handler_ints.hpp.

1217  {
1218  _c4dbgpf("{}/{}: key scalar", m_evt_pos, m_evt_size);
1219  if(m_evt_pos + 3 < m_evt_size)
1220  {
1221  m_evt[m_evt_pos] |= ievt::SCLR|ievt::KEY_|flags;
1222  _add_scalar_(m_evt_pos, scalar);
1223  }
1224  m_curr->evt_id = m_evt_pos;
1225  m_evt_prev = m_evt_pos;
1226  m_evt_pos += 3;
1227  }

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

1230  {
1231  _c4dbgpf("{}/{}: val scalar", m_evt_pos, m_evt_size);
1232  if(m_evt_pos + 3 < m_evt_size)
1233  {
1234  m_evt[m_evt_pos] |= ievt::SCLR|ievt::VAL_|flags;
1235  _add_scalar_(m_evt_pos, scalar);
1236  }
1237  m_curr->evt_id = m_evt_pos;
1238  m_evt_prev = m_evt_pos;
1239  m_evt_pos += 3;
1240  }

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

1243  {
1244  _c4dbgpf("{}/{}: send str", m_evt_pos, m_evt_size);
1245  if(m_evt_pos + 3 < m_evt_size)
1246  {
1247  m_evt[m_evt_pos] |= flags;
1248  _add_scalar_(m_evt_pos, scalar);
1249  }
1250  m_curr->evt_id = m_evt_pos;
1251  m_evt_prev = m_evt_pos;
1252  m_evt_pos += 3;
1253  }

◆ _clear_tag_directives_()

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

Definition at line 1255 of file event_handler_ints.hpp.

1256  {
1257  for(TagDirective &td : m_tag_directives)
1258  td = {};
1259  }

◆ _num_tag_directives()

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

Definition at line 1260 of file event_handler_ints.hpp.

1261  {
1262  // this assumes we have a very small number of tag directives
1263  id_type i = 0;
1264  for(; i < RYML_MAX_TAG_DIRECTIVES; ++i)
1265  if(m_tag_directives[i].handle.empty())
1266  break;
1267  return i;
1268  }

References RYML_MAX_TAG_DIRECTIVES.

◆ _transform_directive()

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

Definition at line 1269 of file event_handler_ints.hpp.

1270  {
1271  // lookup from the end. We want to find the first directive that
1272  // matches the tag and has a target node id leq than the given
1273  // node_id.
1274  for(id_type i = RYML_MAX_TAG_DIRECTIVES-1; i != NONE; --i)
1275  {
1276  TagDirective const& td = m_tag_directives[i];
1277  if(td.handle.empty())
1278  continue;
1279  if(tag.begins_with(td.handle) && (td.handle != td.prefix))
1280  {
1281  substr rem = arena_rem();
1282  size_t len = td.transform(tag, rem, m_stack.m_callbacks, /*with_brackets*/false);
1283  if(len == 0)
1284  return tag;
1285  alloc_arena(len);
1286  return rem.first(len <= rem.len ? len : 0);
1287  }
1288  }
1289  if(tag.begins_with('!'))
1290  {
1291  if(is_custom_tag(tag))
1292  {
1293  _RYML_CB_ERR_(m_stack.m_callbacks, "tag not found", m_curr->pos);
1294  }
1295  }
1296  return tag;
1297  }
bool is_custom_tag(csubstr tag)
Definition: tag.cpp:8
@ NONE
an index to none
Definition: common.hpp:260

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,
pfn_relocate_arena  relocate_arena,
void *  relocate_arena_data 
)
inlineprotectedinherited

Definition at line 64 of file event_handler_stack.hpp.

65  {
66  _RYML_CB_ASSERT(m_stack.m_callbacks, m_curr != nullptr);
67  _RYML_CB_ASSERT(m_stack.m_callbacks, relocate_arena != nullptr);
68  _RYML_CB_ASSERT(m_stack.m_callbacks, relocate_arena_data != nullptr);
69  m_curr->start_parse(filename, m_curr->node_id);
70  m_relocate_arena = relocate_arena;
71  m_relocate_arena_data = relocate_arena_data;
72  }
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 74 of file event_handler_stack.hpp.

75  {
76  }

◆ _stack_reset_root()

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

Definition at line 80 of file event_handler_stack.hpp.

81  {
82  m_stack.clear();
83  m_stack.push({});
84  m_parent = nullptr;
85  m_curr = &m_stack.top();
86  }

◆ _stack_reset_non_root()

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

Definition at line 88 of file event_handler_stack.hpp.

89  {
90  m_stack.clear();
91  m_stack.push({}); // parent
92  m_stack.push({}); // node
93  m_parent = &m_stack.top(1);
94  m_curr = &m_stack.top();
95  }

◆ _stack_push()

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

Definition at line 97 of file event_handler_stack.hpp.

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

◆ _stack_pop()

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

Definition at line 105 of file event_handler_stack.hpp.

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

◆ _stack_should_push_on_begin_doc()

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

Definition at line 126 of file event_handler_stack.hpp.

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

◆ _stack_should_pop_on_end_doc()

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

Definition at line 132 of file event_handler_stack.hpp.

133  {
134  const bool is_root = (m_stack.size() == 1u);
135  return !is_root && _has_any_(DOC);
136  }

◆ _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 140 of file event_handler_stack.hpp.

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

◆ _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 156 of file event_handler_stack.hpp.

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

◆ 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 171 of file event_handler_stack.hpp.

172  {
173  const bool is_root = (m_stack.size() == 1u);
174  const bool isndoc = (m_curr->flags & NDOC) != 0;
175  const bool suspicious = _has_any_(MAP|SEQ|VAL);
176  _c4dbgpf("target={} isroot={} suspicious={} ndoc={}", m_curr->node_id, is_root, suspicious, isndoc);
177  if((is_root || _has_any_(DOC)) && suspicious && !isndoc)
178  _RYML_CB_ERR_(m_stack.m_callbacks, "parse error", m_curr->pos);
179  }
@ 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.


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