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