1 #ifndef C4_YML_TREE_HPP_
2 #define C4_YML_TREE_HPP_
7 #include "c4/error.hpp"
9 #ifndef C4_LANGUAGE_HPP_
10 #include "c4/language.hpp"
12 #ifndef C4_YML_FWD_HPP_
15 #ifndef C4_YML_COMMON_HPP_
18 #ifndef C4_YML_NODE_TYPE_HPP_
21 #ifndef C4_YML_TAG_HPP_
24 #ifndef C4_YML_ERROR_HPP_
27 #ifndef C4_YML_SCALAR_CHARCONV_HPP_
35 C4_SUPPRESS_WARNING_PUSH
36 C4_SUPPRESS_WARNING_GCC(
"-Wtype-limits")
37 C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
38 C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast")
39 #if defined(__GNUC__) && (__GNUC__ >= 6)
40 C4_SUPPRESS_WARNING_GCC(
"-Wnull-dereference")
42 C4_SUPPRESS_WARNING_CLANG(
"-Wnull-dereference")
43 C4_SUPPRESS_WARNING_CLANG("-Wtautological-compare")
44 C4_SUPPRESS_WARNING_MSVC(4127)
45 C4_SUPPRESS_WARNING_MSVC(4296)
46 C4_SUPPRESS_WARNING_MSVC(4251)
56 using _is_string_nocvref = is_string<typename detail::_remove_cvref<T>::type>;
83 #if (C4_CPP >= 17) || defined(__DOXYGEN__)
111 if constexpr (_is_string_nocvref<T>::value)
114 return serialize_to_arena_scalar<T>(tree, scalar);
117 #else // pre-C++17: need to use SFINAE
121 ->
typename std::enable_if<_is_string_nocvref<T>::value,
csubstr>::type
128 ->
typename std::enable_if< ! _is_string_nocvref<T>::value,
csubstr>::type
130 return serialize_to_arena_scalar<T>(tree, scalar);
133 #endif // pre-C++17: need to use SFINAE
149 template<
class T>
void write(Tree * tree,
id_type id, T
const& v);
152 template<
class T> C4_NODISCARD C4_ALWAYS_INLINE ReadResult
read(Tree
const* tree,
id_type id, T * v);
153 template<
class T> C4_NODISCARD C4_ALWAYS_INLINE ReadResult
read_key(Tree
const* tree,
id_type id, T * v);
154 template<
class Wrapper> C4_NODISCARD C4_ALWAYS_INLINE ReadResult
read(Tree
const* tree,
id_type id, Wrapper
const& w);
155 template<
class Wrapper> C4_NODISCARD C4_ALWAYS_INLINE ReadResult
read_key(Tree
const* tree,
id_type id, Wrapper
const& w);
182 NodeScalar(
const char (&s)[N]) noexcept : tag(), scalar(s), anchor() {}
186 template<
size_t N,
size_t M>
187 NodeScalar(
const char (&t)[N],
const char (&s)[N]) noexcept : tag(t), scalar(s), anchor() {}
200 bool empty() const noexcept {
return tag.
empty() && scalar.
empty() && anchor.
empty(); }
208 if((!has_scalar) || !scalar.
ends_with(trimmed))
212 static_assert(std::is_trivially_copyable<NodeScalar>::value,
"must be trivially copyable");
220 struct RYML_DEPRECATED("") NodeInit
230 NodeInit() : type(
NOTYPE), key(), val() {}
232 NodeInit(
type_bits t) : type(t), key(), val() {}
234 NodeInit(NodeScalar
const& v) : type(
VAL), key(), val(v) { _add_flags(); }
236 NodeInit(NodeScalar
const& v,
type_bits t) : type(t|
VAL), key(), val(v) { _add_flags(); }
238 NodeInit( NodeScalar
const& k, NodeScalar
const& v) : type(
KEYVAL), key(k), val(v) { _add_flags(); }
240 NodeInit(
type_bits t, NodeScalar
const& k, NodeScalar
const& v) : type(t), key(k), val(v) { _add_flags(); }
242 NodeInit(
type_bits t, NodeScalar
const& k ) : type(t), key(k), val( ) { _add_flags(
KEY); }
255 type = (type.m_bits|more_flags);
256 if( ! key.tag.empty())
257 type = (type.m_bits|
KEYTAG);
258 if( ! val.tag.empty())
259 type = (type.m_bits|
VALTAG);
260 if( ! key.anchor.empty())
262 if( ! val.anchor.empty())
269 RYML_ASSERT_BASIC_(key.scalar.empty() == ((type &
KEY) == 0));
271 RYML_ASSERT_BASIC_(key.tag.empty() == ((type &
KEYTAG) == 0));
273 RYML_ASSERT_BASIC_(((type &
VAL) != 0) || val.scalar.empty());
275 RYML_ASSERT_BASIC_(val.tag.empty() == ((type &
VALTAG) == 0));
300 static_assert(std::is_trivially_copyable<NodeData>::value,
"must be trivially copyable");
325 Tree& operator= (
Tree && that) noexcept;
340 void clear_arena() { m_arena_pos = 0; }
343 bool empty()
const {
return m_size == 0; }
347 id_type slack()
const { RYML_ASSERT_BASIC_(m_cap >= m_size);
return m_cap - m_size; }
365 RYML_ASSERT_VISIT_CB_(m_callbacks, node >= 0 && node < m_cap,
this, node);
374 RYML_ASSERT_VISIT_CB_(m_callbacks, node >= 0 && node < m_cap,
this, node);
380 NodeData *
_p(
id_type node) { RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
return m_buf + node; }
383 NodeData const *
_p(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
return m_buf + node; }
396 RYML_ASSERT_VISIT_CB_(m_callbacks, n >= m_buf && n < m_buf + m_cap,
this,
NONE);
397 return static_cast<id_type>(n - m_buf);
454 csubstr const&
key (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node);
return _p(node)->m_key.scalar; }
455 csubstr const&
key_tag (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key_tag(node),
this, node);
return _p(node)->m_key.tag; }
456 csubstr const&
key_ref (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, is_key_ref(node),
this, node);
return _p(node)->m_key.anchor; }
457 csubstr const&
key_anchor(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key_anchor(node),
this, node);
return _p(node)->m_key.anchor; }
458 NodeScalar const&
keysc (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node);
return _p(node)->m_key; }
460 csubstr const&
val (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val(node),
this, node);
return _p(node)->m_val.scalar; }
461 csubstr const&
val_tag (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val_tag(node),
this, node);
return _p(node)->m_val.tag; }
462 csubstr const&
val_ref (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, is_val_ref(node),
this, node);
return _p(node)->m_val.anchor; }
463 csubstr const&
val_anchor(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val_anchor(node),
this, node);
return _p(node)->m_val.anchor; }
464 NodeScalar const&
valsc (
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val(node),
this, node);
return _p(node)->m_val; }
477 C4_ALWAYS_INLINE
bool is_stream(
id_type node)
const {
return _p(node)->m_type.is_stream(); }
478 C4_ALWAYS_INLINE
bool is_doc(
id_type node)
const {
return _p(node)->m_type.is_doc(); }
480 C4_ALWAYS_INLINE
bool is_map(
id_type node)
const {
return _p(node)->m_type.is_map(); }
481 C4_ALWAYS_INLINE
bool is_seq(
id_type node)
const {
return _p(node)->m_type.is_seq(); }
482 C4_ALWAYS_INLINE
bool has_key(
id_type node)
const {
return _p(node)->m_type.has_key(); }
483 C4_ALWAYS_INLINE
bool has_val(
id_type node)
const {
return _p(node)->m_type.has_val(); }
484 C4_ALWAYS_INLINE
bool is_val(
id_type node)
const {
return _p(node)->m_type.is_val(); }
485 C4_ALWAYS_INLINE
bool is_keyval(
id_type node)
const {
return _p(node)->m_type.is_keyval(); }
493 C4_ALWAYS_INLINE
bool is_ref(
id_type node)
const {
return _p(node)->m_type.is_ref(); }
495 C4_ALWAYS_INLINE
bool parent_is_seq(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_parent(node),
this, node);
return is_seq(_p(node)->m_parent); }
496 C4_ALWAYS_INLINE
bool parent_is_map(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_parent(node),
this, node);
return is_map(_p(node)->m_parent); }
499 C4_ALWAYS_INLINE
bool has_anchor(
id_type node,
csubstr a)
const {
return _p(node)->m_key.anchor == a || _p(node)->m_val.anchor == a; }
504 C4_ALWAYS_INLINE
bool key_is_null(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node);
NodeData const* C4_RESTRICT n = _p(node);
return !n->m_type.is_key_quoted() && (n->m_type.key_is_null() ||
scalar_is_null(n->m_key.scalar)); }
508 C4_ALWAYS_INLINE
bool val_is_null(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val(node),
this, node);
NodeData const* C4_RESTRICT n = _p(node);
return !n->m_type.is_val_quoted() && (n->m_type.val_is_null() ||
scalar_is_null(n->m_val.scalar)); }
517 RYML_DEPRECATED(
"use has_key_anchor()") bool is_key_anchor(
id_type node)
const {
return _p(node)->m_type.has_key_anchor(); }
518 RYML_DEPRECATED(
"use has_val_anchor()") bool is_val_anchor(
id_type node)
const {
return _p(node)->m_type.has_val_anchor(); }
519 RYML_DEPRECATED(
"use has_anchor()") bool is_anchor(
id_type node)
const {
return _p(node)->m_type.has_anchor(); }
520 RYML_DEPRECATED(
"use has_anchor_or_ref()") bool is_anchor_or_ref(
id_type node)
const {
return _p(node)->m_type.has_anchor() || _p(node)->m_type.is_ref(); }
529 bool is_root(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, _p(node)->m_parent !=
NONE || node == 0,
this, node);
return _p(node)->m_parent ==
NONE; }
537 bool empty(
id_type node)
const {
return ! has_children(node) && _p(node)->m_key.empty() && (( ! (_p(node)->m_type &
VAL)) || _p(node)->m_val.empty()); }
591 id_type sibling_pos(
id_type node,
id_type sib)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, ! is_root(node) || node == root_id(),
this, node);
return child_pos(_p(node)->m_parent, sib); }
605 id_type doc(
id_type i)
const {
id_type rid = root_id(); RYML_ASSERT_VISIT_CB_(m_callbacks, is_stream(rid),
this, rid);
return child(rid, i); }
629 C4_ALWAYS_INLINE
bool is_block(
id_type node)
const {
return _p(node)->m_type.is_block(); }
631 RYML_DEPRECATED(
"use one of .is_flow_ml{1,n,x}()")
632 C4_ALWAYS_INLINE
bool is_flow_ml(
id_type node)
const {
return _p(node)->m_type.is_flow_ml1(); }
636 C4_ALWAYS_INLINE
bool is_flow(
id_type node)
const {
return _p(node)->m_type.is_flow(); }
653 C4_ALWAYS_INLINE
bool is_quoted(
id_type node)
const {
return _p(node)->m_type.is_quoted(); }
655 C4_ALWAYS_INLINE
NodeType key_style(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node);
return _p(node)->m_type.key_style(); }
656 C4_ALWAYS_INLINE
NodeType val_style(
id_type node)
const { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val(node) || is_root(node),
this, node);
return _p(node)->m_type.val_style(); }
658 C4_ALWAYS_INLINE
void set_container_style(
id_type node,
type_bits style) { RYML_ASSERT_VISIT_CB_(m_callbacks, is_container(node),
this, node); _p(node)->m_type.set_container_style(style); }
659 C4_ALWAYS_INLINE
void set_key_style(
id_type node,
type_bits style) { RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node); _p(node)->m_type.set_key_style(style); }
660 C4_ALWAYS_INLINE
void set_val_style(
id_type node,
type_bits style) { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val(node),
this, node); _p(node)->m_type.set_val_style(style); }
662 void clear_style(
id_type node,
bool recurse=
false);
663 void set_style_conditionally(
id_type node,
677 RYML_ASSERT_VISIT_CB_(m_callbacks, is_root(node),
this, node);
678 RYML_ASSERT_VISIT_CB_(m_callbacks, (_p(node)->m_type & (
DOC|
MAP|
VAL)) == 0,
this, node);
679 _p(node)->m_type |=
STREAM;
684 RYML_ASSERT_VISIT_CB_(m_callbacks, is_root(node) || (is_root(parent(node)) && is_stream(parent(node))),
this, node);
685 _p(node)->m_type |=
DOC;
690 RYML_ASSERT_VISIT_CB_(m_callbacks, (_p(node)->m_type & (
SEQ|
MAP)) == 0,
this, node);
691 RYML_ASSERT_VISIT_CB_(m_callbacks, (parent(node) ==
NONE || (_p(parent(node))->m_type & (
SEQ|
MAP))),
this, node);
692 NodeData *C4_RESTRICT nd = _p(node);
694 nd->m_val.scalar = val;
698 RYML_ASSERT_VISIT_CB_(m_callbacks, (_p(node)->m_type & (
SEQ|
MAP)) == 0,
this, node);
699 RYML_ASSERT_VISIT_CB_(m_callbacks, (parent(node) ==
NONE || (_p(parent(node))->m_type & (
SEQ|
MAP))),
this, node);
700 NodeData *C4_RESTRICT nd = _p(node);
701 nd->m_type |=
VAL|more_flags;
702 nd->m_val.scalar = val;
707 RYML_ASSERT_VISIT_CB_(m_callbacks, (parent(node) !=
NONE && (_p(parent(node))->m_type &
MAP)),
this, node);
708 NodeData *C4_RESTRICT nd = _p(node);
710 nd->m_key.scalar = key;
714 RYML_ASSERT_VISIT_CB_(m_callbacks, (parent(node) !=
NONE && (_p(parent(node))->m_type &
MAP)),
this, node);
715 NodeData *C4_RESTRICT nd = _p(node);
716 nd->m_type |=
KEY|more_flags;
717 nd->m_key.scalar = key;
722 RYML_ASSERT_VISIT_CB_(m_callbacks, (_p(node)->m_type & (
VAL|
MAP)) == 0,
this, node);
723 _p(node)->m_type |=
SEQ;
727 RYML_ASSERT_VISIT_CB_(m_callbacks, ((_p(node)->m_type|more_flags) & (
VAL|
MAP)) == 0,
this, node);
728 _p(node)->m_type |=
SEQ|more_flags;
733 RYML_ASSERT_VISIT_CB_(m_callbacks, (_p(node)->m_type & (
VAL|
SEQ)) == 0,
this, node);
734 _p(node)->m_type |=
MAP;
738 RYML_ASSERT_VISIT_CB_(m_callbacks, ((_p(node)->m_type|more_flags) & (
VAL|
SEQ)) == 0,
this, node);
739 _p(node)->m_type |=
MAP|more_flags;
743 void set_val_tag(
id_type node,
csubstr tag) { RYML_ASSERT_VISIT_CB_(m_callbacks, has_val(node) || is_container(node),
this, node); _p(node)->m_val.tag = tag; _add_flags(node,
VALTAG); }
747 void set_key_ref (
id_type node,
csubstr ref ) { RYML_ASSERT_VISIT_CB_(m_callbacks, ! has_key_anchor(node),
this, node);
NodeData* C4_RESTRICT n = _p(node); n->m_key.set_ref_maybe_replacing_scalar(ref, n->m_type.has_key()); _add_flags(node,
KEY|
KEYREF); }
748 void set_val_ref (
id_type node,
csubstr ref ) { RYML_ASSERT_VISIT_CB_(m_callbacks, ! has_val_anchor(node),
this, node);
NodeData* C4_RESTRICT n = _p(node); n->m_val.set_ref_maybe_replacing_scalar(ref, n->m_type.has_val()); _add_flags(node,
VAL|
VALREF); }
760 C4_NORETURN C4_NO_INLINE C4_COLD
761 void err_visit_(
id_type node)
const
763 RYML_ERR_VISIT_CB_(m_callbacks,
this, node,
"invalid node");
774 if C4_LIKELY(node !=
NONE && node < m_cap && node >= 0)
776 write(
this, node, val);
784 if C4_LIKELY(node !=
NONE && node < m_cap && node >= 0)
786 write(
this, node, val);
787 _p(node)->m_type |= more_flags;
796 if C4_LIKELY(node !=
NONE && node < m_cap && node >= 0)
806 if C4_LIKELY(node !=
NONE && node < m_cap && node >= 0)
809 _p(node)->m_type |= more_flags;
825 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
826 write(
this, node, val);
831 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
832 write(
this, node, val);
833 _p(node)->m_type |= more_flags;
839 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
845 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
847 _p(node)->m_type |= more_flags;
871 C4_ALWAYS_INLINE
void load(
id_type node, T * v,
bool check_readable=
true)
const
873 const bool can_read_val = (node !=
NONE && node < m_cap && node >= 0 && (_p(node)->m_type & (
VAL|
MAP|
SEQ)));
874 RYML_ASSERT_VISIT_CB_(m_callbacks, can_read_val,
this, node);
875 if C4_LIKELY(!check_readable || can_read_val)
887 template<
class Wrapper>
888 C4_ALWAYS_INLINE
void load(
id_type node, Wrapper
const& w,
bool check_readable=
true)
const
890 RYML_CHECK_TYPE_IS_WRAPPER_LIKE_(Wrapper);
891 const bool can_read_val = (node !=
NONE && node < m_cap && node >= 0 && (_p(node)->m_type & (
VAL|
MAP|
SEQ)));
892 RYML_ASSERT_VISIT_CB_(m_callbacks, can_read_val,
this, node);
893 if C4_LIKELY(!check_readable || can_read_val)
914 const bool can_read_key = (node !=
NONE && node < m_cap && node >= 0 && (_p(node)->m_type &
KEY));
915 RYML_ASSERT_VISIT_CB_(m_callbacks, can_read_key,
this, node);
916 if C4_LIKELY(!check_readable || can_read_key)
928 template<
class Wrapper>
929 C4_ALWAYS_INLINE
void load_key(
id_type node, Wrapper
const& w,
bool check_readable=
true)
const
931 RYML_CHECK_TYPE_IS_WRAPPER_LIKE_(Wrapper);
932 bool can_read_key = (node !=
NONE && node < m_cap && node >= 0 && (_p(node)->m_type &
KEY));
933 RYML_ASSERT_VISIT_CB_(m_callbacks, can_read_key,
this, node);
934 if C4_LIKELY(!check_readable || can_read_key)
956 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
957 RYML_ASSERT_VISIT_CB_(m_callbacks, _p(node)->m_type & (
VAL|
MAP|
SEQ),
this, node);
963 template<
class Wrapper>
966 RYML_CHECK_TYPE_IS_WRAPPER_LIKE_(Wrapper);
967 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
968 RYML_ASSERT_VISIT_CB_(m_callbacks, _p(node)->m_type & (
VAL|
MAP|
SEQ),
this, node);
977 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
978 RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node);
984 template<
class Wrapper>
987 RYML_CHECK_TYPE_IS_WRAPPER_LIKE_(Wrapper);
988 RYML_ASSERT_VISIT_CB_(m_callbacks, node !=
NONE && node >= 0 && node < m_cap,
this, node);
989 RYML_ASSERT_VISIT_CB_(m_callbacks, has_key(node),
this, node);
1014 ReadResult r = find_child_r(node, child_key, &ch);
1016 r = deserialize(ch, v);
1024 if(find_child_r(node, child_key, &ch))
1025 return deserialize(ch, v);
1030 template<
class Wrapper>
1034 ReadResult r = find_child_r(node, child_key, &ch);
1036 r = deserialize(ch, wrapper);
1052 RYML_ASSERT_VISIT_CB_(m_callbacks, is_container(node),
this, node);
1054 ReadResult r = child_r(node, child_pos, &ch);
1056 r = deserialize(ch, v);
1063 RYML_ASSERT_VISIT_CB_(m_callbacks, is_container(node),
this, node);
1065 if(child_r(node, child_pos, &ch))
1066 return deserialize(ch, v);
1072 template<
class Wrapper>
1075 RYML_ASSERT_VISIT_CB_(m_callbacks, is_container(node),
this, node);
1077 ReadResult r = child_r(node, child_pos, &ch);
1079 r = deserialize(ch, wrapper);
1112 void resolve(
bool clear_anchors=
true);
1133 void resolve_tags(
TagCache &cache,
bool all=
true);
1134 void normalize_tags();
1135 void normalize_tags_long();
1137 id_type num_tag_directives()
const;
1139 void clear_tag_directives();
1147 size_t needed = resolve_tag(output, tag, node_id);
1148 return needed <= output.
len ? output.
first(needed) : output;
1154 RYML_DEPRECATED(
"use c4::yml::tag_directive_const_iterator") typedef
TagDirective const* tag_directive_const_iterator;
1170 RYML_ASSERT_VISIT_CB_(m_callbacks, parent !=
NONE,
this, parent);
1171 RYML_ASSERT_VISIT_CB_(m_callbacks, is_container(parent) || is_root(parent),
this, parent);
1172 RYML_ASSERT_VISIT_CB_(m_callbacks, after ==
NONE || (_p(after)->m_parent == parent),
this, parent);
1174 _set_hierarchy(child, parent, after);
1184 _set_hierarchy(child, parent, _p(parent)->m_last_child);
1193 return insert_child(_p(node)->m_parent, after);
1204 remove_children(node);
1209 void remove_children(
id_type node);
1244 void set_root_as_stream();
1249 return change_type(node, (
NodeType)type);
1313 size_t arena_slack()
const { RYML_ASSERT_VISIT_CB_(m_callbacks, m_arena.len >= m_arena_pos,
this,
NONE);
return m_arena.len - m_arena_pos; }
1314 RYML_DEPRECATED(
"use arena_size() instead") size_t arena_pos()
const {
return m_arena_pos; }
1329 return m_arena.is_super(s);
1372 RYML_ASSERT_VISIT_CB_(m_callbacks, !s.
overlaps(m_arena),
this,
NONE);
1374 RYML_ASSERT_VISIT_CB_(m_callbacks, cp.len == s.
len,
this,
NONE);
1375 RYML_ASSERT_VISIT_CB_(m_callbacks, !s.
overlaps(cp),
this,
NONE);
1376 C4_SUPPRESS_WARNING_GCC_PUSH
1377 #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10)
1378 C4_SUPPRESS_WARNING_GCC(
"-Wstringop-overflow=")
1379 C4_SUPPRESS_WARNING_GCC(
"-Wrestrict")
1382 memcpy(cp.str, s.
str, s.
len);
1383 C4_SUPPRESS_WARNING_GCC_POP
1399 if(sz > arena_slack())
1400 _grow_arena(sz - arena_slack());
1401 substr s = _request_span(sz);
1411 if(arena_cap > m_arena.len)
1414 buf.
str = RYML_CB_ALLOC_(m_callbacks,
char, arena_cap);
1415 buf.
len = arena_cap;
1418 RYML_ASSERT_VISIT_CB_(m_callbacks, m_arena.len >= 0,
this,
NONE);
1420 RYML_CB_FREE_(m_callbacks, m_arena.str,
char, m_arena.len);
1432 substr _grow_arena(
size_t more)
1434 size_t cap = m_arena.
len + more;
1436 cap = cap < 2 * m_arena.len ? 2 * m_arena.len : cap;
1438 return m_arena.sub(m_arena_pos);
1441 substr _request_span(
size_t sz)
1443 RYML_ASSERT_VISIT_CB_(m_callbacks, m_arena_pos + sz <= m_arena.len,
this,
NONE);
1445 s = m_arena.
sub(m_arena_pos, sz);
1452 RYML_ASSERT_VISIT_CB_(m_callbacks, m_arena.is_super(s) || s.len == 0,
this,
NONE);
1453 RYML_ASSERT_VISIT_CB_(m_callbacks, m_arena.sub(0, m_arena_pos).is_super(s) || s.len == 0,
this,
NONE);
1454 auto pos = (s.str - m_arena.str);
1455 substr r(next_arena.str + pos, s.len);
1456 RYML_ASSERT_VISIT_CB_(m_callbacks, r.str - next_arena.str == pos,
this,
NONE);
1457 RYML_ASSERT_VISIT_CB_(m_callbacks, next_arena.sub(0, m_arena_pos).is_super(r) || r.len == 0,
this,
NONE);
1475 operator bool()
const {
return target !=
NONE; }
1505 struct _lookup_path_token
1509 _lookup_path_token() : value(), type() {}
1510 _lookup_path_token(
csubstr v, NodeType t) : value(v), type(t) {}
1511 operator bool()
const {
return type !=
NOTYPE; }
1517 void _lookup_path (lookup_result *r)
const;
1518 void _lookup_path_modify(lookup_result *r);
1520 id_type _next_node (lookup_result *r, _lookup_path_token *parent)
const;
1521 id_type _next_node_modify(lookup_result *r, _lookup_path_token *parent);
1523 static void _advance(lookup_result *r,
size_t more);
1525 _lookup_path_token _next_token(lookup_result *r, _lookup_path_token
const& parent)
const;
1531 void _copy(Tree
const& that);
1532 void _move(Tree & that) noexcept;
1534 void _relocate(
substr next_arena);
1540 #if ! RYML_USE_ASSERT
1545 NodeData *n = _p(node);
1550 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (f &
SEQ) == 0,
this, node,
"cannot mark simultaneously as map and seq");
1551 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (f &
VAL) == 0,
this, node,
"cannot mark simultaneously as map and val");
1552 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (o &
SEQ) == 0,
this, node,
"cannot turn a seq into a map; clear first");
1553 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (o &
VAL) == 0,
this, node,
"cannot turn a val into a map; clear first");
1557 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (f & MAP) == 0,
this, node,
"cannot mark simultaneously as seq and map");
1558 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (f &
VAL) == 0,
this, node,
"cannot mark simultaneously as seq and val");
1559 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (o & MAP) == 0,
this, node,
"cannot turn a map into a seq; clear first");
1560 RYML_ASSERT_VISIT_MSG_CB_(m_callbacks, (o &
VAL) == 0,
this, node,
"cannot turn a val into a seq; clear first");
1564 RYML_ASSERT_VISIT_CB_(m_callbacks, !is_root(node),
this, node);
1565 RYML_ASSERT_VISIT_CB_(m_callbacks, is_map(parent(node)),
this, node);
1567 if((f &
VAL) && !is_root(node))
1569 auto pid = parent(node); C4_UNUSED(pid);
1570 RYML_ASSERT_VISIT_CB_(m_callbacks, is_map(pid) || is_seq(pid),
this, node);
1575 void _add_flags(
id_type node,
type_bits f) { NodeData *d = _p(node);
type_bits fb = f | d->m_type; _check_next_flags(node, fb); d->m_type = fb; }
1576 void _rem_flags(
id_type node,
type_bits f) { NodeData *d = _p(node);
type_bits fb = d->m_type & ~f; _check_next_flags(node, fb); d->m_type = fb; }
1587 _copy_props(dst_,
this, src_);
1592 _copy_props_wo_key(dst_,
this, src_);
1595 void _copy_props(
id_type dst_, Tree
const* that_tree,
id_type src_)
1597 NodeData & C4_RESTRICT dst = *_p(dst_);
1598 NodeData
const& C4_RESTRICT src = *that_tree->_p(src_);
1599 dst.m_type = src.m_type;
1600 dst.m_key = src.m_key;
1601 dst.m_val = src.m_val;
1606 NodeData & C4_RESTRICT dst = *_p(dst_);
1607 NodeData
const& C4_RESTRICT src = *that_tree->_p(src_);
1608 dst.m_type = (src.m_type & src_mask) | (dst.m_type & ~src_mask);
1609 dst.m_key = src.m_key;
1610 dst.m_val = src.m_val;
1613 void _copy_props_wo_key(
id_type dst_, Tree
const* that_tree,
id_type src_)
1615 auto & C4_RESTRICT dst = *_p(dst_);
1616 auto const& C4_RESTRICT src = *that_tree->_p(src_);
1617 dst.m_type = (src.m_type & ~KEYMASK_) | (dst.m_type & KEYMASK_);
1618 dst.m_val = src.m_val;
1623 auto & C4_RESTRICT dst = *_p(dst_);
1624 auto const& C4_RESTRICT src = *that_tree->_p(src_);
1625 dst.m_type = (src.m_type & ((~KEYMASK_)|src_mask)) | (dst.m_type & (KEYMASK_|~src_mask));
1626 dst.m_val = src.m_val;
1629 void _clear_type(
id_type node)
1631 _p(node)->m_type =
NOTYPE;
1636 auto *C4_RESTRICT n = _p(node);
1641 n->m_first_child =
NONE;
1642 n->m_last_child =
NONE;
1647 _p(node)->m_key.clear();
1648 _rem_flags(node, KEY);
1653 _p(node)->m_val.clear();
1654 _rem_flags(node, VAL);
1666 void _free_list_add(
id_type node);
1667 void _free_list_rem(
id_type node);
1670 void _rem_hierarchy(
id_type node);
1693 C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
1694 C4_SUPPRESS_WARNING_MSVC_PUSH
1695 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wdeprecated")
1696 C4_SUPPRESS_WARNING_GCC_CLANG("-Wdeprecated-declarations")
1697 C4_SUPPRESS_WARNING_MSVC(4996)
1698 RYML_DEPRECATED("use .type().type_str(buf)") const
char* type_str(
id_type node)
const {
return NodeType::type_str(_p(node)->m_type); }
1699 RYML_DEPRECATED(
"use has_other_siblings()") static
bool has_siblings(
id_type ) {
return true; }
1704 RYML_DEPRECATED("use set_map()")
void to_map(
id_type node,
type_bits more_flags=0);
1705 RYML_DEPRECATED("use set_seq()")
void to_seq(
id_type node,
type_bits more_flags=0);
1706 RYML_DEPRECATED("use set_doc()")
void to_doc(
id_type node,
type_bits more_flags=0);
1707 RYML_DEPRECATED("use set_stream()")
void to_stream(
id_type node,
type_bits more_flags=0);
1708 RYML_DEPRECATED("use resolve_tags(TagCache&)")
void resolve_tags() { TagCache cache; resolve_tags(cache); }
1709 RYML_DEPRECATED(
"") void _set(
id_type node, NodeInit const& i)
1711 RYML_ASSERT_VISIT_CB_(m_callbacks, i._check(),
this, node);
1712 NodeData *n = _p(node);
1713 RYML_ASSERT_VISIT_CB_(m_callbacks, n->m_key.scalar.empty() || i.key.scalar.empty() || i.key.scalar == n->m_key.scalar,
this, node);
1714 _add_flags(node, i.type);
1715 if(n->m_key.scalar.empty())
1717 if( ! i.key.scalar.empty())
1719 set_key(node, i.key.scalar);
1722 n->m_key.tag = i.key.tag;
1725 RYML_DEPRECATED(
"") void _set_key(
id_type node, NodeScalar const& key, NodeType more_flags=0)
1727 _p(node)->m_key = key;
1728 _add_flags(node, KEY|more_flags);
1730 RYML_DEPRECATED(
"") void _set_val(
id_type node, NodeScalar const& val, NodeType more_flags=0)
1732 _p(node)->m_val = val;
1733 _add_flags(node, VAL|more_flags);
1735 C4_SUPPRESS_WARNING_MSVC_POP
1736 C4_SUPPRESS_WARNING_GCC_CLANG_POP
1759 if C4_LIKELY(num <= buf.
len)
1761 buf = buf.
first(num);
1765 buf = tree->_grow_arena(num);
1780 #if (C4_CPP >= 17) || defined(__DOXYGEN__)
1787 if constexpr (std::is_arithmetic_v<T>)
1797 if constexpr (std::is_arithmetic_v<T>)
1803 #else // pre-C++17 implementation: need to use SFINAE
1807 -> typename std::enable_if<std::is_arithmetic<T>::value,
type_bits>::type
1813 -> typename std::enable_if<std::is_arithmetic<T>::value,
type_bits>::type
1820 -> typename std::enable_if< ! std::is_arithmetic<T>::value,
type_bits>::type
1826 -> typename std::enable_if< ! std::is_arithmetic<T>::value,
type_bits>::type
1831 #endif // pre-C++17 implementation
1876 NodeData const* C4_RESTRICT nd = tree->
_p(
id);
1881 template<
class Wrapper>
1887 NodeData const* C4_RESTRICT nd = tree->
_p(
id);
1905 template<
class Wrapper>
1921 C4_SUPPRESS_WARNING_POP
csubstr const & key(id_type node) const
csubstr const & val(id_type node) const
ReadResult deserialize(id_type node, Wrapper const &w) const
(2) like (1), but for a wrapper type like those used in tag functions
bool has_anchor(id_type node) const
void set_val(id_type node, csubstr val) RYML_NOEXCEPT
NodeScalar const & keysc(id_type node) const
mark val scalar as plain scalar (unquoted, even when multiline)
ReadResult child_r(id_type node, id_type pos, id_type *child_id) const
void load(id_type node, Wrapper const &w, bool check_readable=true) const
(2) like (1), but for wrapper tag types such as c4::fmt::base64()
bool scalar_is_null(csubstr s) noexcept
YAML-sense query of nullity.
bool is_doc(id_type node) const
bool has_sibling(id_type node, csubstr key) const
true if one of the node's siblings has the given key
NodeData const * _p(id_type node) const
An if-less form of get() that demands a valid node index. This function is implementation only; use a...
bool type_has_any(id_type node, type_bits bits) const
bool is_container(id_type node) const
id_type num_siblings(id_type node) const
O(num_siblings)
substr arena()
get the current arena
void load_key(id_type node, 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...
id_type first_child(id_type node) const
ReadResult deserialize_child(id_type node, id_type child_pos, Wrapper const &wrapper) const
(3) like (1), but for wrapper tag types such as c4::fmt::base64()
bool has_val(id_type node) const
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
bool is_doc() const noexcept
A lightweight truthy type, used to enable reporting the offending node when a deserializing error hap...
ReadResult deserialize_child(id_type node, id_type child_pos, T *v, T const &fallback) const
(2) like (1), but assign from fallback if no such child exists
substr copy_to_arena(csubstr s)
copy the given string to the tree's arena, growing the arena by the required size.
void set_val_style(id_type node, type_bits style)
csubstr serialize_to_arena(Tree *, std::nullptr_t) noexcept
implementation for null values
bool is_stream(id_type node) const
ReadResult deserialize_child(id_type node, csubstr child_key, T *v, T const &fallback) const
(2) like (1), but assign from fallback if no such child exists.
NodeData * _p(id_type node)
An if-less form of get() that demands a valid node index. This function is implementation only; use a...
void set_map(id_type node) RYML_NOEXCEPT
size_t scalar_serialize(substr buf, T const &a)
Serialize a scalar to the buffer, dispatching to to_chars() or to_chars_float() as appropriate...
bool empty() const
Query for zero size.
bool is_key_folded(id_type node) const
ReadResult find_child_r(id_type node, csubstr const &key, id_type *child_id) const
like Tree::find_child(), but return a ReadResult with the status
contains the data for each YAML node.
id_type last_child(id_type node) const
static ReadResult to_result_(ReadResult notlegacy, id_type) noexcept
bool is_val_dquo(id_type node) const
bool key_is_null(id_type node) const
true if the node key is empty, or its scalar verifies scalar_is_null().
size_t arena_slack() const
get the current slack of the tree's internal arena
bool is_block(id_type node) const
#define RYML_DEFAULT_TREE_CAPACITY
default capacity for the tree when not set explicitly
id_type parent(id_type node) const
C * str
a restricted pointer to the first character of the substring
csubstr serialize_to_arena_scalar(Tree *tree, T const &scalar)
Serialize a scalar to the tree's arena.
void set_key_serialized(id_type node, T const &key, NodeType more_flags) RYML_NOEXCEPT
A c-style callbacks class to customize behavior on errors or allocation.
id_type root_id_maybe() const
Get the id of the root node, or NONE if the tree is empty.
void write(Tree *tree, id_type id, T const &v)
Serialize a variable to the tree's arena, and set it as the node's val.
void set_val_ref(id_type node, csubstr ref)
bool is_val_ref(id_type node) const
bool ends_with(const C c) const noexcept
true if the last character of the string is c
void set_map(id_type node, NodeType more_flags) RYML_NOEXCEPT
id_type first_sibling(id_type node) const
void load(id_type node, T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
id_type append_sibling(id_type node)
void set_serialized(id_type node, T const &val, NodeType more_flags) RYML_NOEXCEPT
bool has_anchor(id_type node, csubstr a) const
true when the node has an anchor named a
bool has_val_anchor(id_type node) const
bool scalar_deserialize(csubstr str, T *val)
Deserialize a scalar from its string representation, dispatching to one of from_chars(), from_chars_float() or from_chars_integral() as appropriate.
id_type _append_child__unprotected(id_type parent)
bool val_is_null(id_type node) const
true if the node val is empty, or its scalar verifies scalar_is_null().
void save(id_type node, T const &val, NodeType more_flags)
bool is_map(id_type node) const
void set_key_style(id_type node, type_bits style)
csubstr arena() const
get the current arena
Accelerator structure to reduce memory requirements by enabling reuse of resolved tags...
lookup_result(csubstr path_, id_type start)
void set_key_serialized(id_type node, T const &key) RYML_NOEXCEPT
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
csubstr const & key_anchor(id_type node) const
bool is_val_plain(id_type node) const
TagDirectives m_tag_directives
bool is_key_unfiltered(id_type node) const
true if the key was a scalar requiring filtering and was left unfiltered during the parsing (see Pars...
id_type doc(id_type i) const
gets the i document node index.
ReadResult read_key(Tree const *tree, id_type id, Wrapper const &w)
overload to enable use of wrapper tag-types like eg c4::fmt::base64()
bool has_key(id_type node) const
bool is_val_unfiltered(id_type node) const
true if the val was a scalar requiring filtering and was left unfiltered during the parsing (see Pars...
#define RYML_DEFAULT_TREE_ARENA_CAPACITY
default capacity for the tree's arena when not set explicitly
void set_key_tag(id_type node, csubstr tag)
Common utilities and infrastructure used by ryml.
id_type root_id() const
Get the id of the root node. The tree must not be empty. The tree can be empty only when constructed ...
bool from_chars(ryml::csubstr buf, vec2< T > *v)
void rem_anchor_ref(id_type node)
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
void set_doc(id_type node)
bool is_flow_sl(id_type node) const
void set_key(id_type node, csubstr key, NodeType more_flags) RYML_NOEXCEPT
void rem_val_ref(id_type node)
bool has_children(id_type node) const
true if node has any children
type_bits scalar_flags_key(T const &) noexcept
Return extra style flags to use when setting a scalar as key.
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
id_type append_child(id_type parent)
create and insert a node as the last child of parent
size_t arena_capacity() const
get the current capacity of the tree's internal arena
id_type prev_sibling(id_type node) const
bool is_key_styled(id_type node) const
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...
void set_val_anchor(id_type node, csubstr anchor)
id_type prepend_sibling(id_type node)
create and insert a node as the first node of parent
id_type last_sibling(id_type node) const
NodeType val_style(id_type node) const
bool change_type(id_type node, type_bits type)
csubstr arena_rem() const
get the free space at the end of the arena
NodeScalar(const char(&t)[N], const char(&s)[N]) noexcept
initialize as a tagged scalar
bool is_val(id_type node) const
bool is_quoted(id_type node) const
size_t arena_size() const
get the current size of the tree's internal arena
void reserve_arena(size_t arena_cap=RYML_DEFAULT_TREE_ARENA_CAPACITY)
ensure the tree's internal string arena is at least the given capacity
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
bool is_val_styled(id_type node) const
basic_substring sub(size_t first) const noexcept
return [first,len[
bool is_seq(id_type node) const
static ReadResult to_result_(bool, id_type node) noexcept
bool is_val_quoted(id_type node) const
Callbacks const & callbacks() const
csubstr to_csubstr(const char(&s)[N]) noexcept
bool is_key_plain(id_type node) const
csubstr const & val_ref(id_type node) const
NodeScalar const & valsc(id_type node) const
#define RYML_NOEXCEPT
Conditionally expands to noexcept when RYML_USE_ASSERT is 0 and is empty otherwise.
basic_substring< char > substr
a mutable string view
ReadResult deserialize_key(id_type node, Wrapper const &w) const
(2) like (1), but for a wrapper type like those used in tag functions
basic_substring< const char > csubstr
an immutable string view
bool is_container_styled(id_type node) const
void set_ref_maybe_replacing_scalar(csubstr ref, bool has_scalar) RYML_NOEXCEPT
ReadResult find_sibling_r(id_type node, csubstr const &key, id_type *sibling_id) const
like Tree::find_sibling(), but return a ReadResult if with the status
NodeType type(id_type node) const
ReadResult sibling_r(id_type node, id_type pos, id_type *sibling_id) const
like Tree::sibling(), but return a ReadResult with the status
bool is_ref(id_type node) const
id_type num_other_siblings(id_type node) const
does not count with this
holds a source or yaml file position, for example when an error is detected; See also location_format...
bool has_sibling(id_type node, id_type sib) const
true if node has a sibling with id sib
void write_key(Tree *tree, id_type id, T const &v)
Serialize a variable to the tree's arena, and set it as the node's key.
ReadResult deserialize(id_type node, T *v) const
(1) deserialize a node's contents to a variable
id_type prepend_child(id_type parent)
create and insert a node as the first child of parent
bool parent_is_map(id_type node) const
void set_seq(id_type node, NodeType more_flags) RYML_NOEXCEPT
id_type insert_sibling(id_type node, id_type after)
create and insert a new sibling of n. insert after "after"
void rem_key_anchor(id_type node)
a *reference: the val references an &anchor
bool type_has_none(id_type node, type_bits bits) const
bool is_key_ref(id_type node) const
bool has_flow_space(id_type node) const
id_type sibling_pos(id_type node, id_type sib) const
Holds a pointer to an existing tree, and a node id.
the scalar to the left of : in a map's member
a *reference: the key references an &anchor
bool is_flow_mln(id_type node) const
basic_substring triml(const C c) const
trim left
id_type next_sibling(id_type node) const
void set_serialized(id_type node, T const &val) RYML_NOEXCEPT
bool is_keyval(id_type node) const
bool parent_is_seq(id_type node) const
no node type or style is set
bool is_flow_ml1(id_type node) const
size_t len
the length of the substring
type_bits scalar_flags_val(T const &) noexcept
Return extra style flags to use when setting a scalar as val.
mark key scalar as plain scalar (unquoted, even when multiline)
c4::yml::TagDirectiveRange tag_directives() const
Error utilities used by ryml.
bool is_key_dquo(id_type node) const
void set_val(id_type node, csubstr val, NodeType more_flags) RYML_NOEXCEPT
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.
csubstr resolve_tag_sub(substr output, csubstr tag, id_type node_id) const
Wrapper for Tree::resolve_tag(), returning a substring.
id_type ancestor_doc(id_type node) const
get the document which is a parent document of node i, or the root if the tree is not a stream ...
csubstr const & key_tag(id_type node) const
bool has_key_anchor(id_type node) const
csubstr serialize_to_arena_str(Tree *tree, csubstr scalar)
Serialize a string type (as specified by c4::is_string) to a tree's arena, ensuring that there is an ...
bool is_flow_mlx(id_type node) const
Callbacks const & get_callbacks()
get the global callbacks
bool empty() const noexcept
void set_key_anchor(id_type node, csubstr anchor)
substr alloc_arena(size_t sz)
grow the tree's string arena by the given size and return a substr of the added portion ...
bool has_other_siblings(id_type node) const
true if node is not a single child
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
NodeType key_style(id_type node) const
csubstr const & val_anchor(id_type node) const
csubstr const & val_tag(id_type node) const
Reusable object to resolve references/aliases in a Tree.
bool type_has_all(id_type node, type_bits bits) const
bool empty(id_type node) const
true when key and val are empty, and has no children
void set_key(id_type node, csubstr key) RYML_NOEXCEPT
substr arena_rem()
get the free space at the end of the arena
ReadResult deserialize_child(id_type node, csubstr child_key, Wrapper const &wrapper) const
(3) like (1), but for wrapper tag types such as c4::fmt::base64()
bool is_flow(id_type node) const
bool is_val_literal(id_type node) const
NodeScalar(csubstr t, csubstr s) noexcept
void load_key(id_type node, Wrapper const &w, bool check_readable=true) const
(2) like (1), but for wrapper tag types such as c4::fmt::base64()
ReadResult deserialize_key(id_type node, T *v) const
(1) deserialize a node's key to a variable
bool is_root(id_type node) const
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
NodeScalar() noexcept
initialize as an empty scalar
ReadResult deserialize_child(id_type node, id_type child_pos, T *v) const
(1) find a child by position and deserialize its contents to the given variable (ie call ...
bool is_val_folded(id_type node) const
NodeScalar(csubstr s) noexcept
Tree(id_type node_capacity, size_t arena_capacity=RYML_DEFAULT_TREE_ARENA_CAPACITY)
Wraps a type_bits mask of NodeTypeBits flags with some syntactic sugar and predicates.
ReadResult deserialize_child(id_type node, csubstr child_key, T *v) const
(1) find a child by name and deserialize its contents to the given variable (ie call ...
bool has_child(id_type node, csubstr key) const
true if node has a child with key key
bool has_key_tag(id_type node) const
bool has_child(id_type node, id_type ch) const
true if node has a child with id ch
bool is_val_squo(id_type node) const
id_type id(NodeData const *n) const
get the id of a node belonging to this tree. n can be nullptr, in which case NONE is returned n must ...
bool is_key_squo(id_type node) const
NodeScalar(const char(&s)[N]) noexcept
initialize as an untagged scalar
bool is_key_literal(id_type node) const
bool is_key_quoted(id_type node) const
id_type find_sibling(id_type node, csubstr const &key) const
bool begins_with(const C c) const noexcept
true if the first character of the string is c
void callbacks(Callbacks const &cb)
bool has_parent(id_type node) const
bool has_val_tag(id_type node) const
a seq: a parent of VAL/SEQ/MAP nodes
void set_seq(id_type node) RYML_NOEXCEPT
ReadResult read(Tree const *tree, id_type id, Wrapper const &w)
overload to enable use of wrapper tag-types like eg c4::fmt::base64()
#define RYML_DEFAULT_TREE_ARENA_CAPACITY_START
default starting capacity for the tree's arena when it is first allocated. should be larger than RYML...
void set_key_ref(id_type node, csubstr ref)
void set_val_tag(id_type node, csubstr tag)
a node scalar is a csubstr, which may be tagged and anchored.
csubstr const & key_ref(id_type node) const
void set_container_style(id_type node, type_bits style)
csubstr to_arena(T const &a)
serialize the given variable to the tree's arena, growing it as needed to accomodate the serializatio...
void set_stream(id_type node)
id_type sibling(id_type node, id_type pos) const
void rem_key_ref(id_type node)
void save_key(id_type node, T const &key)
void rem_val_anchor(id_type node)
void save_key(id_type node, T const &key, NodeType more_flags)
void save(id_type node, T const &val)