Skip to content

Commit 39001bc

Browse files
committed
Reimplement merge key support in detail::node.
1 parent 3a8ca56 commit 39001bc

2 files changed

Lines changed: 33 additions & 31 deletions

File tree

include/yaml-cpp/node/detail/node.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,48 @@ class node : private boost::noncopyable {
112112
value.add_dependency(*this);
113113
}
114114

115+
template <typename Key>
116+
inline node* GetValueFromMergeKey(const Key& key, node* currentValue,
117+
shared_memory_holder pMemory) const {
118+
node* mergeValue =
119+
static_cast<const node_ref&>(*m_pRef).get(to_value("<<"), pMemory);
120+
if (mergeValue) {
121+
if (mergeValue->type() == NodeType::Map) {
122+
return &mergeValue->get(key, pMemory);
123+
} else if (mergeValue->type() == NodeType::Sequence) {
124+
for (const_node_iterator it = mergeValue->begin();
125+
it != mergeValue->end(); ++it) {
126+
if (it->pNode && it->pNode->type() == NodeType::Map) {
127+
node* value = it->pNode->get(key, pMemory);
128+
if (value && value->type() != NodeType::Undefined) {
129+
return value;
130+
}
131+
}
132+
}
133+
}
134+
}
135+
return currentValue;
136+
}
137+
115138
// indexing
116139
template <typename Key>
117140
node* get(const Key& key, shared_memory_holder pMemory) const {
118141
// NOTE: this returns a non-const node so that the top-level Node can wrap
119142
// it, and returns a pointer so that it can be NULL (if there is no such
120143
// key).
121-
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
144+
node* value = static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
145+
if (!value || value->type() == NodeType::Undefined) {
146+
return GetValueFromMergeKey(key, value, pMemory);
147+
}
148+
return value;
122149
}
123150
template <typename Key>
124151
node& get(const Key& key, shared_memory_holder pMemory) {
125152
node& value = m_pRef->get(key, pMemory);
126153
value.add_dependency(*this);
154+
if (value.type() == NodeType::Undefined) {
155+
return *GetValueFromMergeKey(key, &value, pMemory);
156+
}
127157
return value;
128158
}
129159
template <typename Key>

include/yaml-cpp/node/impl.h

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,8 @@ inline const Node Node::operator[](const Key& key) const {
369369
EnsureNodeExists();
370370
detail::node* value = static_cast<const detail::node&>(*m_pNode)
371371
.get(detail::to_value(key), m_pMemory);
372-
if (!value || value->type() == NodeType::Undefined) {
373-
return GetValueFromMergeKey(key, value);
372+
if (!value) {
373+
return Node(ZombieNode);
374374
}
375375
return Node(*value, m_pMemory);
376376
}
@@ -381,37 +381,9 @@ inline Node Node::operator[](const Key& key) {
381381
throw InvalidNode();
382382
EnsureNodeExists();
383383
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
384-
if (value.type() == NodeType::Undefined) {
385-
return GetValueFromMergeKey(key, &value);
386-
}
387384
return Node(value, m_pMemory);
388385
}
389386

390-
template <typename Key>
391-
inline Node Node::GetValueFromMergeKey(const Key& key,
392-
detail::node* currentValue) const {
393-
detail::node* mergeValue = static_cast<const detail::node&>(*m_pNode)
394-
.get(detail::to_value("<<"), m_pMemory);
395-
if (mergeValue && mergeValue->type() != NodeType::Undefined) {
396-
Node mergeNode(*mergeValue, m_pMemory);
397-
// Merge keys are used with maps and sequences of maps. Aliases may be used,
398-
// but yaml-cpp resolves them automatically.
399-
if (mergeNode.IsMap()) {
400-
return mergeNode[key];
401-
} else if (mergeNode.IsSequence()) {
402-
for (const_iterator it = mergeNode.begin(); it != mergeNode.end(); ++it) {
403-
if (it->IsMap() && (*it)[key]) {
404-
return (*it)[key];
405-
}
406-
}
407-
}
408-
}
409-
if (!currentValue) {
410-
return Node(ZombieNode);
411-
}
412-
return Node(*currentValue, m_pMemory);
413-
}
414-
415387
template <typename Key>
416388
inline bool Node::remove(const Key& key) {
417389
if (!m_isValid)

0 commit comments

Comments
 (0)