Skip to content

Commit

Permalink
Enable items to be removed from a sequence (#582)
Browse files Browse the repository at this point in the history
  • Loading branch information
StarJiao authored and jbeder committed May 14, 2018
1 parent ab5f925 commit 4fb1c4b
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1 +1,2 @@
build/
/tags
63 changes: 48 additions & 15 deletions include/yaml-cpp/node/detail/impl.h
Expand Up @@ -32,7 +32,7 @@ struct get_idx<Key,

static node* get(std::vector<node*>& 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());
Expand All @@ -56,6 +56,37 @@ struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
}
};

template <typename Key, typename Enable = void>
struct remove_idx {
static bool remove(std::vector<node*>&, const Key&) { return false; }
};

template <typename Key>
struct remove_idx<
Key, typename std::enable_if<std::is_unsigned<Key>::value &&
!std::is_same<Key, bool>::value>::type> {

static bool remove(std::vector<node*>& sequence, const Key& key) {
if (key >= sequence.size()) {
return false;
} else {
sequence.erase(sequence.begin() + key);
return true;
}
}
};

template <typename Key>
struct remove_idx<Key,
typename std::enable_if<std::is_signed<Key>::value>::type> {

static bool remove(std::vector<node*>& sequence, const Key& key) {
return key >= 0 ? remove_idx<std::size_t>::remove(
sequence, static_cast<std::size_t>(key))
: false;
}
};

template <typename T>
inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
T lhs;
Expand Down Expand Up @@ -129,21 +160,23 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {

template <typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
if (m_type != NodeType::Map)
return false;

for (kv_pairs::iterator it = m_undefinedPairs.begin();
it != m_undefinedPairs.end();) {
kv_pairs::iterator jt = std::next(it);
if (it->first->equals(key, pMemory))
m_undefinedPairs.erase(it);
it = jt;
}
if (m_type == NodeType::Sequence) {
return remove_idx<Key>::remove(m_sequence, key);
} else 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;
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;
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/node_data.cpp
Expand Up @@ -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);
Expand Down
48 changes: 45 additions & 3 deletions test/node/node_test.cpp
@@ -1,10 +1,10 @@
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/detail/impl.h"
#include "yaml-cpp/node/emit.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/detail/impl.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
Expand Down Expand Up @@ -47,13 +47,47 @@ 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.IsSequence());
EXPECT_EQ(2, node.size());
EXPECT_EQ("a", node[0].as<std::string>());
EXPECT_EQ("c", node[1].as<std::string>());
}

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<std::string>());
EXPECT_EQ("b", node[1].as<std::string>());
}

TEST(NodeTest, MapElementRemoval) {
Node node;
node["foo"] = "bar";
node.remove("foo");
EXPECT_TRUE(!node["foo"]);
}

TEST(NodeTest, MapIntegerElementRemoval) {
Node node;
node[1] = "hello";
node[2] = 'c';
node["foo"] = "bar";
EXPECT_TRUE(node.IsMap());
node.remove(1);
EXPECT_TRUE(node.IsMap());
}

TEST(NodeTest, SimpleAssignSequence) {
Node node;
node[0] = 10;
Expand Down Expand Up @@ -106,6 +140,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");
Expand Down
2 changes: 2 additions & 0 deletions util/CMakeLists.txt
@@ -1,3 +1,5 @@
cmake_minimum_required(VERSION 3.5)

add_sources(parse.cpp)
add_executable(parse parse.cpp)
target_link_libraries(parse yaml-cpp)
Expand Down

1 comment on commit 4fb1c4b

@DDRDmakar
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YAY !!

Please sign in to comment.