rapidyaml  0.13.0
parse and emit YAML, and do it fast
node.hpp
Go to the documentation of this file.
1 #ifndef _C4_YML_NODE_HPP_
2 #define _C4_YML_NODE_HPP_
3 
4 /** @file node.hpp Node classes */
5 
6 #include <cstddef>
7 
8 #include "c4/yml/tree.hpp"
9 #include "c4/base64.hpp"
10 
11 #ifdef __clang__
12 # pragma clang diagnostic push
13 # pragma clang diagnostic ignored "-Wtype-limits"
14 # pragma clang diagnostic ignored "-Wold-style-cast"
15 #elif defined(__GNUC__)
16 # pragma GCC diagnostic push
17 # pragma GCC diagnostic ignored "-Wtype-limits"
18 # pragma GCC diagnostic ignored "-Wold-style-cast"
19 # pragma GCC diagnostic ignored "-Wuseless-cast"
20 #elif defined(_MSC_VER)
21 # pragma warning(push)
22 # pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/)
23 # pragma warning(disable: 4296/*expression is always 'boolean_value'*/)
24 # pragma warning(disable: 4996/*deprecated*/)
25 #endif
26 
27 // NOLINTBEGIN(modernize-avoid-c-style-cast)
28 
29 namespace c4 {
30 namespace yml {
31 
32 /** @addtogroup doc_node_classes
33  *
34  * @{
35  */
36 
37 
38 /** @defgroup doc_serialization_helpers Serialization helpers
39  *
40  * @{
41  */
42 template<class K> struct Key { K & k; }; // NOLINT
44 template<> struct Key<fmt::base64_wrapper> { fmt::base64_wrapper wrapper; };
45 
46 template<class K> C4_ALWAYS_INLINE Key<K> key(K & k) { return Key<K>{k}; }
48 C4_ALWAYS_INLINE Key<fmt::base64_wrapper> key(fmt::base64_wrapper w) { return {w}; }
49 
50 
51 template<class T> void write(NodeRef *n, T const& v);
52 
53 template<class T> inline bool read(ConstNodeRef const& C4_RESTRICT n, T *v);
54 template<class T> inline bool read(NodeRef const& C4_RESTRICT n, T *v);
55 template<class T> inline bool readkey(ConstNodeRef const& C4_RESTRICT n, T *v);
56 template<class T> inline bool readkey(NodeRef const& C4_RESTRICT n, T *v);
57 
58 /** @} */
59 
60 
61 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
63 //-----------------------------------------------------------------------------
64 
65 // forward decls
66 class NodeRef;
67 class ConstNodeRef;
68 
69 
70 //-----------------------------------------------------------------------------
71 //-----------------------------------------------------------------------------
72 //-----------------------------------------------------------------------------
73 
74 /** @cond dev */
75 namespace detail {
76 
77 template<class NodeRefType>
78 struct child_iterator
79 {
80  using value_type = NodeRefType;
81  using tree_type = typename NodeRefType::tree_type;
82 
83  tree_type * C4_RESTRICT m_tree;
84  id_type m_child_id;
85 
86  child_iterator(tree_type * t, id_type id) : m_tree(t), m_child_id(id) {}
87 
88  child_iterator& operator++ () { _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_child_id != NONE, m_tree, NONE); m_child_id = m_tree->next_sibling(m_child_id); return *this; }
89  child_iterator& operator-- () { _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_child_id != NONE, m_tree, NONE); m_child_id = m_tree->prev_sibling(m_child_id); return *this; }
90 
91  NodeRefType operator* () const { return NodeRefType(m_tree, m_child_id); }
92  NodeRefType operator-> () const { return NodeRefType(m_tree, m_child_id); }
93 
94  bool operator!= (child_iterator that) const { _RYML_ASSERT_VISIT(m_tree == that.m_tree, m_tree, NONE); return m_child_id != that.m_child_id; }
95  bool operator== (child_iterator that) const { _RYML_ASSERT_VISIT(m_tree == that.m_tree, m_tree, NONE); return m_child_id == that.m_child_id; }
96 };
97 
98 template<class NodeRefType>
99 struct children_view_
100 {
101  using n_iterator = child_iterator<NodeRefType>;
102 
103  n_iterator b, e;
104 
105  children_view_(n_iterator const& C4_RESTRICT b_,
106  n_iterator const& C4_RESTRICT e_) : b(b_), e(e_) {}
107 
108  n_iterator begin() const { return b; }
109  n_iterator end () const { return e; }
110 };
111 
112 template<class NodeRefType, class Visitor>
113 bool _visit(NodeRefType &node, Visitor fn, id_type indentation_level, bool skip_root=false)
114 {
115  id_type increment = 0;
116  if( ! (node.is_root() && skip_root))
117  {
118  if(fn(node, indentation_level))
119  return true;
120  ++increment;
121  }
122  if(node.has_children())
123  {
124  for(auto ch : node.children())
125  {
126  if(_visit(ch, fn, indentation_level + increment, false)) // no need to forward skip_root as it won't be root
127  {
128  return true;
129  }
130  }
131  }
132  return false;
133 }
134 
135 template<class NodeRefType, class Visitor>
136 bool _visit_stacked(NodeRefType &node, Visitor fn, id_type indentation_level, bool skip_root=false)
137 {
138  id_type increment = 0;
139  if( ! (node.is_root() && skip_root))
140  {
141  if(fn(node, indentation_level))
142  {
143  return true;
144  }
145  ++increment;
146  }
147  if(node.has_children())
148  {
149  fn.push(node, indentation_level);
150  for(auto ch : node.children())
151  {
152  if(_visit_stacked(ch, fn, indentation_level + increment, false)) // no need to forward skip_root as it won't be root
153  {
154  fn.pop(node, indentation_level);
155  return true;
156  }
157  }
158  fn.pop(node, indentation_level);
159  }
160  return false;
161 }
162 
163 template<class Impl, class ConstImpl>
164 struct RoNodeMethods;
165 } // detail
166 /** @endcond */
167 
168 //-----------------------------------------------------------------------------
169 //-----------------------------------------------------------------------------
170 //-----------------------------------------------------------------------------
171 
172 
173 /** a CRTP base providing read-only methods for @ref ConstNodeRef and @ref NodeRef */
174 namespace detail {
175 template<class Impl, class ConstImpl>
176 struct RoNodeMethods // NOLINT
177 {
178  C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wcast-align")
179  /** @cond dev */
180  // helper CRTP macros, undefined at the end
181  #define tree_ ((ConstImpl const* C4_RESTRICT)this)->m_tree
182  #define id_ ((ConstImpl const* C4_RESTRICT)this)->m_id
183  #define tree__ ((Impl const* C4_RESTRICT)this)->m_tree
184  #define id__ ((Impl const* C4_RESTRICT)this)->m_id
185  // require readable: this is a precondition for reading from the
186  // tree using this object.
187  #define _C4RR() \
188  _RYML_ASSERT_BASIC(tree_ != nullptr); \
189  _RYML_ASSERT_VISIT_(tree_->m_callbacks, id_ != NONE, tree_, id_); \
190  _RYML_ASSERT_VISIT_(tree_->m_callbacks, (((Impl const* C4_RESTRICT)this)->readable()), tree_, id_)
191  // a SFINAE beautifier to enable a function only if the
192  // implementation is mutable
193  #define _C4_IF_MUTABLE(ty) typename std::enable_if<!std::is_same<U, ConstImpl>::value, ty>::type
194  /** @endcond */
195 
196 public:
197 
198  /** @name node property getters */
199  /** @{ */
200 
201  /** returns the data or null when the id is NONE */
202  C4_ALWAYS_INLINE NodeData const* get() const RYML_NOEXCEPT { return ((Impl const*)this)->readable() ? tree_->get(id_) : nullptr; }
203 
204  /** returns the data or null when the id is NONE */
205  template<class U=Impl>
206  C4_ALWAYS_INLINE auto get() RYML_NOEXCEPT -> _C4_IF_MUTABLE(NodeData*) { return ((Impl const*)this)->readable() ? tree__->get(id__) : nullptr; }
207 
208  C4_ALWAYS_INLINE NodeType type() const RYML_NOEXCEPT { _C4RR(); return tree_->type(id_); } /**< Forward to @ref Tree::type(). Node must be readable. */
209  C4_ALWAYS_INLINE const char* type_str() const RYML_NOEXCEPT { _C4RR(); return tree_->type_str(id_); } /**< Forward to @ref Tree::type_str(). Node must be readable. */
210 
211  C4_ALWAYS_INLINE csubstr key() const RYML_NOEXCEPT { _C4RR(); return tree_->key(id_); } /**< Forward to @ref Tree::key(). Node must be readable. */
212  C4_ALWAYS_INLINE csubstr key_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->key_tag(id_); } /**< Forward to @ref Tree::key_tag(). Node must be readable. */
213  C4_ALWAYS_INLINE csubstr key_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->key_ref(id_); } /**< Forward to @ref Tree::key_ref(). Node must be readable. */
214  C4_ALWAYS_INLINE csubstr key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->key_anchor(id_); } /**< Forward to @ref Tree::key_anchor(). Node must be readable. */
215 
216  C4_ALWAYS_INLINE csubstr val() const RYML_NOEXCEPT { _C4RR(); return tree_->val(id_); } /**< Forward to @ref Tree::val(). Node must be readable. */
217  C4_ALWAYS_INLINE csubstr val_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->val_tag(id_); } /**< Forward to @ref Tree::val_tag(). Node must be readable. */
218  C4_ALWAYS_INLINE csubstr val_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->val_ref(id_); } /**< Forward to @ref Tree::val_ref(). Node must be readable. */
219  C4_ALWAYS_INLINE csubstr val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->val_anchor(id_); } /**< Forward to @ref Tree::val_anchor(). Node must be readable. */
220 
221  C4_ALWAYS_INLINE NodeScalar const& keysc() const RYML_NOEXCEPT { _C4RR(); return tree_->keysc(id_); } /**< Forward to @ref Tree::keysc(). Node must be readable. */
222  C4_ALWAYS_INLINE NodeScalar const& valsc() const RYML_NOEXCEPT { _C4RR(); return tree_->valsc(id_); } /**< Forward to @ref Tree::valsc(). Node must be readable. */
223 
224  C4_ALWAYS_INLINE bool key_is_null() const RYML_NOEXCEPT { _C4RR(); return tree_->key_is_null(id_); } /**< Forward to @ref Tree::key_is_null(). Node must be readable. */
225  C4_ALWAYS_INLINE bool val_is_null() const RYML_NOEXCEPT { _C4RR(); return tree_->val_is_null(id_); } /**< Forward to @ref Tree::val_is_null(). Node must be readable. */
226 
227  C4_ALWAYS_INLINE bool is_key_unfiltered() const noexcept { _C4RR(); return tree_->is_key_unfiltered(id_); } /**< Forward to @ref Tree::is_key_unfiltered(). Node must be readable. */
228  C4_ALWAYS_INLINE bool is_val_unfiltered() const noexcept { _C4RR(); return tree_->is_val_unfiltered(id_); } /**< Forward to @ref Tree::is_val_unfiltered(). Node must be readable. */
229 
230  /** @} */
231 
232 public:
233 
234  /** @name node type predicates */
235  /** @{ */
236 
237  C4_ALWAYS_INLINE bool empty() const RYML_NOEXCEPT { _C4RR(); return tree_->empty(id_); } /**< Forward to @ref Tree::empty(). Node must be readable. */
238  C4_ALWAYS_INLINE bool is_stream() const RYML_NOEXCEPT { _C4RR(); return tree_->is_stream(id_); } /**< Forward to @ref Tree::is_stream(). Node must be readable. */
239  C4_ALWAYS_INLINE bool is_doc() const RYML_NOEXCEPT { _C4RR(); return tree_->is_doc(id_); } /**< Forward to @ref Tree::is_doc(). Node must be readable. */
240  C4_ALWAYS_INLINE bool is_container() const RYML_NOEXCEPT { _C4RR(); return tree_->is_container(id_); } /**< Forward to @ref Tree::is_container(). Node must be readable. */
241  C4_ALWAYS_INLINE bool is_map() const RYML_NOEXCEPT { _C4RR(); return tree_->is_map(id_); } /**< Forward to @ref Tree::is_map(). Node must be readable. */
242  C4_ALWAYS_INLINE bool is_seq() const RYML_NOEXCEPT { _C4RR(); return tree_->is_seq(id_); } /**< Forward to @ref Tree::is_seq(). Node must be readable. */
243  C4_ALWAYS_INLINE bool has_val() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val(id_); } /**< Forward to @ref Tree::has_val(). Node must be readable. */
244  C4_ALWAYS_INLINE bool has_key() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key(id_); } /**< Forward to @ref Tree::has_key(). Node must be readable. */
245  C4_ALWAYS_INLINE bool is_val() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val(id_); } /**< Forward to @ref Tree::is_val(). Node must be readable. */
246  C4_ALWAYS_INLINE bool is_keyval() const RYML_NOEXCEPT { _C4RR(); return tree_->is_keyval(id_); } /**< Forward to @ref Tree::is_keyval(). Node must be readable. */
247  C4_ALWAYS_INLINE bool has_key_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_tag(id_); } /**< Forward to @ref Tree::has_key_tag(). Node must be readable. */
248  C4_ALWAYS_INLINE bool has_val_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_tag(id_); } /**< Forward to @ref Tree::has_val_tag(). Node must be readable. */
249  C4_ALWAYS_INLINE bool has_key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_anchor(id_); } /**< Forward to @ref Tree::has_key_anchor(). Node must be readable. */
250  C4_ALWAYS_INLINE bool has_val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_anchor(id_); } /**< Forward to @ref Tree::has_val_anchor(). Node must be readable. */
251  C4_ALWAYS_INLINE bool has_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_anchor(id_); } /**< Forward to @ref Tree::has_anchor(). Node must be readable. */
252  C4_ALWAYS_INLINE bool is_key_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_ref(id_); } /**< Forward to @ref Tree::is_key_ref(). Node must be readable. */
253  C4_ALWAYS_INLINE bool is_val_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_ref(id_); } /**< Forward to @ref Tree::is_val_ref(). Node must be readable. */
254  C4_ALWAYS_INLINE bool is_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_ref(id_); } /**< Forward to @ref Tree::is_ref(). Node must be readable. */
255  C4_ALWAYS_INLINE bool parent_is_seq() const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_seq(id_); } /**< Forward to @ref Tree::parent_is_seq(). Node must be readable. */
256  C4_ALWAYS_INLINE bool parent_is_map() const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_map(id_); } /**< Forward to @ref Tree::parent_is_map(). Node must be readable. */
257 
258  RYML_DEPRECATED("use has_key_anchor()") bool is_key_anchor() const noexcept { _C4RR(); return tree_->has_key_anchor(id_); }
259  RYML_DEPRECATED("use has_val_anchor()") bool is_val_hanchor() const noexcept { _C4RR(); return tree_->has_val_anchor(id_); }
260  RYML_DEPRECATED("use has_anchor()") bool is_anchor() const noexcept { _C4RR(); return tree_->has_anchor(id_); }
261  RYML_DEPRECATED("use has_anchor() || is_ref()") bool is_anchor_or_ref() const noexcept { _C4RR(); return tree_->is_anchor_or_ref(id_); }
262 
263  /** @} */
264 
265 public:
266 
267  /** @name style predicates */
268  /** @{ */
269 
270  // documentation to the right -->
271 
272  C4_ALWAYS_INLINE bool type_has_any(NodeType_e bits) const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_any(id_, bits); } /**< Forward to @ref Tree::type_has_any(). Node must be readable. */
273  C4_ALWAYS_INLINE bool type_has_all(NodeType_e bits) const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_all(id_, bits); } /**< Forward to @ref Tree::type_has_all(). Node must be readable. */
274  C4_ALWAYS_INLINE bool type_has_none(NodeType_e bits) const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_none(id_, bits); } /**< Forward to @ref Tree::type_has_none(). Node must be readable. */
275 
276  C4_ALWAYS_INLINE NodeType key_style() const RYML_NOEXCEPT { _C4RR(); return tree_->key_style(id_); } /**< Forward to @ref Tree::key_style(). Node must be readable. */
277  C4_ALWAYS_INLINE NodeType val_style() const RYML_NOEXCEPT { _C4RR(); return tree_->val_style(id_); } /**< Forward to @ref Tree::val_style(). Node must be readable. */
278 
279  C4_ALWAYS_INLINE bool is_container_styled() const RYML_NOEXCEPT { _C4RR(); return tree_->is_container_styled(id_); } /**< Forward to @ref Tree::is_container_styled(). Node must be readable. */
280  C4_ALWAYS_INLINE bool is_block() const RYML_NOEXCEPT { _C4RR(); return tree_->is_block(id_); } /**< Forward to @ref Tree::is_block(). Node must be readable. */
281  C4_ALWAYS_INLINE bool is_flow_sl() const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow_sl(id_); } /**< Forward to @ref Tree::is_flow_sl(). Node must be readable. */
282  C4_ALWAYS_INLINE bool is_flow_ml() const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow_ml(id_); } /**< Forward to @ref Tree::is_flow_ml(). Node must be readable. */
283  C4_ALWAYS_INLINE bool is_flow() const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow(id_); } /**< Forward to @ref Tree::is_flow(). Node must be readable. */
284 
285  C4_ALWAYS_INLINE bool is_key_styled() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_styled(id_); } /**< Forward to @ref Tree::is_key_styled(). Node must be readable. */
286  C4_ALWAYS_INLINE bool is_val_styled() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_styled(id_); } /**< Forward to @ref Tree::is_val_styled(). Node must be readable. */
287  C4_ALWAYS_INLINE bool is_key_literal() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_literal(id_); } /**< Forward to @ref Tree::is_key_literal(). Node must be readable. */
288  C4_ALWAYS_INLINE bool is_val_literal() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_literal(id_); } /**< Forward to @ref Tree::is_val_literal(). Node must be readable. */
289  C4_ALWAYS_INLINE bool is_key_folded() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_folded(id_); } /**< Forward to @ref Tree::is_key_folded(). Node must be readable. */
290  C4_ALWAYS_INLINE bool is_val_folded() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_folded(id_); } /**< Forward to @ref Tree::is_val_folded(). Node must be readable. */
291  C4_ALWAYS_INLINE bool is_key_squo() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_squo(id_); } /**< Forward to @ref Tree::is_key_squo(). Node must be readable. */
292  C4_ALWAYS_INLINE bool is_val_squo() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_squo(id_); } /**< Forward to @ref Tree::is_val_squo(). Node must be readable. */
293  C4_ALWAYS_INLINE bool is_key_dquo() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_dquo(id_); } /**< Forward to @ref Tree::is_key_dquo(). Node must be readable. */
294  C4_ALWAYS_INLINE bool is_val_dquo() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_dquo(id_); } /**< Forward to @ref Tree::is_val_dquo(). Node must be readable. */
295  C4_ALWAYS_INLINE bool is_key_plain() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_plain(id_); } /**< Forward to @ref Tree::is_key_plain(). Node must be readable. */
296  C4_ALWAYS_INLINE bool is_val_plain() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_plain(id_); } /**< Forward to @ref Tree::is_val_plain(). Node must be readable. */
297  C4_ALWAYS_INLINE bool is_key_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_quoted(id_); } /**< Forward to @ref Tree::is_key_quoted(). Node must be readable. */
298  C4_ALWAYS_INLINE bool is_val_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_quoted(id_); } /**< Forward to @ref Tree::is_val_quoted(). Node must be readable. */
299  C4_ALWAYS_INLINE bool is_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_quoted(id_); } /**< Forward to @ref Tree::is_quoted(). Node must be readable. */
300 
301  /** @} */
302 
303 public:
304 
305  /** @name hierarchy predicates */
306  /** @{ */
307 
308  // documentation to the right -->
309 
310  C4_ALWAYS_INLINE bool is_root() const RYML_NOEXCEPT { _C4RR(); return tree_->is_root(id_); } /**< Forward to @ref Tree::is_root(). Node must be readable. */
311  C4_ALWAYS_INLINE bool has_parent() const RYML_NOEXCEPT { _C4RR(); return tree_->has_parent(id_); } /**< Forward to @ref Tree::has_parent() Node must be readable. */
312  C4_ALWAYS_INLINE bool is_ancestor(ConstImpl const& ancestor) const RYML_NOEXCEPT { _C4RR(); return tree_->is_ancestor(id_, ancestor.m_id); } /**< Forward to @ref Tree::is_ancestor() Node must be readable. */
313 
314  C4_ALWAYS_INLINE bool has_child(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_child(id_, n.m_id) : false; } /**< Forward to @ref Tree::has_child(). Node must be readable. */
315  C4_ALWAYS_INLINE bool has_child(id_type node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, node); } /**< Forward to @ref Tree::has_child(). Node must be readable. */
316  C4_ALWAYS_INLINE bool has_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, name); } /**< Forward to @ref Tree::has_child(). Node must be readable. */
317  C4_ALWAYS_INLINE bool has_children() const RYML_NOEXCEPT { _C4RR(); return tree_->has_children(id_); } /**< Forward to @ref Tree::has_children(). Node must be readable. */
318 
319  C4_ALWAYS_INLINE bool has_sibling(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_sibling(id_, n.m_id) : false; } /**< Forward to @ref Tree::has_sibling(). Node must be readable. */
320  C4_ALWAYS_INLINE bool has_sibling(id_type node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, node); } /**< Forward to @ref Tree::has_sibling(). Node must be readable. */
321  C4_ALWAYS_INLINE bool has_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, name); } /**< Forward to @ref Tree::has_sibling(). Node must be readable. */
322  C4_ALWAYS_INLINE bool has_other_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->has_other_siblings(id_); } /**< Forward to @ref Tree::has_other_siblings(). Node must be readable. */
323 
324  RYML_DEPRECATED("use has_other_siblings()") bool has_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->has_siblings(id_); }
325 
326  /** @} */
327 
328 public:
329 
330  /** @name hierarchy getters */
331  /** @{ */
332 
333  // documentation to the right -->
334 
335  template<class U=Impl>
336  C4_ALWAYS_INLINE auto doc(id_type i) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _RYML_ASSERT_BASIC(tree_); return {tree__, tree__->doc(i)}; } /**< Forward to @ref Tree::doc(). Node must be readable. */
337  C4_ALWAYS_INLINE ConstImpl doc(id_type i) const RYML_NOEXCEPT { _RYML_ASSERT_BASIC(tree_); return {tree_, tree_->doc(i)}; } /**< Forward to @ref Tree::doc(). Node must be readable. succeeds even when the node may have invalid or seed id */
338 
339  template<class U=Impl>
340  C4_ALWAYS_INLINE auto parent() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->parent(id__)}; } /**< Forward to @ref Tree::parent(). Node must be readable. */
341  C4_ALWAYS_INLINE ConstImpl parent() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->parent(id_)}; } /**< Forward to @ref Tree::parent(). Node must be readable. */
342 
343  template<class U=Impl>
344  C4_ALWAYS_INLINE auto first_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_child(id__)}; } /**< Forward to @ref Tree::first_child(). Node must be readable. */
345  C4_ALWAYS_INLINE ConstImpl first_child() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_child(id_)}; } /**< Forward to @ref Tree::first_child(). Node must be readable. */
346 
347  template<class U=Impl>
348  C4_ALWAYS_INLINE auto last_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_child(id__)}; } /**< Forward to @ref Tree::last_child(). Node must be readable. */
349  C4_ALWAYS_INLINE ConstImpl last_child () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_child (id_)}; } /**< Forward to @ref Tree::last_child(). Node must be readable. */
350 
351  template<class U=Impl>
352  C4_ALWAYS_INLINE auto child(id_type pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->child(id__, pos)}; } /**< Forward to @ref Tree::child(). Node must be readable. */
353  C4_ALWAYS_INLINE ConstImpl child(id_type pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->child(id_, pos)}; } /**< Forward to @ref Tree::child(). Node must be readable. */
354 
355  template<class U=Impl>
356  C4_ALWAYS_INLINE auto find_child(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_child(id__, name)}; } /**< Forward to @ref Tree::find_child(). Node must be readable. */
357  C4_ALWAYS_INLINE ConstImpl find_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_child(id_, name)}; } /**< Forward to @ref Tree::find_child(). Node must be readable. */
358 
359  template<class U=Impl>
360  C4_ALWAYS_INLINE auto prev_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->prev_sibling(id__)}; } /**< Forward to @ref Tree::prev_sibling(). Node must be readable. */
361  C4_ALWAYS_INLINE ConstImpl prev_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->prev_sibling(id_)}; } /**< Forward to @ref Tree::prev_sibling(). Node must be readable. */
362 
363  template<class U=Impl>
364  C4_ALWAYS_INLINE auto next_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->next_sibling(id__)}; } /**< Forward to @ref Tree::next_sibling(). Node must be readable. */
365  C4_ALWAYS_INLINE ConstImpl next_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->next_sibling(id_)}; } /**< Forward to @ref Tree::next_sibling(). Node must be readable. */
366 
367  template<class U=Impl>
368  C4_ALWAYS_INLINE auto first_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_sibling(id__)}; } /**< Forward to @ref Tree::first_sibling(). Node must be readable. */
369  C4_ALWAYS_INLINE ConstImpl first_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_sibling(id_)}; } /**< Forward to @ref Tree::first_sibling(). Node must be readable. */
370 
371  template<class U=Impl>
372  C4_ALWAYS_INLINE auto last_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_sibling(id__)}; } /**< Forward to @ref Tree::last_sibling(). Node must be readable. */
373  C4_ALWAYS_INLINE ConstImpl last_sibling () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_sibling(id_)}; } /**< Forward to @ref Tree::last_sibling(). Node must be readable. */
374 
375  template<class U=Impl>
376  C4_ALWAYS_INLINE auto sibling(id_type pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->sibling(id__, pos)}; } /**< Forward to @ref Tree::sibling(). Node must be readable. */
377  C4_ALWAYS_INLINE ConstImpl sibling(id_type pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->sibling(id_, pos)}; } /**< Forward to @ref Tree::sibling(). Node must be readable. */
378 
379  template<class U=Impl>
380  C4_ALWAYS_INLINE auto find_sibling(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_sibling(id__, name)}; } /**< Forward to @ref Tree::find_sibling(). Node must be readable. */
381  C4_ALWAYS_INLINE ConstImpl find_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_sibling(id_, name)}; } /**< Forward to @ref Tree::find_sibling(). Node must be readable. */
382 
383  template<class U=Impl>
384  C4_ALWAYS_INLINE auto ancestor_doc() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->ancestor_doc(id__)}; } /**< Forward to @ref Tree::ancestor_doc(). Node must be readable. */
385  C4_ALWAYS_INLINE ConstImpl ancestor_doc() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->ancestor_doc(id_)}; } /**< Forward to @ref Tree::ancestor_doc(). Node must be readable. */
386 
387  C4_ALWAYS_INLINE id_type num_children() const RYML_NOEXCEPT { _C4RR(); return tree_->num_children(id_); } /**< O(num_children). Forward to @ref Tree::num_children(). */
388  C4_ALWAYS_INLINE id_type num_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->num_siblings(id_); } /**< O(num_children). Forward to @ref Tree::num_siblings(). */
389  C4_ALWAYS_INLINE id_type num_other_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->num_other_siblings(id_); } /**< O(num_siblings). Forward to @ref Tree::num_other_siblings(). */
390  C4_ALWAYS_INLINE id_type child_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_ASSERT_VISIT_(tree_->m_callbacks, n.readable(), n.tree(), n.id()); return tree_->child_pos(id_, n.m_id); } /**< O(num_children). Forward to @ref Tree::child_pos(). */
391  C4_ALWAYS_INLINE id_type sibling_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_ASSERT_VISIT_(tree_->callbacks(), n.readable(), n.tree(), n.id()); return tree_->child_pos(tree_->parent(id_), n.m_id); } /**< O(num_siblings). Forward to @ref Tree::sibling_pos(). */
392 
393  C4_ALWAYS_INLINE id_type depth_asc() const RYML_NOEXCEPT { _C4RR(); return tree_->depth_asc(id_); } /** O(log(num_nodes)). Forward to Tree::depth_asc(). Node must be readable. */
394  C4_ALWAYS_INLINE id_type depth_desc() const RYML_NOEXCEPT { _C4RR(); return tree_->depth_desc(id_); } /** O(num_nodes). Forward to Tree::depth_desc(). Node must be readable. */
395 
396  /** @} */
397 
398 public:
399 
400  /** @name square_brackets
401  * operator[] */
402  /** @{ */
403 
404  /** Find child by key; complexity is O(num_children).
405  *
406  * Returns the requested node, or an object in seed state if no
407  * such child is found (see @ref NodeRef for an explanation of
408  * what is seed state). When the object is in seed state, using it
409  * to read from the tree is UB. The seed node can be used to write
410  * to the tree provided that its create() method is called prior
411  * to writing, which happens in most modifying methods in
412  * NodeRef. It is the caller's responsibility to verify that the
413  * returned node is readable before subsequently using it to read
414  * from the tree.
415  *
416  * @warning the calling object must be readable. This precondition
417  * is asserted. The assertion is performed only if @ref
418  * RYML_USE_ASSERT is set to true. As with the non-const overload,
419  * it is UB to call this method if the node is not readable.
420  *
421  * @see https://github.com/biojppm/rapidyaml/issues/389 */
422  template<class U=Impl>
423  C4_ALWAYS_INLINE auto operator[] (csubstr key) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl)
424  {
425  _C4RR();
426  id_type ch = tree__->find_child(id__, key);
427  return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, key);
428  }
429 
430  /** Find child by position; complexity is O(pos).
431  *
432  * Returns the requested node, or an object in seed state if no
433  * such child is found (see @ref NodeRef for an explanation of
434  * what is seed state). When the object is in seed state, using it
435  * to read from the tree is UB. The seed node can be used to write
436  * to the tree provided that its create() method is called prior
437  * to writing, which happens in most modifying methods in
438  * NodeRef. It is the caller's responsibility to verify that the
439  * returned node is readable before subsequently using it to read
440  * from the tree.
441  *
442  * @warning the calling object must be readable. This precondition
443  * is asserted. The assertion is performed only if @ref
444  * RYML_USE_ASSERT is set to true. As with the non-const overload,
445  * it is UB to call this method if the node is not readable.
446  *
447  * @see https://github.com/biojppm/rapidyaml/issues/389 */
448  template<class U=Impl>
449  C4_ALWAYS_INLINE auto operator[] (id_type pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl)
450  {
451  _C4RR();
452  id_type ch = tree__->child(id__, pos);
453  return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, pos);
454  }
455 
456  /** Find a child by key; complexity is O(num_children).
457  *
458  * Behaves similar to the non-const overload, but further asserts
459  * that the returned node is readable (because it can never be in
460  * a seed state). The assertion is performed only if @ref
461  * RYML_USE_ASSERT is set to true. As with the non-const overload,
462  * it is UB to use the return value if it is not valid.
463  *
464  * @see https://github.com/biojppm/rapidyaml/issues/389 */
465  C4_ALWAYS_INLINE ConstImpl operator[] (csubstr key) const RYML_NOEXCEPT
466  {
467  _C4RR();
468  id_type ch = tree_->find_child(id_, key);
469  _RYML_ASSERT_VISIT_(tree_->m_callbacks, ch != NONE, tree_, id_);
470  return {tree_, ch};
471  }
472 
473  /** Find a child by position; complexity is O(pos).
474  *
475  * Behaves similar to the non-const overload, but further asserts
476  * that the returned node is readable (because it can never be in
477  * a seed state). This assertion is performed only if @ref
478  * RYML_USE_ASSERT is set to true. As with the non-const overload,
479  * it is UB to use the return value if it is not valid.
480  *
481  * @see https://github.com/biojppm/rapidyaml/issues/389 */
482  C4_ALWAYS_INLINE ConstImpl operator[] (id_type pos) const RYML_NOEXCEPT
483  {
484  _C4RR();
485  id_type ch = tree_->child(id_, pos);
486  _RYML_ASSERT_VISIT_(tree_->m_callbacks, ch != NONE, tree_, id_);
487  return {tree_, ch};
488  }
489 
490  /** @} */
491 
492 public:
493 
494  /** @name at
495  *
496  * These functions are the analogue to operator[], with the
497  * difference that they emit an error instead of an
498  * assertion. That is, if any of the pre or post conditions is
499  * violated, an error is always emitted (resulting in a call to
500  * the error callback).
501  *
502  * @{ */
503 
504  /** Find child by key; complexity is O(num_children).
505  *
506  * Returns the requested node, or an object in seed state if no
507  * such child is found (see @ref NodeRef for an explanation of
508  * what is seed state). When the object is in seed state, using it
509  * to read from the tree is UB. The seed node can be subsequently
510  * used to write to the tree provided that its create() method is
511  * called prior to writing, which happens inside most mutating
512  * methods in NodeRef. It is the caller's responsibility to verify
513  * that the returned node is readable before subsequently using it
514  * to read from the tree.
515  *
516  * @warning This method will call the error callback (regardless
517  * of build type or of the value of RYML_USE_ASSERT) whenever any
518  * of the following preconditions is violated: a) the object is
519  * valid (points at a tree and a node), b) the calling object must
520  * be readable (must not be in seed state), c) the calling object
521  * must be pointing at a MAP node. The preconditions are similar
522  * to the non-const operator[](csubstr), but instead of using
523  * assertions, this function directly checks those conditions and
524  * calls the error callback if any of the checks fail.
525  *
526  * @note since it is valid behavior for the returned node to be in
527  * seed state, the error callback is not invoked when this
528  * happens. */
529  template<class U=Impl>
530  C4_ALWAYS_INLINE auto at(csubstr key) -> _C4_IF_MUTABLE(Impl)
531  {
532  _RYML_CHECK_BASIC(tree_ != nullptr);
533  _RYML_CHECK_VISIT_(tree_->m_callbacks, (id_ >= 0 && id_ < tree_->capacity()), tree_, id_);
534  _RYML_CHECK_VISIT_(tree_->m_callbacks, ((Impl const*)this)->readable(), tree_, id_);
535  _RYML_CHECK_VISIT_(tree_->m_callbacks, tree_->is_map(id_), tree_, id_);
536  id_type ch = tree__->find_child(id__, key);
537  return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, key);
538  }
539 
540  /** Find child by position; complexity is O(pos).
541  *
542  * Returns the requested node, or an object in seed state if no
543  * such child is found (see @ref NodeRef for an explanation of
544  * what is seed state). When the object is in seed state, using it
545  * to read from the tree is UB. The seed node can be used to write
546  * to the tree provided that its create() method is called prior
547  * to writing, which happens in most modifying methods in
548  * NodeRef. It is the caller's responsibility to verify that the
549  * returned node is readable before subsequently using it to read
550  * from the tree.
551  *
552  * @warning This method will call the error callback (regardless
553  * of build type or of the value of RYML_USE_ASSERT) whenever any
554  * of the following preconditions is violated: a) the object is
555  * valid (points at a tree and a node), b) the calling object must
556  * be readable (must not be in seed state), c) the calling object
557  * must be pointing at a MAP node. The preconditions are similar
558  * to the non-const operator[](id_type), but instead of using
559  * assertions, this function directly checks those conditions and
560  * calls the error callback if any of the checks fail.
561  *
562  * @note since it is valid behavior for the returned node to be in
563  * seed state, the error callback is not invoked when this
564  * happens. */
565  template<class U=Impl>
566  C4_ALWAYS_INLINE auto at(id_type pos) -> _C4_IF_MUTABLE(Impl)
567  {
568  _RYML_CHECK_BASIC(tree_ != nullptr);
569  const id_type cap = tree_->capacity();
570  _RYML_CHECK_VISIT_(tree_->m_callbacks, (id_ >= 0 && id_ < cap), tree_, id_);
571  _RYML_CHECK_VISIT_(tree_->m_callbacks, (pos >= 0 && pos < cap), tree_, id_);
572  _RYML_CHECK_VISIT_(tree_->m_callbacks, ((Impl const*)this)->readable(), tree_, id_);
573  _RYML_CHECK_VISIT_(tree_->m_callbacks, tree_->is_container(id_), tree_, id_);
574  id_type ch = tree__->child(id__, pos);
575  return ch != NONE ? Impl(tree__, ch) : Impl(tree__, id__, pos);
576  }
577 
578  /** Get a child by name, with error checking; complexity is
579  * O(num_children).
580  *
581  * Behaves as operator[](csubstr) const, but always raises an
582  * error (even when RYML_USE_ASSERT is set to false) when the
583  * returned node does not exist, or when this node is not
584  * readable, or when it is not a map. This behaviour is similar to
585  * std::vector::at(), but the error consists in calling the error
586  * callback instead of directly raising an exception. */
587  ConstImpl at(csubstr key) const
588  {
589  _RYML_CHECK_BASIC(tree_ != nullptr);
590  _RYML_CHECK_VISIT_(tree_->m_callbacks, (id_ >= 0 && id_ < tree_->capacity()), tree_, id_);
591  _RYML_CHECK_VISIT_(tree_->m_callbacks, ((Impl const*)this)->readable(), tree_, id_);
592  _RYML_CHECK_VISIT_(tree_->m_callbacks, tree_->is_map(id_), tree_, id_);
593  id_type ch = tree_->find_child(id_, key);
594  _RYML_CHECK_VISIT_(tree_->m_callbacks, ch != NONE, tree_, id_);
595  return {tree_, ch};
596  }
597 
598  /** Get a child by position, with error checking; complexity is
599  * O(pos).
600  *
601  * Behaves as operator[](id_type) const, but always raises an error
602  * (even when RYML_USE_ASSERT is set to false) when the returned
603  * node does not exist, or when this node is not readable, or when
604  * it is not a container. This behaviour is similar to
605  * std::vector::at(), but the error consists in calling the error
606  * callback instead of directly raising an exception. */
607  ConstImpl at(id_type pos) const
608  {
609  _RYML_CHECK_BASIC(tree_ != nullptr);
610  const id_type cap = tree_->capacity();
611  _RYML_CHECK_VISIT_(tree_->m_callbacks, (id_ >= 0 && id_ < cap), tree_, id_);
612  _RYML_CHECK_VISIT_(tree_->m_callbacks, (pos >= 0 && pos < cap), tree_, id_);
613  _RYML_CHECK_VISIT_(tree_->m_callbacks, ((Impl const*)this)->readable(), tree_, id_);
614  _RYML_CHECK_VISIT_(tree_->m_callbacks, tree_->is_container(id_), tree_, id_);
615  const id_type ch = tree_->child(id_, pos);
616  _RYML_CHECK_VISIT_(tree_->m_callbacks, ch != NONE, tree_, id_);
617  return {tree_, ch};
618  }
619 
620  /** @} */
621 
622 public:
623 
624  /** @name locations */
625  /** @{ */
626 
627  Location location(Parser const& parser) const
628  {
629  _C4RR();
630  return tree_->location(parser, id_);
631  }
632 
633  /** @} */
634 
635 public:
636 
637  /** @name deserialization */
638  /** @{ */
639 
640  /** deserialize the node's val to the given variable, forwarding
641  * to the user-overrideable @ref read() function. */
642  template<class T>
643  ConstImpl const& operator>> (T &v) const
644  {
645  _C4RR();
646  if( ! read((ConstImpl const&)*this, &v))
647  _RYML_ERR_VISIT_(tree_->m_callbacks, tree_, id_, "could not deserialize value");
648  return *((ConstImpl const*)this);
649  }
650 
651  /** deserialize the node's key to the given variable, forwarding
652  * to the user-overrideable @ref read() function; use @ref key()
653  * to disambiguate; for example: `node >> ryml::key(var)` */
654  template<class T>
655  ConstImpl const& operator>> (Key<T> v) const
656  {
657  _C4RR();
658  if( ! readkey((ConstImpl const&)*this, &v.k))
659  _RYML_ERR_VISIT_(tree_->m_callbacks, tree_, id_, "could not deserialize key");
660  return *((ConstImpl const*)this);
661  }
662 
663  /** look for a child by name, if it exists assign to var. return
664  * true if the child existed. */
665  template<class T>
666  bool get_if(csubstr name, T *var) const
667  {
668  _C4RR();
669  ConstImpl ch = find_child(name);
670  if(!ch.readable())
671  return false;
672  ch >> *var;
673  return true;
674  }
675 
676  /** look for a child by name, if it exists assign to var,
677  * otherwise default to fallback. return true if the child
678  * existed. */
679  template<class T>
680  bool get_if(csubstr name, T *var, T const& fallback) const
681  {
682  _C4RR();
683  ConstImpl ch = find_child(name);
684  if(ch.readable())
685  {
686  ch >> *var;
687  return true;
688  }
689  else
690  {
691  *var = fallback;
692  return false;
693  }
694  }
695 
696  /** @name deserialization_base64 */
697  /** @{ */
698 
699  /** deserialize the node's key as base64. lightweight wrapper over @ref deserialize_key() */
700  ConstImpl const& operator>> (Key<fmt::base64_wrapper> w) const
701  {
703  return *((ConstImpl const*)this);
704  }
705 
706  /** deserialize the node's val as base64. lightweight wrapper over @ref deserialize_val() */
707  ConstImpl const& operator>> (fmt::base64_wrapper w) const
708  {
709  deserialize_val(w);
710  return *((ConstImpl const*)this);
711  }
712 
713  /** decode the base64-encoded key and assign the
714  * decoded blob to the given buffer/
715  * @return the size of base64-decoded blob */
717  {
718  _C4RR();
719  return from_chars(key(), &v);
720  }
721  /** decode the base64-encoded key and assign the
722  * decoded blob to the given buffer/
723  * @return the size of base64-decoded blob */
725  {
726  _C4RR();
727  return from_chars(val(), &v);
728  };
729 
730  /** @} */
731 
732  /** @} */
733 
734 public:
735 
736  #if defined(__clang__) // NOLINT
737  # pragma clang diagnostic push
738  # pragma clang diagnostic ignored "-Wnull-dereference"
739  #elif defined(__GNUC__)
740  # pragma GCC diagnostic push
741  # if __GNUC__ >= 6
742  # pragma GCC diagnostic ignored "-Wnull-dereference"
743  # endif
744  #endif
745 
746  /** @name iteration */
747  /** @{ */
748 
749  using iterator = detail::child_iterator<Impl>;
750  using const_iterator = detail::child_iterator<ConstImpl>;
751  using children_view = detail::children_view_<Impl>;
752  using const_children_view = detail::children_view_<ConstImpl>;
753 
754  template<class U=Impl>
755  C4_ALWAYS_INLINE auto begin() RYML_NOEXCEPT -> _C4_IF_MUTABLE(iterator) { _C4RR(); return iterator(tree__, tree__->first_child(id__)); } /**< get a mutable iterator to the first child. NOT AVAILABLE for ConstNodeRef. */
756  C4_ALWAYS_INLINE const_iterator begin() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, tree_->first_child(id_)); } /**< get an iterator to the first child */
757  C4_ALWAYS_INLINE const_iterator cbegin() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, tree_->first_child(id_)); } /**< get an iterator to the first child */
758 
759  template<class U=Impl>
760  C4_ALWAYS_INLINE auto end() RYML_NOEXCEPT -> _C4_IF_MUTABLE(iterator) { _C4RR(); return iterator(tree__, NONE); } /**< get an iterator to after the last child. NOT AVAILABLE for ConstNodeRef. */
761  /** get an iterator to after the last child */
762  C4_ALWAYS_INLINE const_iterator end() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, NONE); } /**< get an iterator to after the last child */
763  /** get an iterator to after the last child */
764  C4_ALWAYS_INLINE const_iterator cend() const RYML_NOEXCEPT { _C4RR(); return const_iterator(tree_, NONE); } /**< get an iterator to after the last child */
765 
766  template<class U=Impl>
767  C4_ALWAYS_INLINE auto children() RYML_NOEXCEPT -> _C4_IF_MUTABLE(children_view) { _C4RR(); return children_view(begin(), end()); } /**< get an iterable view over children. NOT AVAILABLE for ConstNodeRef. */
768  C4_ALWAYS_INLINE const_children_view children() const RYML_NOEXCEPT { _C4RR(); return const_children_view(begin(), end()); } /**< get an iterable view over children */
769  C4_ALWAYS_INLINE const_children_view cchildren() const RYML_NOEXCEPT { _C4RR(); return const_children_view(begin(), end()); } /**< get an iterable view over children */
770 
771  /** get an iterable view over all siblings (including the calling node) */
772  template<class U=Impl>
773  C4_ALWAYS_INLINE auto siblings() RYML_NOEXCEPT -> _C4_IF_MUTABLE(children_view)
774  {
775  _C4RR();
776  NodeData const *nd = tree__->get(id__);
777  return (nd->m_parent != NONE) ? // does it have a parent?
778  children_view(iterator(tree__, tree_->get(nd->m_parent)->m_first_child), iterator(tree__, NONE))
779  :
780  children_view(end(), end());
781  }
782  /** get an iterable view over all siblings (including the calling node) */
783  C4_ALWAYS_INLINE const_children_view siblings() const RYML_NOEXCEPT
784  {
785  _C4RR();
786  NodeData const *nd = tree_->get(id_);
787  return (nd->m_parent != NONE) ? // does it have a parent?
788  const_children_view(const_iterator(tree_, tree_->get(nd->m_parent)->m_first_child), const_iterator(tree_, NONE))
789  :
791  }
792  /** get an iterable view over all siblings (including the calling node) */
793  C4_ALWAYS_INLINE const_children_view csiblings() const RYML_NOEXCEPT { return siblings(); }
794 
795  /** visit every child node calling fn(node) */
796  template<class Visitor>
797  bool visit(Visitor fn, id_type indentation_level=0, bool skip_root=true) const RYML_NOEXCEPT
798  {
799  _C4RR();
800  return detail::_visit(*(ConstImpl const*)this, fn, indentation_level, skip_root);
801  }
802  /** visit every child node calling fn(node) */
803  template<class Visitor, class U=Impl>
804  auto visit(Visitor fn, id_type indentation_level=0, bool skip_root=true) RYML_NOEXCEPT
805  -> _C4_IF_MUTABLE(bool)
806  {
807  _C4RR();
808  return detail::_visit(*(Impl*)this, fn, indentation_level, skip_root);
809  }
810 
811  /** visit every child node calling fn(node, level) */
812  template<class Visitor>
813  bool visit_stacked(Visitor fn, id_type indentation_level=0, bool skip_root=true) const RYML_NOEXCEPT
814  {
815  _C4RR();
816  return detail::_visit_stacked(*(ConstImpl const*)this, fn, indentation_level, skip_root);
817  }
818  /** visit every child node calling fn(node, level) */
819  template<class Visitor, class U=Impl>
820  auto visit_stacked(Visitor fn, id_type indentation_level=0, bool skip_root=true) RYML_NOEXCEPT
821  -> _C4_IF_MUTABLE(bool)
822  {
823  _C4RR();
824  return detail::_visit_stacked(*(Impl*)this, fn, indentation_level, skip_root);
825  }
826 
827  /** @} */
828 
829  #if defined(__clang__)
830  # pragma clang diagnostic pop
831  #elif defined(__GNUC__)
832  # pragma GCC diagnostic pop
833  #endif
834 
835  #undef _C4_IF_MUTABLE
836  #undef _C4RR
837  #undef tree_
838  #undef tree__
839  #undef id_
840  #undef id__
841 
842  C4_SUPPRESS_WARNING_GCC_CLANG_POP
843 };
844 } // detail
845 
846 
847 //-----------------------------------------------------------------------------
848 //-----------------------------------------------------------------------------
849 //-----------------------------------------------------------------------------
850 /** Holds a pointer to an existing tree, and a node id. It can be used
851  * only to read from the tree.
852  *
853  * @warning The lifetime of the tree must be larger than that of this
854  * object. It is up to the user to ensure that this happens. */
855 class RYML_EXPORT ConstNodeRef : public detail::RoNodeMethods<ConstNodeRef, ConstNodeRef> // NOLINT
856 {
857 public:
858 
859  using tree_type = Tree const;
860 
861 public:
862 
863  Tree const* C4_RESTRICT m_tree;
865 
866  friend NodeRef;
868 
869 public:
870 
871  /** @name construction */
872  /** @{ */
873 
874  ConstNodeRef() noexcept : m_tree(nullptr), m_id(NONE) {}
875  ConstNodeRef(Tree const &t) noexcept : m_tree(&t), m_id(t .root_id()) {}
876  ConstNodeRef(Tree const *t) noexcept : m_tree(t ), m_id(t->root_id()) {}
877  ConstNodeRef(Tree const *t, id_type id) noexcept : m_tree(t), m_id(id) {}
878  ConstNodeRef(std::nullptr_t) noexcept : m_tree(nullptr), m_id(NONE) {}
879 
880  ConstNodeRef(ConstNodeRef const&) noexcept = default;
881  ConstNodeRef(ConstNodeRef &&) noexcept = default;
882 
883  inline ConstNodeRef(NodeRef const&) noexcept;
884  inline ConstNodeRef(NodeRef &&) noexcept;
885 
886  /** @} */
887 
888 public:
889 
890  /** @name assignment */
891  /** @{ */
892 
893  ConstNodeRef& operator= (std::nullptr_t) noexcept { m_tree = nullptr; m_id = NONE; return *this; }
894 
895  ConstNodeRef& operator= (ConstNodeRef const&) noexcept = default;
896  ConstNodeRef& operator= (ConstNodeRef &&) noexcept = default;
897 
898  ConstNodeRef& operator= (NodeRef const&) noexcept;
899  ConstNodeRef& operator= (NodeRef &&) noexcept;
900 
901  /** @} */
902 
903 public:
904 
905  /** @name state queries
906  *
907  * see @ref NodeRef for an explanation on what these states mean */
908  /** @{ */
909 
910  C4_ALWAYS_INLINE bool invalid() const noexcept { return (!m_tree) || (m_id == NONE); }
911  /** because a ConstNodeRef cannot be used to write to the tree,
912  * readable() has the same meaning as !invalid() */
913  C4_ALWAYS_INLINE bool readable() const noexcept { return m_tree != nullptr && m_id != NONE; }
914  /** because a ConstNodeRef cannot be used to write to the tree, it can never be a seed.
915  * This method is provided for API equivalence between ConstNodeRef and NodeRef. */
916  constexpr static C4_ALWAYS_INLINE bool is_seed() noexcept { return false; }
917 
918  RYML_DEPRECATED("use one of readable(), is_seed() or !invalid()") bool valid() const noexcept { return m_tree != nullptr && m_id != NONE; }
919 
920  /** @} */
921 
922 public:
923 
924  /** @name member getters */
925  /** @{ */
926 
927  C4_ALWAYS_INLINE Tree const* tree() const noexcept { return m_tree; }
928  C4_ALWAYS_INLINE id_type id() const noexcept { return m_id; }
929 
930  /** @} */
931 
932 public:
933 
934  /** @name comparisons */
935  /** @{ */
936 
937  C4_ALWAYS_INLINE bool operator== (ConstNodeRef const& that) const RYML_NOEXCEPT { return that.m_tree == m_tree && m_id == that.m_id; }
938  C4_ALWAYS_INLINE bool operator!= (ConstNodeRef const& that) const RYML_NOEXCEPT { return ! this->operator== (that); }
939 
940  /** @cond dev */
941  RYML_DEPRECATED("use invalid()") bool operator== (std::nullptr_t) const noexcept { return m_tree == nullptr || m_id == NONE; }
942  RYML_DEPRECATED("use !invalid()") bool operator!= (std::nullptr_t) const noexcept { return !(m_tree == nullptr || m_id == NONE); }
943 
944  RYML_DEPRECATED("use (this->val() == s)") bool operator== (csubstr s) const RYML_NOEXCEPT { _RYML_ASSERT_BASIC(m_tree); _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_id != NONE, m_tree, NONE); return m_tree->val(m_id) == s; }
945  RYML_DEPRECATED("use (this->val() != s)") bool operator!= (csubstr s) const RYML_NOEXCEPT { _RYML_ASSERT_BASIC(m_tree); _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_id != NONE, m_tree, NONE); return m_tree->val(m_id) != s; }
946  /** @endcond */
947 
948  /** @} */
949 
950 };
951 
952 
953 //-----------------------------------------------------------------------------
954 //-----------------------------------------------------------------------------
955 //-----------------------------------------------------------------------------
956 
957 // NOLINTBEGIN(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator)
958 
959 /** A reference to a node in an existing yaml tree, offering a more
960  * convenient API than the index-based API used in the tree.
961  *
962  * Unlike its imutable ConstNodeRef peer, a NodeRef can be used to
963  * mutate the tree, both by writing to existing nodes and by creating
964  * new nodes to subsequently write to. Semantically, a NodeRef
965  * object can be in one of three states:
966  *
967  * ```text
968  * invalid := not pointing at anything
969  * readable := points at an existing tree/node
970  * seed := points at an existing tree, and the node
971  * may come to exist, if we write to it.
972  * ```
973  *
974  * So both `readable` and `seed` are states where the node is also `valid`.
975  *
976  * ```cpp
977  * Tree t = parse_in_arena("{a: b}");
978  * NodeRef invalid; // not pointing at anything.
979  * NodeRef readable = t["a"]; // also valid, because "a" exists
980  * NodeRef seed = t["none"]; // also valid, but is seed because "none" is not in the map
981  * ```
982  *
983  * When the object is in seed state, using it to read from the tree is
984  * UB. The seed node can be used to write to the tree, provided that
985  * its create() method is called prior to writing, which happens in
986  * most modifying methods in NodeRef.
987  *
988  * It is the owners's responsibility to verify that an existing
989  * node is readable before subsequently using it to read from the
990  * tree.
991  *
992  * @warning The lifetime of the tree must be larger than that of this
993  * object. It is up to the user to ensure that this happens.
994  */
995 class RYML_EXPORT NodeRef : public detail::RoNodeMethods<NodeRef, ConstNodeRef> // NOLINT
996 {
997 public:
998 
999  using tree_type = Tree;
1001 
1002 private:
1003 
1004  Tree *C4_RESTRICT m_tree;
1005  id_type m_id;
1006 
1007  /** This member is used to enable lazy operator[] writing. When a child
1008  * with a key or index is not found, m_id is set to the id of the parent
1009  * and the asked-for key or index are stored in this member until a write
1010  * does happen. Then it is given as key or index for creating the child.
1011  * When a key is used, the csubstr stores it (so the csubstr's string is
1012  * non-null and the csubstr's size is different from NONE). When an index is
1013  * used instead, the csubstr's string is set to null, and only the csubstr's
1014  * size is set to a value different from NONE. Otherwise, when operator[]
1015  * does find the child then this member is empty: the string is null and
1016  * the size is NONE. */
1017  csubstr m_seed;
1018 
1020  friend struct detail::RoNodeMethods<NodeRef, ConstNodeRef>;
1021 
1022  // require valid: a helper macro, undefined at the end
1023  #define _C4RR() \
1024  _RYML_ASSERT_BASIC(m_tree != nullptr); \
1025  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_id != NONE && !is_seed(), m_tree, m_id)
1026  // require id: a helper macro, undefined at the end
1027  #define _C4RID() \
1028  _RYML_ASSERT_BASIC(m_tree != nullptr); \
1029  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_id != NONE, m_tree, m_id)
1030 
1031 public:
1032 
1033  /** @name construction */
1034  /** @{ */
1035 
1036  NodeRef() noexcept : m_tree(nullptr), m_id(NONE), m_seed() { _clear_seed(); }
1037  NodeRef(Tree &t) noexcept : m_tree(&t), m_id(t .root_id()), m_seed() { _clear_seed(); }
1038  NodeRef(Tree *t) noexcept : m_tree(t ), m_id(t->root_id()), m_seed() { _clear_seed(); }
1039  NodeRef(Tree *t, id_type id) noexcept : m_tree(t), m_id(id), m_seed() { _clear_seed(); }
1040  NodeRef(Tree *t, id_type id, id_type seed_pos) noexcept : m_tree(t), m_id(id), m_seed() { m_seed.str = nullptr; m_seed.len = (size_t)seed_pos; }
1041  NodeRef(Tree *t, id_type id, csubstr seed_key) noexcept : m_tree(t), m_id(id), m_seed(seed_key) {}
1042  NodeRef(std::nullptr_t) noexcept : m_tree(nullptr), m_id(NONE), m_seed() {}
1043 
1044  void _clear_seed() noexcept { /*do the following manually or an assert is triggered: */ m_seed.str = nullptr; m_seed.len = npos; }
1045 
1046  /** @} */
1047 
1048 public:
1049 
1050  /** @name assignment */
1051  /** @{ */
1052 
1053  NodeRef(NodeRef const&) noexcept = default;
1054  NodeRef(NodeRef &&) noexcept = default;
1055 
1056  NodeRef& operator= (NodeRef const&) noexcept = default;
1057  NodeRef& operator= (NodeRef &&) noexcept = default;
1058 
1059  /** @} */
1060 
1061 public:
1062 
1063  /** @name state_queries
1064  * @{ */
1065 
1066  /** true if the object is not referring to any existing or seed node. @see the doc for @ref NodeRef */
1067  bool invalid() const noexcept { return m_tree == nullptr || m_id == NONE; }
1068  /** true if the object is not invalid and in seed state. @see the doc for @ref NodeRef */
1069  bool is_seed() const noexcept { return (m_tree != nullptr && m_id != NONE) && (m_seed.str != nullptr || m_seed.len != (size_t)NONE); }
1070  /** true if the object is not invalid and not in seed state. @see the doc for @ref NodeRef */
1071  bool readable() const noexcept { return (m_tree != nullptr && m_id != NONE) && (m_seed.str == nullptr && m_seed.len == (size_t)NONE); }
1072 
1073  RYML_DEPRECATED("use one of readable(), is_seed() or !invalid()") inline bool valid() const { return m_tree != nullptr && m_id != NONE; }
1074 
1075  /** @} */
1076 
1077 public:
1078 
1079  /** @name comparisons */
1080  /** @{ */
1081 
1082  bool operator== (NodeRef const& that) const
1083  {
1084  if(m_tree == that.m_tree && m_id == that.m_id)
1085  {
1086  bool seed = is_seed();
1087  if(seed == that.is_seed())
1088  {
1089  if(seed)
1090  {
1091  return (m_seed.len == that.m_seed.len)
1092  && (m_seed.str == that.m_seed.str
1093  || m_seed == that.m_seed); // do strcmp only in the last resort
1094  }
1095  return true;
1096  }
1097  }
1098  return false;
1099  }
1100  bool operator!= (NodeRef const& that) const { return ! this->operator==(that); }
1101 
1102  bool operator== (ConstNodeRef const& that) const { return m_tree == that.m_tree && m_id == that.m_id && !is_seed(); }
1103  bool operator!= (ConstNodeRef const& that) const { return ! this->operator==(that); }
1104 
1105  /** @cond dev */
1106  RYML_DEPRECATED("use !readable()") bool operator== (std::nullptr_t) const { return m_tree == nullptr || m_id == NONE || is_seed(); }
1107  RYML_DEPRECATED("use readable()") bool operator!= (std::nullptr_t) const { return !(m_tree == nullptr || m_id == NONE || is_seed()); }
1108 
1109  RYML_DEPRECATED("use `this->val() == s`") bool operator== (csubstr s) const { _C4RR(); _RYML_ASSERT_VISIT_(m_tree->m_callbacks, has_val(), m_tree, m_id); return m_tree->val(m_id) == s; }
1110  RYML_DEPRECATED("use `this->val() != s`") bool operator!= (csubstr s) const { _C4RR(); _RYML_ASSERT_VISIT_(m_tree->m_callbacks, has_val(), m_tree, m_id); return m_tree->val(m_id) != s; }
1111  /** @endcond */
1112 
1113 public:
1114 
1115  /** @name node_property_getters
1116  * @{ */
1117 
1118  C4_ALWAYS_INLINE Tree * tree() noexcept { return m_tree; }
1119  C4_ALWAYS_INLINE Tree const* tree() const noexcept { return m_tree; }
1120 
1121  C4_ALWAYS_INLINE id_type id() const noexcept { return m_id; }
1122 
1123  /** @} */
1124 
1125 public:
1126 
1127  /** @name node_modifiers */
1128  /** @{ */
1129 
1130  void create() { _apply_seed(); }
1131 
1132  void change_type(NodeType t) { _C4RR(); m_tree->change_type(m_id, t); }
1133 
1134  void set_type(NodeType t) { _apply_seed(); m_tree->_set_flags(m_id, t); }
1135  void set_key(csubstr key) { _apply_seed(); m_tree->_set_key(m_id, key); }
1136  void set_val(csubstr val) { _apply_seed(); m_tree->_set_val(m_id, val); }
1137  void set_key_tag(csubstr key_tag) { _apply_seed(); m_tree->set_key_tag(m_id, key_tag); }
1138  void set_val_tag(csubstr val_tag) { _apply_seed(); m_tree->set_val_tag(m_id, val_tag); }
1139  void set_key_anchor(csubstr key_anchor) { _apply_seed(); m_tree->set_key_anchor(m_id, key_anchor); }
1140  void set_val_anchor(csubstr val_anchor) { _apply_seed(); m_tree->set_val_anchor(m_id, val_anchor); }
1141  void set_key_ref(csubstr key_ref) { _apply_seed(); m_tree->set_key_ref(m_id, key_ref); }
1142  void set_val_ref(csubstr val_ref) { _apply_seed(); m_tree->set_val_ref(m_id, val_ref); }
1143 
1144  void set_container_style(NodeType_e style) { _C4RR(); m_tree->set_container_style(m_id, style); }
1145  void set_key_style(NodeType_e style) { _C4RR(); m_tree->set_key_style(m_id, style); }
1146  void set_val_style(NodeType_e style) { _C4RR(); m_tree->set_val_style(m_id, style); }
1147  void clear_style(bool recurse=false) { _C4RR(); m_tree->clear_style(m_id, recurse); }
1149  NodeType rem_style_flags,
1150  NodeType add_style_flags,
1151  bool recurse=false)
1152  {
1153  _C4RR(); m_tree->set_style_conditionally(m_id, type_mask, rem_style_flags, add_style_flags, recurse);
1154  }
1155 
1156 public:
1157 
1158  void clear()
1159  {
1160  if(is_seed())
1161  return;
1162  m_tree->remove_children(m_id);
1163  m_tree->_clear(m_id);
1164  }
1165 
1166  void clear_key()
1167  {
1168  if(is_seed())
1169  return;
1170  m_tree->_clear_key(m_id);
1171  }
1172 
1173  void clear_val()
1174  {
1175  if(is_seed())
1176  return;
1177  m_tree->_clear_val(m_id);
1178  }
1179 
1181  {
1182  if(is_seed())
1183  return;
1184  m_tree->remove_children(m_id);
1185  }
1186 
1187  void operator= (NodeType_e t)
1188  {
1189  _apply_seed();
1190  m_tree->_add_flags(m_id, t);
1191  }
1192 
1194  {
1195  _apply_seed();
1196  m_tree->_add_flags(m_id, t);
1197  }
1198 
1199  void operator= (NodeInit const& v)
1200  {
1201  _apply_seed();
1202  _apply(v);
1203  }
1204 
1205  void operator= (NodeScalar const& v)
1206  {
1207  _apply_seed();
1208  _apply(v);
1209  }
1210 
1211  void operator= (std::nullptr_t)
1212  {
1213  _apply_seed();
1214  _apply(csubstr{});
1215  }
1216 
1217  void operator= (csubstr v)
1218  {
1219  _apply_seed();
1220  _apply(v);
1221  }
1222 
1223  template<size_t N>
1224  void operator= (const char (&v)[N])
1225  {
1226  _apply_seed();
1227  csubstr sv;
1228  sv.assign<N>(v);
1229  _apply(sv);
1230  }
1231 
1232  /** @} */
1233 
1234 public:
1235 
1236  /** @name serialization */
1237  /** @{ */
1238 
1239  /** serialize a variable to the arena */
1240  template<class T>
1241  csubstr to_arena(T const& C4_RESTRICT s)
1242  {
1243  _RYML_ASSERT_BASIC(m_tree); // no need for valid or readable
1244  return m_tree->to_arena(s);
1245  }
1246 
1247  template<class T>
1248  size_t set_key_serialized(T const& C4_RESTRICT k)
1249  {
1250  _apply_seed();
1251  csubstr s = m_tree->to_arena(k);
1252  m_tree->_set_key(m_id, s);
1253  return s.len;
1254  }
1255  size_t set_key_serialized(std::nullptr_t)
1256  {
1257  _apply_seed();
1258  m_tree->_set_key(m_id, csubstr{});
1259  return 0;
1260  }
1261 
1262  template<class T>
1263  size_t set_val_serialized(T const& C4_RESTRICT v)
1264  {
1265  _apply_seed();
1266  csubstr s = m_tree->to_arena(v);
1267  m_tree->_set_val(m_id, s);
1268  return s.len;
1269  }
1270  size_t set_val_serialized(std::nullptr_t)
1271  {
1272  _apply_seed();
1273  m_tree->_set_val(m_id, csubstr{});
1274  return 0;
1275  }
1276 
1277  /** encode a blob as base64 into the tree's arena, then assign the
1278  * result to the node's key
1279  * @return the size of base64-encoded blob */
1280  size_t set_key_serialized(fmt::const_base64_wrapper w);
1281  /** encode a blob as base64 into the tree's arena, then assign the
1282  * result to the node's val
1283  * @return the size of base64-encoded blob */
1284  size_t set_val_serialized(fmt::const_base64_wrapper w);
1285 
1286  /** serialize a variable, then assign the result to the node's val */
1287  NodeRef& operator<< (csubstr s)
1288  {
1289  // this overload is needed to prevent ambiguity (there's also
1290  // operator<< for writing a substr to a stream)
1291  _apply_seed();
1292  write(this, s);
1293  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, val() == s, m_tree, m_id);
1294  return *this;
1295  }
1296 
1297  template<class T>
1298  NodeRef& operator<< (T const& C4_RESTRICT v)
1299  {
1300  _apply_seed();
1301  write(this, v);
1302  return *this;
1303  }
1304 
1305  /** serialize a variable, then assign the result to the node's key */
1306  template<class T>
1307  NodeRef& operator<< (Key<const T> const& C4_RESTRICT v)
1308  {
1309  _apply_seed();
1310  set_key_serialized(v.k);
1311  return *this;
1312  }
1313 
1314  /** serialize a variable, then assign the result to the node's key */
1315  template<class T>
1316  NodeRef& operator<< (Key<T> const& C4_RESTRICT v)
1317  {
1318  _apply_seed();
1319  set_key_serialized(v.k);
1320  return *this;
1321  }
1322 
1324  {
1325  set_key_serialized(w.wrapper);
1326  return *this;
1327  }
1328 
1330  {
1331  set_val_serialized(w);
1332  return *this;
1333  }
1334 
1335  /** @} */
1336 
1337 private:
1338 
1339  void _apply_seed()
1340  {
1341  _C4RID();
1342  if(m_seed.str) // we have a seed key: use it to create the new child
1343  {
1344  m_id = m_tree->append_child(m_id);
1345  m_tree->_set_key(m_id, m_seed);
1346  m_seed.str = nullptr;
1347  m_seed.len = (size_t)NONE;
1348  }
1349  else if(m_seed.len != (size_t)NONE) // we have a seed index: create a child at that position
1350  {
1351  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, (size_t)m_tree->num_children(m_id) == m_seed.len, m_tree, m_id);
1352  m_id = m_tree->append_child(m_id);
1353  m_seed.str = nullptr;
1354  m_seed.len = (size_t)NONE;
1355  }
1356  else
1357  {
1358  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, readable(), m_tree, m_id);
1359  }
1360  }
1361 
1362  void _apply(csubstr v)
1363  {
1364  m_tree->_set_val(m_id, v);
1365  }
1366 
1367  void _apply(NodeScalar const& v)
1368  {
1369  m_tree->_set_val(m_id, v);
1370  }
1371 
1372  void _apply(NodeInit const& i)
1373  {
1374  m_tree->_set(m_id, i);
1375  }
1376 
1377 public:
1378 
1379  /** @name modification of hierarchy */
1380  /** @{ */
1381 
1383  {
1384  _C4RR();
1385  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, after.m_tree == m_tree, m_tree, m_id);
1386  NodeRef r(m_tree, m_tree->insert_child(m_id, after.m_id));
1387  return r;
1388  }
1389 
1391  {
1392  _C4RR();
1393  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, after.m_tree == m_tree, m_tree, m_id);
1394  NodeRef r(m_tree, m_tree->insert_child(m_id, after.m_id));
1395  r._apply(i);
1396  return r;
1397  }
1398 
1400  {
1401  _C4RR();
1402  NodeRef r(m_tree, m_tree->insert_child(m_id, NONE));
1403  return r;
1404  }
1405 
1407  {
1408  _C4RR();
1409  NodeRef r(m_tree, m_tree->insert_child(m_id, NONE));
1410  r._apply(i);
1411  return r;
1412  }
1413 
1415  {
1416  _C4RR();
1417  NodeRef r(m_tree, m_tree->append_child(m_id));
1418  return r;
1419  }
1420 
1422  {
1423  _C4RR();
1424  NodeRef r(m_tree, m_tree->append_child(m_id));
1425  r._apply(i);
1426  return r;
1427  }
1428 
1430  {
1431  _C4RR();
1432  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, after.m_tree == m_tree, m_tree, m_id);
1433  NodeRef r(m_tree, m_tree->insert_sibling(m_id, after.m_id));
1434  return r;
1435  }
1436 
1438  {
1439  _C4RR();
1440  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, after.m_tree == m_tree, m_tree, m_id);
1441  NodeRef r(m_tree, m_tree->insert_sibling(m_id, after.m_id));
1442  r._apply(i);
1443  return r;
1444  }
1445 
1447  {
1448  _C4RR();
1449  NodeRef r(m_tree, m_tree->prepend_sibling(m_id));
1450  return r;
1451  }
1452 
1454  {
1455  _C4RR();
1456  NodeRef r(m_tree, m_tree->prepend_sibling(m_id));
1457  r._apply(i);
1458  return r;
1459  }
1460 
1462  {
1463  _C4RR();
1464  NodeRef r(m_tree, m_tree->append_sibling(m_id));
1465  return r;
1466  }
1467 
1469  {
1470  _C4RR();
1471  NodeRef r(m_tree, m_tree->append_sibling(m_id));
1472  r._apply(i);
1473  return r;
1474  }
1475 
1476 public:
1477 
1478  void remove_child(NodeRef & child)
1479  {
1480  _C4RR();
1481  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, has_child(child), m_tree, m_id);
1482  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, child.parent().id() == id(), m_tree, m_id);
1483  m_tree->remove(child.id());
1484  child.clear();
1485  }
1486 
1487  //! remove the nth child of this node
1489  {
1490  _C4RR();
1491  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, pos >= 0 && pos < num_children(), m_tree, m_id);
1492  id_type child = m_tree->child(m_id, pos);
1493  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, child != NONE, m_tree, m_id);
1494  m_tree->remove(child);
1495  }
1496 
1497  //! remove a child by name
1498  void remove_child(csubstr key)
1499  {
1500  _C4RR();
1501  id_type child = m_tree->find_child(m_id, key);
1502  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, child != NONE, m_tree, m_id);
1503  m_tree->remove(child);
1504  }
1505 
1506 public:
1507 
1508  /** change the node's position within its parent, placing it after
1509  * @p after. To move to the first position in the parent, simply
1510  * pass an empty or default-constructed reference like this:
1511  * `n.move({})`. */
1512  void move(ConstNodeRef const& after)
1513  {
1514  _C4RR();
1515  m_tree->move(m_id, after.m_id);
1516  }
1517 
1518  /** move the node to a different @p parent (which may belong to a
1519  * different tree), placing it after @p after. When the
1520  * destination parent is in a new tree, then this node's tree
1521  * pointer is reset to the tree of the parent node. */
1522  void move(NodeRef const& parent, ConstNodeRef const& after)
1523  {
1524  _C4RR();
1525  if(parent.m_tree == m_tree)
1526  {
1527  m_tree->move(m_id, parent.m_id, after.m_id);
1528  }
1529  else
1530  {
1531  parent.m_tree->move(m_tree, m_id, parent.m_id, after.m_id);
1532  m_tree = parent.m_tree;
1533  }
1534  }
1535 
1536  /** duplicate the current node somewhere within its parent, and
1537  * place it after the node @p after. To place into the first
1538  * position of the parent, simply pass an empty or
1539  * default-constructed reference like this: `n.move({})`. */
1540  NodeRef duplicate(ConstNodeRef const& after) const
1541  {
1542  _C4RR();
1543  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, m_tree == after.m_tree || after.m_id == NONE, m_tree, m_id);
1544  id_type dup = m_tree->duplicate(m_id, m_tree->parent(m_id), after.m_id);
1545  NodeRef r(m_tree, dup);
1546  return r;
1547  }
1548 
1549  /** duplicate the current node somewhere into a different @p parent
1550  * (possibly from a different tree), and place it after the node
1551  * @p after. To place into the first position of the parent,
1552  * simply pass an empty or default-constructed reference like
1553  * this: `n.move({})`. */
1554  NodeRef duplicate(NodeRef const& parent, ConstNodeRef const& after) const
1555  {
1556  _C4RR();
1557  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, parent.m_tree == after.m_tree || after.m_id == NONE, m_tree, m_id);
1558  if(parent.m_tree == m_tree)
1559  {
1560  id_type dup = m_tree->duplicate(m_id, parent.m_id, after.m_id);
1561  NodeRef r(m_tree, dup);
1562  return r;
1563  }
1564  else
1565  {
1566  id_type dup = parent.m_tree->duplicate(m_tree, m_id, parent.m_id, after.m_id);
1567  NodeRef r(parent.m_tree, dup);
1568  return r;
1569  }
1570  }
1571 
1572  void duplicate_children(NodeRef const& parent, ConstNodeRef const& after) const
1573  {
1574  _C4RR();
1575  _RYML_ASSERT_VISIT_(m_tree->m_callbacks, parent.m_tree == after.m_tree, m_tree, m_id);
1576  if(parent.m_tree == m_tree)
1577  {
1578  m_tree->duplicate_children(m_id, parent.m_id, after.m_id);
1579  }
1580  else
1581  {
1582  parent.m_tree->duplicate_children(m_tree, m_id, parent.m_id, after.m_id);
1583  }
1584  }
1585 
1586  /** @} */
1587 
1588 #undef _C4RR
1589 #undef _C4RID
1590 };
1591 
1592 // NOLINTEND(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator)
1593 
1594 
1595 //-----------------------------------------------------------------------------
1596 
1597 inline ConstNodeRef::ConstNodeRef(NodeRef const& that) noexcept
1598  : m_tree(that.m_tree)
1599  , m_id(!that.is_seed() ? that.id() : (id_type)NONE)
1600 {
1601 }
1602 
1603 inline ConstNodeRef::ConstNodeRef(NodeRef && that) noexcept // NOLINT
1604  : m_tree(that.m_tree)
1605  , m_id(!that.is_seed() ? that.id() : (id_type)NONE)
1606 {
1607 }
1608 
1609 
1610 inline ConstNodeRef& ConstNodeRef::operator= (NodeRef const& that) noexcept
1611 {
1612  m_tree = (that.m_tree);
1613  m_id = (!that.is_seed() ? that.id() : (id_type)NONE);
1614  return *this;
1615 }
1616 
1617 inline ConstNodeRef& ConstNodeRef::operator= (NodeRef && that) noexcept // NOLINT
1618 {
1619  m_tree = (that.m_tree);
1620  m_id = (!that.is_seed() ? that.id() : (id_type)NONE);
1621  return *this;
1622 }
1623 
1624 
1625 //-----------------------------------------------------------------------------
1626 
1627 /** @addtogroup doc_serialization_helpers
1628  *
1629  * @{
1630  */
1631 
1632 template<class T>
1633 C4_ALWAYS_INLINE void write(NodeRef *n, T const& v)
1634 {
1635  n->set_val_serialized(v);
1636 }
1637 
1638 template<class T>
1639 C4_ALWAYS_INLINE bool read(ConstNodeRef const& C4_RESTRICT n, T *v)
1640 {
1641  return read(n.m_tree, n.m_id, v);
1642 }
1643 
1644 template<class T>
1645 C4_ALWAYS_INLINE bool read(NodeRef const& C4_RESTRICT n, T *v)
1646 {
1647  return read(n.tree(), n.id(), v);
1648 }
1649 
1650 template<class T>
1651 C4_ALWAYS_INLINE bool readkey(ConstNodeRef const& C4_RESTRICT n, T *v)
1652 {
1653  return readkey(n.m_tree, n.m_id, v);
1654 }
1655 
1656 template<class T>
1657 C4_ALWAYS_INLINE bool readkey(NodeRef const& C4_RESTRICT n, T *v)
1658 {
1659  return readkey(n.tree(), n.id(), v);
1660 }
1661 
1662 /** @} */
1663 
1664 /** @} */
1665 
1666 
1667 } // namespace yml
1668 } // namespace c4
1669 
1670 // NOLINTEND(modernize-avoid-c-style-cast)
1671 
1672 #ifdef __clang__
1673 # pragma clang diagnostic pop
1674 #elif defined(__GNUC__)
1675 # pragma GCC diagnostic pop
1676 #elif defined(_MSC_VER)
1677 # pragma warning(pop)
1678 #endif
1679 
1680 #endif /* _C4_YML_NODE_HPP_ */
encoding/decoding for base64.
Holds a pointer to an existing tree, and a node id.
Definition: node.hpp:856
Tree const * tree() const noexcept
Definition: node.hpp:927
ConstNodeRef() noexcept
Definition: node.hpp:874
ConstNodeRef(ConstNodeRef const &) noexcept=default
id_type id() const noexcept
Definition: node.hpp:928
ConstNodeRef(ConstNodeRef &&) noexcept=default
ConstNodeRef(Tree const *t) noexcept
Definition: node.hpp:876
ConstNodeRef(std::nullptr_t) noexcept
Definition: node.hpp:878
ConstNodeRef(Tree const *t, id_type id) noexcept
Definition: node.hpp:877
constexpr static bool is_seed() noexcept
because a ConstNodeRef cannot be used to write to the tree, it can never be a seed.
Definition: node.hpp:916
ConstNodeRef(Tree const &t) noexcept
Definition: node.hpp:875
Tree const tree_type
Definition: node.hpp:859
Tree const * m_tree
Definition: node.hpp:863
ConstNodeRef & operator=(std::nullptr_t) noexcept
Definition: node.hpp:893
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
Definition: node.hpp:913
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition: node.hpp:996
void set_val_anchor(csubstr val_anchor)
Definition: node.hpp:1140
void move(ConstNodeRef const &after)
change the node's position within its parent, placing it after after.
Definition: node.hpp:1512
void set_key_style(NodeType_e style)
Definition: node.hpp:1145
void set_style_conditionally(NodeType type_mask, NodeType rem_style_flags, NodeType add_style_flags, bool recurse=false)
Definition: node.hpp:1148
NodeRef prepend_child(NodeInit const &i)
Definition: node.hpp:1406
NodeRef insert_sibling(ConstNodeRef const &after)
Definition: node.hpp:1429
NodeRef(Tree *t, id_type id, csubstr seed_key) noexcept
Definition: node.hpp:1041
void set_val_tag(csubstr val_tag)
Definition: node.hpp:1138
void clear_style(bool recurse=false)
Definition: node.hpp:1147
NodeRef append_sibling(NodeInit const &i)
Definition: node.hpp:1468
NodeRef insert_sibling(NodeInit const &i, ConstNodeRef const &after)
Definition: node.hpp:1437
NodeRef(NodeRef &&) noexcept=default
NodeRef(Tree *t, id_type id, id_type seed_pos) noexcept
Definition: node.hpp:1040
NodeRef prepend_sibling(NodeInit const &i)
Definition: node.hpp:1453
csubstr to_arena(T const &s)
serialize a variable to the arena
Definition: node.hpp:1241
void _clear_seed() noexcept
Definition: node.hpp:1044
NodeRef insert_child(NodeRef after)
Definition: node.hpp:1382
void set_val(csubstr val)
Definition: node.hpp:1136
NodeRef prepend_sibling()
Definition: node.hpp:1446
void clear()
Definition: node.hpp:1158
size_t set_key_serialized(T const &k)
Definition: node.hpp:1248
void clear_children()
Definition: node.hpp:1180
void set_val_style(NodeType_e style)
Definition: node.hpp:1146
NodeRef(Tree *t, id_type id) noexcept
Definition: node.hpp:1039
NodeRef insert_child(NodeInit const &i, NodeRef after)
Definition: node.hpp:1390
Tree const * tree() const noexcept
Definition: node.hpp:1119
NodeRef() noexcept
Definition: node.hpp:1036
void clear_val()
Definition: node.hpp:1173
NodeRef append_sibling()
Definition: node.hpp:1461
size_t set_val_serialized(std::nullptr_t)
Definition: node.hpp:1270
id_type id() const noexcept
Definition: node.hpp:1121
void move(NodeRef const &parent, ConstNodeRef const &after)
move the node to a different parent (which may belong to a different tree), placing it after after.
Definition: node.hpp:1522
void set_container_style(NodeType_e style)
Definition: node.hpp:1144
NodeRef duplicate(ConstNodeRef const &after) const
duplicate the current node somewhere within its parent, and place it after the node after.
Definition: node.hpp:1540
bool readable() const noexcept
true if the object is not invalid and not in seed state.
Definition: node.hpp:1071
void duplicate_children(NodeRef const &parent, ConstNodeRef const &after) const
Definition: node.hpp:1572
NodeRef(Tree *t) noexcept
Definition: node.hpp:1038
NodeRef append_child()
Definition: node.hpp:1414
void clear_key()
Definition: node.hpp:1166
size_t set_val_serialized(T const &v)
Definition: node.hpp:1263
void create()
Definition: node.hpp:1130
NodeRef duplicate(NodeRef const &parent, ConstNodeRef const &after) const
duplicate the current node somewhere into a different parent (possibly from a different tree),...
Definition: node.hpp:1554
void set_type(NodeType t)
Definition: node.hpp:1134
void remove_child(csubstr key)
remove a child by name
Definition: node.hpp:1498
NodeRef prepend_child()
Definition: node.hpp:1399
NodeRef(NodeRef const &) noexcept=default
void set_key_tag(csubstr key_tag)
Definition: node.hpp:1137
size_t set_key_serialized(std::nullptr_t)
Definition: node.hpp:1255
NodeRef append_child(NodeInit const &i)
Definition: node.hpp:1421
NodeRef(std::nullptr_t) noexcept
Definition: node.hpp:1042
void set_key_ref(csubstr key_ref)
Definition: node.hpp:1141
void remove_child(NodeRef &child)
Definition: node.hpp:1478
void set_key_anchor(csubstr key_anchor)
Definition: node.hpp:1139
void change_type(NodeType t)
Definition: node.hpp:1132
NodeRef(Tree &t) noexcept
Definition: node.hpp:1037
bool is_seed() const noexcept
true if the object is not invalid and in seed state.
Definition: node.hpp:1069
void set_key(csubstr key)
Definition: node.hpp:1135
void set_val_ref(csubstr val_ref)
Definition: node.hpp:1142
Tree * tree() noexcept
Definition: node.hpp:1118
void remove_child(id_type pos)
remove the nth child of this node
Definition: node.hpp:1488
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens,...
void move(id_type node, id_type after)
change the node's position in the parent
Definition: tree.cpp:819
id_type duplicate(id_type node, id_type new_parent, id_type after)
recursively duplicate a node from this tree into a new parent, placing it after one of its children
Definition: tree.cpp:958
id_type duplicate_children(id_type node, id_type parent, id_type after)
recursively duplicate the node's children (but not the node)
Definition: tree.cpp:980
#define RYML_NOEXCEPT
Conditionally expands to noexcept when RYML_USE_ASSERT is 0 and is empty otherwise.
Definition: common.hpp:192
#define RYML_EXPORT
Definition: export.hpp:18
base64_wrapper_< byte > base64_wrapper
a tag type to mark a payload to be encoded as base64
Definition: base64.hpp:80
base64_wrapper_< cbyte > const_base64_wrapper
a tag type to mark a payload as base64-encoded
Definition: base64.hpp:78
OStream & operator<<(OStream &s, Tree const &t)
emit YAML to an STL-like ostream
Definition: emit.hpp:521
bool from_chars(csubstr buf, uint8_t *v) noexcept
Definition: charconv.hpp:2368
NodeType_e & operator|=(NodeType_e &subject, NodeType_e bits) noexcept
Definition: node_type.hpp:112
NodeType_e
a bit mask for marking node types and styles
Definition: node_type.hpp:34
bool readkey(ConstNodeRef const &n, T *v)
Definition: node.hpp:1651
void write(NodeRef *n, T const &v)
Definition: node.hpp:1633
Key< K > key(K &k)
Definition: node.hpp:46
bool read(ConstNodeRef const &n, T *v)
Definition: node.hpp:1639
bool operator!=(const char(&s)[N], basic_substring< C > const that) noexcept
Definition: substr.hpp:2283
bool operator==(const char(&s)[N], basic_substring< C > const that) noexcept
Definition: substr.hpp:2282
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:244
@ npos
a null string position
Definition: common.hpp:258
@ NONE
an index to none
Definition: common.hpp:251
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition: common.cpp:14
#define _C4RR()
Definition: node.hpp:1023
#define _C4RID()
Definition: node.hpp:1027
fmt::base64_wrapper wrapper
Definition: node.hpp:44
fmt::const_base64_wrapper wrapper
Definition: node.hpp:43
holds a source or yaml file position, for example when an error is detected; See also location_format...
Definition: common.hpp:284
contains the data for each YAML node.
Definition: tree.hpp:228
id_type m_parent
Definition: tree.hpp:234
convenience class to initialize nodes
Definition: tree.hpp:162
a node scalar is a csubstr, which may be tagged and anchored.
Definition: tree.hpp:111
wraps a NodeType_e element with some syntactic sugar and predicates
Definition: node_type.hpp:121
auto at(csubstr key) -> Impl
Find child by key; complexity is O(num_children).
Definition: node.hpp:530
bool type_has_none(NodeType_e bits) const RYML_NOEXCEPT
Forward to Tree::type_has_none().
Definition: node.hpp:274
const_children_view cchildren() const RYML_NOEXCEPT
get an iterable view over children
Definition: node.hpp:769
bool is_key_anchor() const noexcept
Definition: node.hpp:258
auto first_child() RYML_NOEXCEPT -> Impl
Forward to Tree::first_child().
Definition: node.hpp:344
id_type depth_asc() const RYML_NOEXCEPT
Definition: node.hpp:393
bool get_if(csubstr name, T *var) const
look for a child by name, if it exists assign to var.
Definition: node.hpp:666
id_type depth_desc() const RYML_NOEXCEPT
O(log(num_nodes)).
Definition: node.hpp:394
bool has_anchor() const RYML_NOEXCEPT
Forward to Tree::has_anchor().
Definition: node.hpp:251
auto children() RYML_NOEXCEPT -> children_view
get an iterable view over children.
Definition: node.hpp:767
bool is_flow_ml() const RYML_NOEXCEPT
Forward to Tree::is_flow_ml().
Definition: node.hpp:282
bool is_val() const RYML_NOEXCEPT
Forward to Tree::is_val().
Definition: node.hpp:245
bool is_key_styled() const RYML_NOEXCEPT
Forward to Tree::is_key_styled().
Definition: node.hpp:285
bool is_root() const RYML_NOEXCEPT
Forward to Tree::is_root().
Definition: node.hpp:310
csubstr key_anchor() const RYML_NOEXCEPT
Forward to Tree::key_anchor().
Definition: node.hpp:214
bool has_val_anchor() const RYML_NOEXCEPT
Forward to Tree::has_val_anchor().
Definition: node.hpp:250
bool has_siblings() const RYML_NOEXCEPT
Definition: node.hpp:324
auto last_child() RYML_NOEXCEPT -> Impl
Forward to Tree::last_child().
Definition: node.hpp:348
auto visit_stacked(Visitor fn, id_type indentation_level=0, bool skip_root=true) RYML_NOEXCEPT -> bool
visit every child node calling fn(node, level)
Definition: node.hpp:820
bool is_key_plain() const RYML_NOEXCEPT
Forward to Tree::is_key_plain().
Definition: node.hpp:295
bool is_key_quoted() const RYML_NOEXCEPT
Forward to Tree::is_key_quoted().
Definition: node.hpp:297
bool is_stream() const RYML_NOEXCEPT
Forward to Tree::is_stream().
Definition: node.hpp:238
NodeType type() const RYML_NOEXCEPT
Forward to Tree::type().
Definition: node.hpp:208
bool empty() const RYML_NOEXCEPT
Forward to Tree::empty().
Definition: node.hpp:237
NodeScalar const & valsc() const RYML_NOEXCEPT
Forward to Tree::valsc().
Definition: node.hpp:222
auto parent() RYML_NOEXCEPT -> Impl
Forward to Tree::parent().
Definition: node.hpp:340
bool has_key_anchor() const RYML_NOEXCEPT
Forward to Tree::has_key_anchor().
Definition: node.hpp:249
bool is_key_unfiltered() const noexcept
Forward to Tree::is_key_unfiltered().
Definition: node.hpp:227
id_type sibling_pos(ConstImpl const &n) const RYML_NOEXCEPT
O(num_siblings).
Definition: node.hpp:391
const_children_view siblings() const RYML_NOEXCEPT
get an iterable view over all siblings (including the calling node)
Definition: node.hpp:783
bool is_key_literal() const RYML_NOEXCEPT
Forward to Tree::is_key_literal().
Definition: node.hpp:287
const_iterator cbegin() const RYML_NOEXCEPT
get an iterator to the first child
Definition: node.hpp:757
csubstr key_ref() const RYML_NOEXCEPT
Forward to Tree::key_ref().
Definition: node.hpp:213
ConstImpl sibling(id_type pos) const RYML_NOEXCEPT
Forward to Tree::sibling().
Definition: node.hpp:377
bool visit_stacked(Visitor fn, id_type indentation_level=0, bool skip_root=true) const RYML_NOEXCEPT
visit every child node calling fn(node, level)
Definition: node.hpp:813
bool has_child(ConstImpl const &n) const RYML_NOEXCEPT
Forward to Tree::has_child().
Definition: node.hpp:314
ConstImpl const & operator>>(T &v) const
deserialize the node's val to the given variable, forwarding to the user-overrideable read() function...
Definition: node.hpp:643
auto next_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::next_sibling().
Definition: node.hpp:364
bool visit(Visitor fn, id_type indentation_level=0, bool skip_root=true) const RYML_NOEXCEPT
visit every child node calling fn(node)
Definition: node.hpp:797
bool is_quoted() const RYML_NOEXCEPT
Forward to Tree::is_quoted().
Definition: node.hpp:299
bool parent_is_map() const RYML_NOEXCEPT
Forward to Tree::parent_is_map().
Definition: node.hpp:256
auto last_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::last_sibling().
Definition: node.hpp:372
bool has_child(csubstr name) const RYML_NOEXCEPT
Forward to Tree::has_child().
Definition: node.hpp:316
auto find_sibling(csubstr name) RYML_NOEXCEPT -> Impl
Forward to Tree::find_sibling().
Definition: node.hpp:380
bool get_if(csubstr name, T *var, T const &fallback) const
look for a child by name, if it exists assign to var, otherwise default to fallback.
Definition: node.hpp:680
bool is_map() const RYML_NOEXCEPT
Forward to Tree::is_map().
Definition: node.hpp:241
bool type_has_any(NodeType_e bits) const RYML_NOEXCEPT
Forward to Tree::type_has_any().
Definition: node.hpp:272
ConstImpl last_sibling() const RYML_NOEXCEPT
Forward to Tree::last_sibling().
Definition: node.hpp:373
bool is_container() const RYML_NOEXCEPT
Forward to Tree::is_container().
Definition: node.hpp:240
id_type num_siblings() const RYML_NOEXCEPT
O(num_children).
Definition: node.hpp:388
ConstImpl last_child() const RYML_NOEXCEPT
Forward to Tree::last_child().
Definition: node.hpp:349
bool has_key() const RYML_NOEXCEPT
Forward to Tree::has_key().
Definition: node.hpp:244
csubstr key_tag() const RYML_NOEXCEPT
Forward to Tree::key_tag().
Definition: node.hpp:212
const_children_view csiblings() const RYML_NOEXCEPT
get an iterable view over all siblings (including the calling node)
Definition: node.hpp:793
auto find_child(csubstr name) RYML_NOEXCEPT -> Impl
Forward to Tree::find_child().
Definition: node.hpp:356
detail::child_iterator< Impl > iterator
Definition: node.hpp:749
csubstr val_ref() const RYML_NOEXCEPT
Forward to Tree::val_ref().
Definition: node.hpp:218
csubstr key() const RYML_NOEXCEPT
Forward to Tree::key().
Definition: node.hpp:211
ConstImpl child(id_type pos) const RYML_NOEXCEPT
Forward to Tree::child().
Definition: node.hpp:353
bool has_sibling(csubstr name) const RYML_NOEXCEPT
Forward to Tree::has_sibling().
Definition: node.hpp:321
NodeType key_style() const RYML_NOEXCEPT
Forward to Tree::key_style().
Definition: node.hpp:276
NodeScalar const & keysc() const RYML_NOEXCEPT
Forward to Tree::keysc().
Definition: node.hpp:221
size_t deserialize_val(fmt::base64_wrapper v) const
decode the base64-encoded key and assign the decoded blob to the given buffer/
Definition: node.hpp:724
bool has_key_tag() const RYML_NOEXCEPT
Forward to Tree::has_key_tag().
Definition: node.hpp:247
bool is_anchor() const noexcept
Definition: node.hpp:260
csubstr val_tag() const RYML_NOEXCEPT
Forward to Tree::val_tag().
Definition: node.hpp:217
bool is_ancestor(ConstImpl const &ancestor) const RYML_NOEXCEPT
Forward to Tree::is_ancestor() Node must be readable.
Definition: node.hpp:312
ConstImpl next_sibling() const RYML_NOEXCEPT
Forward to Tree::next_sibling().
Definition: node.hpp:365
ConstImpl find_sibling(csubstr name) const RYML_NOEXCEPT
Forward to Tree::find_sibling().
Definition: node.hpp:381
bool is_anchor_or_ref() const noexcept
Definition: node.hpp:261
const char * type_str() const RYML_NOEXCEPT
Forward to Tree::type_str().
Definition: node.hpp:209
csubstr val_anchor() const RYML_NOEXCEPT
Forward to Tree::val_anchor().
Definition: node.hpp:219
const_children_view children() const RYML_NOEXCEPT
get an iterable view over children
Definition: node.hpp:768
auto end() RYML_NOEXCEPT -> iterator
get an iterator to after the last child.
Definition: node.hpp:760
auto siblings() RYML_NOEXCEPT -> children_view
get an iterable view over all siblings (including the calling node)
Definition: node.hpp:773
bool has_parent() const RYML_NOEXCEPT
Forward to Tree::has_parent() Node must be readable.
Definition: node.hpp:311
bool is_val_squo() const RYML_NOEXCEPT
Forward to Tree::is_val_squo().
Definition: node.hpp:292
ConstImpl find_child(csubstr name) const RYML_NOEXCEPT
Forward to Tree::find_child().
Definition: node.hpp:357
NodeData const * get() const RYML_NOEXCEPT
returns the data or null when the id is NONE
Definition: node.hpp:202
ConstImpl at(csubstr key) const
Get a child by name, with error checking; complexity is O(num_children).
Definition: node.hpp:587
bool is_val_ref() const RYML_NOEXCEPT
Forward to Tree::is_val_ref().
Definition: node.hpp:253
bool has_other_siblings() const RYML_NOEXCEPT
Forward to Tree::has_other_siblings().
Definition: node.hpp:322
ConstImpl ancestor_doc() const RYML_NOEXCEPT
Forward to Tree::ancestor_doc().
Definition: node.hpp:385
bool is_val_styled() const RYML_NOEXCEPT
Forward to Tree::is_val_styled().
Definition: node.hpp:286
bool val_is_null() const RYML_NOEXCEPT
Forward to Tree::val_is_null().
Definition: node.hpp:225
auto begin() RYML_NOEXCEPT -> iterator
get a mutable iterator to the first child.
Definition: node.hpp:755
bool has_sibling(id_type node) const RYML_NOEXCEPT
Forward to Tree::has_sibling().
Definition: node.hpp:320
id_type child_pos(ConstImpl const &n) const RYML_NOEXCEPT
O(num_children).
Definition: node.hpp:390
bool is_container_styled() const RYML_NOEXCEPT
Forward to Tree::is_container_styled().
Definition: node.hpp:279
detail::children_view_< ConstImpl > const_children_view
Definition: node.hpp:752
auto first_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::first_sibling().
Definition: node.hpp:368
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
Definition: node.hpp:216
bool type_has_all(NodeType_e bits) const RYML_NOEXCEPT
Forward to Tree::type_has_all().
Definition: node.hpp:273
bool is_key_ref() const RYML_NOEXCEPT
Forward to Tree::is_key_ref().
Definition: node.hpp:252
const_iterator end() const RYML_NOEXCEPT
get an iterator to after the last child
Definition: node.hpp:762
ConstImpl parent() const RYML_NOEXCEPT
Forward to Tree::parent().
Definition: node.hpp:341
bool key_is_null() const RYML_NOEXCEPT
Forward to Tree::key_is_null().
Definition: node.hpp:224
NodeType val_style() const RYML_NOEXCEPT
Forward to Tree::val_style().
Definition: node.hpp:277
auto get() RYML_NOEXCEPT -> NodeData *
returns the data or null when the id is NONE
Definition: node.hpp:206
detail::children_view_< Impl > children_view
Definition: node.hpp:751
bool parent_is_seq() const RYML_NOEXCEPT
Forward to Tree::parent_is_seq().
Definition: node.hpp:255
bool is_doc() const RYML_NOEXCEPT
Forward to Tree::is_doc().
Definition: node.hpp:239
auto doc(id_type i) RYML_NOEXCEPT -> Impl
Forward to Tree::doc().
Definition: node.hpp:336
auto visit(Visitor fn, id_type indentation_level=0, bool skip_root=true) RYML_NOEXCEPT -> bool
visit every child node calling fn(node)
Definition: node.hpp:804
bool is_key_dquo() const RYML_NOEXCEPT
Forward to Tree::is_key_dquo().
Definition: node.hpp:293
size_t deserialize_key(fmt::base64_wrapper v) const
decode the base64-encoded key and assign the decoded blob to the given buffer/
Definition: node.hpp:716
id_type num_children() const RYML_NOEXCEPT
O(num_children).
Definition: node.hpp:387
bool is_val_unfiltered() const noexcept
Forward to Tree::is_val_unfiltered().
Definition: node.hpp:228
ConstImpl first_sibling() const RYML_NOEXCEPT
Forward to Tree::first_sibling().
Definition: node.hpp:369
ConstImpl doc(id_type i) const RYML_NOEXCEPT
Forward to Tree::doc().
Definition: node.hpp:337
bool is_flow_sl() const RYML_NOEXCEPT
Forward to Tree::is_flow_sl().
Definition: node.hpp:281
auto at(id_type pos) -> Impl
Find child by position; complexity is O(pos).
Definition: node.hpp:566
bool is_flow() const RYML_NOEXCEPT
Forward to Tree::is_flow().
Definition: node.hpp:283
ConstImpl at(id_type pos) const
Get a child by position, with error checking; complexity is O(pos).
Definition: node.hpp:607
auto child(id_type pos) RYML_NOEXCEPT -> Impl
Forward to Tree::child().
Definition: node.hpp:352
bool is_block() const RYML_NOEXCEPT
Forward to Tree::is_block().
Definition: node.hpp:280
const_iterator cend() const RYML_NOEXCEPT
get an iterator to after the last child
Definition: node.hpp:764
bool is_key_folded() const RYML_NOEXCEPT
Forward to Tree::is_key_folded().
Definition: node.hpp:289
auto ancestor_doc() RYML_NOEXCEPT -> Impl
Forward to Tree::ancestor_doc().
Definition: node.hpp:384
Location location(Parser const &parser) const
Definition: node.hpp:627
bool is_val_plain() const RYML_NOEXCEPT
Forward to Tree::is_val_plain().
Definition: node.hpp:296
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
Definition: node.hpp:242
bool is_val_folded() const RYML_NOEXCEPT
Forward to Tree::is_val_folded().
Definition: node.hpp:290
detail::child_iterator< ConstImpl > const_iterator
Definition: node.hpp:750
bool has_children() const RYML_NOEXCEPT
Forward to Tree::has_children().
Definition: node.hpp:317
bool is_val_quoted() const RYML_NOEXCEPT
Forward to Tree::is_val_quoted().
Definition: node.hpp:298
auto sibling(id_type pos) RYML_NOEXCEPT -> Impl
Forward to Tree::sibling().
Definition: node.hpp:376
bool is_val_literal() const RYML_NOEXCEPT
Forward to Tree::is_val_literal().
Definition: node.hpp:288
bool has_child(id_type node) const RYML_NOEXCEPT
Forward to Tree::has_child().
Definition: node.hpp:315
bool is_key_squo() const RYML_NOEXCEPT
Forward to Tree::is_key_squo().
Definition: node.hpp:291
bool is_val_hanchor() const noexcept
Definition: node.hpp:259
auto operator[](csubstr key) RYML_NOEXCEPT -> Impl
Find child by key; complexity is O(num_children).
Definition: node.hpp:423
bool has_val() const RYML_NOEXCEPT
Forward to Tree::has_val().
Definition: node.hpp:243
ConstImpl first_child() const RYML_NOEXCEPT
Forward to Tree::first_child().
Definition: node.hpp:345
bool has_sibling(ConstImpl const &n) const RYML_NOEXCEPT
Forward to Tree::has_sibling().
Definition: node.hpp:319
bool is_keyval() const RYML_NOEXCEPT
Forward to Tree::is_keyval().
Definition: node.hpp:246
bool has_val_tag() const RYML_NOEXCEPT
Forward to Tree::has_val_tag().
Definition: node.hpp:248
auto prev_sibling() RYML_NOEXCEPT -> Impl
Forward to Tree::prev_sibling().
Definition: node.hpp:360
ConstImpl prev_sibling() const RYML_NOEXCEPT
Forward to Tree::prev_sibling().
Definition: node.hpp:361
id_type num_other_siblings() const RYML_NOEXCEPT
O(num_siblings).
Definition: node.hpp:389
const_iterator begin() const RYML_NOEXCEPT
get an iterator to the first child
Definition: node.hpp:756
bool is_val_dquo() const RYML_NOEXCEPT
Forward to Tree::is_val_dquo().
Definition: node.hpp:294
bool is_ref() const RYML_NOEXCEPT
Forward to Tree::is_ref().
Definition: node.hpp:254