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