1 #ifndef _C4_YML_EVENT_HANDLER_YAMLSTD_HPP_
2 #define _C4_YML_EVENT_HANDLER_YAMLSTD_HPP_
4 #ifdef RYML_SINGLE_HEADER
5 #include <ryml_all.hpp>
7 #ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
10 #ifndef _C4_YML_DETAIL_PRINT_HPP_
11 #include "c4/yml/detail/print.hpp"
15 #ifndef _C4_YML_EXTRA_STRING_HPP_
16 #include "./string.hpp"
19 C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
20 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
21 C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
66 extra::string_vector m_val_buffers;
67 extra::string m_key_tag_buf;
68 extra::string m_val_tag_buf;
70 bool m_has_yaml_directive;
71 extra::string m_arena;
75 #define _enable_(bits) _enable__<bits>()
76 #define _disable_(bits) _disable__<bits>()
77 #define _has_any_(bits) _has_any__<bits>()
97 m_has_yaml_directive =
false;
100 m_val_buffers.clear();
101 m_val_buffers.resize((
size_t)m_stack.size());
103 m_arena.reserve(1024);
104 m_key_tag_buf.resize(256);
105 m_val_tag_buf.resize(256);
118 this->_stack_start_parse(filename, relocate_arena, relocate_arena_data);
123 if((_num_tag_directives() || m_has_yaml_directive) && !m_has_docs)
124 _RYML_CB_ERR_(m_stack.m_callbacks,
"directives cannot be used without a document", {});
125 this->_stack_finish_parse();
130 while(m_stack.size() > 1)
163 _c4dbgp(
"begin_doc");
164 if(_stack_should_push_on_begin_doc())
178 if(_stack_should_pop_on_end_doc())
188 _c4dbgp(
"begin_doc_expl");
189 if(_stack_should_push_on_begin_doc())
194 _send_(
"+DOC ---\n");
201 _c4dbgp(
"end_doc_expl");
202 _send_(
"-DOC ...\n");
203 if(_stack_should_pop_on_end_doc())
208 m_has_yaml_directive =
false;
224 _mark_parent_with_children_();
234 _mark_parent_with_children_();
245 _mark_parent_with_children_();
255 _mark_parent_with_children_();
279 _mark_parent_with_children_();
289 _mark_parent_with_children_();
300 _mark_parent_with_children_();
310 _mark_parent_with_children_();
330 _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
331 _buf_flush_to_(m_curr->level, m_parent->level);
332 m_curr->ev_data = {};
344 _buf_ensure_(tmp +
id_type(2));
346 _buf_flush_to_(m_curr->level, tmp);
350 begin_map_val_flow();
351 _RYML_CB_ASSERT(m_stack.m_callbacks, tmp != m_curr->level);
353 _buf_flush_to_(tmp, m_curr->level);
365 substr full = sink;(void)full;
367 _RYML_CB_ASSERT(m_stack.m_callbacks, full.len);
368 _RYML_CB_ASSERT(m_stack.m_callbacks, !full.count(
'\r'));
369 size_t docpos = sink.find_last(
"+DOC\n");
372 _RYML_CB_ASSERT(m_stack.m_callbacks, (m_stack.size() == 1u) ? (docpos >= 5u) : (docpos == 0u));
373 _RYML_CB_ASSERT(m_stack.m_callbacks, docpos + 5u < full.len);
374 sink.insert(
"+MAP\n", docpos + 5u);
379 docpos = sink.find_last(
"+DOC ---\n");
380 _RYML_CB_ASSERT(m_stack.m_callbacks, docpos !=
npos);
381 _RYML_CB_ASSERT(m_stack.m_callbacks, (m_stack.size() == 1u) ? (docpos >= 5u) : (docpos == 0u));
382 _RYML_CB_ASSERT(m_stack.m_callbacks, docpos + 9u < full.len);
383 sink.insert(
"+MAP\n", docpos + 9u);
398 _c4dbgpf(
"node[{}]: set key scalar plain: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
399 _send_key_scalar_(scalar,
':');
404 _c4dbgpf(
"node[{}]: set val scalar plain: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
405 _send_val_scalar_(scalar,
':');
412 _c4dbgpf(
"node[{}]: set key scalar dquot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
413 _send_key_scalar_(scalar,
'"');
418 _c4dbgpf(
"node[{}]: set val scalar dquot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
419 _send_val_scalar_(scalar,
'"');
426 _c4dbgpf(
"node[{}]: set key scalar squot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
427 _send_key_scalar_(scalar,
'\'');
432 _c4dbgpf(
"node[{}]: set val scalar squot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
433 _send_val_scalar_(scalar,
'\'');
440 _c4dbgpf(
"node[{}]: set key scalar literal: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
441 _send_key_scalar_(scalar,
'|');
446 _c4dbgpf(
"node[{}]: set val scalar literal: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
447 _send_val_scalar_(scalar,
'|');
454 _c4dbgpf(
"node[{}]: set key scalar folded: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
455 _send_key_scalar_(scalar,
'>');
460 _c4dbgpf(
"node[{}]: set val scalar folded: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
461 _send_val_scalar_(scalar,
'>');
468 C4_NOT_IMPLEMENTED();
472 C4_NOT_IMPLEMENTED();
484 _c4dbgpf(
"node[{}]: set key anchor: [{}]~~~{}~~~", m_curr->node_id, anchor.len, anchor);
486 _RYML_CB_ERR_(m_stack.m_callbacks,
"key cannot have both anchor and ref", m_curr->pos);
487 _RYML_CB_ASSERT(m_stack.m_callbacks, !anchor.begins_with(
'&'));
489 m_curr->ev_data.m_key.anchor = anchor;
493 _c4dbgpf(
"node[{}]: set val anchor: [{}]~~~{}~~~", m_curr->node_id, anchor.len, anchor);
495 _RYML_CB_ERR_(m_stack.m_callbacks,
"val cannot have both anchor and ref", m_curr->pos);
496 _RYML_CB_ASSERT(m_stack.m_callbacks, !anchor.begins_with(
'&'));
498 m_curr->ev_data.m_val.anchor = anchor;
503 _c4dbgpf(
"node[{}]: set key ref: [{}]~~~{}~~~", m_curr->node_id, ref.len, ref);
505 _RYML_CB_ERR_(m_stack.m_callbacks,
"key cannot have both anchor and ref", m_curr->pos);
506 _RYML_CB_ASSERT(m_stack.m_callbacks, ref.begins_with(
'*'));
514 _c4dbgpf(
"node[{}]: set val ref: [{}]~~~{}~~~", m_curr->node_id, ref.len, ref);
516 _RYML_CB_ERR_(m_stack.m_callbacks,
"val cannot have both anchor and ref", m_curr->pos);
517 _RYML_CB_ASSERT(m_stack.m_callbacks, ref.begins_with(
'*'));
533 _c4dbgpf(
"node[{}]: set key tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag);
535 m_curr->ev_data.m_key.tag = _transform_directive(tag, &m_key_tag_buf);
539 _c4dbgpf(
"node[{}]: set val tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag);
541 m_curr->ev_data.m_val.tag = _transform_directive(tag, &m_val_tag_buf);
553 _RYML_CB_ASSERT(m_stack.m_callbacks, directive.begins_with(
'%'));
554 if(directive.begins_with(
"%TAG"))
556 const id_type pos = _num_tag_directives();
558 _RYML_CB_ERR_(m_stack.m_callbacks,
"too many directives", m_curr->pos);
559 if(C4_UNLIKELY(!m_tag_directives[pos].create_from_str(directive)))
560 _RYML_CB_ERR_(m_stack.m_callbacks,
"failed to add directive", m_curr->pos);
562 else if(directive.begins_with(
"%YAML"))
564 _c4dbgpf(
"%YAML directive! ignoring...: {}", directive);
565 if(C4_UNLIKELY(m_has_yaml_directive))
566 _RYML_CB_ERR_(m_stack.m_callbacks,
"multiple yaml directives", m_curr->pos);
567 m_has_yaml_directive =
true;
571 _c4dbgpf(
"unknown directive! ignoring... {}", directive);
584 const size_t sz = m_arena.size();
585 csubstr prev = m_arena;
586 m_arena.resize(sz + len);
589 if(curr.str != prev.str)
590 _stack_relocate_to_new_arena(prev, curr);
596 csubstr prev = m_arena;
597 if(!prev.is_super(*relocated))
598 return alloc_arena(len);
599 substr out = alloc_arena(len);
601 if(curr.str != prev.str)
602 *relocated = _stack_relocate_to_new_arena(*relocated, prev, curr);
617 _buf_ensure_(m_stack.size() +
id_type(1));
619 m_curr->ev_data = {};
620 _c4dbgpf(
"pushed! level={}", m_curr->level);
626 _buf_flush_to_(m_curr->level, m_parent->level);
630 template<type_bits bits> C4_ALWAYS_INLINE
void _enable__() noexcept
632 m_curr->ev_data.m_type.type =
static_cast<NodeType_e>(m_curr->ev_data.m_type.type | bits);
634 template<type_bits bits> C4_ALWAYS_INLINE
void _disable__() noexcept
636 m_curr->ev_data.m_type.type =
static_cast<NodeType_e>(m_curr->ev_data.m_type.type & (~bits));
638 template<type_bits bits> C4_ALWAYS_INLINE
bool _has_any__() const noexcept
640 return (m_curr->ev_data.m_type.type & bits) != 0;
643 void _mark_parent_with_children_()
646 m_parent->has_children =
true;
649 EventSink& _buf_() noexcept
651 _RYML_CB_ASSERT(m_stack.m_callbacks, m_curr->level < m_val_buffers.size());
652 return m_val_buffers[m_curr->level];
655 EventSink& _buf_(
id_type level) noexcept
657 _RYML_CB_ASSERT(m_stack.m_callbacks, level < m_val_buffers.size());
658 return m_val_buffers[level];
661 EventSink
const& _buf_(
id_type level)
const noexcept
663 _RYML_CB_ASSERT(m_stack.m_callbacks, level < m_val_buffers.size());
664 return m_val_buffers[level];
667 static void _buf_flush_to_(EventSink &C4_RESTRICT src, EventSink &C4_RESTRICT dst) noexcept
673 void _buf_flush_to_(
id_type level_src,
id_type level_dst) noexcept
675 auto &src = _buf_(level_src);
676 auto &dst = _buf_(level_dst);
677 _buf_flush_to_(src, dst);
680 void _buf_flush_() noexcept
682 _buf_flush_to_(_buf_(), *m_sink);
685 void _buf_ensure_(
id_type size_needed) noexcept
687 if(size_needed > m_val_buffers.size())
688 m_val_buffers.resize(size_needed);
691 C4_ALWAYS_INLINE
void _send_(csubstr s) noexcept { _buf_().append(s); }
692 C4_ALWAYS_INLINE
void _send_(
char c) noexcept { _buf_().append(c); }
694 void _send_key_scalar_(csubstr scalar,
char scalar_type_code)
699 _send_(scalar_type_code);
703 void _send_val_scalar_(csubstr scalar,
char scalar_type_code)
708 _send_(scalar_type_code);
713 void _send_key_props_()
718 _send_(m_curr->ev_data.m_key.anchor);
722 _send_tag_(m_curr->ev_data.m_key.tag);
724 m_curr->ev_data.m_key = {};
727 void _send_val_props_()
732 _send_(m_curr->ev_data.m_val.anchor);
734 if(m_curr->ev_data.m_type.type &
VALTAG)
736 _send_tag_(m_curr->ev_data.m_val.tag);
738 m_curr->ev_data.m_val = {};
741 void _send_tag_(csubstr tag)
743 _RYML_CB_ASSERT(m_stack.m_callbacks, !tag.empty());
744 if(tag.str[0] ==
'<')
757 void _clear_tag_directives_()
759 for(TagDirective &td : m_tag_directives)
762 id_type _num_tag_directives()
const
766 if(m_tag_directives[i].handle.empty())
770 csubstr _transform_directive(csubstr tag, extra::string *output)
777 TagDirective
const& td = m_tag_directives[i];
778 if(td.handle.empty())
780 if(tag.begins_with(td.handle))
784 size_t len = td.
transform(tag, *output, m_stack.m_callbacks);
787 if(tag.begins_with(
"!<"))
791 if(len > output->size())
793 _RYML_CB_CHECK(m_stack.m_callbacks, !retry);
796 output->resize(output->capacity());
799 return csubstr(*output).first(len);
802 if(tag.begins_with(
'!'))
806 _RYML_CB_ERR_(m_stack.m_callbacks,
"tag not found", m_curr->pos);
814 _RYML_CB_CHECK(m_stack.m_callbacks, !retry);
816 output->resize(result.len);
817 output->resize(output->capacity());
835 C4_SUPPRESS_WARNING_GCC_POP
Callbacks const & get_callbacks()
get the global callbacks
void append_escaped(extra::string *s, csubstr val)
NodeType_e
a bit mask for marking node types and styles
@ VALANCH
the val has an &anchor
@ KEY_DQUO
mark key scalar as double quoted "
@ VALREF
a *reference: the val references an &anchor
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
@ KEY
is member of a map, must have non-empty key
@ VAL_FOLDED
mark val scalar as multiline, block folded >
@ VAL_STYLE
mask of all the scalar styles for val (not container styles!)
@ 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 >
substr to_substr(substr s) noexcept
neutral version for use in generic code
bool is_custom_tag(csubstr tag)
csubstr normalize_tag_long(csubstr tag)
#define RYML_MAX_TAG_DIRECTIVES
the maximum number of tag directives in a Tree
void(*)(void *, csubstr prev_arena, substr next_arena) pfn_relocate_arena
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...
@ npos
a null string position
@ RTOP
reading at top level
@ RUNK
reading unknown state (when starting): must determine whether scalar, map or seq
a c-style callbacks class.
Use this class a base of implementations of event handler to simplify the stack logic.
The stack state needed specifically by EventHandlerYamlStd.
The event handler producing standard YAML events as used in the YAML test suite.
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.
substr alloc_arena(size_t len, substr *relocated)
void begin_map_val_block()
void set_key_scalar_plain(csubstr scalar)
void begin_doc()
implicit doc start (without —)
EventHandlerYamlStd(EventSink *sink, Callbacks const &cb)
void begin_seq_key_flow()
void set_key_anchor(csubstr anchor)
void end_doc()
implicit doc end (without ...)
void begin_seq_key_block()
void set_key_scalar_folded(csubstr scalar)
void set_key_scalar_dquoted(csubstr scalar)
void add_directive(csubstr directive)
void set_val_scalar_literal(csubstr scalar)
void set_val_ref(csubstr ref)
void begin_doc_expl()
explicit doc start, with —
void mark_key_scalar_unfiltered()
void set_key_scalar_literal(csubstr scalar)
void set_val_scalar_folded(csubstr scalar)
substr alloc_arena(size_t len)
void end_doc_expl()
explicit doc end, with ...
void set_val_scalar_plain(csubstr scalar)
void start_parse(const char *filename, detail::pfn_relocate_arena relocate_arena, void *relocate_arena_data)
EventHandlerYamlStd(Callbacks const &cb)
void begin_map_val_flow()
void set_key_ref(csubstr ref)
void set_val_scalar_dquoted(csubstr scalar)
void mark_val_scalar_unfiltered()
void begin_seq_val_flow()
void set_key_scalar_squoted(csubstr scalar)
void set_key_tag(csubstr tag)
void set_val_tag(csubstr tag)
void set_val_anchor(csubstr anchor)
void begin_map_key_flow()
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_squoted(csubstr scalar)
void begin_map_key_block()
void begin_seq_val_block()
EventHandlerYamlStd(EventSink *sink)
contains the data for each YAML node.
size_t transform(csubstr tag, substr output, Callbacks const &callbacks) const