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