Skip to content

Commit ff4bb63

Browse files
committed
Tree::duplicate_no_rep(): improve naming, add debug logs
1 parent 8d56f59 commit ff4bb63

3 files changed

Lines changed: 53 additions & 19 deletions

File tree

src/c4/yml/reference_resolver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ void ReferenceResolver::resolve_()
240240
_RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->has_key_anchor(refdata.target) || m_tree->has_val_anchor(refdata.target));
241241
if(m_tree->has_val_anchor(refdata.target) && m_tree->val_anchor(refdata.target) == m_tree->key_ref(refdata.node))
242242
{
243+
_c4dbgpf("instance[{}:node{}] target.anchor==val.anchor=={}", i, refdata.node, m_tree->val_anchor(refdata.target));
243244
_RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
244245
_RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
245246
const type_bits existing_style_flags = VAL_STYLE & m_tree->_p(refdata.target)->m_type.type;
@@ -249,6 +250,7 @@ void ReferenceResolver::resolve_()
249250
}
250251
else
251252
{
253+
_c4dbgpf("instance[{}:node{}] don't inherit container flags", i, refdata.node);
252254
_RYML_CB_CHECK(m_tree->m_callbacks, m_tree->key_anchor(refdata.target) == m_tree->key_ref(refdata.node));
253255
m_tree->_p(refdata.node)->m_key.scalar = m_tree->key(refdata.target);
254256
// keys cannot be containers, so don't inherit container flags
@@ -262,6 +264,7 @@ void ReferenceResolver::resolve_()
262264
_RYML_CB_ASSERT(m_tree->m_callbacks, refdata.type.is_val_ref());
263265
if(m_tree->has_key_anchor(refdata.target) && m_tree->key_anchor(refdata.target) == m_tree->val_ref(refdata.node))
264266
{
267+
_c4dbgpf("instance[{}:node{}] target.anchor==key.anchor=={}", i, refdata.node, m_tree->val_anchor(refdata.target));
265268
_RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
266269
_RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
267270
// keys cannot be containers, so don't inherit container flags
@@ -272,6 +275,7 @@ void ReferenceResolver::resolve_()
272275
}
273276
else
274277
{
278+
_c4dbgpf("instance[{}:node{}] duplicate contents", i, refdata.node);
275279
m_tree->duplicate_contents(refdata.target, refdata.node);
276280
}
277281
}

src/c4/yml/tree.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -984,49 +984,59 @@ id_type Tree::duplicate_children_no_rep(Tree const *src, id_type node, id_type p
984984
_RYML_CB_CHECK(m_callbacks, this != src || (parent != i && !is_ancestor(parent, i)));
985985
if(is_seq(parent))
986986
{
987-
prev = duplicate(i, parent, prev);
987+
_c4dbgpf("duplicate_no_rep: {} is seq", parent);
988+
prev = duplicate(src, i, parent, prev);
988989
}
989990
else
990991
{
992+
_c4dbgpf("duplicate_no_rep: {} is map", parent);
991993
_RYML_CB_ASSERT(m_callbacks, is_map(parent));
992994
// does the parent already have a node with key equal to that of the current duplicate?
993-
id_type rep = NONE, rep_pos = NONE;
994-
for(id_type j = first_child(parent), jcount = 0; j != NONE; ++jcount, j = next_sibling(j))
995+
id_type dstnode_dup = NONE, dstnode_dup_pos = NONE;
995996
{
996-
if(key(j) == key(i))
997+
csubstr srckey = src->key(i);
998+
for(id_type j = first_child(parent), jcount = 0; j != NONE; ++jcount, j = next_sibling(j))
997999
{
998-
rep = j;
999-
rep_pos = jcount;
1000-
break;
1000+
if(key(j) == srckey)
1001+
{
1002+
_c4dbgpf("duplicate_no_rep: found matching key '{}' src={}/{} dst={}/{}", srckey, node, i, parent, j);
1003+
dstnode_dup = j;
1004+
dstnode_dup_pos = jcount;
1005+
break;
1006+
}
10011007
}
10021008
}
1003-
if(rep == NONE) // there is no repetition; just duplicate
1009+
_c4dbgpf("duplicate_no_rep: dstnode_dup={} dstnode_dup_pos={} after_pos={}", dstnode_dup, dstnode_dup_pos, after_pos);
1010+
if(dstnode_dup == NONE) // there is no repetition; just duplicate
10041011
{
10051012
_c4dbgpf("duplicate_no_rep: no repetition, just duplicate i={} parent={} prev={}", i, parent, prev);
10061013
prev = duplicate(src, i, parent, prev);
10071014
}
10081015
else // yes, there is a repetition
10091016
{
1010-
if(after_pos != NONE && rep_pos < after_pos)
1017+
if(after_pos != NONE && dstnode_dup_pos < after_pos)
10111018
{
1012-
// rep is located before the node which will be inserted,
1019+
// the dst duplicate is located before the node which will be inserted,
10131020
// and will be overridden by the duplicate. So replace it.
1014-
remove(rep);
1021+
_c4dbgpf("duplicate_no_dstnode_dup: replace {}/{} with {}/{}", parent, dstnode_dup, node, i);
1022+
remove(dstnode_dup);
10151023
prev = duplicate(src, i, parent, prev);
10161024
}
10171025
else if(prev == NONE)
10181026
{
1019-
// first iteration with prev = after = NONE and repetition
1020-
prev = rep;
1027+
_c4dbgpf("duplicate_no_dstnode_dup: {}=prev <- {}", prev, dstnode_dup);
1028+
// first iteration with prev = after = NONE and dstnode_dupetition
1029+
prev = dstnode_dup;
10211030
}
1022-
else if(rep != prev)
1031+
else if(dstnode_dup != prev)
10231032
{
1024-
// rep is located after the node which will be inserted
1025-
// and overrides it. So move the rep into this node's place.
1026-
move(rep, prev);
1027-
prev = rep;
1033+
// dstnode_dup is located after the node which will be inserted
1034+
// and overrides it. So move the dstnode_dup into this node's place.
1035+
_c4dbgpf("duplicate_no_dstnode_dup: move({}, {})", dstnode_dup, prev);
1036+
move(dstnode_dup, prev);
1037+
prev = dstnode_dup;
10281038
}
1029-
} // there's a repetition
1039+
} // there's a dstnode_dupetition
10301040
}
10311041
}
10321042

test/test_anchor.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,26 @@ top5: &anchor5
553553
ASSERT_EQ(t["top62"]["key62"].has_key_anchor(), false);
554554
}
555555

556+
TEST(simple_anchor, merge_seqs)
557+
{
558+
const Tree src = parse_in_arena(R"([0, 1])");
559+
{
560+
Tree dst = parse_in_arena(R"([2, 3])");
561+
dst.duplicate_children_no_rep(&src, 0, 0, NONE);
562+
EXPECT_EQ(emitrs_yaml<std::string>(dst), "[0,1,2,3]");
563+
}
564+
{
565+
Tree dst = parse_in_arena(R"([2, 3])");
566+
dst.duplicate_children_no_rep(&src, 0, 0, 1);
567+
EXPECT_EQ(emitrs_yaml<std::string>(dst), "[2,0,1,3]");
568+
}
569+
{
570+
Tree dst = parse_in_arena(R"([2, 3])");
571+
dst.duplicate_children_no_rep(&src, 0, 0, 2);
572+
EXPECT_EQ(emitrs_yaml<std::string>(dst), "[2,3,0,1]");
573+
}
574+
}
575+
556576
TEST(simple_anchor, issue_400)
557577
{
558578
csubstr yaml = R"(

0 commit comments

Comments
 (0)