Merge a54ac25254 into eaf7205372
This commit is contained in:
commit
ec02fb0b85
@ -15,6 +15,11 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||||
|
#include <optional>
|
||||||
|
#define YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
inline Node::Node()
|
inline Node::Node()
|
||||||
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
|
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
|
||||||
@ -88,6 +93,18 @@ inline NodeType::value Node::Type() const {
|
|||||||
// access
|
// access
|
||||||
|
|
||||||
// template helpers
|
// template helpers
|
||||||
|
#ifdef YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct decode_dispatcher {
|
||||||
|
static std::optional<T> dispatch(const Node& node) {
|
||||||
|
T t;
|
||||||
|
if (convert<T>::decode(node, t))
|
||||||
|
return {t};
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
struct as_if {
|
struct as_if {
|
||||||
explicit as_if(const Node& node_) : node(node_) {}
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
@ -97,10 +114,14 @@ struct as_if {
|
|||||||
if (!node.m_pNode)
|
if (!node.m_pNode)
|
||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
|
#ifdef YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
return decode_dispatcher<T>::dispatch(node).value_or(fallback);
|
||||||
|
#else
|
||||||
T t;
|
T t;
|
||||||
if (convert<T>::decode(node, t))
|
if (convert<T>::decode(node, t))
|
||||||
return t;
|
return t;
|
||||||
return fallback;
|
return fallback;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,9 +148,15 @@ struct as_if<T, void> {
|
|||||||
if (!node.m_pNode)
|
if (!node.m_pNode)
|
||||||
throw TypedBadConversion<T>(node.Mark());
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
|
|
||||||
|
#ifdef YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
auto t = decode_dispatcher<T>::dispatch(node);
|
||||||
|
if (t)
|
||||||
|
return *t;
|
||||||
|
#else
|
||||||
T t;
|
T t;
|
||||||
if (convert<T>::decode(node, t))
|
if (convert<T>::decode(node, t))
|
||||||
return t;
|
return t;
|
||||||
|
#endif
|
||||||
throw TypedBadConversion<T>(node.Mark());
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -42,6 +42,23 @@ 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>>>;
|
template <class K, class V, class C=std::less<K>> using CustomMap = std::map<K,V,C,CustomAllocator<std::pair<const K,V>>>;
|
||||||
template <class K, class V, class H=std::hash<K>, class P=std::equal_to<K>> using CustomUnorderedMap = std::unordered_map<K,V,H,P,CustomAllocator<std::pair<const K,V>>>;
|
template <class K, class V, class H=std::hash<K>, class P=std::equal_to<K>> using CustomUnorderedMap = std::unordered_map<K,V,H,P,CustomAllocator<std::pair<const K,V>>>;
|
||||||
|
|
||||||
|
struct Vec3 {
|
||||||
|
double x, y, z;
|
||||||
|
bool operator==(const Vec3& rhs) const {
|
||||||
|
return x == rhs.x && y == rhs.y && z == rhs.z;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
struct NonDefCtorVec3 {
|
||||||
|
double x, y, z;
|
||||||
|
NonDefCtorVec3(double x, double y, double z) : x(x), y(y), z(z) {}
|
||||||
|
bool operator==(const NonDefCtorVec3& rhs) const {
|
||||||
|
return x == rhs.x && y == rhs.y && z == rhs.z;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
using ::testing::AnyOf;
|
using ::testing::AnyOf;
|
||||||
@ -56,6 +73,41 @@ using ::testing::Eq;
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct convert<Vec3> {
|
||||||
|
static Node encode(const Vec3& rhs) {
|
||||||
|
Node node;
|
||||||
|
node.push_back(rhs.x);
|
||||||
|
node.push_back(rhs.y);
|
||||||
|
node.push_back(rhs.z);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, Vec3& rhs) {
|
||||||
|
if(!node.IsSequence() || node.size() != 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rhs.x = node[0].as<double>();
|
||||||
|
rhs.y = node[1].as<double>();
|
||||||
|
rhs.z = node[2].as<double>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
template <>
|
||||||
|
struct decode_dispatcher<NonDefCtorVec3> {
|
||||||
|
static std::optional<NonDefCtorVec3> dispatch(const Node& node) {
|
||||||
|
if (!node.IsSequence() || node.size() != 3) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return {{node[0].as<double>(), node[1].as<double>(), node[2].as<double>()}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
TEST(NodeTest, SimpleScalar) {
|
TEST(NodeTest, SimpleScalar) {
|
||||||
Node node = Node("Hello, World!");
|
Node node = Node("Hello, World!");
|
||||||
@ -725,6 +777,28 @@ TEST(NodeTest, AccessNonexistentKeyOnConstNode) {
|
|||||||
ASSERT_FALSE(other["5"]);
|
ASSERT_FALSE(other["5"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, CustomClassDecoding) {
|
||||||
|
YAML::Node node;
|
||||||
|
node.push_back(1.0);
|
||||||
|
node.push_back(2.0);
|
||||||
|
node.push_back(3.0);
|
||||||
|
ASSERT_TRUE(node.IsSequence());
|
||||||
|
EXPECT_EQ(node.as<Vec3>(), (Vec3{1.0, 2.0, 3.0}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, CustomNonDefaultConstructibleClassDecoding) {
|
||||||
|
#ifdef YAML_CPP_HAS_DECODE_DISPATCHER
|
||||||
|
YAML::Node node;
|
||||||
|
node.push_back(1.0);
|
||||||
|
node.push_back(2.0);
|
||||||
|
node.push_back(3.0);
|
||||||
|
ASSERT_TRUE(node.IsSequence());
|
||||||
|
EXPECT_EQ(node.as<NonDefCtorVec3>(), (NonDefCtorVec3{1.0, 2.0, 3.0}));
|
||||||
|
#else
|
||||||
|
GTEST_SKIP() << "Compile with C++17 for customizing non-default-constructible custom types.";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
class NodeEmitterTest : public ::testing::Test {
|
class NodeEmitterTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void ExpectOutput(const std::string& output, const Node& node) {
|
void ExpectOutput(const std::string& output, const Node& node) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user