diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index cdf766e..285fc33 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -120,6 +120,10 @@ class Exception : public std::runtime_error { private: static const std::string build_what(const Mark& mark, const std::string& msg) { + if (mark.is_null()) { + return msg.c_str(); + } + std::stringstream output; output << "yaml-cpp: error at line " << mark.line + 1 << ", column " << mark.column + 1 << ": " << msg; @@ -178,14 +182,14 @@ class InvalidNode : public RepresentationException { class BadConversion : public RepresentationException { public: - BadConversion() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {} + explicit BadConversion(const Mark& mark_) + : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {} }; template class TypedBadConversion : public BadConversion { public: - TypedBadConversion() : BadConversion() {} + explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {} }; class BadDereference : public RepresentationException { diff --git a/include/yaml-cpp/mark.h b/include/yaml-cpp/mark.h index 9ad7c43..bf94b4f 100644 --- a/include/yaml-cpp/mark.h +++ b/include/yaml-cpp/mark.h @@ -15,6 +15,8 @@ struct YAML_CPP_API Mark { static const Mark null_mark() { return Mark(-1, -1, -1); } + bool is_null() const { return pos == -1 && line == -1 && column == -1; } + int pos; int line, column; diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index 830958f..bbb497d 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -25,6 +25,7 @@ class node : private boost::noncopyable { const node_ref* ref() const { return m_pRef.get(); } bool is_defined() const { return m_pRef->is_defined(); } + const Mark& mark() const { return m_pRef->mark(); } NodeType::value type() const { return m_pRef->type(); } const std::string& scalar() const { return m_pRef->scalar(); } @@ -64,6 +65,10 @@ class node : private boost::noncopyable { m_pRef->set_data(*rhs.m_pRef); } + void set_mark(const Mark& mark) { + m_pRef->set_mark(mark); + } + void set_type(NodeType::value type) { if (type != NodeType::Undefined) mark_defined(); diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 10108cb..6030867 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -34,6 +34,7 @@ class YAML_CPP_API node_data : private boost::noncopyable { node_data(); void mark_defined(); + void set_mark(const Mark& mark); void set_type(NodeType::value type); void set_tag(const std::string& tag); void set_null(); @@ -41,6 +42,7 @@ class YAML_CPP_API node_data : private boost::noncopyable { void set_style(EmitterStyle::value style); bool is_defined() const { return m_isDefined; } + const Mark& mark() const { return m_mark; } NodeType::value type() const { return m_isDefined ? m_type : NodeType::Undefined; } @@ -97,6 +99,7 @@ class YAML_CPP_API node_data : private boost::noncopyable { private: bool m_isDefined; + Mark m_mark; NodeType::value m_type; std::string m_tag; EmitterStyle::value m_style; diff --git a/include/yaml-cpp/node/detail/node_ref.h b/include/yaml-cpp/node/detail/node_ref.h index eb50a25..26b1872 100644 --- a/include/yaml-cpp/node/detail/node_ref.h +++ b/include/yaml-cpp/node/detail/node_ref.h @@ -20,6 +20,7 @@ class node_ref : private boost::noncopyable { node_ref() : m_pData(new node_data) {} bool is_defined() const { return m_pData->is_defined(); } + const Mark& mark() const { return m_pData->mark(); } NodeType::value type() const { return m_pData->type(); } const std::string& scalar() const { return m_pData->scalar(); } const std::string& tag() const { return m_pData->tag(); } @@ -28,6 +29,7 @@ class node_ref : private boost::noncopyable { void mark_defined() { m_pData->mark_defined(); } void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } + void set_mark(const Mark& mark) { m_pData->set_mark(mark); } void set_type(NodeType::value type) { m_pData->set_type(type); } void set_tag(const std::string& tag) { m_pData->set_tag(tag); } void set_null() { m_pData->set_null(); } diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 164c533..26cccbd 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -66,6 +66,13 @@ inline bool Node::IsDefined() const { return m_pNode ? m_pNode->is_defined() : true; } +inline Mark Node::Mark() const { + if (!m_isValid) { + throw InvalidNode(); + } + return m_pNode ? m_pNode->mark() : Mark::null_mark(); +} + inline NodeType::value Node::Type() const { if (!m_isValid) throw InvalidNode(); @@ -110,12 +117,12 @@ struct as_if { const T operator()() const { if (!node.m_pNode) - throw TypedBadConversion(); + throw TypedBadConversion(node.Mark()); T t; if (convert::decode(node, t)) return t; - throw TypedBadConversion(); + throw TypedBadConversion(node.Mark()); } }; @@ -126,7 +133,7 @@ struct as_if { const std::string operator()() const { if (node.Type() != NodeType::Scalar) - throw TypedBadConversion(); + throw TypedBadConversion(node.Mark()); return node.Scalar(); } }; diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index b32b456..4ec3543 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -11,6 +11,7 @@ #include "yaml-cpp/dll.h" #include "yaml-cpp/emitterstyle.h" +#include "yaml-cpp/mark.h" #include "yaml-cpp/node/detail/bool_type.h" #include "yaml-cpp/node/detail/iterator_fwd.h" #include "yaml-cpp/node/ptr.h" @@ -48,6 +49,7 @@ class YAML_CPP_API Node { Node(const Node& rhs); ~Node(); + YAML::Mark Mark() const; NodeType::value Type() const; bool IsDefined() const; bool IsNull() const { return Type() == NodeType::Null; } diff --git a/src/node_data.cpp b/src/node_data.cpp index 4c07532..a1ca900 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -17,6 +17,7 @@ std::string node_data::empty_scalar; node_data::node_data() : m_isDefined(false), + m_mark(Mark::null_mark()), m_type(NodeType::Null), m_style(EmitterStyle::Default), m_seqSize(0) {} @@ -27,6 +28,10 @@ void node_data::mark_defined() { m_isDefined = true; } +void node_data::set_mark(const Mark& mark) { + m_mark = mark; +} + void node_data::set_type(NodeType::value type) { if (type == NodeType::Undefined) { m_type = type; diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp index 69f9702..20ec3ac 100644 --- a/src/nodebuilder.cpp +++ b/src/nodebuilder.cpp @@ -28,8 +28,8 @@ void NodeBuilder::OnDocumentStart(const Mark&) {} void NodeBuilder::OnDocumentEnd() {} -void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) { - detail::node& node = Push(anchor); +void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) { + detail::node& node = Push(mark, anchor); node.set_null(); Pop(); } @@ -40,18 +40,18 @@ void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) { Pop(); } -void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, +void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) { - detail::node& node = Push(anchor); + detail::node& node = Push(mark, anchor); node.set_scalar(value); node.set_tag(tag); Pop(); } -void NodeBuilder::OnSequenceStart(const Mark& /* mark */, +void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor, EmitterStyle::value style) { - detail::node& node = Push(anchor); + detail::node& node = Push(mark, anchor); node.set_tag(tag); node.set_type(NodeType::Sequence); node.set_style(style); @@ -59,9 +59,9 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */, void NodeBuilder::OnSequenceEnd() { Pop(); } -void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, +void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor, EmitterStyle::value style) { - detail::node& node = Push(anchor); + detail::node& node = Push(mark, anchor); node.set_type(NodeType::Map); node.set_tag(tag); node.set_style(style); @@ -74,8 +74,9 @@ void NodeBuilder::OnMapEnd() { Pop(); } -detail::node& NodeBuilder::Push(anchor_t anchor) { +detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) { detail::node& node = m_pMemory->create_node(); + node.set_mark(mark); RegisterAnchor(anchor, node); Push(node); return node; diff --git a/src/nodebuilder.h b/src/nodebuilder.h index 79b3201..a6a47f0 100644 --- a/src/nodebuilder.h +++ b/src/nodebuilder.h @@ -48,7 +48,7 @@ class NodeBuilder : public EventHandler { virtual void OnMapEnd(); private: - detail::node& Push(anchor_t anchor); + detail::node& Push(const Mark& mark, anchor_t anchor); void Push(detail::node& node); void Pop(); void RegisterAnchor(anchor_t anchor, detail::node& node);