1#ifndef _C4_YML_EXTRA_EVENT_HANDLER_INTS_HPP_
2#define _C4_YML_EXTRA_EVENT_HANDLER_INTS_HPP_
12#ifndef RYML_SINGLE_HEADER
13#ifndef _C4_YML_NODE_TYPE_HPP_
16#ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
19#ifndef _C4_YML_TAG_HPP_
22#ifndef _C4_YML_DETAIL_DBGPRINT_HPP_
23#include <c4/yml/detail/dbgprint.hpp>
162C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
163C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
164C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
175struct EventHandlerIntsState :
public c4::yml::ParserState
443 using state = EventHandlerIntsState;
462 #define _enable_(bits) _enable__<bits>()
463 #define _disable_(bits) _disable__<bits>()
464 #define _has_any_(bits) _has_any__<bits>()
492 m_evt_size = dst_size;
496 m_tag_directives.
clear();
520 return m_evt_pos <= m_evt_size && m_arena_pos <= m_arena.
len;
583 _c4dbgpf(
"{}/{}: begin_doc", m_evt_pos, m_evt_size);
595 _c4dbgpf(
"{}/{}: end_doc", m_evt_pos, m_evt_size);
608 _c4dbgpf(
"{}/{}: begin_doc_expl", m_evt_pos, m_evt_size);
617 _c4dbgpf(
"{}/{}: end_doc_expl", m_evt_pos, m_evt_size);
636 _c4dbgpf(
"{}/{}: bmap key flow", m_evt_pos, m_evt_size);
644 _c4dbgpf(
"{}/{}: bmap key block", m_evt_pos, m_evt_size);
653 _c4dbgpf(
"{}/{}: bmap flow", m_evt_pos, m_evt_size);
661 _c4dbgpf(
"{}/{}: bmap block", m_evt_pos, m_evt_size);
689 _c4dbgpf(
"{}/{}: bseq key flow", m_evt_pos, m_evt_size);
697 _c4dbgpf(
"{}/{}: bseq key block", m_evt_pos, m_evt_size);
706 _c4dbgpf(
"{}/{}: bseq flow", m_evt_pos, m_evt_size);
714 _c4dbgpf(
"{}/{}: bseq block", m_evt_pos, m_evt_size);
756 _c4dbgpf(
"{}/{}: set_key_scalar_plain_empty", m_evt_pos, m_evt_size);
762 _c4dbgpf(
"{}/{}: set_val_scalar_plain_empty", m_evt_pos, m_evt_size);
770 _c4dbgpf(
"{}/{}: set_key_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str-
m_src.str, scalar.
len, scalar);
776 _c4dbgpf(
"{}/{}: set_val_scalar_plain: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str-
m_src.str, scalar.
len, scalar);
784 _c4dbgpf(
"{}/{}: set_key_scalar_dquo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str?
size_t(scalar.
str-
m_src.str):
m_src.len, scalar.
len, scalar.
str?scalar:
csubstr{});
790 _c4dbgpf(
"{}/{}: set_val_scalar_dquo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str?
size_t(scalar.
str-
m_src.str):
m_src.len, scalar.
len, scalar.
str?scalar:
csubstr{});
798 _c4dbgpf(
"{}/{}: set_key_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str-
m_src.str, scalar.
len, scalar);
804 _c4dbgpf(
"{}/{}: set_val_scalar_squo: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str-
m_src.str, scalar.
len, scalar);
812 _c4dbgpf(
"{}/{}: set_key_scalar_literal: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str?
size_t(scalar.
str-
m_src.str):
m_src.len, scalar.
len, scalar.
str?scalar:
csubstr{});
818 _c4dbgpf(
"{}/{}: set_val_scalar_literal: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str?
size_t(scalar.
str-
m_src.str):
m_src.len, scalar.
len, scalar.
str?scalar:
csubstr{});
826 _c4dbgpf(
"{}/{}: set_key_scalar_folded: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str?
size_t(scalar.
str-
m_src.str):
m_src.len, scalar.
len, scalar.
str?scalar:
csubstr{});
832 _c4dbgpf(
"{}/{}: set_val_scalar_folded: @{} [{}]~~~{}~~~", m_evt_pos, m_evt_size, scalar.
str?
size_t(scalar.
str-
m_src.str):
m_src.len, scalar.
len, scalar.
str?scalar:
csubstr{});
840 _c4dbgpf(
"{}/{}: mark_key_scalar_unfiltered", m_evt_pos, m_evt_size);
841 if(m_evt_pos < m_evt_size)
846 _c4dbgpf(
"{}/{}: mark_val_scalar_unfiltered", m_evt_pos, m_evt_size);
847 if(m_evt_pos < m_evt_size)
856 #define _add_scalar_(i, scalar) \
857 _c4dbgpf("{}/{}: scalar!", i, m_evt_size); \
858 _RYML_ASSERT_BASIC_(m_stack.m_callbacks, _is_sub_(scalar)); \
859 _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_evt[i] & ievt::WSTR); \
860 _RYML_ASSERT_BASIC_(m_stack.m_callbacks, i + 3 < m_evt_size); \
861 if(C4_LIKELY(scalar.is_sub(m_src))) \
863 m_evt[i + 1] = (ievt::DataType)(scalar.str - m_src.str); \
867 m_evt[i] |= ievt::AREN; \
868 m_evt[i + 1] = (ievt::DataType)(scalar.str - m_arena.str); \
869 _c4dbgpf("{}/{}: arena! ->{}", i, m_evt_size, m_evt[i+1]); \
871 m_evt[i + 2] = (ievt::DataType)scalar.len; \
872 m_evt[i + 3] = ievt::PSTR
882 _c4dbgpf(
"{}/{}: set_key_anchor: {}", m_evt_pos, m_evt_size, anchor);
885 if(m_evt_pos + 3 < m_evt_size)
888 _add_scalar_(m_evt_pos, anchor);
890 m_evt_prev = m_evt_pos;
895 _c4dbgpf(
"{}/{}: set_val_anchor: {}", m_evt_pos, m_evt_size, anchor);
898 if(m_evt_pos + 3 < m_evt_size)
901 _add_scalar_(m_evt_pos, anchor);
903 m_evt_prev = m_evt_pos;
909 _c4dbgpf(
"{}/{}: set_key_ref: {}", m_evt_pos, m_evt_size, ref);
912 _RYML_ERR_PARSE_(
m_stack.m_callbacks,
m_curr->pos,
"key cannot have both anchor and ref");
918 _c4dbgpf(
"{}/{}: set_val_ref: {}", m_evt_pos, m_evt_size, ref);
921 _RYML_ERR_PARSE_(
m_stack.m_callbacks,
m_curr->pos,
"val cannot have both anchor and ref");
935 _c4dbgpf(
"{}/{}: set key tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, tag.
len, tag.
str ? tag :
csubstr(
"(arena full)"));
942 _c4dbgpf(
"{}/{}: set val tag [{}]~~~{}~~~", m_evt_pos, m_evt_size, tag.
len, tag.
str ? tag :
csubstr(
"(arena full)"));
957 _c4dbgpf(
"{}/{}: %YAML directive! version={}", m_evt_pos, m_evt_size, yaml_version);
963 _c4dbgpf(
"{}/{}: %TAG directive! handle={} prefix={} doc_id={}", m_evt_pos, m_evt_size, handle, prefix, m_curr_doc);
964 if(C4_UNLIKELY(!m_tag_directives.
add(handle, prefix, m_curr_doc)))
965 _RYML_ERR_PARSE_(
m_stack.m_callbacks,
m_curr->pos,
"too many %TAG directives");
984 _c4dbgpf(
"{}/{}: prev={} actually_val_is_first_key_of_new_map_flow", m_evt_pos, m_evt_size, m_evt_prev);
985 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, m_evt_pos > 2);
986 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, m_evt_prev > 0);
995 if(m_evt_pos < m_evt_size)
999 _c4dbgpf(
"{}/{}: WSTR", m_evt_pos, m_evt_size);
1000 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, m_evt_prev > 0);
1002 if(m_evt_pos + 1 < m_evt_size)
1004 for(int32_t i = pos; i <= m_evt_prev; i =
_next(i))
1007 m_evt[i] &=
~ievt::VAL_;
1009 int32_t num_move = m_evt_pos + 1 - pos;
1010 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, num_move > 0);
1011 memmove(m_evt + pos + 1, m_evt + pos, (
size_t)num_move *
sizeof(
ievt::DataType));
1018 m_evt[pos + 1] &=
~ievt::PSTR;
1023 _c4dbgpf(
"{}/{}: container key", m_evt_pos, m_evt_size);
1026 _c4dbgpf(
"{}/{}: find matching open for {}", m_evt_pos, m_evt_size, m_evt_prev);
1036 _c4dbgpf(
"{}/{}: matching open for {}={}", m_evt_pos, m_evt_size, m_evt_prev, pos);
1037 _RYML_CHECK_BASIC_(
m_stack.m_callbacks, pos >= 0);
1038 _RYML_CHECK_BASIC_(
m_stack.m_callbacks, pos < m_evt_prev);
1042 int32_t posp1 = pos + 1;
1043 if(m_evt_pos + 1 < m_evt_size)
1045 int32_t num_move = m_evt_pos + 1 - pos;
1046 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, num_move > 0);
1047 memmove(m_evt + posp1, m_evt + pos, (
size_t)num_move *
sizeof(
ievt::DataType));
1049 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, posp1 < m_evt_pos);
1054 m_evt[posp1] &=
~ievt::VAL_;
1059 m_evt[posp1] &=
~ievt::PSTR;
1063 m_curr->evt_id = m_evt_pos - 2;
1078 _c4dbgpf(
"{}/{}: prev={} actually_val_is_first_key_of_new_map_block", m_evt_pos, m_evt_size, m_evt_prev);
1079 if(m_evt_pos < m_evt_size)
1085 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_size);
1086 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_pos);
1088 if(m_evt_pos < m_evt_size)
1091 int32_t num_move = m_evt_pos - pos;
1092 int32_t posp1 = pos + 1;
1094 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, num_move > 0);
1096 memmove(m_evt + posp1, m_evt + pos, (
size_t)num_move *
sizeof(
ievt::DataType));
1098 m_evt[posp1] &=
~ievt::VAL_;
1118 return m_arena.
first(m_arena_pos < m_arena.
len ? m_arena_pos : m_arena.
len);
1122 return C4_LIKELY(m_arena_pos <= m_arena.
len) ? m_arena.
sub(m_arena_pos) : m_arena.
last(0);
1128 if(C4_LIKELY(len <= s.
len))
1157 template<c4::yml::type_bits bits> C4_ALWAYS_INLINE
void _enable__() noexcept
1159 m_curr->evt_type |= bits;
1161 template<c4::yml::type_bits bits> C4_ALWAYS_INLINE
void _disable__() noexcept
1163 m_curr->evt_type &= ~bits;
1165 template<c4::yml::type_bits bits> C4_ALWAYS_INLINE
bool _has_any__() const noexcept
1170 C4_ALWAYS_INLINE int32_t
_next(int32_t pos)
const noexcept
1172 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_size);
1173 return pos + ((m_evt[pos] &
ievt::WSTR) ? 3 : 1);
1176 C4_ALWAYS_INLINE int32_t
_prev(int32_t pos)
const noexcept
1178 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_size);
1179 return pos - ((m_evt[pos] &
ievt::PSTR) ? 3 : 1);
1184 return (!str.str || str.is_sub(
m_src) || str.is_sub(m_arena));
1189 _c4dbgpf(
"{}/{}: flag only", m_evt_pos, m_evt_size);
1190 if(m_evt_pos < m_evt_size)
1191 m_evt[m_evt_pos] |= flags;
1192 m_curr->evt_id = m_evt_pos;
1193 m_evt_prev = m_evt_pos;
1195 if(m_evt_pos < m_evt_size)
1196 m_evt[m_evt_pos] = {};
1201 _c4dbgpf(
"{}/{}: send str", m_evt_pos, m_evt_size);
1202 if(m_evt_pos + 3 < m_evt_size)
1204 m_evt[m_evt_pos] |= flags;
1205 _add_scalar_(m_evt_pos, scalar);
1207 m_curr->evt_id = m_evt_pos;
1208 m_evt_prev = m_evt_pos;
1223 return m_src.first(0);
1228 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_size);
1241 _c4dbgpf(
"find_matching: start at {}", pos);
1242 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_size);
1243 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, (m_evt[pos] & close) == close);
1244 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, (m_evt[pos] & open) == (close & ~
ievt::END_));
1250 _c4dbgpf(
"find_matching: pos={} count={} e={}", pos, count, m_evt[pos]);
1251 if((e & close) == close)
1253 _c4dbgpf(
".............: pos={} close! count={} e={}", pos, count, m_evt[pos]);
1256 else if((e & open) == open)
1258 _c4dbgpf(
".............: pos={} open! count={} e={}", pos, count, m_evt[pos]);
1266 _c4dbgpf(
"find_matching: not found!", 0);
1272 _RYML_ASSERT_BASIC_(
m_stack.m_callbacks, pos < m_evt_size);
1273 int32_t prev =
_prev(pos);
1276 _c4dbgpf(
"{}/{}: {} is anchor/tag. extend to {}", m_evt_pos, m_evt_size, prev, prev);
1300C4_SUPPRESS_WARNING_GCC_CLANG_POP
Callbacks const & get_callbacks()
get the global callbacks
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...
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
@ VALANCH
the val has an &anchor
@ KEY_DQUO
mark key scalar as double quoted "
@ VALREF
a *reference: the val references an &anchor
@ VALNIL
the val is null (eg {a : } results in a null val)
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
@ VAL_FOLDED
mark val scalar as multiline, block folded >
@ KEYTAG
the key has a tag
@ FLOW_SL
mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,...
@ VAL
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
@ VALTAG
the val has a tag
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
@ VAL_SQUO
mark val scalar as single quoted '
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
@ KEYREF
a *reference: the key references an &anchor
@ BLOCK
mark container with block style (seqs as '- val ', maps as 'key: val')
@ KEYANCH
the key has an &anchor
@ VAL_DQUO
mark val scalar as double quoted "
@ KEY_SQUO
mark key scalar as single quoted '
@ VAL_LITERAL
mark val scalar as multiline, block literal |
@ KEY_LITERAL
mark key scalar as multiline, block literal |
@ KEY_PLAIN
mark key scalar as plain scalar (unquoted, even when multiline)
@ KEY_FOLDED
mark key scalar as multiline, block folded >
@ KEYNIL
the key is null (eg { : b} results in a null key)
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
@ RTOP
reading at top level
@ RUNK
reading unknown state (when starting): must determine whether scalar, map or seq
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...
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
bool begins_with(const C c) const noexcept
true if the first character of the string is c
size_t len
the length of the substring
basic_substring last(size_t num) const noexcept
return the last num elements: [len-num,len[
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
basic_substring sub(size_t first) const noexcept
return [first,len[
C * str
a restricted pointer to the first character of the substring
A c-style callbacks class to customize behavior on errors or allocation.
Use this class a base of implementations of event handler to simplify the stack logic.
void _stack_finish_parse()
bool _stack_should_push_on_begin_doc() const
void _stack_start_parse(const char *filename, substr ymlsrc)
detail::stack< state > m_stack
bool _stack_should_pop_on_end_doc() const
Accelerator structure to reduce memory requirements by enabling reuse of resolved tags.
TagDirective const * add(csubstr handle, csubstr prefix, id_type doc_id) noexcept
bool _has_any__() const noexcept
void begin_doc_expl()
explicit doc start, with —
void end_doc_expl()
explicit doc end, with ...
void set_val_anchor(csubstr anchor)
void add_directive_tag(csubstr handle, csubstr prefix)
void set_key_scalar_literal(csubstr scalar)
void set_val_scalar_plain_empty()
void begin_map_val_block()
void start_parse(const char *filename, substr src)
int32_t _next(int32_t pos) const noexcept
bool fits_buffers() const
Predicate to test if the event and arena buffers successfully accomodated all the parse events.
int32_t _find_matching_open(ievt::DataType open, ievt::DataType close, int32_t pos) const
void begin_doc()
implicit doc start (without —)
void _send_flag_only_(ievt::DataType flags)
void begin_map_key_block()
void set_key_tag(csubstr tag)
void _enable__() noexcept
substr alloc_arena(size_t len)
this may fail, in which case an empty string is returned
void mark_val_scalar_unfiltered()
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.
void begin_seq_val_block()
void set_key_scalar_squoted(csubstr scalar)
void set_key_scalar_folded(csubstr scalar)
void set_key_anchor(csubstr anchor)
EventHandlerInts(c4::yml::Callbacks const &cb)
void set_key_scalar_plain_empty()
void set_val_ref(csubstr ref)
void begin_map_val_flow()
void set_key_scalar_plain(csubstr scalar)
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 o...
void set_val_scalar_literal(csubstr scalar)
int required_size_events() const
get the size needed for the event buffer from the previous parse
void set_val_scalar_folded(csubstr scalar)
int32_t _extend_left_to_include_tag_and_or_anchor(int32_t pos) const
void set_val_scalar_dquoted(csubstr scalar)
void _pop()
end the current scope
void _send_str_(csubstr scalar, ievt::DataType flags)
void set_key_scalar_dquoted(csubstr scalar)
void begin_seq_key_flow()
csubstr _get_latest_empty_scalar() const
EventHandlerIntsState state
size_t required_size_arena() const
get the size needed for the arena from the previous parse
@ requires_strings_on_buffers
int32_t _prev(int32_t pos) const noexcept
int32_t _find_last_bdoc(int32_t pos) const
bool _is_sub_(csubstr str) const noexcept
void mark_key_scalar_unfiltered()
void set_key_ref(csubstr ref)
TagDirectives & tag_directives()
void begin_seq_key_block()
void set_val_scalar_plain(csubstr scalar)
void end_doc()
implicit doc end (without ...)
ievt::DataType value_type
void add_directive_yaml(csubstr yaml_version)
void _push()
push a new parent, add a child to the new parent, and set the child as the current node
void begin_seq_val_flow()
void set_val_scalar_squoted(csubstr scalar)
void begin_map_key_flow()
void reset(substr str, substr arena, ievt::DataType *dst, int32_t dst_size)
void _mark_parent_with_children_()
void _disable__() noexcept
void set_val_tag(csubstr tag)