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