1 #ifndef _C4_YML_EVENT_HANDLER_TREE_HPP_
2 #define _C4_YML_EVENT_HANDLER_TREE_HPP_
4 #ifndef _C4_YML_TREE_HPP_
8 #ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
12 C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702)
44 Tree *C4_RESTRICT m_tree;
46 size_t m_num_directives;
47 bool m_yaml_directive;
50 #define _enable_(bits) _enable__<bits>(); _c4dbgpf("node[{}]: enable {}", m_curr->node_id, #bits)
51 #define _disable_(bits) _disable__<bits>(); _c4dbgpf("node[{}]: disable {}", m_curr->node_id, #bits)
53 #define _enable_(bits) _enable__<bits>()
54 #define _disable_(bits) _disable__<bits>()
56 #define _has_any_(bits) _has_any__<bits>()
73 if(C4_UNLIKELY(!tree))
74 _RYML_CB_ERR(m_stack.m_callbacks,
"null tree");
75 if(C4_UNLIKELY(
id >= tree->
capacity()))
76 _RYML_CB_ERR(tree->
callbacks(),
"invalid node");
77 if(C4_UNLIKELY(!tree->
is_root(
id)))
79 if(C4_UNLIKELY(!tree->
has_key(
id)))
80 _RYML_CB_ERR(tree->
callbacks(),
"destination node belongs to a map and has no key");
83 if(m_tree->is_root(
id))
86 _reset_parser_state(m_curr,
id, m_tree->root_id());
90 _stack_reset_non_root();
91 _reset_parser_state(m_parent,
id, m_tree->parent(
id));
92 _reset_parser_state(m_curr,
id,
id);
95 m_yaml_directive =
false;
107 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree !=
nullptr);
108 this->_stack_start_parse(filename, relocate_arena, relocate_arena_data);
113 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree !=
nullptr);
114 if(m_num_directives && !m_tree->is_stream(m_tree->root_id()))
115 _RYML_CB_ERR_(m_stack.m_callbacks,
"directives cannot be used without a document", {});
116 this->_stack_finish_parse();
158 _c4dbgp(
"begin_doc");
159 if(_stack_should_push_on_begin_doc())
162 _set_root_as_stream();
171 if(_stack_should_pop_on_end_doc())
173 _remove_speculative();
182 _c4dbgp(
"begin_doc_expl");
183 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->root_id() == m_curr->node_id);
184 if(!m_tree->is_stream(m_tree->root_id()))
186 _c4dbgp(
"ensure stream");
187 _set_root_as_stream();
188 id_type first = m_tree->first_child(m_tree->root_id());
189 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_stream(m_tree->root_id()));
190 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->num_children(m_tree->root_id()) == 1u);
191 if(m_tree->has_children(first) || m_tree->is_val(first))
200 _remove_speculative();
201 m_curr->node_id = m_tree->last_child(m_tree->root_id());
202 m_curr->tr_data = m_tree->_p(m_curr->node_id);
215 _c4dbgp(
"end_doc_expl");
216 _remove_speculative();
217 if(_stack_should_pop_on_end_doc())
222 m_yaml_directive =
false;
234 _RYML_CB_ERR_(m_stack.m_callbacks,
"ryml trees cannot handle containers as keys", m_curr->pos);
238 _RYML_CB_ERR_(m_stack.m_callbacks,
"ryml trees cannot handle containers as keys", m_curr->pos);
243 _c4dbgpf(
"node[{}]: begin_map_val_flow", m_curr->node_id);
251 _c4dbgpf(
"node[{}]: begin_map_val_block", m_curr->node_id);
261 _c4dbgpf(
"node[{}]: end_map_val", m_curr->node_id);
273 _RYML_CB_ERR_(m_stack.m_callbacks,
"ryml trees cannot handle containers as keys", m_curr->pos);
277 _RYML_CB_ERR_(m_stack.m_callbacks,
"ryml trees cannot handle containers as keys", m_curr->pos);
282 _c4dbgpf(
"node[{}]: begin_seq_val_flow", m_curr->node_id);
290 _c4dbgpf(
"node[{}]: begin_seq_val_block", m_curr->node_id);
300 _c4dbgpf(
"node[{}]: end_seq_val", m_curr->node_id);
312 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
313 _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
314 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->has_children(m_parent->node_id));
315 NodeData const* prev = m_tree->m_buf;
316 _set_state_(m_curr, m_tree->_append_child__unprotected(m_parent->node_id));
317 if(prev != m_tree->m_buf)
318 _refresh_after_relocation();
319 _c4dbgpf(
"node[{}]: added sibling={} prev={}", m_parent->node_id, m_curr->node_id, m_tree->prev_sibling(m_curr->node_id));
329 if(C4_UNLIKELY(m_tree->is_container(m_curr->node_id)))
330 _RYML_CB_ERR_(m_stack.m_callbacks,
"ryml trees cannot handle containers as keys", m_curr->pos);
331 _RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
332 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_seq(m_parent->node_id));
333 _RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->is_container(m_curr->node_id));
334 _RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->has_key(m_curr->node_id));
335 const NodeData tmp = _val2key_(*m_curr->tr_data);
337 m_curr->tr_data->m_val = {};
338 begin_map_val_flow();
339 m_curr->tr_data->m_type = tmp.
m_type;
340 m_curr->tr_data->m_key = tmp.
m_key;
351 _RYML_CB_ERR_(m_stack.m_callbacks,
"ryml trees cannot handle containers as keys", m_curr->pos);
364 _c4dbgpf(
"node[{}]: set key scalar plain: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
365 m_curr->tr_data->m_key.scalar = scalar;
370 _c4dbgpf(
"node[{}]: set val scalar plain: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
371 m_curr->tr_data->m_val.scalar = scalar;
378 _c4dbgpf(
"node[{}]: set key scalar dquot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
379 m_curr->tr_data->m_key.scalar = scalar;
384 _c4dbgpf(
"node[{}]: set val scalar dquot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
385 m_curr->tr_data->m_val.scalar = scalar;
392 _c4dbgpf(
"node[{}]: set key scalar squot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
393 m_curr->tr_data->m_key.scalar = scalar;
398 _c4dbgpf(
"node[{}]: set val scalar squot: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
399 m_curr->tr_data->m_val.scalar = scalar;
406 _c4dbgpf(
"node[{}]: set key scalar literal: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
407 m_curr->tr_data->m_key.scalar = scalar;
412 _c4dbgpf(
"node[{}]: set val scalar literal: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
413 m_curr->tr_data->m_val.scalar = scalar;
420 _c4dbgpf(
"node[{}]: set key scalar folded: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
421 m_curr->tr_data->m_key.scalar = scalar;
426 _c4dbgpf(
"node[{}]: set val scalar folded: [{}]~~~{}~~~ ({})", m_curr->node_id, scalar.len, scalar,
reinterpret_cast<void const*
>(scalar.str));
427 m_curr->tr_data->m_val.scalar = scalar;
450 _c4dbgpf(
"node[{}]: set key anchor: [{}]~~~{}~~~", m_curr->node_id, anchor.len, anchor);
451 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
453 _RYML_CB_ERR_(m_tree->callbacks(),
"key cannot have both anchor and ref", m_curr->pos);
454 _RYML_CB_ASSERT(m_tree->callbacks(), !anchor.begins_with(
'&'));
456 m_curr->tr_data->m_key.anchor = anchor;
460 _c4dbgpf(
"node[{}]: set val anchor: [{}]~~~{}~~~", m_curr->node_id, anchor.len, anchor);
461 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
463 _RYML_CB_ERR_(m_tree->callbacks(),
"val cannot have both anchor and ref", m_curr->pos);
464 _RYML_CB_ASSERT(m_tree->callbacks(), !anchor.begins_with(
'&'));
466 m_curr->tr_data->m_val.anchor = anchor;
471 _c4dbgpf(
"node[{}]: set key ref: [{}]~~~{}~~~", m_curr->node_id, ref.len, ref);
472 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
474 _RYML_CB_ERR_(m_tree->callbacks(),
"key cannot have both anchor and ref", m_curr->pos);
475 _RYML_CB_ASSERT(m_tree->callbacks(), ref.begins_with(
'*'));
477 m_curr->tr_data->m_key.anchor = ref.sub(1);
478 m_curr->tr_data->m_key.scalar = ref;
482 _c4dbgpf(
"node[{}]: set val ref: [{}]~~~{}~~~", m_curr->node_id, ref.len, ref);
483 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
485 _RYML_CB_ERR_(m_tree->callbacks(),
"val cannot have both anchor and ref", m_curr->pos);
486 _RYML_CB_ASSERT(m_tree->callbacks(), ref.begins_with(
'*'));
488 m_curr->tr_data->m_val.anchor = ref.sub(1);
489 m_curr->tr_data->m_val.scalar = ref;
501 _c4dbgpf(
"node[{}]: set key tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag);
503 m_curr->tr_data->m_key.tag = tag;
507 _c4dbgpf(
"node[{}]: set val tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag);
509 m_curr->tr_data->m_val.tag = tag;
521 _c4dbgpf(
"% directive! {}", directive);
522 _RYML_CB_ASSERT(m_tree->callbacks(), directive.begins_with(
'%'));
523 if(directive.begins_with(
"%TAG"))
525 if(C4_UNLIKELY(!m_tree->add_tag_directive(directive)))
526 _RYML_CB_ERR_(m_stack.m_callbacks,
"failed to add directive", m_curr->pos);
528 else if(directive.begins_with(
"%YAML"))
530 _c4dbgpf(
"%YAML directive! ignoring...: {}", directive);
531 if(C4_UNLIKELY(m_yaml_directive))
532 _RYML_CB_ERR_(m_stack.m_callbacks,
"multiple yaml directives", m_curr->pos);
533 m_yaml_directive =
true;
537 _c4dbgpf(
"unknown directive! ignoring... {}", directive);
551 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
552 csubstr prev = m_tree->arena();
553 substr out = m_tree->alloc_arena(len);
554 substr curr = m_tree->arena();
555 if(curr.str != prev.str)
556 _stack_relocate_to_new_arena(prev, curr);
562 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
563 csubstr prev = m_tree->arena();
564 if(!prev.is_super(*relocated))
565 return alloc_arena(len);
566 substr out = alloc_arena(len);
567 substr curr = m_tree->arena();
568 if(curr.str != prev.str)
569 *relocated = _stack_relocate_to_new_arena(*relocated, prev, curr);
578 void _reset_parser_state(state* st,
id_type parse_root,
id_type node)
580 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
581 _set_state_(st, node);
585 _c4dbgpf(
"resetting state: initial flags={}", detail::_parser_flags_to_str(flagbuf, st->flags));
589 _c4dbgpf(
"node[{}] is notype", node);
590 if(m_tree->is_root(parse_root))
592 _c4dbgpf(
"node[{}] is root", node);
597 _c4dbgpf(
"node[{}] is not root. setting USTY", node);
603 _c4dbgpf(
"node[{}] is map", node);
608 _c4dbgpf(
"node[{}] is map", node);
613 _c4dbgpf(
"node[{}] has key. setting USTY", node);
618 _RYML_CB_ERR(m_tree->callbacks(),
"cannot append to node");
622 _c4dbgpf(
"node[{}] is doc", node);
626 _c4dbgpf(
"resetting state: final flags={}", detail::_parser_flags_to_str(flagbuf, st->flags));
635 NodeData
const* prev = m_tree->m_buf;
636 m_curr->node_id = m_tree->_append_child__unprotected(m_parent->node_id);
637 m_curr->tr_data = m_tree->_p(m_curr->node_id);
638 if(prev != m_tree->m_buf)
639 _refresh_after_relocation();
640 _c4dbgpf(
"pushed! level={}. top is now node={} (parent={})", m_curr->level, m_curr->node_id, m_parent ? m_parent->node_id :
NONE);
645 _remove_speculative_with_parent();
651 template<type_bits bits> C4_HOT C4_ALWAYS_INLINE
void _enable__() noexcept
653 m_curr->tr_data->m_type.type =
static_cast<NodeType_e>(m_curr->tr_data->m_type.type | bits);
655 template<type_bits bits> C4_HOT C4_ALWAYS_INLINE
void _disable__() noexcept
657 m_curr->tr_data->m_type.type =
static_cast<NodeType_e>(m_curr->tr_data->m_type.type & (~bits));
659 template<type_bits bits> C4_HOT C4_ALWAYS_INLINE
bool _has_any__() const noexcept
661 return (m_curr->tr_data->m_type.type & bits) != 0;
666 C4_ALWAYS_INLINE
void _set_state_(state *C4_RESTRICT s,
id_type id) noexcept
669 s->tr_data = m_tree->_p(
id);
671 void _refresh_after_relocation()
673 _c4dbgp(
"tree: refreshing stack data after tree data relocation");
674 for(
auto &st : m_stack)
675 st.tr_data = m_tree->_p(st.node_id);
678 void _set_root_as_stream()
680 _c4dbgp(
"set root as stream");
681 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->root_id() == 0u);
682 _RYML_CB_ASSERT(m_tree->callbacks(), m_curr->node_id == 0u);
683 const bool hack = !m_tree->has_children(m_curr->node_id) && !m_tree->is_val(m_curr->node_id);
685 m_tree->_p(m_tree->root_id())->m_type.add(
VAL);
686 m_tree->set_root_as_stream();
687 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_stream(m_tree->root_id()));
688 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_children(m_tree->root_id()));
689 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_doc(m_tree->first_child(m_tree->root_id())));
691 m_tree->_p(m_tree->first_child(m_tree->root_id()))->m_type.rem(
VAL);
692 _set_state_(m_curr, m_tree->root_id());
695 static NodeData _val2key_(NodeData
const& C4_RESTRICT d) noexcept
701 static_assert((
_VALMASK >> 1u) ==
_KEYMASK,
"required for this function to work");
705 r.m_type.type = (r.m_type.type |
KEY);
709 void _remove_speculative()
711 _c4dbgp(
"remove speculative node");
712 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
713 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->size() > 0);
714 const id_type last_added = m_tree->size() - 1;
715 if(m_tree->has_parent(last_added))
716 if(m_tree->_p(last_added)->m_type ==
NOTYPE)
717 m_tree->remove(last_added);
720 void _remove_speculative_with_parent()
722 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
723 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->size() > 0);
724 const id_type last_added = m_tree->size() - 1;
725 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_parent(last_added));
726 if(m_tree->_p(last_added)->m_type ==
NOTYPE)
728 _c4dbgpf(
"remove speculative node with parent. parent={} node={} parent(node)={}", m_parent->node_id, last_added, m_tree->parent(last_added));
729 m_tree->remove(last_added);
733 C4_ALWAYS_INLINE
void _save_loc()
735 _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
736 _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->_p(m_curr->node_id)->m_val.scalar.len == 0);
737 m_tree->_p(m_curr->node_id)->m_val.scalar.str = m_curr->line_contents.rem.str;
752 C4_SUPPRESS_WARNING_MSVC_POP
bool is_map(id_type node) const
bool is_root(id_type node) const
bool has_key(id_type node) const
id_type parent(id_type node) const
Callbacks const & callbacks() const
NodeType_e
a bit mask for marking node types and styles
@ VALANCH
the val has an &anchor
@ NOTYPE
no node type or style is set
@ 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_UNFILT
the val scalar was left unfiltered; the parser was set not to filter.
@ 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 '
@ KEY_STYLE
mask of all the scalar styles for key (not container styles!)
@ 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_UNFILT
the key scalar was left unfiltered; the parser was set not to filter.
@ 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 >
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...
@ RTOP
reading at top level
@ RUNK
reading unknown state (when starting): must determine whether scalar, map or seq
@ USTY
reading in unknown style mode - must determine FLOW or BLCK reading an implicit map nested in an expl...
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 EventHandlerTree.
The event handler to create a ryml Tree.
void set_key_scalar_plain(csubstr scalar) noexcept
void set_val_tag(csubstr tag) noexcept
void mark_val_scalar_unfiltered() noexcept
void end_doc_expl()
explicit doc end, with ...
void begin_map_key_flow()
void end_doc()
implicit doc end (without ...)
void begin_doc()
implicit doc start (without —)
void set_val_scalar_plain(csubstr scalar) noexcept
EventHandlerTree(Callbacks const &cb)
void mark_key_scalar_unfiltered() noexcept
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_folded(csubstr scalar) noexcept
void begin_doc_expl()
explicit doc start, with —
void add_directive(csubstr directive)
void begin_map_val_flow()
void end_stream() const noexcept
void set_val_scalar_dquoted(csubstr scalar) noexcept
void start_parse(const char *filename, detail::pfn_relocate_arena relocate_arena, void *relocate_arena_data)
void begin_seq_val_flow()
void begin_map_key_block()
substr alloc_arena(size_t len, substr *relocated)
void begin_seq_key_block()
void begin_map_val_block()
void begin_seq_val_block()
void set_val_scalar_squoted(csubstr scalar) noexcept
void set_val_ref(csubstr ref)
void set_key_ref(csubstr ref)
void reset(Tree *tree, id_type id)
void set_val_anchor(csubstr anchor)
void set_key_scalar_literal(csubstr scalar) noexcept
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.
EventHandlerTree(Tree *tree, id_type id)
void begin_seq_key_flow()
void set_key_tag(csubstr tag) noexcept
void set_key_scalar_folded(csubstr scalar) noexcept
void begin_stream() const noexcept
void set_key_anchor(csubstr anchor)
substr alloc_arena(size_t len)
void set_key_scalar_dquoted(csubstr scalar) noexcept
void set_val_scalar_literal(csubstr scalar) noexcept
void set_key_scalar_squoted(csubstr scalar) noexcept
contains the data for each YAML node.
wraps a NodeType_e element with some syntactic sugar and predicates
bool has_key() const noexcept
bool is_doc() const noexcept
bool is_seq() const noexcept
bool is_map() const noexcept