Merge 5fe775248a into 26faac387c
This commit is contained in:
commit
28eb173991
@ -12,11 +12,29 @@
|
|||||||
#include "yaml-cpp/node/detail/node.h"
|
#include "yaml-cpp/node/detail/node.h"
|
||||||
#include "yaml-cpp/node/iterator.h"
|
#include "yaml-cpp/node/iterator.h"
|
||||||
#include "yaml-cpp/node/node.h"
|
#include "yaml-cpp/node/node.h"
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
|
#include <cassert>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
inline Node::Node()
|
namespace detail {
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
using ::std::exchange;
|
||||||
|
#else
|
||||||
|
template<class T, class U = T>
|
||||||
|
T exchange(T& obj, U&& new_value) {
|
||||||
|
T old_value = std::move(obj);
|
||||||
|
obj = std::forward<U>(new_value);
|
||||||
|
return old_value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace YAML
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
inline Node::Node() YAML_CPP_NOEXCEPT
|
||||||
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
|
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
|
||||||
|
|
||||||
inline Node::Node(NodeType::value type)
|
inline Node::Node(NodeType::value type)
|
||||||
@ -44,6 +62,13 @@ inline Node::Node(const detail::iterator_value& rhs)
|
|||||||
|
|
||||||
inline Node::Node(const Node& rhs) = default;
|
inline Node::Node(const Node& rhs) = default;
|
||||||
|
|
||||||
|
inline Node::Node(Node&& rhs) YAML_CPP_NOEXCEPT
|
||||||
|
: m_isValid(detail::exchange(rhs.m_isValid, true)),
|
||||||
|
m_invalidKey(std::move(rhs.m_invalidKey)),
|
||||||
|
m_pMemory(std::move(rhs.m_pMemory)),
|
||||||
|
m_pNode(detail::exchange(rhs.m_pNode, nullptr)) {
|
||||||
|
}
|
||||||
|
|
||||||
inline Node::Node(Zombie)
|
inline Node::Node(Zombie)
|
||||||
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
|
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
|
||||||
|
|
||||||
@ -188,6 +213,13 @@ inline void Node::SetStyle(EmitterStyle::value style) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assignment
|
// assignment
|
||||||
|
inline bool Node::CheckValidMove(const Node& rhs) const YAML_CPP_NOEXCEPT {
|
||||||
|
// Note: Both m_pNode's can be nullptr.
|
||||||
|
return
|
||||||
|
m_isValid && rhs.m_isValid &&
|
||||||
|
(!m_pNode || !rhs.m_pNode || !m_pNode->is(*rhs.m_pNode));
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Node::is(const Node& rhs) const {
|
inline bool Node::is(const Node& rhs) const {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
throw InvalidNode(m_invalidKey);
|
throw InvalidNode(m_invalidKey);
|
||||||
@ -209,6 +241,38 @@ inline Node& Node::operator=(const Node& rhs) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Node& Node::operator=(Node&& rhs) YAML_CPP_NOEXCEPT {
|
||||||
|
if (!CheckValidMove(rhs)) {
|
||||||
|
assert(false);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node tmp(std::move(rhs));
|
||||||
|
|
||||||
|
if (!m_pNode) {
|
||||||
|
// we don't have a node so do what AssignNode does in this case
|
||||||
|
m_pNode = tmp.m_pNode;
|
||||||
|
m_pMemory = tmp.m_pMemory;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tmp.m_pNode) {
|
||||||
|
// We have an m_pNode but tmp doesn't. Instead of calling tmp.EnsureNodeExists(),
|
||||||
|
// which can potentially throw, and then AssignNodeDetail, we do set_null() on it
|
||||||
|
// and swap with the empty, but valid, tmp. While this does not ensure m_pNode
|
||||||
|
// to exist afterwards as before (quite the opposite), it leaves us in a valid
|
||||||
|
// state.
|
||||||
|
m_pNode->set_null();
|
||||||
|
std::swap(*this, tmp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both m_pNode's are present and the merge should (hopefully) be noexcept.
|
||||||
|
AssignNodeDetail(tmp);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline void Node::reset(const YAML::Node& rhs) {
|
inline void Node::reset(const YAML::Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
throw InvalidNode(m_invalidKey);
|
throw InvalidNode(m_invalidKey);
|
||||||
@ -258,6 +322,10 @@ inline void Node::AssignNode(const Node& rhs) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssignNodeDetail(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::AssignNodeDetail(const Node& rhs) YAML_CPP_NOEXCEPT {
|
||||||
m_pNode->set_ref(*rhs.m_pNode);
|
m_pNode->set_ref(*rhs.m_pNode);
|
||||||
m_pMemory->merge(*rhs.m_pMemory);
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
m_pNode = rhs.m_pNode;
|
m_pNode = rhs.m_pNode;
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -41,12 +42,13 @@ class YAML_CPP_API Node {
|
|||||||
using iterator = YAML::iterator;
|
using iterator = YAML::iterator;
|
||||||
using const_iterator = YAML::const_iterator;
|
using const_iterator = YAML::const_iterator;
|
||||||
|
|
||||||
Node();
|
Node() YAML_CPP_NOEXCEPT;
|
||||||
explicit Node(NodeType::value type);
|
explicit Node(NodeType::value type);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
explicit Node(const T& rhs);
|
explicit Node(const T& rhs);
|
||||||
explicit Node(const detail::iterator_value& rhs);
|
explicit Node(const detail::iterator_value& rhs);
|
||||||
Node(const Node& rhs);
|
Node(const Node& rhs);
|
||||||
|
Node(Node&& rhs) YAML_CPP_NOEXCEPT;
|
||||||
~Node();
|
~Node();
|
||||||
|
|
||||||
YAML::Mark Mark() const;
|
YAML::Mark Mark() const;
|
||||||
@ -77,10 +79,12 @@ class YAML_CPP_API Node {
|
|||||||
void SetStyle(EmitterStyle::value style);
|
void SetStyle(EmitterStyle::value style);
|
||||||
|
|
||||||
// assignment
|
// assignment
|
||||||
|
bool CheckValidMove(const Node& rhs) const YAML_CPP_NOEXCEPT;
|
||||||
bool is(const Node& rhs) const;
|
bool is(const Node& rhs) const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Node& operator=(const T& rhs);
|
Node& operator=(const T& rhs);
|
||||||
Node& operator=(const Node& rhs);
|
Node& operator=(const Node& rhs);
|
||||||
|
Node& operator=(Node&& rhs) YAML_CPP_NOEXCEPT;
|
||||||
void reset(const Node& rhs = Node());
|
void reset(const Node& rhs = Node());
|
||||||
|
|
||||||
// size/iterator
|
// size/iterator
|
||||||
@ -128,6 +132,7 @@ class YAML_CPP_API Node {
|
|||||||
|
|
||||||
void AssignData(const Node& rhs);
|
void AssignData(const Node& rhs);
|
||||||
void AssignNode(const Node& rhs);
|
void AssignNode(const Node& rhs);
|
||||||
|
void AssignNodeDetail(const Node& rhs) YAML_CPP_NOEXCEPT;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isValid;
|
bool m_isValid;
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using ::testing::AnyOf;
|
using ::testing::AnyOf;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
|
|
||||||
@ -135,6 +137,36 @@ TEST(NodeTest, NodeAssignment) {
|
|||||||
EXPECT_EQ(node1[3], node2[3]);
|
EXPECT_EQ(node1[3], node2[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, EqualRepresentationAfterMoveAssignment) {
|
||||||
|
Node node1;
|
||||||
|
Node node2;
|
||||||
|
std::ostringstream ss1, ss2;
|
||||||
|
node1["foo"] = "bar";
|
||||||
|
ss1 << node1;
|
||||||
|
node2["hello"] = "world";
|
||||||
|
node2 = std::move(node1);
|
||||||
|
ss2 << node2;
|
||||||
|
EXPECT_FALSE(node2["hello"]);
|
||||||
|
EXPECT_EQ("bar", node2["foo"].as<std::string>());
|
||||||
|
EXPECT_EQ(ss1.str(), ss2.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, NodeIsNullWhenMovedFromByCtor) {
|
||||||
|
Node node1;
|
||||||
|
node1[1] = 1;
|
||||||
|
Node node2 = std::move(node1);
|
||||||
|
EXPECT_TRUE(node1.IsNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NodeTest, NodeIsNullWhenMovedFromByAssignment) {
|
||||||
|
Node node1;
|
||||||
|
Node node2;
|
||||||
|
node1[1] = 1;
|
||||||
|
node2[2] = 2;
|
||||||
|
node2 = std::move(node1);
|
||||||
|
EXPECT_TRUE(node1.IsNull());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(NodeTest, MapElementRemoval) {
|
TEST(NodeTest, MapElementRemoval) {
|
||||||
Node node;
|
Node node;
|
||||||
node["foo"] = "bar";
|
node["foo"] = "bar";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user