diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index 5931826..67d89d7 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -32,7 +32,7 @@ struct get_idx& sequence, const Key& key, shared_memory_holder pMemory) { - if (key > sequence.size() || (key > 0 && !sequence[key-1]->is_defined())) + if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined())) return 0; if (key == sequence.size()) sequence.push_back(&pMemory->create_node()); @@ -56,6 +56,41 @@ struct get_idx::value>::type> { } }; +template +struct remove_idx { + static char remove(std::vector& /* sequence */, const Key& /* key */) { + return 0; + } +}; + +template +struct remove_idx< + Key, typename std::enable_if::value && + !std::is_same::value>::type> { + + static char remove(std::vector& sequence, const Key& key) { + if (key >= sequence.size() || !sequence[key]->is_defined()) + return 0; + if (key + 1 == sequence.size()) { + sequence.pop_back(); + return 1; + } + + return 2; + } +}; + +template +struct remove_idx::value>::type> { + + static char remove(std::vector& sequence, const Key& key) { + return key >= 0 ? remove_idx::remove( + sequence, static_cast(key)) + : 0; + } +}; + template inline bool node::equals(const T& rhs, shared_memory_holder pMemory) { T lhs; @@ -129,24 +164,31 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) { template inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { - if (m_type != NodeType::Map) - return false; - - kv_pairs::iterator it = m_undefinedPairs.begin(); - while (it != m_undefinedPairs.end()) { - kv_pairs::iterator jt = std::next(it); - if (it->first->equals(key, pMemory)) - m_undefinedPairs.erase(it); - it = jt; - } - - for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { - if (it->first->equals(key, pMemory)) { - m_map.erase(it); + if (m_type == NodeType::Sequence) { + char result = remove_idx::remove(m_sequence, key); + if (result == 0) + return false; + if (result == 1) return true; + convert_to_map(pMemory); + } + if (m_type == NodeType::Map) { + + kv_pairs::iterator it = m_undefinedPairs.begin(); + while (it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = std::next(it); + if (it->first->equals(key, pMemory)) + m_undefinedPairs.erase(it); + it = jt; + } + + for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (it->first->equals(key, pMemory)) { + m_map.erase(it); + return true; + } } } - return false; } diff --git a/src/node_data.cpp b/src/node_data.cpp index 77cd465..2dfcd7b 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -235,6 +235,14 @@ bool node_data::remove(node& key, shared_memory_holder /* pMemory */) { if (m_type != NodeType::Map) return false; + kv_pairs::iterator it = m_undefinedPairs.begin(); + while (it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = std::next(it); + if (it->first->is(key)) + m_undefinedPairs.erase(it); + it = jt; + } + for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { if (it->first->is(key)) { m_map.erase(it); diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 485ad09..a513b55 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -47,6 +47,30 @@ TEST(NodeTest, SimpleAppendSequence) { EXPECT_TRUE(node.IsSequence()); } +TEST(NodeTest, SequenceElementRemoval) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + node.remove(1); + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(2, node.size()); + EXPECT_EQ("a", node[0].as()); + EXPECT_EQ("c", node[2].as()); +} + +TEST(NodeTest, SequenceLastElementRemoval) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + node.remove(2); + EXPECT_TRUE(node.IsSequence()); + EXPECT_EQ(2, node.size()); + EXPECT_EQ("a", node[0].as()); + EXPECT_EQ("b", node[1].as()); +} + TEST(NodeTest, MapElementRemoval) { Node node; node["foo"] = "bar"; @@ -106,6 +130,14 @@ TEST(NodeTest, RemoveUnassignedNode) { EXPECT_EQ(0, node.size()); } +TEST(NodeTest, RemoveUnassignedNodeFromMap) { + Node node(NodeType::Map); + Node n; + node[n]; + node.remove(n); + EXPECT_EQ(0, node.size()); +} + TEST(NodeTest, MapForceInsert) { Node node; Node k1("k1");