soa hierarchy wip

This commit is contained in:
Joao Paulo Magalhaes
2024-05-12 14:35:10 +01:00
parent 5d0763056c
commit 9d16212401
5 changed files with 347 additions and 310 deletions

View File

@@ -34,11 +34,10 @@ inline void check_invariants(Tree const& t, id_type node)
node = t.root_id(); node = t.root_id();
} }
NodeRelation const& n = t.m_relation[node];
#if defined(RYML_DBG) && 0 #if defined(RYML_DBG) && 0
if(n.m_first_child != NONE || n.m_last_child != NONE) if(t.m_first_child[node] != NONE || t.m_last_child[node] != NONE)
{ {
printf("check(%zu): fc=%zu lc=%zu\n", node, n.m_first_child, n.m_last_child); printf("check(%zu): fc=%zu lc=%zu\n", node, t.m_first_child[node], t.m_last_child[node]);
} }
else else
{ {
@@ -46,78 +45,77 @@ inline void check_invariants(Tree const& t, id_type node)
} }
#endif #endif
C4_CHECK(n.m_parent != node); C4_CHECK(t.m_parent[node] != node);
if(n.m_parent == NONE) if(t.m_parent[node] == NONE)
{ {
C4_CHECK(t.is_root(node)); C4_CHECK(t.is_root(node));
} }
else //if(n.m_parent != NONE) else //if(t.m_parent[node] != NONE)
{ {
C4_CHECK(t.has_child(n.m_parent, node)); C4_CHECK(t.has_child(t.m_parent[node], node));
NodeRelation const& p = t.m_relation[n.m_parent]; id_type p = t.m_parent[node];
if(n.m_prev_sibling == NONE) if(t.m_prev_sibling[node] == NONE)
{ {
C4_CHECK(p.m_first_child == node); C4_CHECK(t.m_first_child[p] == node);
C4_CHECK(t.first_sibling(node) == node); C4_CHECK(t.first_sibling(node) == node);
} }
else else
{ {
C4_CHECK(p.m_first_child != node); C4_CHECK(t.m_first_child[p] != node);
C4_CHECK(t.first_sibling(node) != node); C4_CHECK(t.first_sibling(node) != node);
} }
if(n.m_next_sibling == NONE) if(t.m_next_sibling[node] == NONE)
{ {
C4_CHECK(p.m_last_child == node); C4_CHECK(t.m_last_child[p] == node);
C4_CHECK(t.last_sibling(node) == node); C4_CHECK(t.last_sibling(node) == node);
} }
else else
{ {
C4_CHECK(p.m_last_child != node); C4_CHECK(t.m_last_child[p] != node);
C4_CHECK(t.last_sibling(node) != node); C4_CHECK(t.last_sibling(node) != node);
} }
} }
C4_CHECK(n.m_first_child != node); C4_CHECK(t.m_first_child[node] != node);
C4_CHECK(n.m_last_child != node); C4_CHECK(t.m_last_child[node] != node);
if(n.m_first_child != NONE || n.m_last_child != NONE) if(t.m_first_child[node] != NONE || t.m_last_child[node] != NONE)
{ {
C4_CHECK(n.m_first_child != NONE); C4_CHECK(t.m_first_child[node] != NONE);
C4_CHECK(n.m_last_child != NONE); C4_CHECK(t.m_last_child[node] != NONE);
} }
C4_CHECK(n.m_prev_sibling != node); C4_CHECK(t.m_prev_sibling[node] != node);
C4_CHECK(n.m_next_sibling != node); C4_CHECK(t.m_next_sibling[node] != node);
if(n.m_prev_sibling != NONE) if(t.m_prev_sibling[node] != NONE)
{ {
C4_CHECK(t.m_relation[n.m_prev_sibling].m_next_sibling == node); C4_CHECK(t.m_next_sibling[t.m_prev_sibling[node]] == node);
C4_CHECK(t.m_relation[n.m_prev_sibling].m_prev_sibling != node); C4_CHECK(t.m_prev_sibling[t.m_prev_sibling[node]] != node);
} }
if(n.m_next_sibling != NONE) if(t.m_next_sibling[node] != NONE)
{ {
C4_CHECK(t.m_relation[n.m_next_sibling].m_prev_sibling == node); C4_CHECK(t.m_prev_sibling[t.m_next_sibling[node]] == node);
C4_CHECK(t.m_relation[n.m_next_sibling].m_next_sibling != node); C4_CHECK(t.m_next_sibling[t.m_next_sibling[node]] != node);
} }
id_type count = 0; id_type count = 0;
for(id_type i = n.m_first_child; i != NONE; i = t.next_sibling(i)) for(id_type i = t.m_first_child[node]; i != NONE; i = t.next_sibling(i))
{ {
#if defined(RYML_DBG) && 0 #if defined(RYML_DBG) && 0
printf("check(%zu): descend to child[%zu]=%zu\n", node, count, i); printf("check(%zu): descend to child[%zu]=%zu\n", node, count, i);
#endif #endif
NodeRelation const& ch = t.m_relation[i]; C4_CHECK(t.m_parent[i] == node);
C4_CHECK(ch.m_parent == node); C4_CHECK(t.m_next_sibling[i] != i);
C4_CHECK(ch.m_next_sibling != i);
++count; ++count;
} }
C4_CHECK(count == t.num_children(node)); C4_CHECK(count == t.num_children(node));
if(n.m_prev_sibling == NONE && n.m_next_sibling == NONE) if(t.m_prev_sibling[node] == NONE && t.m_next_sibling[node] == NONE)
{ {
if(n.m_parent != NONE) if(t.m_parent[node] != NONE)
{ {
C4_CHECK(t.num_children(n.m_parent) == 1); C4_CHECK(t.num_children(t.m_parent[node]) == 1);
C4_CHECK(t.num_siblings(node) == 1); C4_CHECK(t.num_siblings(node) == 1);
} }
} }
@@ -153,19 +151,18 @@ inline void check_free_list(Tree const& t)
C4_CHECK(t.m_free_head >= 0 && t.m_free_head < t.m_cap); C4_CHECK(t.m_free_head >= 0 && t.m_free_head < t.m_cap);
C4_CHECK(t.m_free_tail >= 0 && t.m_free_tail < t.m_cap); C4_CHECK(t.m_free_tail >= 0 && t.m_free_tail < t.m_cap);
NodeRelation const& head = t.m_relation[t.m_free_head]; id_type head = t.m_free_head;
//NodeRelation const& tail = t.m_relation[t.m_free_tail]; //id_type tail = t.m_free_tail;
//C4_CHECK(head.m_prev_sibling == NONE); //C4_CHECK(m_prev_sibling[head] == NONE);
//C4_CHECK(tail.m_next_sibling == NONE); //C4_CHECK(m_next_sibling[tail] == NONE);
id_type count = 0; id_type count = 0;
for(id_type i = t.m_free_head, prev = NONE; i != NONE; i = t.m_relation[i].m_next_sibling) for(id_type i = t.m_free_head, prev = NONE; i != NONE; i = t.m_next_sibling[i])
{ {
NodeRelation const& elm = t.m_relation[i]; if(i != head)
if(&elm != &head)
{ {
C4_CHECK(elm.m_prev_sibling == prev); C4_CHECK(t.m_prev_sibling[i] == prev);
} }
prev = i; prev = i;
++count; ++count;

View File

@@ -13,6 +13,7 @@ namespace c4 {
namespace yml { namespace yml {
#define _ryml_num_val_arrays (size_t(6u)) #define _ryml_num_val_arrays (size_t(6u))
#define _ryml_num_hcy_arrays (size_t(5u))
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -82,8 +83,8 @@ ConstNodeRef Tree::cdocref(id_type i) const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// the tree's node data arrays are allocated all into a single buffer. // the tree's node data and hierarchy arrays are allocated all into a
// these utilities help doing that. // single buffer. these utilities help doing that.
namespace { namespace {
template<class T> template<class T>
bool _is_aligned(T const* ptr) bool _is_aligned(T const* ptr)
@@ -108,9 +109,9 @@ struct node_buf_data
size_for_val_align = _get_padding(size_for_type, alignof(csubstr)); size_for_val_align = _get_padding(size_for_type, alignof(csubstr));
val_start = size_for_type + size_for_val_align; val_start = size_for_type + size_for_val_align;
size_for_val = _ryml_num_val_arrays * new_cap * sizeof(csubstr); size_for_val = _ryml_num_val_arrays * new_cap * sizeof(csubstr);
size_for_rel_align = _get_padding(val_start + size_for_val, alignof(NodeRelation)); size_for_rel_align = _get_padding(val_start + size_for_val, alignof(id_type));
rel_start = val_start + size_for_val + size_for_rel_align; rel_start = val_start + size_for_val + size_for_rel_align;
size_for_rel = new_cap * sizeof(NodeRelation); size_for_rel = _ryml_num_val_arrays * new_cap * sizeof(id_type);
total_size = rel_start + size_for_rel; total_size = rel_start + size_for_rel;
} }
size_t size_for_type; size_t size_for_type;
@@ -132,20 +133,28 @@ C4_NO_INLINE void _resize_node_data(Callbacks const& cb,
csubstr *C4_RESTRICT * m_key, csubstr *C4_RESTRICT * m_key,
csubstr *C4_RESTRICT * m_key_tag, csubstr *C4_RESTRICT * m_key_tag,
csubstr *C4_RESTRICT * m_key_anchor, csubstr *C4_RESTRICT * m_key_anchor,
NodeRelation *C4_RESTRICT * m_relation) id_type *C4_RESTRICT * m_parent,
id_type *C4_RESTRICT * m_first_child,
id_type *C4_RESTRICT * m_last_child,
id_type *C4_RESTRICT * m_prev_sibling,
id_type *C4_RESTRICT * m_next_sibling)
{ {
_RYML_CB_ASSERT(cb, new_cap > 0); _RYML_CB_ASSERT(cb, new_cap > 0);
const node_buf_data newsz(new_cap); const node_buf_data newsz(new_cap);
uint8_t *buf = _RYML_CB_ALLOC_HINT(cb, uint8_t, (size_t)newsz.total_size, *m_type); uint8_t *buf = _RYML_CB_ALLOC_HINT(cb, uint8_t, (size_t)newsz.total_size, *m_type);
_RYML_CB_CHECK(cb, buf != nullptr); _RYML_CB_CHECK(cb, buf != nullptr);
NodeType *type = reinterpret_cast<NodeType*>(buf); NodeType *type = reinterpret_cast<NodeType*>(buf);
csubstr *val = reinterpret_cast<csubstr*>(buf + newsz.val_start); csubstr *val = reinterpret_cast<csubstr*>(buf + newsz.val_start);
csubstr *val_tag = reinterpret_cast<csubstr*>(buf + newsz.val_start + 1 * new_cap * sizeof(csubstr)); csubstr *val_tag = reinterpret_cast<csubstr*>(buf + newsz.val_start + 1 * new_cap * sizeof(csubstr));
csubstr *val_anchor = reinterpret_cast<csubstr*>(buf + newsz.val_start + 2 * new_cap * sizeof(csubstr)); csubstr *val_anchor = reinterpret_cast<csubstr*>(buf + newsz.val_start + 2 * new_cap * sizeof(csubstr));
csubstr *key = reinterpret_cast<csubstr*>(buf + newsz.val_start + 3 * new_cap * sizeof(csubstr)); csubstr *key = reinterpret_cast<csubstr*>(buf + newsz.val_start + 3 * new_cap * sizeof(csubstr));
csubstr *key_tag = reinterpret_cast<csubstr*>(buf + newsz.val_start + 4 * new_cap * sizeof(csubstr)); csubstr *key_tag = reinterpret_cast<csubstr*>(buf + newsz.val_start + 4 * new_cap * sizeof(csubstr));
csubstr *key_anchor = reinterpret_cast<csubstr*>(buf + newsz.val_start + 5 * new_cap * sizeof(csubstr)); csubstr *key_anchor = reinterpret_cast<csubstr*>(buf + newsz.val_start + 5 * new_cap * sizeof(csubstr));
NodeRelation *rel = reinterpret_cast<NodeRelation*>(buf + newsz.rel_start); id_type *parent = reinterpret_cast<id_type*>(buf + newsz.rel_start + 0 * new_cap * sizeof(id_type));
id_type *first_child = reinterpret_cast<id_type*>(buf + newsz.rel_start + 1 * new_cap * sizeof(id_type));
id_type *last_child = reinterpret_cast<id_type*>(buf + newsz.rel_start + 2 * new_cap * sizeof(id_type));
id_type *prev_sibling = reinterpret_cast<id_type*>(buf + newsz.rel_start + 3 * new_cap * sizeof(id_type));
id_type *next_sibling = reinterpret_cast<id_type*>(buf + newsz.rel_start + 4 * new_cap * sizeof(id_type));
_RYML_CB_ASSERT(cb, _is_aligned(type)); _RYML_CB_ASSERT(cb, _is_aligned(type));
_RYML_CB_ASSERT(cb, _is_aligned(val)); _RYML_CB_ASSERT(cb, _is_aligned(val));
_RYML_CB_ASSERT(cb, _is_aligned(val_tag)); _RYML_CB_ASSERT(cb, _is_aligned(val_tag));
@@ -153,7 +162,11 @@ C4_NO_INLINE void _resize_node_data(Callbacks const& cb,
_RYML_CB_ASSERT(cb, _is_aligned(key)); _RYML_CB_ASSERT(cb, _is_aligned(key));
_RYML_CB_ASSERT(cb, _is_aligned(key_tag)); _RYML_CB_ASSERT(cb, _is_aligned(key_tag));
_RYML_CB_ASSERT(cb, _is_aligned(key_anchor)); _RYML_CB_ASSERT(cb, _is_aligned(key_anchor));
_RYML_CB_ASSERT(cb, _is_aligned(rel)); _RYML_CB_ASSERT(cb, _is_aligned(parent));
_RYML_CB_ASSERT(cb, _is_aligned(first_child));
_RYML_CB_ASSERT(cb, _is_aligned(last_child));
_RYML_CB_ASSERT(cb, _is_aligned(prev_sibling));
_RYML_CB_ASSERT(cb, _is_aligned(next_sibling));
if(old_cap) if(old_cap)
{ {
memcpy(type, *m_type, old_cap * sizeof(NodeType)); memcpy(type, *m_type, old_cap * sizeof(NodeType));
@@ -163,7 +176,11 @@ C4_NO_INLINE void _resize_node_data(Callbacks const& cb,
memcpy(key, *m_key, old_cap * sizeof(csubstr)); memcpy(key, *m_key, old_cap * sizeof(csubstr));
memcpy(key_tag, *m_key_tag, old_cap * sizeof(csubstr)); memcpy(key_tag, *m_key_tag, old_cap * sizeof(csubstr));
memcpy(key_anchor, *m_key_anchor, old_cap * sizeof(csubstr)); memcpy(key_anchor, *m_key_anchor, old_cap * sizeof(csubstr));
memcpy(rel, *m_relation, old_cap * sizeof(NodeRelation)); memcpy(parent, *m_parent, old_cap * sizeof(id_type));
memcpy(first_child, *m_first_child, old_cap * sizeof(id_type));
memcpy(last_child, *m_last_child, old_cap * sizeof(id_type));
memcpy(prev_sibling, *m_prev_sibling, old_cap * sizeof(id_type));
memcpy(next_sibling, *m_next_sibling, old_cap * sizeof(id_type));
const node_buf_data oldsz(old_cap); const node_buf_data oldsz(old_cap);
_RYML_CB_FREE(cb, *m_type, uint8_t, oldsz.total_size); _RYML_CB_FREE(cb, *m_type, uint8_t, oldsz.total_size);
} }
@@ -174,7 +191,11 @@ C4_NO_INLINE void _resize_node_data(Callbacks const& cb,
*m_key = key; *m_key = key;
*m_key_tag = key_tag; *m_key_tag = key_tag;
*m_key_anchor = key_anchor; *m_key_anchor = key_anchor;
*m_relation = rel; *m_parent = parent;
*m_first_child = first_child;
*m_last_child = last_child;
*m_prev_sibling = prev_sibling;
*m_next_sibling = next_sibling;
} }
} // namespace } // namespace
@@ -188,7 +209,11 @@ Tree::Tree(Callbacks const& cb)
, m_key(nullptr) , m_key(nullptr)
, m_key_tag(nullptr) , m_key_tag(nullptr)
, m_key_anchor(nullptr) , m_key_anchor(nullptr)
, m_relation(nullptr) , m_parent(nullptr)
, m_first_child(nullptr)
, m_last_child(nullptr)
, m_prev_sibling(nullptr)
, m_next_sibling(nullptr)
, m_cap(0) , m_cap(0)
, m_size(0) , m_size(0)
, m_free_head(NONE) , m_free_head(NONE)
@@ -244,7 +269,7 @@ void Tree::_free()
if(m_type) // allocated for everything if(m_type) // allocated for everything
{ {
_RYML_CB_ASSERT(m_callbacks, m_cap > 0); _RYML_CB_ASSERT(m_callbacks, m_cap > 0);
const node_buf_data oldsz(m_cap); const node_buf_data oldsz((size_t)m_cap);
_RYML_CB_FREE(m_callbacks, m_type, uint8_t, oldsz.total_size); _RYML_CB_FREE(m_callbacks, m_type, uint8_t, oldsz.total_size);
} }
if(m_arena.str) if(m_arena.str)
@@ -264,7 +289,11 @@ void Tree::_clear()
m_key = nullptr; m_key = nullptr;
m_key_tag = nullptr; m_key_tag = nullptr;
m_key_anchor = nullptr; m_key_anchor = nullptr;
m_relation = nullptr; m_parent = nullptr;
m_first_child = nullptr;
m_last_child = nullptr;
m_prev_sibling = nullptr;
m_next_sibling = nullptr;
m_cap = 0; m_cap = 0;
m_size = 0; m_size = 0;
m_free_head = 0; m_free_head = 0;
@@ -284,14 +313,18 @@ void Tree::_copy(Tree const& that)
_RYML_CB_ASSERT(m_callbacks, m_key == nullptr); _RYML_CB_ASSERT(m_callbacks, m_key == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_key_tag == nullptr); _RYML_CB_ASSERT(m_callbacks, m_key_tag == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_key_anchor == nullptr); _RYML_CB_ASSERT(m_callbacks, m_key_anchor == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_relation == nullptr); _RYML_CB_ASSERT(m_callbacks, m_parent == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_first_child == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_last_child == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_prev_sibling == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_next_sibling == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr); _RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_arena.len == 0); _RYML_CB_ASSERT(m_callbacks, m_arena.len == 0);
if(that.m_cap) if(that.m_cap)
{ {
_resize_node_data(m_callbacks, _resize_node_data(m_callbacks,
0, (size_t)0,
that.m_cap, (size_t)that.m_cap,
&m_type, &m_type,
&m_val, &m_val,
&m_val_tag, &m_val_tag,
@@ -299,10 +332,14 @@ void Tree::_copy(Tree const& that)
&m_key, &m_key,
&m_key_tag, &m_key_tag,
&m_key_anchor, &m_key_anchor,
&m_relation); &m_parent,
&m_first_child,
&m_last_child,
&m_prev_sibling,
&m_next_sibling);
memcpy(m_type, that.m_type, (size_t)that.m_cap * sizeof(NodeType)); memcpy(m_type, that.m_type, (size_t)that.m_cap * sizeof(NodeType));
memcpy(m_val, that.m_val, (size_t)that.m_cap * _ryml_num_val_arrays * sizeof(csubstr)); memcpy(m_val, that.m_val, _ryml_num_val_arrays * (size_t)that.m_cap * sizeof(csubstr));
memcpy(m_relation, that.m_relation, (size_t)that.m_cap * sizeof(NodeRelation)); memcpy(m_parent, that.m_parent, _ryml_num_hcy_arrays * (size_t)that.m_cap * sizeof(id_type));
m_cap = that.m_cap; m_cap = that.m_cap;
m_size = that.m_size; m_size = that.m_size;
m_free_head = that.m_free_head; m_free_head = that.m_free_head;
@@ -332,7 +369,11 @@ void Tree::_move(Tree & that) noexcept
_RYML_CB_ASSERT(m_callbacks, m_key == nullptr); _RYML_CB_ASSERT(m_callbacks, m_key == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_key_tag == nullptr); _RYML_CB_ASSERT(m_callbacks, m_key_tag == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_key_anchor == nullptr); _RYML_CB_ASSERT(m_callbacks, m_key_anchor == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_relation == nullptr); _RYML_CB_ASSERT(m_callbacks, m_parent == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_first_child == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_last_child == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_prev_sibling == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_next_sibling == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr); _RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr);
_RYML_CB_ASSERT(m_callbacks, m_arena.len == 0); _RYML_CB_ASSERT(m_callbacks, m_arena.len == 0);
m_type = that.m_type; m_type = that.m_type;
@@ -342,7 +383,11 @@ void Tree::_move(Tree & that) noexcept
m_key = that.m_key; m_key = that.m_key;
m_key_tag = that.m_key_tag; m_key_tag = that.m_key_tag;
m_key_anchor = that.m_key_anchor; m_key_anchor = that.m_key_anchor;
m_relation = that.m_relation; m_parent = that.m_parent;
m_first_child = that.m_first_child;
m_last_child = that.m_last_child;
m_prev_sibling = that.m_prev_sibling;
m_next_sibling = that.m_next_sibling;
m_cap = that.m_cap; m_cap = that.m_cap;
m_size = that.m_size; m_size = that.m_size;
m_free_head = that.m_free_head; m_free_head = that.m_free_head;
@@ -407,7 +452,11 @@ void Tree::reserve(id_type cap)
&m_key, &m_key,
&m_key_tag, &m_key_tag,
&m_key_anchor, &m_key_anchor,
&m_relation); &m_parent,
&m_first_child,
&m_last_child,
&m_prev_sibling,
&m_next_sibling);
id_type first = m_cap; id_type first = m_cap;
id_type del = cap - m_cap; id_type del = cap - m_cap;
m_cap = cap; m_cap = cap;
@@ -416,8 +465,8 @@ void Tree::reserve(id_type cap)
{ {
_RYML_CB_ASSERT(m_callbacks, m_val != nullptr); _RYML_CB_ASSERT(m_callbacks, m_val != nullptr);
_RYML_CB_ASSERT(m_callbacks, m_free_tail != NONE); _RYML_CB_ASSERT(m_callbacks, m_free_tail != NONE);
m_relation[m_free_tail].m_next_sibling = first; m_next_sibling[m_free_tail] = first;
m_relation[first].m_prev_sibling = m_free_tail; m_prev_sibling[first] = m_free_tail;
m_free_tail = cap-1; m_free_tail = cap-1;
} }
else else
@@ -472,10 +521,10 @@ void Tree::_clear_range(id_type first, id_type num)
for(id_type i = first, e = first + num; i < e; ++i) for(id_type i = first, e = first + num; i < e; ++i)
{ {
_clear(i); _clear(i);
m_relation[i].m_prev_sibling = i - 1; m_prev_sibling[i] = i - 1;
m_relation[i].m_next_sibling = i + 1; m_next_sibling[i] = i + 1;
} }
m_relation[first + num - 1].m_next_sibling = NONE; m_next_sibling[first + num - 1] = NONE;
// we don't need to clear the node data // we don't need to clear the node data
} }
@@ -495,12 +544,11 @@ void Tree::_release(id_type i)
void Tree::_free_list_add(id_type i) void Tree::_free_list_add(id_type i)
{ {
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap); _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
NodeRelation &C4_RESTRICT w = m_relation[i]; m_parent[i] = NONE;
w.m_parent = NONE; m_next_sibling[i] = m_free_head;
w.m_next_sibling = m_free_head; m_prev_sibling[i] = NONE;
w.m_prev_sibling = NONE;
if(m_free_head != NONE) if(m_free_head != NONE)
m_relation[m_free_head].m_prev_sibling = i; m_prev_sibling[m_free_head] = i;
m_free_head = i; m_free_head = i;
if(m_free_tail == NONE) if(m_free_tail == NONE)
m_free_tail = m_free_head; m_free_tail = m_free_head;
@@ -510,7 +558,7 @@ void Tree::_free_list_rem(id_type i)
{ {
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap); _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
if(m_free_head == i) if(m_free_head == i)
m_free_head = m_relation[i].m_next_sibling; m_free_head = m_next_sibling[i];
_rem_hierarchy(i); _rem_hierarchy(i);
} }
@@ -528,7 +576,7 @@ id_type Tree::_claim()
_RYML_CB_ASSERT(m_callbacks, m_free_head >= 0 && m_free_head < m_cap); _RYML_CB_ASSERT(m_callbacks, m_free_head >= 0 && m_free_head < m_cap);
const id_type ichild = m_free_head; const id_type ichild = m_free_head;
++m_size; ++m_size;
m_free_head = m_relation[ichild].m_next_sibling; m_free_head = m_next_sibling[ichild];
if(m_free_head == NONE) if(m_free_head == NONE)
{ {
m_free_tail = NONE; m_free_tail = NONE;
@@ -553,52 +601,47 @@ C4_SUPPRESS_WARNING_GCC("-Wanalyzer-fd-leak")
#endif #endif
#endif #endif
void Tree::_set_hierarchy(id_type ichild, id_type iparent, id_type iprev_sibling) void Tree::_set_hierarchy(id_type child, id_type parent, id_type iprev_sibling)
{ {
_RYML_CB_ASSERT(m_callbacks, m_relation != nullptr); _RYML_CB_ASSERT(m_callbacks, m_cap > 0);
_RYML_CB_ASSERT(m_callbacks, ichild >= 0 && ichild < m_cap); _RYML_CB_ASSERT(m_callbacks, m_parent != nullptr);
_RYML_CB_ASSERT(m_callbacks, iparent == NONE || (iparent >= 0 && iparent < m_cap)); _RYML_CB_ASSERT(m_callbacks, child >= 0 && child < m_cap);
_RYML_CB_ASSERT(m_callbacks, parent == NONE || (parent >= 0 && parent < m_cap));
_RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE || (iprev_sibling >= 0 && iprev_sibling < m_cap)); _RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE || (iprev_sibling >= 0 && iprev_sibling < m_cap));
NodeRelation *C4_RESTRICT child = &m_relation[ichild]; m_parent[child] = parent;
child->m_parent = iparent; m_prev_sibling[child] = NONE;
child->m_prev_sibling = NONE; m_next_sibling[child] = NONE;
child->m_next_sibling = NONE; _RYML_CB_ASSERT(m_callbacks, parent != NONE || child == 0);
_RYML_CB_ASSERT(m_callbacks, iparent != NONE || ichild == 0); _RYML_CB_ASSERT(m_callbacks, parent != NONE || iprev_sibling == NONE);
_RYML_CB_ASSERT(m_callbacks, iparent != NONE || iprev_sibling == NONE); if(parent == NONE)
if(iparent == NONE)
return; return;
id_type inext_sibling = iprev_sibling != NONE ? next_sibling(iprev_sibling) : first_child(iparent); id_type inext_sibling = iprev_sibling != NONE ? next_sibling(iprev_sibling) : first_child(parent);
NodeRelation *C4_RESTRICT psib = nullptr;
NodeRelation *C4_RESTRICT nsib = nullptr;
if(iprev_sibling != NONE) if(iprev_sibling != NONE)
{ {
psib = &m_relation[iprev_sibling];
_RYML_CB_ASSERT(m_callbacks, next_sibling(iprev_sibling) == inext_sibling); _RYML_CB_ASSERT(m_callbacks, next_sibling(iprev_sibling) == inext_sibling);
child->m_prev_sibling = iprev_sibling; m_prev_sibling[child] = iprev_sibling;
psib->m_next_sibling = ichild; m_next_sibling[iprev_sibling] = child;
_RYML_CB_ASSERT(m_callbacks, psib->m_prev_sibling != psib->m_next_sibling || psib->m_prev_sibling == NONE); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[iprev_sibling] != m_next_sibling[iprev_sibling] || m_prev_sibling[iprev_sibling] == NONE);
} }
if(inext_sibling != NONE) if(inext_sibling != NONE)
{ {
nsib = &m_relation[inext_sibling];
_RYML_CB_ASSERT(m_callbacks, prev_sibling(inext_sibling) == iprev_sibling); _RYML_CB_ASSERT(m_callbacks, prev_sibling(inext_sibling) == iprev_sibling);
child->m_next_sibling = inext_sibling; m_next_sibling[child] = inext_sibling;
nsib->m_prev_sibling = ichild; m_prev_sibling[inext_sibling] = child;
_RYML_CB_ASSERT(m_callbacks, nsib->m_prev_sibling != nsib->m_next_sibling || nsib->m_prev_sibling == NONE); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[inext_sibling] != m_next_sibling[inext_sibling] || m_prev_sibling[inext_sibling]);
} }
NodeRelation *C4_RESTRICT parent = &m_relation[iparent]; if(m_first_child[parent] != NONE)
if(parent->m_first_child != NONE)
{ {
if(child->m_next_sibling == parent->m_first_child) if(m_next_sibling[child] == m_first_child[parent])
parent->m_first_child = ichild; m_first_child[parent] = child;
if(child->m_prev_sibling == parent->m_last_child) if(m_prev_sibling[child] == m_last_child[parent])
parent->m_last_child = ichild; m_last_child[parent] = child;
} }
else else
{ {
_RYML_CB_ASSERT(m_callbacks, parent->m_last_child == NONE); _RYML_CB_ASSERT(m_callbacks, m_last_child[parent] == NONE);
parent->m_first_child = ichild; m_first_child[parent] = child;
parent->m_last_child = ichild; m_last_child[parent] = child;
} }
} }
@@ -610,32 +653,20 @@ C4_SUPPRESS_WARNING_CLANG_POP
void Tree::_rem_hierarchy(id_type i) void Tree::_rem_hierarchy(id_type i)
{ {
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap); _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
NodeRelation &C4_RESTRICT w = m_relation[i];
// remove from the parent // remove from the parent
if(w.m_parent != NONE) const id_type parent = m_parent[i];
if(parent != NONE)
{ {
NodeRelation &C4_RESTRICT p = m_relation[w.m_parent]; if(m_first_child[parent] == i)
if(p.m_first_child == i) m_first_child[parent] = m_next_sibling[i];
{ if(m_last_child[parent] == i)
p.m_first_child = w.m_next_sibling; m_last_child[parent] = m_prev_sibling[i];
}
if(p.m_last_child == i)
{
p.m_last_child = w.m_prev_sibling;
}
} }
// remove from the used list // remove from the used list
if(w.m_prev_sibling != NONE) if(m_prev_sibling[i] != NONE)
{ m_next_sibling[m_prev_sibling[i]] = m_next_sibling[i];
NodeRelation *C4_RESTRICT prev = &m_relation[w.m_prev_sibling]; if(m_next_sibling[i] != NONE)
prev->m_next_sibling = w.m_next_sibling; m_prev_sibling[m_next_sibling[i]] = m_prev_sibling[i];
}
if(w.m_next_sibling != NONE)
{
NodeRelation *C4_RESTRICT next = &m_relation[w.m_next_sibling];
next->m_prev_sibling = w.m_prev_sibling;
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -701,153 +732,151 @@ void Tree::_swap(id_type n_, id_type m_)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Tree::_swap_hierarchy(id_type ia, id_type ib) void Tree::_swap_hierarchy(id_type a, id_type b)
{ {
if(ia == ib) return; if(a == b) return;
for(id_type i = first_child(ia); i != NONE; i = next_sibling(i)) for(id_type i = first_child(a); i != NONE; i = next_sibling(i))
{ {
if(i == ib || i == ia) if(i == b || i == a)
continue; continue;
m_relation[i].m_parent = ib; m_parent[i] = b;
} }
for(id_type i = first_child(ib); i != NONE; i = next_sibling(i)) for(id_type i = first_child(b); i != NONE; i = next_sibling(i))
{ {
if(i == ib || i == ia) if(i == b || i == a)
continue; continue;
m_relation[i].m_parent = ia; m_parent[i] = a;
} }
auto & C4_RESTRICT a = m_relation[ia]; auto & C4_RESTRICT pa = m_parent[a];
auto & C4_RESTRICT b = m_relation[ib]; auto & C4_RESTRICT pb = m_parent[b];
auto & C4_RESTRICT pa = m_relation[a.m_parent];
auto & C4_RESTRICT pb = m_relation[b.m_parent];
if(&pa == &pb) if(pa == pb)
{ {
if((pa.m_first_child == ib && pa.m_last_child == ia) if((m_first_child[pa] == b && m_last_child[pa] == a)
|| ||
(pa.m_first_child == ia && pa.m_last_child == ib)) (m_first_child[a] == a && m_last_child[pa] == b))
{ {
std::swap(pa.m_first_child, pa.m_last_child); std::swap(m_first_child[pa], m_last_child[pa]);
} }
else else
{ {
bool changed = false; bool changed = false;
if(pa.m_first_child == ia) if(m_first_child[pa] == a)
{ {
pa.m_first_child = ib; m_first_child[pa] = b;
changed = true; changed = true;
} }
if(pa.m_last_child == ia) if(m_last_child[pa] == a)
{ {
pa.m_last_child = ib; m_last_child[pa] = b;
changed = true; changed = true;
} }
if(pb.m_first_child == ib && !changed) if(m_first_child[pb] == b && !changed)
{ {
pb.m_first_child = ia; m_first_child[pb] = a;
} }
if(pb.m_last_child == ib && !changed) if(m_last_child[pb] == b && !changed)
{ {
pb.m_last_child = ia; m_last_child[pb] = a;
} }
} }
} }
else else
{ {
if(pa.m_first_child == ia) if(m_first_child[pa] == a)
pa.m_first_child = ib; m_first_child[pa] = b;
if(pa.m_last_child == ia) if(m_last_child[pa] == a)
pa.m_last_child = ib; m_last_child[pa] = b;
if(pb.m_first_child == ib) if(m_first_child[pb] == b)
pb.m_first_child = ia; m_first_child[pb] = a;
if(pb.m_last_child == ib) if(m_last_child[pb] == b)
pb.m_last_child = ia; m_last_child[pb] = a;
} }
std::swap(a.m_first_child , b.m_first_child); std::swap(m_first_child[a] , m_first_child[b]);
std::swap(a.m_last_child , b.m_last_child); std::swap(m_last_child[a] , m_last_child[b]);
if(a.m_prev_sibling != ib && b.m_prev_sibling != ia && if(m_prev_sibling[a] != b && m_prev_sibling[b] != a &&
a.m_next_sibling != ib && b.m_next_sibling != ia) m_next_sibling[a] != b && m_next_sibling[b] != a)
{ {
if(a.m_prev_sibling != NONE && a.m_prev_sibling != ib) if(m_prev_sibling[a] != NONE && m_prev_sibling[a] != b)
m_relation[a.m_prev_sibling].m_next_sibling = ib; m_next_sibling[m_prev_sibling[a]] = b;
if(a.m_next_sibling != NONE && a.m_next_sibling != ib) if(m_next_sibling[a] != NONE && m_next_sibling[a] != b)
m_relation[a.m_next_sibling].m_prev_sibling = ib; m_prev_sibling[m_next_sibling[a]] = b;
if(b.m_prev_sibling != NONE && b.m_prev_sibling != ia) if(m_prev_sibling[b] != NONE && m_prev_sibling[b] != a)
m_relation[b.m_prev_sibling].m_next_sibling = ia; m_next_sibling[m_prev_sibling[b]] = a;
if(b.m_next_sibling != NONE && b.m_next_sibling != ia) if(m_next_sibling[b] != NONE && m_next_sibling[b] != a)
m_relation[b.m_next_sibling].m_prev_sibling = ia; m_prev_sibling[m_next_sibling[b]] = a;
std::swap(a.m_prev_sibling, b.m_prev_sibling); std::swap(m_prev_sibling[a], m_prev_sibling[b]);
std::swap(a.m_next_sibling, b.m_next_sibling); std::swap(m_next_sibling[a], m_next_sibling[b]);
} }
else else
{ {
if(a.m_next_sibling == ib) // n will go after m if(m_next_sibling[a] == b) // n will go after m
{ {
_RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling == ia); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[b] == a);
if(a.m_prev_sibling != NONE) if(m_prev_sibling[a] != NONE)
{ {
_RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ib); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[a] != b);
m_relation[a.m_prev_sibling].m_next_sibling = ib; m_next_sibling[m_prev_sibling[a]] = b;
} }
if(b.m_next_sibling != NONE) if(m_next_sibling[b] != NONE)
{ {
_RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ia); _RYML_CB_ASSERT(m_callbacks, m_next_sibling[b] != a);
m_relation[b.m_next_sibling].m_prev_sibling = ia; m_prev_sibling[m_next_sibling[b]] = a;
} }
id_type ns = b.m_next_sibling; id_type ns = m_next_sibling[b];
b.m_prev_sibling = a.m_prev_sibling; m_prev_sibling[b] = m_prev_sibling[a];
b.m_next_sibling = ia; m_next_sibling[b] = a;
a.m_prev_sibling = ib; m_prev_sibling[a] = b;
a.m_next_sibling = ns; m_next_sibling[a] = ns;
} }
else if(a.m_prev_sibling == ib) // m will go after n else if(m_prev_sibling[a] == b) // m will go after n
{ {
_RYML_CB_ASSERT(m_callbacks, b.m_next_sibling == ia); _RYML_CB_ASSERT(m_callbacks, m_next_sibling[b] == a);
if(b.m_prev_sibling != NONE) if(m_prev_sibling[b] != NONE)
{ {
_RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ia); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[b] != a);
m_relation[b.m_prev_sibling].m_next_sibling = ia; m_next_sibling[m_prev_sibling[b]] = a;
} }
if(a.m_next_sibling != NONE) if(m_next_sibling[a] != NONE)
{ {
_RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ib); _RYML_CB_ASSERT(m_callbacks, m_next_sibling[a] != b);
m_relation[a.m_next_sibling].m_prev_sibling = ib; m_prev_sibling[m_next_sibling[a]] = b;
} }
id_type ns = b.m_prev_sibling; id_type ns = m_prev_sibling[b];
a.m_prev_sibling = b.m_prev_sibling; m_prev_sibling[a] = m_prev_sibling[b];
a.m_next_sibling = ib; m_next_sibling[a] = b;
b.m_prev_sibling = ia; m_prev_sibling[b] = a;
b.m_next_sibling = ns; m_next_sibling[b] = ns;
} }
else else
{ {
C4_NEVER_REACH(); C4_NEVER_REACH();
} }
} }
_RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ia); _RYML_CB_ASSERT(m_callbacks, m_next_sibling[a] != a);
_RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ia); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[a] != a);
_RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ib); _RYML_CB_ASSERT(m_callbacks, m_next_sibling[b] != b);
_RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ib); _RYML_CB_ASSERT(m_callbacks, m_prev_sibling[b] != b);
if(a.m_parent != ib && b.m_parent != ia) if(m_parent[a] != b && m_parent[b] != a)
{ {
std::swap(a.m_parent, b.m_parent); std::swap(m_parent[a], m_parent[b]);
} }
else else
{ {
if(a.m_parent == ib && b.m_parent != ia) if(m_parent[a] == b && m_parent[b] != a)
{ {
a.m_parent = b.m_parent; m_parent[a] = m_parent[b];
b.m_parent = ia; m_parent[b] = a;
} }
else if(a.m_parent != ib && b.m_parent == ia) else if(m_parent[a] != b && m_parent[b] == a)
{ {
b.m_parent = a.m_parent; m_parent[b] = m_parent[a];
a.m_parent = ib; m_parent[a] = b;
} }
else else
{ {
@@ -859,34 +888,32 @@ void Tree::_swap_hierarchy(id_type ia, id_type ib)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Tree::_copy_hierarchy(id_type dst_, id_type src_) void Tree::_copy_hierarchy(id_type dst_, id_type src_)
{ {
auto const& C4_RESTRICT src = m_relation[src_]; const id_type prt = m_parent[src_];
auto & C4_RESTRICT dst = m_relation[dst_]; for(id_type i = m_first_child[src_]; i != NONE; i = next_sibling(i))
auto & C4_RESTRICT prt = m_relation[src.m_parent];
for(id_type i = src.m_first_child; i != NONE; i = next_sibling(i))
{ {
m_relation[i].m_parent = dst_; m_parent[i] = dst_;
} }
if(src.m_prev_sibling != NONE) if(m_prev_sibling[src_] != NONE)
{ {
m_relation[src.m_prev_sibling].m_next_sibling = dst_; m_next_sibling[m_prev_sibling[src_]] = dst_;
} }
if(src.m_next_sibling != NONE) if(m_next_sibling[src_] != NONE)
{ {
m_relation[src.m_next_sibling].m_prev_sibling = dst_; m_prev_sibling[m_next_sibling[src_]] = dst_;
} }
if(prt.m_first_child == src_) if(m_first_child[prt] == src_)
{ {
prt.m_first_child = dst_; m_first_child[prt] = dst_;
} }
if(prt.m_last_child == src_) if(m_last_child[prt] == src_)
{ {
prt.m_last_child = dst_; m_last_child[prt] = dst_;
} }
dst.m_parent = src.m_parent; m_parent[dst_] = m_parent[src_];
dst.m_first_child = src.m_first_child; m_first_child[dst_] = m_first_child[src_];
dst.m_last_child = src.m_last_child; m_last_child[dst_] = m_last_child[src_];
dst.m_prev_sibling = src.m_prev_sibling; m_prev_sibling[dst_] = m_prev_sibling[src_];
dst.m_next_sibling = src.m_next_sibling; m_next_sibling[dst_] = m_next_sibling[src_];
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -981,14 +1008,14 @@ void Tree::set_root_as_stream()
void Tree::remove_children(id_type node) void Tree::remove_children(id_type node)
{ {
_ryml_chkid(node); _ryml_chkid(node);
id_type ich = m_relation[node].m_first_child; id_type ich = m_first_child[node];
while(ich != NONE) while(ich != NONE)
{ {
remove_children(ich); remove_children(ich);
_ryml_chkid(ich); _ryml_chkid(ich);
const id_type next = m_relation[ich].m_next_sibling; const id_type next = m_next_sibling[ich];
_release(ich); _release(ich);
if(ich == m_relation[node].m_last_child) if(ich == m_last_child[node])
break; break;
ich = next; ich = next;
} }
@@ -1301,14 +1328,14 @@ id_type Tree::find_child(id_type node, csubstr const& name) const
_ryml_chkid(node); _ryml_chkid(node);
_RYML_CB_ASSERT(m_callbacks, node != NONE); _RYML_CB_ASSERT(m_callbacks, node != NONE);
_RYML_CB_ASSERT(m_callbacks, is_map(node)); _RYML_CB_ASSERT(m_callbacks, is_map(node));
if(m_relation[node].m_first_child == NONE) if(m_first_child[node] == NONE)
{ {
_RYML_CB_ASSERT(m_callbacks, m_relation[node].m_last_child == NONE); _RYML_CB_ASSERT(m_callbacks, m_last_child[node] == NONE);
return NONE; return NONE;
} }
else else
{ {
_RYML_CB_ASSERT(m_callbacks, m_relation[node].m_last_child != NONE); _RYML_CB_ASSERT(m_callbacks, m_last_child[node] != NONE);
} }
for(id_type i = first_child(node); i != NONE; i = next_sibling(i)) for(id_type i = first_child(node); i != NONE; i = next_sibling(i))
{ {

View File

@@ -200,22 +200,6 @@ public:
}; };
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
struct RYML_EXPORT NodeRelation
{
id_type m_parent;
id_type m_first_child;
id_type m_last_child;
id_type m_next_sibling;
id_type m_prev_sibling;
};
C4_MUST_BE_TRIVIAL_COPY(NodeRelation);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -367,8 +351,8 @@ public:
C4_ALWAYS_INLINE bool is_val_ref(id_type node) const { _ryml_chkid(node); return m_type[node].is_val_ref(); } C4_ALWAYS_INLINE bool is_val_ref(id_type node) const { _ryml_chkid(node); return m_type[node].is_val_ref(); }
C4_ALWAYS_INLINE bool is_ref(id_type node) const { _ryml_chkid(node); return m_type[node].is_ref(); } C4_ALWAYS_INLINE bool is_ref(id_type node) const { _ryml_chkid(node); return m_type[node].is_ref(); }
C4_ALWAYS_INLINE bool parent_is_seq(id_type node) const { _ryml_chkid(node); _RYML_CB_ASSERT(m_callbacks, has_parent(node)); return is_seq(m_relation[node].m_parent); } C4_ALWAYS_INLINE bool parent_is_seq(id_type node) const { _ryml_chkid(node); _RYML_CB_ASSERT(m_callbacks, has_parent(node)); return is_seq(m_parent[node]); }
C4_ALWAYS_INLINE bool parent_is_map(id_type node) const { _ryml_chkid(node); _RYML_CB_ASSERT(m_callbacks, has_parent(node)); return is_map(m_relation[node].m_parent); } C4_ALWAYS_INLINE bool parent_is_map(id_type node) const { _ryml_chkid(node); _RYML_CB_ASSERT(m_callbacks, has_parent(node)); return is_map(m_parent[node]); }
/** true when the node has an anchor named a */ /** true when the node has an anchor named a */
C4_ALWAYS_INLINE bool has_anchor(id_type node, csubstr a) const { _ryml_chkid(node); return ((m_type[node] & KEYANCH) && m_key_anchor[node] == a) || ((m_type[node] & VALANCH) && m_val_anchor[node] == a); } C4_ALWAYS_INLINE bool has_anchor(id_type node, csubstr a) const { _ryml_chkid(node); return ((m_type[node] & KEYANCH) && m_key_anchor[node] == a) || ((m_type[node] & VALANCH) && m_val_anchor[node] == a); }
@@ -401,9 +385,9 @@ public:
/** @name hierarchy predicates */ /** @name hierarchy predicates */
/** @{ */ /** @{ */
bool is_root(id_type node) const { _ryml_chkid(node); _RYML_CB_ASSERT(m_callbacks, m_relation[node].m_parent != NONE || node == 0); return m_relation[node].m_parent == NONE; } bool is_root(id_type node) const { _ryml_chkid(node); _RYML_CB_ASSERT(m_callbacks, m_parent[node] != NONE || node == 0); return m_parent[node] == NONE; }
bool has_parent(id_type node) const { _ryml_chkid(node); return m_relation[node].m_parent != NONE; } bool has_parent(id_type node) const { _ryml_chkid(node); return m_parent[node] != NONE; }
/** true when key and val are empty, and has no children */ /** true when key and val are empty, and has no children */
bool empty(id_type node) const bool empty(id_type node) const
@@ -414,26 +398,23 @@ public:
} }
/** true if @p node has a child with id @p ch */ /** true if @p node has a child with id @p ch */
bool has_child(id_type node, id_type ch) const { _ryml_chkid(node); return m_relation[ch].m_parent == node; } bool has_child(id_type node, id_type ch) const { _ryml_chkid(node); return m_parent[ch] == node; }
/** true if @p node has a child with key @p key */ /** true if @p node has a child with key @p key */
bool has_child(id_type node, csubstr key) const { _ryml_chkid(node); return find_child(node, key) != NONE; } bool has_child(id_type node, csubstr key) const { _ryml_chkid(node); return find_child(node, key) != NONE; }
/** true if @p node has any children key */ /** true if @p node has any children key */
bool has_children(id_type node) const { _ryml_chkid(node); return m_relation[node].m_first_child != NONE; } bool has_children(id_type node) const { _ryml_chkid(node); return m_first_child[node] != NONE; }
/** true if @p node has a sibling with id @p sib */ /** true if @p node has a sibling with id @p sib */
bool has_sibling(id_type node, id_type sib) const { _ryml_chkid(node); return m_relation[node].m_parent == m_relation[sib].m_parent; } bool has_sibling(id_type node, id_type sib) const { _ryml_chkid(node); return m_parent[node] == m_parent[sib]; }
/** true if one of the node's siblings has the given key */ /** true if one of the node's siblings has the given key */
bool has_sibling(id_type node, csubstr key) const { _ryml_chkid(node); return find_sibling(node, key) != NONE; } bool has_sibling(id_type node, csubstr key) const { _ryml_chkid(node); return find_sibling(node, key) != NONE; }
/** true if node is not a single child */ /** true if node is not a single child */
bool has_other_siblings(id_type node) const bool has_other_siblings(id_type node) const
{ {
_ryml_chkid(node); _ryml_chkid(node);
NodeRelation const *C4_RESTRICT n = &m_relation[node]; const id_type parent = m_parent[node];
if(C4_LIKELY(n->m_parent != NONE)) if(C4_LIKELY(parent != NONE))
{ return m_first_child[parent] != m_last_child[parent];
n = &m_relation[n->m_parent];
return n->m_first_child != n->m_last_child;
}
return false; return false;
} }
@@ -446,29 +427,29 @@ public:
/** @name hierarchy getters */ /** @name hierarchy getters */
/** @{ */ /** @{ */
id_type parent(id_type node) const { _ryml_chkid(node); return m_relation[node].m_parent; } id_type parent(id_type node) const { _ryml_chkid(node); return m_parent[node]; }
id_type prev_sibling(id_type node) const { _ryml_chkid(node); return m_relation[node].m_prev_sibling; } id_type prev_sibling(id_type node) const { _ryml_chkid(node); return m_prev_sibling[node]; }
id_type next_sibling(id_type node) const { _ryml_chkid(node); return m_relation[node].m_next_sibling; } id_type next_sibling(id_type node) const { _ryml_chkid(node); return m_next_sibling[node]; }
/** O(#num_children) */ /** O(#num_children) */
id_type num_children(id_type node) const; id_type num_children(id_type node) const;
id_type child_pos(id_type node, id_type ch) const; id_type child_pos(id_type node, id_type ch) const;
id_type first_child(id_type node) const { _ryml_chkid(node); return m_relation[node].m_first_child; } id_type first_child(id_type node) const { _ryml_chkid(node); return m_first_child[node]; }
id_type last_child(id_type node) const { _ryml_chkid(node); return m_relation[node].m_last_child; } id_type last_child(id_type node) const { _ryml_chkid(node); return m_last_child[node]; }
id_type child(id_type node, id_type pos) const; id_type child(id_type node, id_type pos) const;
id_type find_child(id_type node, csubstr const& key) const; id_type find_child(id_type node, csubstr const& key) const;
/** O(#num_siblings) */ /** O(#num_siblings) */
/** counts with this */ /** counts with this */
id_type num_siblings(id_type node) const { _ryml_chkid(node); return is_root(node) ? 1 : num_children(m_relation[node].m_parent); } id_type num_siblings(id_type node) const { _ryml_chkid(node); return is_root(node) ? 1 : num_children(m_parent[node]); }
/** does not count with this */ /** does not count with this */
id_type num_other_siblings(id_type node) const { _ryml_chkid(node); id_type ns = num_siblings(node); _RYML_CB_ASSERT(m_callbacks, ns > 0); return ns-1; } id_type num_other_siblings(id_type node) const { _ryml_chkid(node); id_type ns = num_siblings(node); _RYML_CB_ASSERT(m_callbacks, ns > 0); return ns-1; }
id_type sibling_pos(id_type node, id_type sib) const { _ryml_chkid(node); _ryml_chkid(sib); _RYML_CB_ASSERT(m_callbacks, ! is_root(node) || node == root_id()); return child_pos(m_relation[node].m_parent, sib); } id_type sibling_pos(id_type node, id_type sib) const { _ryml_chkid(node); _ryml_chkid(sib); _RYML_CB_ASSERT(m_callbacks, ! is_root(node) || node == root_id()); return child_pos(m_parent[node], sib); }
id_type first_sibling(id_type node) const { _ryml_chkid(node); return is_root(node) ? node : m_relation[m_relation[node].m_parent].m_first_child; } id_type first_sibling(id_type node) const { _ryml_chkid(node); return is_root(node) ? node : m_first_child[m_parent[node]]; }
id_type last_sibling(id_type node) const { _ryml_chkid(node); return is_root(node) ? node : m_relation[m_relation[node].m_parent].m_last_child; } id_type last_sibling(id_type node) const { _ryml_chkid(node); return is_root(node) ? node : m_last_child[m_parent[node]]; }
id_type sibling(id_type node, id_type pos) const { _ryml_chkid(node); return child(m_relation[node].m_parent, pos); } id_type sibling(id_type node, id_type pos) const { _ryml_chkid(node); return child(m_parent[node], pos); }
id_type find_sibling(id_type node, csubstr const& key) const { _ryml_chkid(node); return find_child(m_relation[node].m_parent, key); } id_type find_sibling(id_type node, csubstr const& key) const { _ryml_chkid(node); return find_child(m_parent[node], key); }
id_type doc(id_type i) const { id_type rid = root_id(); _RYML_CB_ASSERT(m_callbacks, is_stream(rid)); return child(rid, i); } //!< gets the @p i document node index. requires that the root node is a stream. id_type doc(id_type i) const { id_type rid = root_id(); _RYML_CB_ASSERT(m_callbacks, is_stream(rid)); return child(rid, i); } //!< gets the @p i document node index. requires that the root node is a stream.
@@ -646,7 +627,7 @@ public:
{ {
_RYML_CB_ASSERT(m_callbacks, parent != NONE); _RYML_CB_ASSERT(m_callbacks, parent != NONE);
_RYML_CB_ASSERT(m_callbacks, is_container(parent) || is_root(parent)); _RYML_CB_ASSERT(m_callbacks, is_container(parent) || is_root(parent));
_RYML_CB_ASSERT(m_callbacks, after == NONE || (m_relation[after].m_parent == parent)); _RYML_CB_ASSERT(m_callbacks, after == NONE || (m_parent[after] == parent));
id_type child = _claim(); id_type child = _claim();
_set_hierarchy(child, parent, after); _set_hierarchy(child, parent, after);
return child; return child;
@@ -654,11 +635,11 @@ public:
/** create and insert a node as the first child of @p parent */ /** create and insert a node as the first child of @p parent */
C4_ALWAYS_INLINE id_type prepend_child(id_type parent) { return insert_child(parent, NONE); } C4_ALWAYS_INLINE id_type prepend_child(id_type parent) { return insert_child(parent, NONE); }
/** create and insert a node as the last child of @p parent */ /** create and insert a node as the last child of @p parent */
C4_ALWAYS_INLINE id_type append_child(id_type parent) { return insert_child(parent, m_relation[parent].m_last_child); } C4_ALWAYS_INLINE id_type append_child(id_type parent) { return insert_child(parent, m_last_child[parent]); }
C4_ALWAYS_INLINE id_type _append_child__unprotected(id_type parent) C4_ALWAYS_INLINE id_type _append_child__unprotected(id_type parent)
{ {
id_type child = _claim(); id_type child = _claim();
_set_hierarchy(child, parent, m_relation[parent].m_last_child); _set_hierarchy(child, parent, m_last_child[parent]);
return child; return child;
} }
@@ -667,11 +648,11 @@ public:
//! create and insert a new sibling of n. insert after "after" //! create and insert a new sibling of n. insert after "after"
C4_ALWAYS_INLINE id_type insert_sibling(id_type node, id_type after) C4_ALWAYS_INLINE id_type insert_sibling(id_type node, id_type after)
{ {
return insert_child(m_relation[node].m_parent, after); return insert_child(m_parent[node], after);
} }
/** create and insert a node as the first node of @p parent */ /** create and insert a node as the first node of @p parent */
C4_ALWAYS_INLINE id_type prepend_sibling(id_type node) { return prepend_child(m_relation[node].m_parent); } C4_ALWAYS_INLINE id_type prepend_sibling(id_type node) { return prepend_child(m_parent[node]); }
C4_ALWAYS_INLINE id_type append_sibling(id_type node) { return append_child(m_relation[node].m_parent); } C4_ALWAYS_INLINE id_type append_sibling(id_type node) { return append_child(m_parent[node]); }
public: public:
@@ -1076,12 +1057,6 @@ public:
/** @cond dev*/ /** @cond dev*/
id_type _id(NodeRelation const* C4_RESTRICT nr) const
{
_RYML_CB_ASSERT(m_callbacks, nr == nullptr || (nr >= m_relation && nr < m_relation + m_cap));
return nr ? (id_type)(nr - m_relation) : NONE;
}
#if ! RYML_USE_ASSERT #if ! RYML_USE_ASSERT
C4_ALWAYS_INLINE void _check_next_flags(id_type, type_bits) {} C4_ALWAYS_INLINE void _check_next_flags(id_type, type_bits) {}
#else #else
@@ -1176,7 +1151,7 @@ public:
void _set_parent_as_container_if_needed(id_type node) void _set_parent_as_container_if_needed(id_type node)
{ {
id_type parent = m_relation[node].m_parent; id_type parent = m_parent[node];
if(parent != NONE) if(parent != NONE)
{ {
if( ! (is_seq(parent) || is_map(parent))) if( ! (is_seq(parent) || is_map(parent)))
@@ -1279,9 +1254,9 @@ public:
//m_val[node].clear(); //m_val[node].clear();
//m_val_tag[node].clear(); //m_val_tag[node].clear();
//m_val_anchor[node].clear(); //m_val_anchor[node].clear();
m_relation[node].m_parent = NONE; m_parent[node] = NONE;
m_relation[node].m_first_child = NONE; m_first_child[node] = NONE;
m_relation[node].m_last_child = NONE; m_last_child[node] = NONE;
} }
inline void _clear_key(id_type node) inline void _clear_key(id_type node)
@@ -1324,13 +1299,19 @@ public:
// formerly NodeData // formerly NodeData
NodeType *C4_RESTRICT m_type; NodeType *C4_RESTRICT m_type;
csubstr *C4_RESTRICT m_val; csubstr *C4_RESTRICT m_val;
csubstr *C4_RESTRICT m_val_tag; csubstr *C4_RESTRICT m_val_tag;
csubstr *C4_RESTRICT m_val_anchor; csubstr *C4_RESTRICT m_val_anchor;
csubstr *C4_RESTRICT m_key; csubstr *C4_RESTRICT m_key;
csubstr *C4_RESTRICT m_key_tag; csubstr *C4_RESTRICT m_key_tag;
csubstr *C4_RESTRICT m_key_anchor; csubstr *C4_RESTRICT m_key_anchor;
NodeRelation *C4_RESTRICT m_relation;
id_type *C4_RESTRICT m_parent;
id_type *C4_RESTRICT m_first_child;
id_type *C4_RESTRICT m_last_child;
id_type *C4_RESTRICT m_prev_sibling;
id_type *C4_RESTRICT m_next_sibling;
id_type m_cap; id_type m_cap;
id_type m_size; id_type m_size;

View File

@@ -562,7 +562,7 @@ size_t test_tree_invariants(ConstNodeRef const& n)
ConstNodeRef parent = n.parent(); ConstNodeRef parent = n.parent();
Tree const& t = *n.tree(); Tree const& t = *n.tree();
id_type id = n.id(); id_type id = n.id();
if(t.m_relation[id].m_prev_sibling == NONE) if(t.m_prev_sibling[id] == NONE)
{ {
if(parent.readable()) if(parent.readable())
{ {
@@ -570,7 +570,7 @@ size_t test_tree_invariants(ConstNodeRef const& n)
} }
} }
if(t.m_relation[id].m_next_sibling == NONE) if(t.m_next_sibling[id] == NONE)
{ {
if(parent.readable()) if(parent.readable())
{ {

View File

@@ -867,7 +867,11 @@ TEST(Tree, reserve)
csubstr const* m_key = t.m_key; csubstr const* m_key = t.m_key;
csubstr const* m_key_tag = t.m_key_tag; csubstr const* m_key_tag = t.m_key_tag;
csubstr const* m_key_anchor = t.m_key_anchor; csubstr const* m_key_anchor = t.m_key_anchor;
NodeRelation const* m_relation = t.m_relation; id_type const* m_parent = t.m_parent;
id_type const* m_first_child = t.m_first_child;
id_type const* m_last_child = t.m_last_child;
id_type const* m_prev_sibling = t.m_prev_sibling;
id_type const* m_next_sibling = t.m_next_sibling;
t.reserve(16); t.reserve(16);
t.reserve_arena(64); t.reserve_arena(64);
EXPECT_EQ(t.m_type, m_type); EXPECT_EQ(t.m_type, m_type);
@@ -877,7 +881,11 @@ TEST(Tree, reserve)
EXPECT_EQ(t.m_key, m_key); EXPECT_EQ(t.m_key, m_key);
EXPECT_EQ(t.m_key_tag, m_key_tag); EXPECT_EQ(t.m_key_tag, m_key_tag);
EXPECT_EQ(t.m_key_anchor, m_key_anchor); EXPECT_EQ(t.m_key_anchor, m_key_anchor);
EXPECT_EQ(t.m_relation, m_relation); EXPECT_EQ(t.m_parent, m_parent);
EXPECT_EQ(t.m_first_child, m_first_child);
EXPECT_EQ(t.m_last_child, m_last_child);
EXPECT_EQ(t.m_prev_sibling, m_prev_sibling);
EXPECT_EQ(t.m_next_sibling, m_next_sibling);
EXPECT_EQ(t.capacity(), 16); EXPECT_EQ(t.capacity(), 16);
EXPECT_EQ(t.slack(), 15); EXPECT_EQ(t.slack(), 15);
EXPECT_EQ(t.size(), 1); EXPECT_EQ(t.size(), 1);
@@ -903,7 +911,11 @@ TEST(Tree, reserve)
m_key = t.m_key; m_key = t.m_key;
m_key_tag = t.m_key_tag; m_key_tag = t.m_key_tag;
m_key_anchor = t.m_key_anchor; m_key_anchor = t.m_key_anchor;
m_relation = t.m_relation; m_parent = t.m_parent;
m_first_child = t.m_first_child;
m_last_child = t.m_last_child;
m_prev_sibling = t.m_prev_sibling;
m_next_sibling = t.m_next_sibling;
parse_in_arena("[a, b, c, d, e, f]", &t); parse_in_arena("[a, b, c, d, e, f]", &t);
EXPECT_EQ(t.m_type, m_type); EXPECT_EQ(t.m_type, m_type);
EXPECT_EQ(t.m_val, m_val); EXPECT_EQ(t.m_val, m_val);
@@ -912,7 +924,11 @@ TEST(Tree, reserve)
EXPECT_EQ(t.m_key, m_key); EXPECT_EQ(t.m_key, m_key);
EXPECT_EQ(t.m_key_tag, m_key_tag); EXPECT_EQ(t.m_key_tag, m_key_tag);
EXPECT_EQ(t.m_key_anchor, m_key_anchor); EXPECT_EQ(t.m_key_anchor, m_key_anchor);
EXPECT_EQ(t.m_relation, m_relation); EXPECT_EQ(t.m_parent, m_parent);
EXPECT_EQ(t.m_first_child, m_first_child);
EXPECT_EQ(t.m_last_child, m_last_child);
EXPECT_EQ(t.m_prev_sibling, m_prev_sibling);
EXPECT_EQ(t.m_next_sibling, m_next_sibling);
EXPECT_EQ(t.capacity(), 32); EXPECT_EQ(t.capacity(), 32);
EXPECT_EQ(t.slack(), 25); EXPECT_EQ(t.slack(), 25);
EXPECT_EQ(t.size(), 7); EXPECT_EQ(t.size(), 7);
@@ -986,7 +1002,11 @@ TEST(Tree, clear)
csubstr const* m_key = t.m_key; csubstr const* m_key = t.m_key;
csubstr const* m_key_tag = t.m_key_tag; csubstr const* m_key_tag = t.m_key_tag;
csubstr const* m_key_anchor = t.m_key_anchor; csubstr const* m_key_anchor = t.m_key_anchor;
NodeRelation const* m_relation = t.m_relation; id_type const* m_parent = t.m_parent;
id_type const* m_first_child = t.m_first_child;
id_type const* m_last_child = t.m_last_child;
id_type const* m_prev_sibling = t.m_prev_sibling;
id_type const* m_next_sibling = t.m_next_sibling;
t.reserve(16); t.reserve(16);
t.reserve_arena(64); t.reserve_arena(64);
EXPECT_EQ(t.m_type, m_type); EXPECT_EQ(t.m_type, m_type);
@@ -996,7 +1016,11 @@ TEST(Tree, clear)
EXPECT_EQ(t.m_key, m_key); EXPECT_EQ(t.m_key, m_key);
EXPECT_EQ(t.m_key_tag, m_key_tag); EXPECT_EQ(t.m_key_tag, m_key_tag);
EXPECT_EQ(t.m_key_anchor, m_key_anchor); EXPECT_EQ(t.m_key_anchor, m_key_anchor);
EXPECT_EQ(t.m_relation, m_relation); EXPECT_EQ(t.m_parent, m_parent);
EXPECT_EQ(t.m_first_child, m_first_child);
EXPECT_EQ(t.m_last_child, m_last_child);
EXPECT_EQ(t.m_prev_sibling, m_prev_sibling);
EXPECT_EQ(t.m_next_sibling, m_next_sibling);
EXPECT_EQ(t.capacity(), 16); EXPECT_EQ(t.capacity(), 16);
EXPECT_EQ(t.slack(), 15); EXPECT_EQ(t.slack(), 15);
EXPECT_EQ(t.size(), 1); EXPECT_EQ(t.size(), 1);
@@ -1022,7 +1046,11 @@ TEST(Tree, clear)
m_key = t.m_key; m_key = t.m_key;
m_key_tag = t.m_key_tag; m_key_tag = t.m_key_tag;
m_key_anchor = t.m_key_anchor; m_key_anchor = t.m_key_anchor;
m_relation = t.m_relation; m_parent = t.m_parent;
m_first_child = t.m_first_child;
m_last_child = t.m_last_child;
m_prev_sibling = t.m_prev_sibling;
m_next_sibling = t.m_next_sibling;
parse_in_arena("[a, b, c, d, e, f]", &t); parse_in_arena("[a, b, c, d, e, f]", &t);
EXPECT_EQ(t.m_type, m_type); EXPECT_EQ(t.m_type, m_type);
EXPECT_EQ(t.m_val, m_val); EXPECT_EQ(t.m_val, m_val);
@@ -1031,7 +1059,11 @@ TEST(Tree, clear)
EXPECT_EQ(t.m_key, m_key); EXPECT_EQ(t.m_key, m_key);
EXPECT_EQ(t.m_key_tag, m_key_tag); EXPECT_EQ(t.m_key_tag, m_key_tag);
EXPECT_EQ(t.m_key_anchor, m_key_anchor); EXPECT_EQ(t.m_key_anchor, m_key_anchor);
EXPECT_EQ(t.m_relation, m_relation); EXPECT_EQ(t.m_parent, m_parent);
EXPECT_EQ(t.m_first_child, m_first_child);
EXPECT_EQ(t.m_last_child, m_last_child);
EXPECT_EQ(t.m_prev_sibling, m_prev_sibling);
EXPECT_EQ(t.m_next_sibling, m_next_sibling);
EXPECT_EQ(t.capacity(), 32); EXPECT_EQ(t.capacity(), 32);
EXPECT_EQ(t.slack(), 25); EXPECT_EQ(t.slack(), 25);
EXPECT_EQ(t.size(), 7); EXPECT_EQ(t.size(), 7);