Fix merge-key handling in case the dictionary contains a sub-dictionary
This commit is contained in:
parent
6bbc603b22
commit
629297180d
@ -70,6 +70,7 @@ void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
|
|||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
node.set_style(style);
|
node.set_style(style);
|
||||||
m_mapDepth++;
|
m_mapDepth++;
|
||||||
|
m_mergeDicts.emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeMapCollection(detail::node& map_to, detail::node& map_from,
|
void MergeMapCollection(detail::node& map_to, detail::node& map_from,
|
||||||
@ -86,11 +87,12 @@ void MergeMapCollection(detail::node& map_to, detail::node& map_from,
|
|||||||
void NodeBuilder::OnMapEnd() {
|
void NodeBuilder::OnMapEnd() {
|
||||||
assert(m_mapDepth > 0);
|
assert(m_mapDepth > 0);
|
||||||
detail::node& collection = *m_stack.back();
|
detail::node& collection = *m_stack.back();
|
||||||
for (detail::node* n : m_mergeDicts) {
|
auto& toMerge = *m_mergeDicts.rbegin();
|
||||||
|
for (detail::node* n : toMerge) {
|
||||||
MergeMapCollection(collection, *n, m_pMemory);
|
MergeMapCollection(collection, *n, m_pMemory);
|
||||||
}
|
}
|
||||||
m_mergeDicts.clear();
|
|
||||||
m_mapDepth--;
|
m_mapDepth--;
|
||||||
|
m_mergeDicts.pop_back();
|
||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,13 +137,13 @@ void NodeBuilder::Pop() {
|
|||||||
((nk.tag() == "tag:yaml.org,2002:merge" && nk.scalar() == "<<") ||
|
((nk.tag() == "tag:yaml.org,2002:merge" && nk.scalar() == "<<") ||
|
||||||
(nk.tag() == "?" && nk.scalar() == "<<"))) {
|
(nk.tag() == "?" && nk.scalar() == "<<"))) {
|
||||||
if (node.type() == NodeType::Map) {
|
if (node.type() == NodeType::Map) {
|
||||||
m_mergeDicts.emplace_back(&node);
|
m_mergeDicts.rbegin()->emplace_back(&node);
|
||||||
m_keys.pop_back();
|
m_keys.pop_back();
|
||||||
} else if (node.type() == NodeType::Sequence) {
|
} else if (node.type() == NodeType::Sequence) {
|
||||||
for (auto i = node.begin(); i != node.end(); i++) {
|
for (auto i = node.begin(); i != node.end(); i++) {
|
||||||
auto v = *i;
|
auto v = *i;
|
||||||
if ((*v).type() == NodeType::Map) {
|
if ((*v).type() == NodeType::Map) {
|
||||||
m_mergeDicts.emplace_back(&(*v));
|
m_mergeDicts.rbegin()->emplace_back(&(*v));
|
||||||
} else {
|
} else {
|
||||||
throw ParserException(
|
throw ParserException(
|
||||||
node.mark(),
|
node.mark(),
|
||||||
|
|||||||
@ -67,7 +67,7 @@ class NodeBuilder : public EventHandler {
|
|||||||
|
|
||||||
using PushedKey = std::pair<detail::node*, bool>;
|
using PushedKey = std::pair<detail::node*, bool>;
|
||||||
std::vector<PushedKey> m_keys;
|
std::vector<PushedKey> m_keys;
|
||||||
Nodes m_mergeDicts;
|
std::vector<Nodes> m_mergeDicts;
|
||||||
std::size_t m_mapDepth;
|
std::size_t m_mapDepth;
|
||||||
};
|
};
|
||||||
} // namespace YAML
|
} // namespace YAML
|
||||||
|
|||||||
@ -188,7 +188,7 @@ TEST(LoadNodeTest, MergeKeyB) {
|
|||||||
Node node = Load(
|
Node node = Load(
|
||||||
"{x: &foo {a : 1,b : 1,c : 1}, y: &bar {d: 2, e : 2, f : 2, a : 2}, z: "
|
"{x: &foo {a : 1,b : 1,c : 1}, y: &bar {d: 2, e : 2, f : 2, a : 2}, z: "
|
||||||
"&stuff { << : *foo, b : 3}, w: { << : [*stuff, *bar], c: 4 }, v: { '<<' "
|
"&stuff { << : *foo, b : 3}, w: { << : [*stuff, *bar], c: 4 }, v: { '<<' "
|
||||||
": *foo } , u : {!!merge << : *bar} }");
|
": *foo } , u : {!!merge << : *bar}, t: {!!merge << : *bar, h: 3} }");
|
||||||
EXPECT_EQ(NodeType::Map, node["z"].Type());
|
EXPECT_EQ(NodeType::Map, node["z"].Type());
|
||||||
EXPECT_EQ(NodeType::Map, node["w"].Type());
|
EXPECT_EQ(NodeType::Map, node["w"].Type());
|
||||||
EXPECT_FALSE(node["z"]["<<"]);
|
EXPECT_FALSE(node["z"]["<<"]);
|
||||||
@ -208,6 +208,10 @@ TEST(LoadNodeTest, MergeKeyB) {
|
|||||||
|
|
||||||
EXPECT_FALSE(node["u"]["<<"]);
|
EXPECT_FALSE(node["u"]["<<"]);
|
||||||
EXPECT_EQ(2, node["u"]["d"].as<int>());
|
EXPECT_EQ(2, node["u"]["d"].as<int>());
|
||||||
|
|
||||||
|
EXPECT_FALSE(node["t"]["<<"]);
|
||||||
|
EXPECT_EQ(2, node["t"]["d"].as<int>());
|
||||||
|
EXPECT_EQ(3, node["t"]["h"].as<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LoadNodeTest, ForceInsertIntoMap) {
|
TEST(LoadNodeTest, ForceInsertIntoMap) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user