From 9fb51534877d16597cfd94c18890d87af0879d65 Mon Sep 17 00:00:00 2001 From: Ian Taylor Date: Wed, 29 Apr 2020 19:29:33 -0400 Subject: [PATCH] implement convert for standard library containers allowing for custom allocators (#855) --- include/yaml-cpp/node/convert.h | 30 ++++++------- test/node/node_test.cpp | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 15 deletions(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 4e3ff6a..d6bd365 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -193,17 +193,17 @@ struct convert { }; // std::map -template -struct convert> { - static Node encode(const std::map& rhs) { +template +struct convert> { + static Node encode(const std::map& rhs) { Node node(NodeType::Map); - for (typename std::map::const_iterator it = rhs.begin(); + for (typename std::map::const_iterator it = rhs.begin(); it != rhs.end(); ++it) node.force_insert(it->first, it->second); return node; } - static bool decode(const Node& node, std::map& rhs) { + static bool decode(const Node& node, std::map& rhs) { if (!node.IsMap()) return false; @@ -220,17 +220,17 @@ struct convert> { }; // std::vector -template -struct convert> { - static Node encode(const std::vector& rhs) { +template +struct convert> { + static Node encode(const std::vector& rhs) { Node node(NodeType::Sequence); - for (typename std::vector::const_iterator it = rhs.begin(); + for (typename std::vector::const_iterator it = rhs.begin(); it != rhs.end(); ++it) node.push_back(*it); return node; } - static bool decode(const Node& node, std::vector& rhs) { + static bool decode(const Node& node, std::vector& rhs) { if (!node.IsSequence()) return false; @@ -247,17 +247,17 @@ struct convert> { }; // std::list -template -struct convert> { - static Node encode(const std::list& rhs) { +template +struct convert> { + static Node encode(const std::list& rhs) { Node node(NodeType::Sequence); - for (typename std::list::const_iterator it = rhs.begin(); + for (typename std::list::const_iterator it = rhs.begin(); it != rhs.end(); ++it) node.push_back(*it); return node; } - static bool decode(const Node& node, std::list& rhs) { + static bool decode(const Node& node, std::list& rhs) { if (!node.IsSequence()) return false; diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index f6106bd..4f577c8 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -11,6 +11,38 @@ #include +namespace { + +// malloc/free based allocator just for testing custom allocators on stl containers +template +class CustomAllocator : public std::allocator { + public: + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template struct rebind { typedef CustomAllocator other; }; + CustomAllocator() : std::allocator() {} + CustomAllocator(const CustomAllocator& other) : std::allocator(other) {} + template CustomAllocator(const CustomAllocator& other) : std::allocator(other) {} + ~CustomAllocator() {} + size_type max_size() const { return (std::numeric_limits::max)()/sizeof(T); } + pointer allocate(size_type num, const void* /*hint*/ = 0) { + if (num > std::size_t(-1) / sizeof(T)) throw std::bad_alloc(); + return static_cast(malloc(num * sizeof(T))); + } + void deallocate(pointer p, size_type /*num*/) { free(p); } +}; + +template using CustomVector = std::vector>; +template using CustomList = std::list>; +template > using CustomMap = std::map>>; + +} // anonymous namespace + using ::testing::AnyOf; using ::testing::Eq; @@ -333,6 +365,20 @@ TEST(NodeTest, StdVector) { EXPECT_EQ(primes, node["primes"].as>()); } +TEST(NodeTest, StdVectorWithCustomAllocator) { + CustomVector primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + Node node; + node["primes"] = primes; + EXPECT_EQ(primes, node["primes"].as>()); +} + TEST(NodeTest, StdList) { std::list primes; primes.push_back(2); @@ -347,6 +393,20 @@ TEST(NodeTest, StdList) { EXPECT_EQ(primes, node["primes"].as>()); } +TEST(NodeTest, StdListWithCustomAllocator) { + CustomList primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + Node node; + node["primes"] = primes; + EXPECT_EQ(primes, node["primes"].as>()); +} + TEST(NodeTest, StdMap) { std::map squares; squares[0] = 0; @@ -361,6 +421,20 @@ TEST(NodeTest, StdMap) { EXPECT_EQ(squares, actualSquares); } +TEST(NodeTest, StdMapWithCustomAllocator) { + CustomMap squares; + squares[0] = 0; + squares[1] = 1; + squares[2] = 4; + squares[3] = 9; + squares[4] = 16; + + Node node; + node["squares"] = squares; + CustomMap actualSquares = node["squares"].as>(); + EXPECT_EQ(squares, actualSquares); +} + TEST(NodeTest, StdPair) { std::pair p; p.first = 5;