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