rapidyaml  0.12.0
parse and emit YAML, and do it fast
event_handler_stack.hpp
Go to the documentation of this file.
1 #ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
2 #define _C4_YML_EVENT_HANDLER_STACK_HPP_
3 
4 #ifndef _C4_YML_DETAIL_STACK_HPP_
5 #include "c4/yml/detail/stack.hpp"
6 #endif
7 
8 #ifndef _C4_YML_NODE_TYPE_HPP_
9 #include "c4/yml/node_type.hpp"
10 #endif
11 
12 #ifndef _C4_YML_DETAIL_DBGPRINT_HPP_
13 #include "c4/yml/detail/dbgprint.hpp"
14 #endif
15 
16 #ifndef _C4_YML_PARSER_STATE_HPP_
17 #include "c4/yml/parser_state.hpp"
18 #endif
19 
20 #ifdef RYML_DBG
21 #ifndef _C4_YML_DETAIL_PRINT_HPP_
22 #include "c4/yml/detail/print.hpp"
23 #endif
24 #endif
25 
26 // NOLINTBEGIN(hicpp-signed-bitwise)
27 
28 namespace c4 {
29 namespace yml {
30 
31 /** @addtogroup doc_event_handlers
32  * @{ */
33 
34 /** Use this class a base of implementations of event handler to
35  * simplify the stack logic. */
36 template<class HandlerImpl, class HandlerState>
38 {
39  static_assert(std::is_base_of<ParserState, HandlerState>::value,
40  "ParserState must be a base of HandlerState");
41 
42  using state = HandlerState;
43 
44 public:
45 
46  detail::stack<state> m_stack;
47  state *C4_RESTRICT m_curr; ///< current stack level: top of the stack. cached here for easier access.
48  state *C4_RESTRICT m_parent; ///< parent of the current stack level.
49  substr m_src;
50 
51 protected:
52 
53  EventHandlerStack() : m_stack(), m_curr(), m_parent(), m_src() {} // NOLINT
54  EventHandlerStack(Callbacks const& cb) : m_stack(cb), m_curr(), m_parent(), m_src() {} // NOLINT
55 
56 protected:
57 
58  void _stack_start_parse(const char *filename, substr ymlsrc)
59  {
60  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_curr != nullptr);
61  m_curr->start_parse(filename, m_curr->node_id);
62  m_src = ymlsrc;
63  }
64 
66  {
67  }
68 
69 protected:
70 
72  {
73  m_stack.clear();
74  m_stack.push({});
75  m_parent = nullptr;
76  m_curr = &m_stack.top();
77  }
78 
80  {
81  m_stack.clear();
82  m_stack.push({}); // parent
83  m_stack.push({}); // node
84  m_parent = &m_stack.top(1);
85  m_curr = &m_stack.top();
86  }
87 
88  void _stack_push()
89  {
90  m_stack.push_top();
91  m_parent = &m_stack.top(1); // don't use m_curr. watch out for relocations inside the prev push
92  m_curr = &m_stack.top();
93  m_curr->reset_after_push();
94  }
95 
96  void _stack_pop()
97  {
98  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_parent);
99  _RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_stack.size() > 1);
100  m_parent->reset_before_pop(*m_curr);
101  m_stack.pop();
102  m_parent = m_stack.size() > 1 ? &m_stack.top(1) : nullptr;
103  m_curr = &m_stack.top();
104  #ifdef RYML_DBG
105  if(m_parent)
106  _c4dbgpf("popped! top is now node={} (parent={})", m_curr->node_id, m_parent->node_id);
107  else
108  _c4dbgpf("popped! top is now node={} @ ROOT", m_curr->node_id);
109  #endif
110  }
111 
112 protected:
113 
114  // undefined below
115  #define _has_any_(bits) (static_cast<HandlerImpl const* C4_RESTRICT>(this)->template _has_any__<bits>())
116 
117  // FIXME. Not happy about where these functions are. They should
118  // be defined and called by the parser, passing the bool result to
119  // begin_doc()/end_doc() as well as begin_doc_expl()/end_doc_expl().
120 
122  {
123  const bool is_root = (m_stack.size() == 1u);
124  return is_root && (m_curr->has_children || _has_any_(DOC|VAL|MAP|SEQ));
125  }
126 
128  {
129  const bool is_root = (m_stack.size() == 1u);
130  return !is_root && _has_any_(DOC);
131  }
132 
133  #undef _has_any_
134 
135 };
136 
137 /** @} */
138 
139 } // namespace yml
140 } // namespace c4
141 
142 // NOLINTEND(hicpp-signed-bitwise)
143 
144 #endif /* _C4_YML_EVENT_HANDLER_STACK_HPP_ */
#define _has_any_(bits)
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
Definition: node_type.hpp:39
@ 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:38
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
Definition: node_type.hpp:40
@ DOC
a document
Definition: node_type.hpp:41
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition: common.cpp:14
A c-style callbacks class to customize behavior on errors or allocation.
Definition: common.hpp:538
Use this class a base of implementations of event handler to simplify the stack logic.
state * m_curr
current stack level: top of the stack. cached here for easier access.
EventHandlerStack(Callbacks const &cb)
void _stack_start_parse(const char *filename, substr ymlsrc)
detail::stack< state > m_stack
state * m_parent
parent of the current stack level.