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_MSVC(4127)
39C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
40C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wold-style-cast")
41C4_SUPPRESS_WARNING_GCC(
"-Wuseless-cast")
42C4_SUPPRESS_WARNING_GCC(
"-Wtype-limits")
43C4_SUPPRESS_WARNING_CLANG(
"-Wnull-dereference")
44#if defined(__GNUC__) && (__GNUC__ >= 6)
45C4_SUPPRESS_WARNING_GCC(
"-Wnull-dereference")
54template<
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;
55template<
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;
56template<
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;
57template<
class T>
bool read(
Tree const* C4_RESTRICT tree,
id_type id, T
const& wrapper);
59template<
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;
60template<
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;
61template<
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;
62template<
class T>
bool readkey(
Tree const* C4_RESTRICT tree,
id_type id, T
const& wrapper);
72 ->
typename std::enable_if<std::is_floating_point<T>::value,
size_t>::type
78 ->
typename std::enable_if< ! std::is_floating_point<T>::value,
size_t>::type
133 template<
size_t N,
size_t M>
153 csubstr trimmed = ref.begins_with(
'*') ? ref.sub(1) : ref;
155 if((!has_scalar) || !
scalar.ends_with(trimmed))
159C4_MUST_BE_TRIVIAL_COPY(NodeScalar);
167struct RYML_DEPRECATED(
"") NodeInit
177 NodeInit() : type(NOTYPE), key(), val() {}
179 NodeInit(NodeType_e t) : type(t), key(), val() {}
181 NodeInit(NodeScalar
const& v) : type(
VAL),
key(), val(v) { _add_flags(); }
183 NodeInit(NodeScalar
const& v, NodeType_e t) : type(t|
VAL),
key(), val(v) { _add_flags(); }
185 NodeInit( NodeScalar
const& k, NodeScalar
const& v) : type(
KEYVAL),
key(k), val(v) { _add_flags(); }
187 NodeInit(NodeType_e t, NodeScalar
const& k, NodeScalar
const& v) : type(t),
key(k), val(v) { _add_flags(); }
189 NodeInit(NodeType_e t, NodeScalar
const& k ) : type(t),
key(k), val( ) { _add_flags(KEY); }
200 void _add_flags(type_bits more_flags=0)
202 type = (type|more_flags);
203 if( !
key.tag.empty())
205 if( ! val.tag.empty())
207 if( !
key.anchor.empty())
209 if( ! val.anchor.empty())
216 _RYML_ASSERT_BASIC(
key.scalar.empty() == ((type & KEY) == 0));
218 _RYML_ASSERT_BASIC(
key.tag.empty() == ((type & KEYTAG) == 0));
220 _RYML_ASSERT_BASIC(((type & VAL) != 0) || val.scalar.empty());
222 _RYML_ASSERT_BASIC(val.tag.empty() == ((type & VALTAG) == 0));
272 Tree& operator= (
Tree && that) noexcept;
426 C4_ALWAYS_INLINE
bool is_doc(
id_type node)
const {
return _p(node)->m_type.is_doc(); }
428 C4_ALWAYS_INLINE
bool is_map(
id_type node)
const {
return _p(node)->m_type.is_map(); }
429 C4_ALWAYS_INLINE
bool is_seq(
id_type node)
const {
return _p(node)->m_type.is_seq(); }
432 C4_ALWAYS_INLINE
bool is_val(
id_type node)
const {
return _p(node)->m_type.is_val(); }
441 C4_ALWAYS_INLINE
bool is_ref(
id_type node)
const {
return _p(node)->m_type.is_ref(); }
465 RYML_DEPRECATED(
"use has_key_anchor()") bool
is_key_anchor(
id_type node)
const {
return _p(node)->m_type.has_key_anchor(); }
466 RYML_DEPRECATED(
"use has_val_anchor()") bool
is_val_anchor(
id_type node)
const {
return _p(node)->m_type.has_val_anchor(); }
467 RYML_DEPRECATED(
"use has_anchor()") bool
is_anchor(
id_type node)
const {
return _p(node)->m_type.has_anchor(); }
468 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(); }
571 RYML_DEPRECATED(
"use one of .is_flow_ml{1,n,x}()")
602 void clear_style(
id_type node,
bool recurse=
false);
603 void set_style_conditionally(
id_type node,
625 _p(node)->m_type |=
DOC;
634 nd->m_val.scalar =
val;
641 nd->m_type |=
VAL|more_flags;
642 nd->m_val.scalar =
val;
650 nd->m_key.scalar =
key;
656 nd->m_type |=
KEY|more_flags;
657 nd->m_key.scalar =
key;
663 _p(node)->m_type |=
SEQ;
667 _RYML_ASSERT_VISIT_(
m_callbacks, ((
_p(node)->m_type|more_flags) & (
VAL|
MAP)) == 0,
this, node);
668 _p(node)->m_type |=
SEQ|more_flags;
674 _p(node)->m_type |=
MAP;
678 _RYML_ASSERT_VISIT_(
m_callbacks, ((
_p(node)->m_type|more_flags) & (
VAL|
SEQ)) == 0,
this, node);
679 _p(node)->m_type |=
MAP|more_flags;
725 void resolve(
bool clear_anchors=
true);
746 void resolve_tags(
TagCache &cache,
bool all=
true);
747 void normalize_tags();
748 void normalize_tags_long();
750 id_type num_tag_directives()
const;
752 void clear_tag_directives();
761 return needed <= output.
len ? output.
first(needed) : output;
767 RYML_DEPRECATED(
"use c4::yml::tag_directive_const_iterator") typedef
TagDirective const* tag_directive_const_iterator;
822 void remove_children(
id_type node);
857 void set_root_as_stream();
989 C4_SUPPRESS_WARNING_GCC_PUSH
990 #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10)
991 C4_SUPPRESS_WARNING_GCC(
"-Wstringop-overflow=")
992 C4_SUPPRESS_WARNING_GCC(
"-Wrestrict")
996 C4_SUPPRESS_WARNING_GCC_POP
1014 substr s = _request_span(sz);
1028 buf.
len = arena_cap;
1045 substr _grow_arena(
size_t more)
1047 size_t cap = m_arena.len + more;
1049 cap = cap < 2 * m_arena.len ? 2 * m_arena.len : cap;
1051 return m_arena.sub(m_arena_pos);
1054 substr _request_span(
size_t sz)
1056 _RYML_ASSERT_VISIT_(m_callbacks, m_arena_pos + sz <= m_arena.len,
this, NONE);
1058 s = m_arena.
sub(m_arena_pos, sz);
1063 substr _relocated(csubstr s, substr next_arena)
const
1065 _RYML_ASSERT_VISIT_(m_callbacks, m_arena.is_super(s) || s.len == 0,
this, NONE);
1066 _RYML_ASSERT_VISIT_(m_callbacks, m_arena.sub(0, m_arena_pos).is_super(s) || s.len == 0,
this, NONE);
1067 auto pos = (s.str - m_arena.str);
1068 substr r(next_arena.str + pos, s.len);
1069 _RYML_ASSERT_VISIT_(m_callbacks, r.str - next_arena.str == pos,
this, NONE);
1070 _RYML_ASSERT_VISIT_(m_callbacks, next_arena.sub(0, m_arena_pos).is_super(r) || r.len == 0,
this, NONE);
1118 struct _lookup_path_token
1122 _lookup_path_token() : value(), type() {}
1123 _lookup_path_token(
csubstr v, NodeType t) : value(v), type(t) {}
1124 operator bool()
const {
return type != NOTYPE; }
1128 id_type _lookup_path_or_create(csubstr path, id_type start);
1130 void _lookup_path (lookup_result *r)
const;
1131 void _lookup_path_modify(lookup_result *r);
1133 id_type _next_node (lookup_result *r, _lookup_path_token *parent)
const;
1134 id_type _next_node_modify(lookup_result *r, _lookup_path_token *parent);
1136 static void _advance(lookup_result *r,
size_t more);
1138 _lookup_path_token _next_token(lookup_result *r, _lookup_path_token
const& parent)
const;
1144 void _copy(Tree
const& that);
1145 void _move(Tree & that)
noexcept;
1147 void _relocate(substr next_arena);
1153 #if ! RYML_USE_ASSERT
1154 C4_ALWAYS_INLINE
void _check_next_flags(id_type, type_bits) {}
1156 void _check_next_flags(id_type node, type_bits f)
1158 NodeData *n = _p(node);
1163 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & SEQ) == 0,
this, node,
"cannot mark simultaneously as map and seq");
1164 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & VAL) == 0,
this, node,
"cannot mark simultaneously as map and val");
1165 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & SEQ) == 0,
this, node,
"cannot turn a seq into a map; clear first");
1166 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & VAL) == 0,
this, node,
"cannot turn a val into a map; clear first");
1170 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & MAP) == 0,
this, node,
"cannot mark simultaneously as seq and map");
1171 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (f & VAL) == 0,
this, node,
"cannot mark simultaneously as seq and val");
1172 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & MAP) == 0,
this, node,
"cannot turn a map into a seq; clear first");
1173 _RYML_ASSERT_VISIT_MSG_(m_callbacks, (o & VAL) == 0,
this, node,
"cannot turn a val into a seq; clear first");
1177 _RYML_ASSERT_VISIT_(m_callbacks, !is_root(node),
this, node);
1178 _RYML_ASSERT_VISIT_(m_callbacks, is_map(parent(node)),
this, node);
1180 if((f & VAL) && !is_root(node))
1182 auto pid = parent(node); C4_UNUSED(pid);
1183 _RYML_ASSERT_VISIT_(m_callbacks, is_map(pid) || is_seq(pid),
this, node);
1188 void _set_flags(id_type node, NodeType_e f) { _check_next_flags(node, f); _p(node)->m_type = f; }
1189 void _set_flags(id_type node, type_bits f) { _check_next_flags(node, f); _p(node)->m_type = f; }
1190 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; }
1191 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; }
1192 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; }
1193 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; }
1195 id_type _do_reorder(id_type *node, id_type count);
1197 void _swap(id_type n_, id_type m_);
1198 void _swap_props(id_type n_, id_type m_);
1199 void _swap_hierarchy(id_type n_, id_type m_);
1200 void _copy_hierarchy(id_type dst_, id_type src_);
1202 void _copy_props(id_type dst_, id_type src_)
1204 _copy_props(dst_,
this, src_);
1207 void _copy_props_wo_key(id_type dst_, id_type src_)
1209 _copy_props_wo_key(dst_,
this, src_);
1212 void _copy_props(id_type dst_, Tree
const* that_tree, id_type src_)
1214 NodeData & C4_RESTRICT dst = *_p(dst_);
1215 NodeData
const& C4_RESTRICT src = *that_tree->_p(src_);
1216 dst.m_type = src.m_type;
1217 dst.m_key = src.m_key;
1218 dst.m_val = src.m_val;
1221 void _copy_props(id_type dst_, Tree
const* that_tree, id_type src_, type_bits src_mask)
1223 NodeData & C4_RESTRICT dst = *_p(dst_);
1224 NodeData
const& C4_RESTRICT src = *that_tree->_p(src_);
1225 dst.m_type = (src.m_type & src_mask) | (dst.m_type & ~src_mask);
1226 dst.m_key = src.m_key;
1227 dst.m_val = src.m_val;
1230 void _copy_props_wo_key(id_type dst_, Tree
const* that_tree, id_type src_)
1232 auto & C4_RESTRICT dst = *_p(dst_);
1233 auto const& C4_RESTRICT src = *that_tree->_p(src_);
1234 dst.m_type = (src.m_type & ~_KEYMASK) | (dst.m_type & _KEYMASK);
1235 dst.m_val = src.m_val;
1238 void _copy_props_wo_key(id_type dst_, Tree
const* that_tree, id_type src_, type_bits src_mask)
1240 auto & C4_RESTRICT dst = *_p(dst_);
1241 auto const& C4_RESTRICT src = *that_tree->_p(src_);
1242 dst.m_type = (src.m_type & ((~_KEYMASK)|src_mask)) | (dst.m_type & (_KEYMASK|~src_mask));
1243 dst.m_val = src.m_val;
1246 void _clear_type(id_type node)
1248 _p(node)->m_type =
NOTYPE;
1251 void _clear(id_type node)
1253 auto *C4_RESTRICT n = _p(node);
1258 n->m_first_child =
NONE;
1259 n->m_last_child =
NONE;
1262 void _clear_key(id_type node)
1264 _p(node)->m_key.clear();
1265 _rem_flags(node, KEY);
1268 void _clear_val(id_type node)
1270 _p(node)->m_val.clear();
1271 _rem_flags(node, VAL);
1278 void _clear_range(id_type first, id_type num);
1282 void _release(id_type node);
1283 void _free_list_add(id_type node);
1284 void _free_list_rem(id_type node);
1286 void _set_hierarchy(id_type node, id_type parent, id_type after_sibling);
1287 void _rem_hierarchy(id_type node);
1310 C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
1311 C4_SUPPRESS_WARNING_MSVC_PUSH
1312 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wdeprecated")
1313 C4_SUPPRESS_WARNING_GCC_CLANG(
"-Wdeprecated-declarations")
1314 C4_SUPPRESS_WARNING_MSVC(4996)
1315 RYML_DEPRECATED(
"use has_other_siblings()") static
bool has_siblings(
id_type ) {
return true; }
1320 RYML_DEPRECATED(
"use set_map()")
void to_map(
id_type node,
type_bits more_flags=0);
1321 RYML_DEPRECATED(
"use set_seq()")
void to_seq(
id_type node,
type_bits more_flags=0);
1322 RYML_DEPRECATED(
"use set_doc()")
void to_doc(
id_type node,
type_bits more_flags=0);
1323 RYML_DEPRECATED(
"use set_stream()")
void to_stream(
id_type node,
type_bits more_flags=0);
1324 RYML_DEPRECATED(
"use resolve_tags(TagCache&)")
void resolve_tags() {
TagCache cache; resolve_tags(cache); }
1325 RYML_DEPRECATED(
"") void _set(id_type node, NodeInit const& i)
1327 _RYML_ASSERT_VISIT_(m_callbacks, i._check(),
this, node);
1328 NodeData *n = _p(node);
1329 _RYML_ASSERT_VISIT_(m_callbacks, n->m_key.scalar.empty() || i.key.scalar.empty() || i.key.scalar == n->m_key.scalar,
this, node);
1330 _add_flags(node, i.type);
1331 if(n->m_key.scalar.empty())
1333 if( ! i.key.scalar.empty())
1335 set_key(node, i.key.scalar);
1338 n->m_key.tag = i.key.tag;
1341 RYML_DEPRECATED(
"") void _set_key(id_type node, NodeScalar const& key, NodeType more_flags=0)
1343 _p(node)->m_key =
key;
1344 _add_flags(node, KEY|more_flags);
1346 RYML_DEPRECATED(
"") void _set_val(id_type node, NodeScalar const& val, NodeType more_flags=0)
1348 _p(node)->m_val = val;
1349 _add_flags(node, VAL|more_flags);
1351 C4_SUPPRESS_WARNING_MSVC_POP
1352 C4_SUPPRESS_WARNING_GCC_CLANG_POP
1369 return C4_LIKELY(!(tree->type(
id) &
VALNIL)) ?
from_chars(tree->val(
id), wrapper) :
false;
1374 return C4_LIKELY(!(tree->type(
id) &
KEYNIL)) ?
from_chars(tree->key(
id), wrapper) :
false;
1387 ->
typename std::enable_if<!std::is_arithmetic<T>::value,
bool>::type
1389 return C4_LIKELY(!(tree->type(
id) &
VALNIL)) ?
from_chars(tree->val(
id), v) :
false;
1398 ->
typename std::enable_if<!std::is_arithmetic<T>::value,
bool>::type
1400 return C4_LIKELY(!(tree->type(
id) &
KEYNIL)) ?
from_chars(tree->key(
id), v) :
false;
1413 ->
typename std::enable_if<std::is_arithmetic<T>::value && !std::is_floating_point<T>::value,
bool>::type
1415 using U =
typename std::remove_cv<T>::type;
1416 enum { ischar = std::is_same<char, U>::value || std::is_same<signed char, U>::value || std::is_same<unsigned char, U>::value };
1423 char first = val.
str[0];
1426 else if(first ==
'+')
1438 ->
typename std::enable_if<std::is_arithmetic<T>::value && !std::is_floating_point<T>::value,
bool>::type
1440 using U =
typename std::remove_cv<T>::type;
1441 enum { ischar = std::is_same<char, U>::value || std::is_same<signed char, U>::value || std::is_same<unsigned char, U>::value };
1448 char first =
key.str[0];
1451 else if(first ==
'+')
1463 static_assert(std::is_floating_point<T>::value,
"must be floating point");
1464 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wfloat-equal")
1465 if(C4_UNLIKELY(std::isnan(val)))
1467 else if(C4_UNLIKELY(val == std::numeric_limits<T>::infinity()))
1469 else if(C4_UNLIKELY(val == -std::numeric_limits<T>::infinity()))
1472 C4_SUPPRESS_WARNING_GCC_CLANG_POP
1481 static_assert(std::is_floating_point<T>::value,
"must be floating point");
1490 else if(C4_UNLIKELY(buf ==
".nan" || buf ==
".NaN" || buf ==
".NAN"))
1492 *val = std::numeric_limits<T>::quiet_NaN();
1495 else if(C4_UNLIKELY(buf ==
".inf" || buf ==
".Inf" || buf ==
".INF"))
1497 *val = std::numeric_limits<T>::infinity();
1500 else if(C4_UNLIKELY(buf ==
"-.inf" || buf ==
"-.Inf" || buf ==
"-.INF"))
1502 *val = -std::numeric_limits<T>::infinity();
1534typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
1564typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
1577 substr rem(tree->m_arena.sub(tree->m_arena_pos));
1581 rem = tree->_grow_arena(num);
1583 _RYML_ASSERT_VISIT_(tree->m_callbacks, num <= rem.
len, tree,
NONE);
1585 rem = tree->_request_span(num);
1601C4_SUPPRESS_WARNING_MSVC_POP
1602C4_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. The tree can be empty only when constructed ...
size_t arena_slack() const
get the current slack of the tree's internal arena
bool has_key_tag(id_type node) const
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
void set_val(id_type node, csubstr val) RYML_NOEXCEPT
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
void set_key(id_type node, csubstr key, NodeType more_flags) RYML_NOEXCEPT
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
bool empty() const
Query for zero size.
void set_seq(id_type node) RYML_NOEXCEPT
void set_stream(id_type node)
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_flow_mln(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. node can be NONE, in which case a nullptr is returned.
bool is_flow_ml1(id_type node) const
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 id of a node belonging to this tree. n can be nullptr, in which case NONE is returned n must ...
substr arena_rem()
get the free space at the end of the arena
void set_map(id_type node, NodeType more_flags) RYML_NOEXCEPT
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
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_val(id_type node, csubstr val, NodeType more_flags) RYML_NOEXCEPT
void set_container_style(id_type node, NodeType_e style)
void set_seq(id_type node, NodeType more_flags) RYML_NOEXCEPT
id_type root_id_maybe() const
Get the id of the root node, or NONE if the tree is empty.
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
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)
bool is_flow_ml(id_type node) const
NodeType val_style(id_type node) const
bool is_key_folded(id_type node) const
csubstr arena_rem() const
get the free space at the end of the arena
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
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
void set_map(id_type node) RYML_NOEXCEPT
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. node 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.
void set_key(id_type node, csubstr key) RYML_NOEXCEPT
bool has_flow_space(id_type node) const
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
void set_doc(id_type node)
bool is_flow_mlx(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
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_DEFAULT_TREE_ARENA_CAPACITY_START
default starting capacity for the tree's arena when it is first allocated. should be larger than RYML...
#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 from_chars(csubstr buf, uint8_t *v) noexcept
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)
@ MAP
a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
@ STREAM
a stream: a seq of docs
@ KEY
the scalar to the left of : in a map's member
@ 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
@ SEQ
a seq: a parent of VAL/SEQ/MAP nodes
@ 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 (see Event Ha...
bool readkey(ConstNodeRef const &n, T *v)
bool read(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)
size_t to_chars(substr buf, escaped_scalar e)
formatting implementation to escape a scalar with escape_scalar()
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.
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)