1#ifndef _C4_YML_TREE_HPP_
2#define _C4_YML_TREE_HPP_
10#include "c4/types.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_CHARCONV_HPP_
35C4_SUPPRESS_WARNING_MSVC_PUSH
36C4_SUPPRESS_WARNING_MSVC(4251)
37C4_SUPPRESS_WARNING_MSVC(4296)
38C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
39C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
40C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
41C4_SUPPRESS_WARNING_GCC(
"-Wtype-limits")
49template<
class T>
inline auto read(Tree
const* C4_RESTRICT tree, id_type
id, T *v) ->
typename std::enable_if<!std::is_arithmetic<T>::value,
bool>::type;
50template<
class T>
inline auto read(Tree
const* C4_RESTRICT tree, id_type
id, T *v) ->
typename std::enable_if<std::is_arithmetic<T>::value && !std::is_floating_point<T>::value,
bool>::type;
51template<
class T>
inline auto read(Tree
const* C4_RESTRICT tree, id_type
id, T *v) ->
typename std::enable_if<std::is_floating_point<T>::value,
bool>::type;
52template<
class T>
bool read(Tree
const* C4_RESTRICT tree, id_type
id, T
const& wrapper);
54template<
class T>
inline auto readkey(Tree
const* C4_RESTRICT tree, id_type
id, T *v) ->
typename std::enable_if<!std::is_arithmetic<T>::value,
bool>::type;
55template<
class T>
inline auto readkey(Tree
const* C4_RESTRICT tree, id_type
id, T *v) ->
typename std::enable_if<std::is_arithmetic<T>::value && !std::is_floating_point<T>::value,
bool>::type;
56template<
class T>
inline auto readkey(Tree
const* C4_RESTRICT tree, id_type
id, T *v) ->
typename std::enable_if<std::is_floating_point<T>::value,
bool>::type;
57template<
class T>
bool readkey(Tree
const* C4_RESTRICT tree, id_type
id, T
const& wrapper);
67 ->
typename std::enable_if<std::is_floating_point<T>::value,
size_t>::type
73 ->
typename std::enable_if< ! std::is_floating_point<T>::value,
size_t>::type
80csubstr serialize_to_arena(Tree * C4_RESTRICT tree, T
const& C4_RESTRICT a);
129 template<
size_t N,
size_t M>
149 csubstr trimmed = ref.begins_with(
'*') ? ref.sub(1) : ref;
151 if((!has_scalar) || !
scalar.ends_with(trimmed))
155C4_MUST_BE_TRIVIAL_COPY(NodeScalar);
199 if( !
key.tag.empty())
201 if( !
val.tag.empty())
203 if( !
key.anchor.empty())
205 if( !
val.anchor.empty())
212 _RYML_ASSERT_BASIC(
key.scalar.empty() == ((
type &
KEY) == 0));
214 _RYML_ASSERT_BASIC(
key.tag.empty() == ((
type &
KEYTAG) == 0));
216 _RYML_ASSERT_BASIC(((
type &
VAL) != 0) ||
val.scalar.empty());
218 _RYML_ASSERT_BASIC(
val.tag.empty() == ((
type &
VALTAG) == 0));
267 Tree& operator= (
Tree && that)
noexcept;
411 C4_ALWAYS_INLINE
bool is_doc(
id_type node)
const {
return _p(node)->m_type.is_doc(); }
413 C4_ALWAYS_INLINE
bool is_map(
id_type node)
const {
return _p(node)->m_type.is_map(); }
414 C4_ALWAYS_INLINE
bool is_seq(
id_type node)
const {
return _p(node)->m_type.is_seq(); }
417 C4_ALWAYS_INLINE
bool is_val(
id_type node)
const {
return _p(node)->m_type.is_val(); }
426 C4_ALWAYS_INLINE
bool is_ref(
id_type node)
const {
return _p(node)->m_type.is_ref(); }
450 RYML_DEPRECATED(
"use has_key_anchor()") bool
is_key_anchor(
id_type node)
const {
return _p(node)->m_type.has_key_anchor(); }
451 RYML_DEPRECATED(
"use has_val_anchor()") bool
is_val_anchor(
id_type node)
const {
return _p(node)->m_type.has_val_anchor(); }
452 RYML_DEPRECATED(
"use has_anchor()") bool
is_anchor(
id_type node)
const {
return _p(node)->m_type.has_anchor(); }
453 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(); }
584 void clear_style(
id_type node,
bool recurse=
false);
585 void set_style_conditionally(
id_type node,
652 void resolve(
bool clear_anchors=
true);
674 void resolve_tags(
TagCache &cache,
bool all=
true);
675 void normalize_tags();
676 void normalize_tags_long();
678 id_type num_tag_directives()
const;
680 void clear_tag_directives();
689 return needed <= output.
len ? output.
first(needed) : output;
695 RYML_DEPRECATED(
"use c4::yml::tag_directive_const_iterator") typedef
TagDirective const* tag_directive_const_iterator;
731 #if defined(__clang__)
732 # pragma clang diagnostic push
733 # pragma clang diagnostic ignored "-Wnull-dereference"
734 #elif defined(__GNUC__)
735 # pragma GCC diagnostic push
737 # pragma GCC diagnostic ignored "-Wnull-dereference"
760 void remove_children(
id_type node);
778 #if defined(__clang__)
779 # pragma clang diagnostic pop
780 #elif defined(__GNUC__)
781 # pragma GCC diagnostic pop
817 void set_root_as_stream();
938 #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10)
939 C4_SUPPRESS_WARNING_GCC_PUSH
940 C4_SUPPRESS_WARNING_GCC(
"-Wstringop-overflow=")
941 C4_SUPPRESS_WARNING_GCC(
"-Wrestrict")
945 #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10)
946 C4_SUPPRESS_WARNING_GCC_POP
965 substr s = _request_span(sz);
996 substr _grow_arena(
size_t more)
998 size_t cap = m_arena.len + more;
999 cap = cap < 2 * m_arena.len ? 2 * m_arena.len : cap;
1000 cap = cap < 64 ? 64 : cap;
1002 return m_arena.sub(m_arena_pos);
1005 substr _request_span(
size_t sz)
1007 _RYML_ASSERT_VISIT_(m_callbacks, m_arena_pos + sz <= m_arena.len,
this, NONE);
1009 s = m_arena.
sub(m_arena_pos, sz);
1014 substr _relocated(csubstr s, substr next_arena)
const
1016 _RYML_ASSERT_VISIT_(m_callbacks, m_arena.is_super(s) || s.len == 0,
this, NONE);
1017 _RYML_ASSERT_VISIT_(m_callbacks, m_arena.sub(0, m_arena_pos).is_super(s) || s.len == 0,
this, NONE);
1018 auto pos = (s.str - m_arena.str);
1019 substr r(next_arena.str + pos, s.len);
1020 _RYML_ASSERT_VISIT_(m_callbacks, r.str - next_arena.str == pos,
this, NONE);
1021 _RYML_ASSERT_VISIT_(m_callbacks, next_arena.sub(0, m_arena_pos).is_super(r) || r.len == 0,
this, NONE);
1069 struct _lookup_path_token
1073 _lookup_path_token() : value(), type() {}
1074 _lookup_path_token(
csubstr v, NodeType t) : value(v), type(t) {}
1075 operator bool()
const {
return type != NOTYPE; }
1079 id_type _lookup_path_or_create(csubstr path, id_type start);
1081 void _lookup_path (lookup_result *r)
const;
1082 void _lookup_path_modify(lookup_result *r);
1084 id_type _next_node (lookup_result *r, _lookup_path_token *parent)
const;
1085 id_type _next_node_modify(lookup_result *r, _lookup_path_token *parent);
1087 static void _advance(lookup_result *r,
size_t more);
1089 _lookup_path_token _next_token(lookup_result *r, _lookup_path_token
const& parent)
const;
1095 void _copy(Tree
const& that);
1096 void _move(Tree & that)
noexcept;
1098 void _relocate(substr next_arena);
1104 #if ! RYML_USE_ASSERT
1105 C4_ALWAYS_INLINE
void _check_next_flags(id_type, type_bits) {}
1107 void _check_next_flags(id_type node, type_bits f)
1109 NodeData *n = _p(node);
1114 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & SEQ) == 0,
this, node,
"cannot mark simultaneously as map and seq");
1115 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & VAL) == 0,
this, node,
"cannot mark simultaneously as map and val");
1116 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & SEQ) == 0,
this, node,
"cannot turn a seq into a map; clear first");
1117 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & VAL) == 0,
this, node,
"cannot turn a val into a map; clear first");
1121 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & MAP) == 0,
this, node,
"cannot mark simultaneously as seq and map");
1122 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & VAL) == 0,
this, node,
"cannot mark simultaneously as seq and val");
1123 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & MAP) == 0,
this, node,
"cannot turn a map into a seq; clear first");
1124 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & VAL) == 0,
this, node,
"cannot turn a val into a seq; clear first");
1128 _RYML_ASSERT_VISIT_(m_callbacks, !is_root(node),
this, node);
1129 auto pid = parent(node); C4_UNUSED(pid);
1130 _RYML_ASSERT_VISIT_(m_callbacks, is_map(pid),
this, node);
1132 if((f & VAL) && !is_root(node))
1134 auto pid = parent(node); C4_UNUSED(pid);
1135 _RYML_ASSERT_VISIT_(m_callbacks, is_map(pid) || is_seq(pid),
this, node);
1140 void _set_flags(id_type node, NodeType_e f) { _check_next_flags(node, f); _p(node)->m_type = f; }
1141 void _set_flags(id_type node, type_bits f) { _check_next_flags(node, f); _p(node)->m_type = f; }
1143 void _add_flags(id_type node, NodeType_e f) { NodeData *d = _p(node);
type_bits fb = f | d->m_type; _check_next_flags(node, fb); d->m_type = (
NodeType_e) fb; }
1144 void _add_flags(id_type node, type_bits f) { NodeData *d = _p(node); f |= d->m_type; _check_next_flags(node, f); d->m_type = f; }
1146 void _rem_flags(id_type node, NodeType_e f) { NodeData *d = _p(node);
type_bits fb = d->m_type & ~f; _check_next_flags(node, fb); d->m_type = (
NodeType_e) fb; }
1147 void _rem_flags(id_type node, type_bits f) { NodeData *d = _p(node); f = d->m_type & ~f; _check_next_flags(node, f); d->m_type = f; }
1149 void _set_key(id_type node, csubstr key, type_bits more_flags=0)
1151 _p(node)->m_key.scalar =
key;
1152 _add_flags(node, KEY|more_flags);
1154 void _set_key(id_type node, NodeScalar
const& key, type_bits more_flags=0)
1156 _p(node)->m_key =
key;
1157 _add_flags(node, KEY|more_flags);
1160 void _set_val(id_type node, csubstr val, type_bits more_flags=0)
1162 _RYML_ASSERT_VISIT_(m_callbacks, num_children(node) == 0,
this, node);
1163 _RYML_ASSERT_VISIT_(m_callbacks, !is_seq(node) && !is_map(node),
this, node);
1164 _p(node)->m_val.scalar = val;
1165 _add_flags(node, VAL|more_flags);
1167 void _set_val(id_type node, NodeScalar
const& val, type_bits more_flags=0)
1169 _RYML_ASSERT_VISIT_(m_callbacks, num_children(node) == 0,
this, node);
1170 _RYML_ASSERT_VISIT_(m_callbacks, ! is_container(node),
this, node);
1171 _p(node)->m_val = val;
1172 _add_flags(node, VAL|more_flags);
1175 void _set(id_type node, NodeInit
const& i)
1177 _RYML_ASSERT_VISIT_(m_callbacks, i._check(),
this, node);
1178 NodeData *n = _p(node);
1179 _RYML_ASSERT_VISIT_(m_callbacks, n->m_key.scalar.empty() || i.key.scalar.empty() || i.key.scalar == n->m_key.scalar,
this, node);
1180 _add_flags(node, i.type);
1181 if(n->m_key.scalar.empty())
1183 if( ! i.key.scalar.empty())
1185 _set_key(node, i.key.scalar);
1188 n->m_key.tag = i.key.tag;
1192 void _set_parent_as_container_if_needed(id_type in)
1194 NodeData
const* n = _p(in);
1198 if( ! (is_seq(ip) || is_map(ip)))
1200 if((in == first_child(ip)) && (in == last_child(ip)))
1202 if( ! n->m_key.empty() || has_key(in))
1204 _add_flags(ip, MAP);
1208 _add_flags(ip, SEQ);
1215 void _seq2map(id_type node)
1217 _RYML_ASSERT_VISIT_(m_callbacks, is_seq(node),
this, node);
1218 for(id_type i = first_child(node); i !=
NONE; i = next_sibling(i))
1220 NodeData *C4_RESTRICT ch = _p(i);
1221 if(ch->m_type.is_keyval())
1223 ch->m_type.add(KEY);
1224 ch->m_key = ch->m_val;
1226 auto *C4_RESTRICT n = _p(node);
1231 id_type _do_reorder(id_type *node, id_type count);
1233 void _swap(id_type n_, id_type m_);
1234 void _swap_props(id_type n_, id_type m_);
1235 void _swap_hierarchy(id_type n_, id_type m_);
1236 void _copy_hierarchy(id_type dst_, id_type src_);
1238 void _copy_props(id_type dst_, id_type src_)
1240 _copy_props(dst_,
this, src_);
1243 void _copy_props_wo_key(id_type dst_, id_type src_)
1245 _copy_props_wo_key(dst_,
this, src_);
1248 void _copy_props(id_type dst_, Tree
const* that_tree, id_type src_)
1250 NodeData & C4_RESTRICT dst = *_p(dst_);
1251 NodeData
const& C4_RESTRICT src = *that_tree->_p(src_);
1252 dst.m_type = src.m_type;
1253 dst.m_key = src.m_key;
1254 dst.m_val = src.m_val;
1257 void _copy_props(id_type dst_, Tree
const* that_tree, id_type src_, type_bits src_mask)
1259 NodeData & C4_RESTRICT dst = *_p(dst_);
1260 NodeData
const& C4_RESTRICT src = *that_tree->_p(src_);
1261 dst.m_type = (src.m_type & src_mask) | (dst.m_type & ~src_mask);
1262 dst.m_key = src.m_key;
1263 dst.m_val = src.m_val;
1266 void _copy_props_wo_key(id_type dst_, Tree
const* that_tree, id_type src_)
1268 auto & C4_RESTRICT dst = *_p(dst_);
1269 auto const& C4_RESTRICT src = *that_tree->_p(src_);
1270 dst.m_type = (src.m_type & ~_KEYMASK) | (dst.m_type & _KEYMASK);
1271 dst.m_val = src.m_val;
1274 void _copy_props_wo_key(id_type dst_, Tree
const* that_tree, id_type src_, type_bits src_mask)
1276 auto & C4_RESTRICT dst = *_p(dst_);
1277 auto const& C4_RESTRICT src = *that_tree->_p(src_);
1278 dst.m_type = (src.m_type & ((~_KEYMASK)|src_mask)) | (dst.m_type & (_KEYMASK|~src_mask));
1279 dst.m_val = src.m_val;
1282 void _clear_type(id_type node)
1284 _p(node)->m_type =
NOTYPE;
1287 void _clear(id_type node)
1289 auto *C4_RESTRICT n = _p(node);
1294 n->m_first_child =
NONE;
1295 n->m_last_child =
NONE;
1298 void _clear_key(id_type node)
1300 _p(node)->m_key.clear();
1301 _rem_flags(node, KEY);
1304 void _clear_val(id_type node)
1306 _p(node)->m_val.clear();
1307 _rem_flags(node, VAL);
1314 void _clear_range(id_type first, id_type num);
1320 void _release(id_type node);
1321 void _free_list_add(id_type node);
1322 void _free_list_rem(id_type node);
1324 void _set_hierarchy(id_type node, id_type parent, id_type after_sibling);
1325 void _rem_hierarchy(id_type node);
1364 return C4_LIKELY(!(tree->type(
id) &
VALNIL)) ?
from_chars(tree->val(
id), wrapper) :
false;
1369 return C4_LIKELY(!(tree->type(
id) &
KEYNIL)) ?
from_chars(tree->key(
id), wrapper) :
false;
1382 ->
typename std::enable_if<!std::is_arithmetic<T>::value,
bool>::type
1384 return C4_LIKELY(!(tree->type(
id) &
VALNIL)) ?
from_chars(tree->val(
id), v) :
false;
1393 ->
typename std::enable_if<!std::is_arithmetic<T>::value,
bool>::type
1395 return C4_LIKELY(!(tree->type(
id) &
KEYNIL)) ?
from_chars(tree->key(
id), v) :
false;
1408 ->
typename std::enable_if<std::is_arithmetic<T>::value && !std::is_floating_point<T>::value,
bool>::type
1410 using U =
typename std::remove_cv<T>::type;
1411 enum { ischar = std::is_same<char, U>::value || std::is_same<signed char, U>::value || std::is_same<unsigned char, U>::value };
1418 char first = val.
str[0];
1421 else if(first ==
'+')
1433 ->
typename std::enable_if<std::is_arithmetic<T>::value && !std::is_floating_point<T>::value,
bool>::type
1435 using U =
typename std::remove_cv<T>::type;
1436 enum { ischar = std::is_same<char, U>::value || std::is_same<signed char, U>::value || std::is_same<unsigned char, U>::value };
1443 char first =
key.str[0];
1446 else if(first ==
'+')
1458 static_assert(std::is_floating_point<T>::value,
"must be floating point");
1459 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal")
1460 if(C4_UNLIKELY(std::isnan(val)))
1462 else if(C4_UNLIKELY(val == std::numeric_limits<T>::infinity()))
1464 else if(C4_UNLIKELY(val == -std::numeric_limits<T>::infinity()))
1467 C4_SUPPRESS_WARNING_GCC_CLANG_POP
1476 static_assert(std::is_floating_point<T>::value,
"must be floating point");
1485 else if(C4_UNLIKELY(buf ==
".nan" || buf ==
".NaN" || buf ==
".NAN"))
1487 *val = std::numeric_limits<T>::quiet_NaN();
1490 else if(C4_UNLIKELY(buf ==
".inf" || buf ==
".Inf" || buf ==
".INF"))
1492 *val = std::numeric_limits<T>::infinity();
1495 else if(C4_UNLIKELY(buf ==
"-.inf" || buf ==
"-.Inf" || buf ==
"-.INF"))
1497 *val = -std::numeric_limits<T>::infinity();
1529typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
1559typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
1572 substr rem(tree->m_arena.sub(tree->m_arena_pos));
1576 rem = tree->_grow_arena(num);
1578 _RYML_ASSERT_VISIT_(tree->m_callbacks, num <= rem.
len, tree,
NONE);
1580 rem = tree->_request_span(num);
1596C4_SUPPRESS_WARNING_MSVC_POP
1597C4_SUPPRESS_WARNING_GCC_CLANG_POP
Lightweight generic type-safe wrappers for converting individual values to/from strings.
Holds a pointer to an existing tree, and a node id.
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
id_type num_other_siblings(id_type node) const
does not count with this
NodeData * _p(id_type node)
An if-less form of get() that demands a valid node index. This function is implementation only; use a...
bool has_sibling(id_type node, csubstr key) const
true if one of the node's siblings has the given key
csubstr resolve_tag_sub(substr output, csubstr tag, id_type node_id) const
Wrapper for Tree::resolve_tag(), returning a substring.
csubstr const & key_ref(id_type node) const
csubstr const & key(id_type node) const
bool is_key_plain(id_type node) const
id_type num_siblings(id_type node) const
O(num_siblings).
id_type first_child(id_type node) const
bool is_stream(id_type node) const
NodeType type(id_type node) const
id_type append_sibling(id_type node)
void set_val_ref(id_type node, csubstr ref)
csubstr const & val_ref(id_type node) const
id_type root_id() const
Get the id of the root node. The tree must not be empty.
size_t arena_slack() const
get the current slack of the tree's internal arena
bool has_key_tag(id_type node) const
void resolve_tags(TagCache &cache, bool all=true)
Resolve tags in the tree such as "!!str" -> "<tag:yaml.org,2002:str>", "!foo" -> "<!...
id_type prev_sibling(id_type node) const
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
id_type prepend_sibling(id_type node)
create and insert a node as the first node of parent
bool is_map(id_type node) const
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...
void callbacks(Callbacks const &cb)
bool is_val_anchor(id_type node) const
id_type sibling(id_type node, id_type pos) const
NodeScalar const & keysc(id_type node) const
c4::yml::TagDirectiveRange tag_directives() const
bool is_key_quoted(id_type node) const
csubstr const & val(id_type node) const
bool has_val_anchor(id_type node) const
id_type insert_child(id_type parent, id_type after)
create and insert a new child of parent.
TagDirectives m_tag_directives
bool is_root(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().
NodeRef ref(id_type node)
Get a NodeRef of a node by id.
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 is_keyval(id_type node) const
bool is_val_folded(id_type node) const
id_type last_sibling(id_type node) const
bool has_key(id_type node) const
bool has_other_siblings(id_type node) const
true if node is not a single child
csubstr const & val_tag(id_type node) const
const char * type_str(id_type node) const
bool in_arena(csubstr s) const
return true if the given substring is part of the tree's string arena
id_type parent(id_type node) const
void set_key_style(id_type node, NodeType_e style)
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...
void rem_key_anchor(id_type node)
size_t resolve_tag(substr output, csubstr tag, id_type node_id) const
resolve the given tag, appearing at node_id.
bool is_key_literal(id_type node) const
NodeType key_style(id_type node) const
bool is_block(id_type node) const
id_type prepend_child(id_type parent)
create and insert a node as the first child of parent
bool is_val(id_type node) const
bool type_has_any(id_type node, NodeType_e bits) const
bool is_container_styled(id_type node) const
id_type sibling_pos(id_type node, id_type sib) const
id_type child_pos(id_type node, id_type ch) const
id_type append_child(id_type parent)
create and insert a node as the last child of parent
bool has_sibling(id_type node, id_type sib) const
true if node has a sibling with id sib
id_type next_sibling(id_type node) const
bool is_key_squo(id_type node) const
bool parent_is_seq(id_type node) const
bool has_anchor(id_type node) const
id_type insert_sibling(id_type node, id_type after)
create and insert a new sibling of n. insert after "after"
bool has_val_tag(id_type node) const
NodeData const * get(id_type node) const
get a pointer to a node's NodeData. i can be NONE, in which case a nullptr is returned.
bool is_key_dquo(id_type node) const
void set_key_tag(id_type node, csubstr tag)
void rem_anchor_ref(id_type node)
id_type last_child(id_type node) const
csubstr const & key_tag(id_type node) const
id_type id(NodeData const *n) const
get the index of a node belonging to this tree. n can be nullptr, in which case NONE is returned
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_val_anchor(id_type node, csubstr anchor)
bool is_val_plain(id_type node) const
static bool has_siblings(id_type)
bool is_doc(id_type node) const
bool has_child(id_type node, csubstr key) const
true if node has a child with key key
void set_container_style(id_type node, NodeType_e style)
bool is_key_ref(id_type node) const
bool is_key_anchor(id_type node) const
void remove_children(id_type node)
remove all the node's children, but keep the node itself
void set_key(id_type node, csubstr key)
bool has_val(id_type node) const
bool is_val_dquo(id_type node) const
Callbacks const & callbacks() const
size_t arena_capacity() const
get the current capacity of the tree's internal arena
id_type doc(id_type i) const
gets the i document node index.
bool change_type(id_type node, NodeType type)
change the type of the node to one of MAP, SEQ or VAL.
bool is_flow_ml(id_type node) const
NodeType val_style(id_type node) const
bool is_key_folded(id_type node) const
Tree(id_type node_capacity, size_t arena_capacity=RYML_DEFAULT_TREE_ARENA_CAPACITY)
bool type_has_all(id_type node, NodeType_e bits) const
bool is_anchor_or_ref(id_type node) const
void set_val(id_type node, csubstr val)
bool is_anchor(id_type node) const
id_type find_sibling(id_type node, csubstr const &key) const
bool is_seq(id_type node) const
bool is_val_styled(id_type node) const
bool parent_is_map(id_type node) const
bool has_key_anchor(id_type node) const
void remove(id_type node)
remove an entire branch at once: ie remove the children and the node itself
id_type find_child(id_type node, csubstr const &key) const
bool is_quoted(id_type node) const
csubstr const & val_anchor(id_type node) const
bool change_type(id_type node, type_bits type)
NodeData * get(id_type node)
get a pointer to a node's NodeData. i can be NONE, in which case a nullptr is returned
void set_val_style(id_type node, NodeType_e style)
substr arena()
get the current arena
void rem_val_ref(id_type node)
bool has_parent(id_type node) const
bool val_is_null(id_type node) const
true if the node val is empty, or its scalar verifies scalar_is_null().
id_type first_sibling(id_type node) const
bool is_flow(id_type node) const
bool is_val_quoted(id_type node) const
bool type_has_none(id_type node, NodeType_e bits) const
bool empty(id_type node) const
true when key and val are empty, and has no children
csubstr const & key_anchor(id_type node) const
bool is_val_squo(id_type node) const
substr copy_to_arena(csubstr s)
copy the given string to the tree's arena, growing the arena by the required size.
id_type num_children(id_type node) const
O(num_children).
csubstr arena() const
get the current arena
bool is_container(id_type node) const
size_t arena_size() const
get the current size of the tree's internal arena
id_type child(id_type node, id_type pos) const
bool is_ref(id_type node) const
void set_val_tag(id_type node, csubstr tag)
bool is_key_styled(id_type node) const
void set_key_anchor(id_type node, csubstr anchor)
bool is_val_ref(id_type node) const
void set_key_ref(id_type node, csubstr ref)
id_type _append_child__unprotected(id_type parent)
bool has_child(id_type node, id_type ch) const
true if node has a child with id ch
bool is_val_literal(id_type node) const
void rem_val_anchor(id_type node)
NodeScalar const & valsc(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...
void rem_key_ref(id_type node)
bool is_flow_sl(id_type node) const
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
bool has_children(id_type node) const
true if node has any children key
bool has_anchor(id_type node, csubstr a) const
true when the node has an anchor named a
Common utilities and infrastructure used by ryml.
#define RYML_DEFAULT_TREE_CAPACITY
default capacity for the tree when not set explicitly
#define RYML_DEFAULT_TREE_ARENA_CAPACITY
default capacity for the tree's arena when not set explicitly
#define RYML_NOEXCEPT
Conditionally expands to noexcept when RYML_USE_ASSERT is 0 and is empty otherwise.
Error utilities used by ryml.
Callbacks const & get_callbacks()
get the global callbacks
bool scalar_is_null(csubstr s) noexcept
YAML-sense query of nullity.
NodeType_e
a bit mask for marking node types and styles
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
@ VALANCH
the val has an &anchor
@ NOTYPE
no node type or style is set
@ VALREF
a *reference: the val references an &anchor
@ VALNIL
the val is null (eg {a : } results in a null val)
@ KEYTAG
the key has a tag
@ VAL
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
@ VALTAG
the val has a tag
@ KEYREF
a *reference: the key references an &anchor
@ KEYANCH
the key has an &anchor
@ KEYNIL
the key is null (eg { : b} results in a null key)
ParseEngine< EventHandlerTree > Parser
This is the main ryml parser, where the parser events are handled to create a ryml tree.
bool read(ryml::ConstNodeRef const &n, my_seq_type< T > *seq)
bool from_chars(ryml::csubstr buf, vec2< T > *v)
size_t to_chars(ryml::substr buf, vec2< T > v)
bool readkey(ConstNodeRef const &n, T *v)
size_t to_chars_float(substr buf, T val)
encode a floating point value to a string.
bool from_chars_float(csubstr buf, T *val)
decode a floating point from string.
csubstr to_csubstr(const char(&s)[N]) noexcept
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
csubstr serialize_to_arena(Tree *tree, csubstr a)
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...
auto serialize_scalar(substr buf, T const &a) -> typename std::enable_if< std::is_floating_point< T >::value, size_t >::type
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
bool begins_with(const C c) const noexcept
true if the first character of the string is c
basic_substring triml(const C c) const
trim left
size_t len
the length of the substring
bool ends_with(const C c) const noexcept
true if the last character of the string is c
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
basic_substring sub(size_t first) const noexcept
return [first,len[
bool empty() const noexcept
C * str
a restricted pointer to the first character of the substring
A c-style callbacks class to customize behavior on errors or allocation.
holds a source or yaml file position, for example when an error is detected; See also location_format...
contains the data for each YAML node.
NodeInit(NodeScalar const &k, NodeScalar const &v)
initialize as a mapping member
NodeInit(NodeType_e t, NodeScalar const &k, NodeScalar const &v)
initialize as a mapping member with explicit type
void _add_flags(type_bits more_flags=0)
NodeInit(NodeScalar const &v, NodeType_e t)
initialize as a sequence member with explicit type
NodeInit(NodeScalar const &v)
initialize as a sequence member
NodeInit(NodeType_e t)
initialize as a typed node
NodeInit(NodeType_e t, NodeScalar const &k)
initialize as a mapping member with explicit type (eg for SEQ or MAP)
NodeInit()
initialize as an empty node
a node scalar is a csubstr, which may be tagged and anchored.
NodeScalar(const char(&t)[N], const char(&s)[N]) noexcept
initialize as a tagged scalar
bool empty() const noexcept
NodeScalar() noexcept
initialize as an empty scalar
NodeScalar(csubstr s) noexcept
NodeScalar(csubstr t, csubstr s) noexcept
NodeScalar(const char(&s)[N]) noexcept
initialize as an untagged scalar
~NodeScalar() noexcept=default
void set_ref_maybe_replacing_scalar(csubstr ref, bool has_scalar) RYML_NOEXCEPT
wraps a NodeType_e element with some syntactic sugar and predicates
bool is_doc() const noexcept
bool is_key_quoted() const noexcept
const char * type_str() const noexcept
return a preset string based on the node type
bool is_val_quoted() const noexcept
Reusable object to resolve references/aliases in a Tree.
Accelerator structure to reduce memory requirements by enabling reuse of resolved tags.
lookup_result(csubstr path_, id_type start)