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