mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 04:41:16 +00:00
implement convert for standard library containers allowing for custom allocators (#855)
This commit is contained in:
@@ -193,17 +193,17 @@ struct convert<bool> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// std::map
|
// std::map
|
||||||
template <typename K, typename V>
|
template <typename K, typename V, typename C, typename A>
|
||||||
struct convert<std::map<K, V>> {
|
struct convert<std::map<K, V, C, A>> {
|
||||||
static Node encode(const std::map<K, V>& rhs) {
|
static Node encode(const std::map<K, V, C, A>& rhs) {
|
||||||
Node node(NodeType::Map);
|
Node node(NodeType::Map);
|
||||||
for (typename std::map<K, V>::const_iterator it = rhs.begin();
|
for (typename std::map<K, V, C, A>::const_iterator it = rhs.begin();
|
||||||
it != rhs.end(); ++it)
|
it != rhs.end(); ++it)
|
||||||
node.force_insert(it->first, it->second);
|
node.force_insert(it->first, it->second);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode(const Node& node, std::map<K, V>& rhs) {
|
static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
|
||||||
if (!node.IsMap())
|
if (!node.IsMap())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -220,17 +220,17 @@ struct convert<std::map<K, V>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// std::vector
|
// std::vector
|
||||||
template <typename T>
|
template <typename T, typename A>
|
||||||
struct convert<std::vector<T>> {
|
struct convert<std::vector<T, A>> {
|
||||||
static Node encode(const std::vector<T>& rhs) {
|
static Node encode(const std::vector<T, A>& rhs) {
|
||||||
Node node(NodeType::Sequence);
|
Node node(NodeType::Sequence);
|
||||||
for (typename std::vector<T>::const_iterator it = rhs.begin();
|
for (typename std::vector<T, A>::const_iterator it = rhs.begin();
|
||||||
it != rhs.end(); ++it)
|
it != rhs.end(); ++it)
|
||||||
node.push_back(*it);
|
node.push_back(*it);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode(const Node& node, std::vector<T>& rhs) {
|
static bool decode(const Node& node, std::vector<T, A>& rhs) {
|
||||||
if (!node.IsSequence())
|
if (!node.IsSequence())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -247,17 +247,17 @@ struct convert<std::vector<T>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// std::list
|
// std::list
|
||||||
template <typename T>
|
template <typename T, typename A>
|
||||||
struct convert<std::list<T>> {
|
struct convert<std::list<T,A>> {
|
||||||
static Node encode(const std::list<T>& rhs) {
|
static Node encode(const std::list<T,A>& rhs) {
|
||||||
Node node(NodeType::Sequence);
|
Node node(NodeType::Sequence);
|
||||||
for (typename std::list<T>::const_iterator it = rhs.begin();
|
for (typename std::list<T,A>::const_iterator it = rhs.begin();
|
||||||
it != rhs.end(); ++it)
|
it != rhs.end(); ++it)
|
||||||
node.push_back(*it);
|
node.push_back(*it);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode(const Node& node, std::list<T>& rhs) {
|
static bool decode(const Node& node, std::list<T,A>& rhs) {
|
||||||
if (!node.IsSequence())
|
if (!node.IsSequence())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@@ -11,6 +11,38 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// malloc/free based allocator just for testing custom allocators on stl containers
|
||||||
|
template <class T>
|
||||||
|
class CustomAllocator : public std::allocator<T> {
|
||||||
|
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<class U> struct rebind { typedef CustomAllocator<U> other; };
|
||||||
|
CustomAllocator() : std::allocator<T>() {}
|
||||||
|
CustomAllocator(const CustomAllocator& other) : std::allocator<T>(other) {}
|
||||||
|
template<class U> CustomAllocator(const CustomAllocator<U>& other) : std::allocator<T>(other) {}
|
||||||
|
~CustomAllocator() {}
|
||||||
|
size_type max_size() const { return (std::numeric_limits<std::ptrdiff_t>::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<pointer>(malloc(num * sizeof(T)));
|
||||||
|
}
|
||||||
|
void deallocate(pointer p, size_type /*num*/) { free(p); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> using CustomVector = std::vector<T,CustomAllocator<T>>;
|
||||||
|
template <class T> using CustomList = std::list<T,CustomAllocator<T>>;
|
||||||
|
template <class K, class V, class C=std::less<K>> using CustomMap = std::map<K,V,C,CustomAllocator<std::pair<const K,V>>>;
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
using ::testing::AnyOf;
|
using ::testing::AnyOf;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
|
|
||||||
@@ -333,6 +365,20 @@ TEST(NodeTest, StdVector) {
|
|||||||
EXPECT_EQ(primes, node["primes"].as<std::vector<int>>());
|
EXPECT_EQ(primes, node["primes"].as<std::vector<int>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, StdVectorWithCustomAllocator) {
|
||||||
|
CustomVector<int> 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<CustomVector<int>>());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(NodeTest, StdList) {
|
TEST(NodeTest, StdList) {
|
||||||
std::list<int> primes;
|
std::list<int> primes;
|
||||||
primes.push_back(2);
|
primes.push_back(2);
|
||||||
@@ -347,6 +393,20 @@ TEST(NodeTest, StdList) {
|
|||||||
EXPECT_EQ(primes, node["primes"].as<std::list<int>>());
|
EXPECT_EQ(primes, node["primes"].as<std::list<int>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, StdListWithCustomAllocator) {
|
||||||
|
CustomList<int> 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<CustomList<int>>());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(NodeTest, StdMap) {
|
TEST(NodeTest, StdMap) {
|
||||||
std::map<int, int> squares;
|
std::map<int, int> squares;
|
||||||
squares[0] = 0;
|
squares[0] = 0;
|
||||||
@@ -361,6 +421,20 @@ TEST(NodeTest, StdMap) {
|
|||||||
EXPECT_EQ(squares, actualSquares);
|
EXPECT_EQ(squares, actualSquares);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, StdMapWithCustomAllocator) {
|
||||||
|
CustomMap<int,int> squares;
|
||||||
|
squares[0] = 0;
|
||||||
|
squares[1] = 1;
|
||||||
|
squares[2] = 4;
|
||||||
|
squares[3] = 9;
|
||||||
|
squares[4] = 16;
|
||||||
|
|
||||||
|
Node node;
|
||||||
|
node["squares"] = squares;
|
||||||
|
CustomMap<int,int> actualSquares = node["squares"].as<CustomMap<int,int>>();
|
||||||
|
EXPECT_EQ(squares, actualSquares);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(NodeTest, StdPair) {
|
TEST(NodeTest, StdPair) {
|
||||||
std::pair<int, std::string> p;
|
std::pair<int, std::string> p;
|
||||||
p.first = 5;
|
p.first = 5;
|
||||||
|
Reference in New Issue
Block a user