diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 2a80494..52f6f5d 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -47,7 +47,7 @@ inline Node::Node(const Node& rhs) inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {} -inline Node::Node(Zombie, std::string key) +inline Node::Node(Zombie, const std::string& key) : m_isValid(false), m_invalidKey(key), m_pNode(NULL) {} inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory) @@ -374,15 +374,25 @@ inline typename to_value_t::return_type to_value(const T& t) { } } -template -std::string key_to_string(const Key& key) { - std::stringstream ss; - if (is_streamable::value) { +template +struct key_to_string_impl { + static std::string impl(const Key& key) { + std::stringstream ss; ss << key; return ss.str(); - } else { + } +}; + +template +struct key_to_string_impl { + static std::string impl(const Key&) { return std::string(); } +}; + +template +std::string key_to_string(const Key& key) { + return key_to_string_impl::value>().impl(key); } // indexing diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index b931945..d0a647e 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -8,7 +8,6 @@ #endif #include -#include #include "yaml-cpp/dll.h" #include "yaml-cpp/emitterstyle.h" @@ -117,7 +116,7 @@ class YAML_CPP_API Node { private: enum Zombie { ZombieNode }; explicit Node(Zombie); - explicit Node(Zombie, std::string); + explicit Node(Zombie, const std::string&); explicit Node(detail::node& node, detail::shared_memory_holder pMemory); void EnsureNodeExists() const; @@ -132,6 +131,7 @@ class YAML_CPP_API Node { private: bool m_isValid; + // string representation of invalid key, if the node is invalid std::string m_invalidKey; mutable detail::shared_memory_holder m_pMemory; mutable detail::node* m_pNode; diff --git a/test/integration/error_messages_test.cpp b/test/integration/error_messages_test.cpp new file mode 100644 index 0000000..a9d09c8 --- /dev/null +++ b/test/integration/error_messages_test.cpp @@ -0,0 +1,54 @@ +#include "specexamples.h" +#include "yaml-cpp/yaml.h" // IWYU pragma: keep + +#include "gtest/gtest.h" + +#define EXPECT_THROW_EXCEPTION(exception_type, statement, message) \ + ASSERT_THROW(statement, exception_type); \ + try { \ + statement; \ + } catch (const exception_type& e) { \ + EXPECT_EQ(e.msg, message); \ + } + +namespace YAML { +namespace { + +TEST(ErrorMessageTest, Ex9_1_BadSubscriptErrorMessage) { + Node doc = Load(ex9_1); + + // Test that printable key is part of error message + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, doc["first"]["second"]["fourth"], + "operator[] call on a scalar (key: 'fourth')"); + + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, doc["first"]["second"][37], + "operator[] call on a scalar (key: '37')"); + + + // Non-printable key is not included in error message + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, + doc["first"]["second"][std::vector()], + "operator[] call on a scalar"); + + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, doc["first"]["second"][Node()], + "operator[] call on a scalar"); +} + +TEST(ErrorMessageTest, Ex9_1_InvalidNodeErrorMessage) { + const Node doc = Load(ex9_1); + + // Test that printable key is part of error message + EXPECT_THROW_EXCEPTION(YAML::InvalidNode, doc["first"]["fourth"].as(), + "invalid node - first invalid key: 'fourth'"); + + EXPECT_THROW_EXCEPTION(YAML::InvalidNode, doc["first"][37].as(), + "invalid node - first invalid key: '37'"); + + // Non-printable key is not included in error message + EXPECT_THROW_EXCEPTION(YAML::InvalidNode, + doc["first"][std::vector()].as(), + "invalid node; this may result from using a map " + "iterator as a sequence iterator, or vice-versa"); +} +} +} diff --git a/test/specexamples.h b/test/specexamples.h index 3c81c77..e4e85ef 100644 --- a/test/specexamples.h +++ b/test/specexamples.h @@ -843,4 +843,9 @@ const char *ex8_22 = " - nested\n" "mapping: !!map\n" " foo: bar\n"; + +const char *ex9_1 = + "first:\n" + " second: 1\n" + " third: 2\n"; }