mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
Merge pull request #296 from WrinklyNinja/useful-conversion-errors
Add more error messages that include the location in a parsed file.
This commit is contained in:
@@ -120,6 +120,10 @@ class Exception : public std::runtime_error {
|
|||||||
private:
|
private:
|
||||||
static const std::string build_what(const Mark& mark,
|
static const std::string build_what(const Mark& mark,
|
||||||
const std::string& msg) {
|
const std::string& msg) {
|
||||||
|
if (mark.is_null()) {
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
std::stringstream output;
|
std::stringstream output;
|
||||||
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
|
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
|
||||||
<< mark.column + 1 << ": " << msg;
|
<< mark.column + 1 << ": " << msg;
|
||||||
@@ -178,14 +182,14 @@ class InvalidNode : public RepresentationException {
|
|||||||
|
|
||||||
class BadConversion : public RepresentationException {
|
class BadConversion : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
BadConversion()
|
explicit BadConversion(const Mark& mark_)
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {}
|
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedBadConversion : public BadConversion {
|
class TypedBadConversion : public BadConversion {
|
||||||
public:
|
public:
|
||||||
TypedBadConversion() : BadConversion() {}
|
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadDereference : public RepresentationException {
|
class BadDereference : public RepresentationException {
|
||||||
|
@@ -15,6 +15,8 @@ struct YAML_CPP_API Mark {
|
|||||||
|
|
||||||
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
||||||
|
|
||||||
|
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
|
||||||
|
|
||||||
int pos;
|
int pos;
|
||||||
int line, column;
|
int line, column;
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ class node : private boost::noncopyable {
|
|||||||
const node_ref* ref() const { return m_pRef.get(); }
|
const node_ref* ref() const { return m_pRef.get(); }
|
||||||
|
|
||||||
bool is_defined() const { return m_pRef->is_defined(); }
|
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(); }
|
NodeType::value type() const { return m_pRef->type(); }
|
||||||
|
|
||||||
const std::string& scalar() const { return m_pRef->scalar(); }
|
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);
|
m_pRef->set_data(*rhs.m_pRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_mark(const Mark& mark) {
|
||||||
|
m_pRef->set_mark(mark);
|
||||||
|
}
|
||||||
|
|
||||||
void set_type(NodeType::value type) {
|
void set_type(NodeType::value type) {
|
||||||
if (type != NodeType::Undefined)
|
if (type != NodeType::Undefined)
|
||||||
mark_defined();
|
mark_defined();
|
||||||
|
@@ -34,6 +34,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
node_data();
|
node_data();
|
||||||
|
|
||||||
void mark_defined();
|
void mark_defined();
|
||||||
|
void set_mark(const Mark& mark);
|
||||||
void set_type(NodeType::value type);
|
void set_type(NodeType::value type);
|
||||||
void set_tag(const std::string& tag);
|
void set_tag(const std::string& tag);
|
||||||
void set_null();
|
void set_null();
|
||||||
@@ -41,6 +42,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
void set_style(EmitterStyle::value style);
|
void set_style(EmitterStyle::value style);
|
||||||
|
|
||||||
bool is_defined() const { return m_isDefined; }
|
bool is_defined() const { return m_isDefined; }
|
||||||
|
const Mark& mark() const { return m_mark; }
|
||||||
NodeType::value type() const {
|
NodeType::value type() const {
|
||||||
return m_isDefined ? m_type : NodeType::Undefined;
|
return m_isDefined ? m_type : NodeType::Undefined;
|
||||||
}
|
}
|
||||||
@@ -97,6 +99,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isDefined;
|
bool m_isDefined;
|
||||||
|
Mark m_mark;
|
||||||
NodeType::value m_type;
|
NodeType::value m_type;
|
||||||
std::string m_tag;
|
std::string m_tag;
|
||||||
EmitterStyle::value m_style;
|
EmitterStyle::value m_style;
|
||||||
|
@@ -20,6 +20,7 @@ class node_ref : private boost::noncopyable {
|
|||||||
node_ref() : m_pData(new node_data) {}
|
node_ref() : m_pData(new node_data) {}
|
||||||
|
|
||||||
bool is_defined() const { return m_pData->is_defined(); }
|
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(); }
|
NodeType::value type() const { return m_pData->type(); }
|
||||||
const std::string& scalar() const { return m_pData->scalar(); }
|
const std::string& scalar() const { return m_pData->scalar(); }
|
||||||
const std::string& tag() const { return m_pData->tag(); }
|
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 mark_defined() { m_pData->mark_defined(); }
|
||||||
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
|
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_type(NodeType::value type) { m_pData->set_type(type); }
|
||||||
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
||||||
void set_null() { m_pData->set_null(); }
|
void set_null() { m_pData->set_null(); }
|
||||||
|
@@ -66,6 +66,13 @@ inline bool Node::IsDefined() const {
|
|||||||
return m_pNode ? m_pNode->is_defined() : true;
|
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 {
|
inline NodeType::value Node::Type() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode();
|
||||||
@@ -110,12 +117,12 @@ struct as_if<T, void> {
|
|||||||
|
|
||||||
const T operator()() const {
|
const T operator()() const {
|
||||||
if (!node.m_pNode)
|
if (!node.m_pNode)
|
||||||
throw TypedBadConversion<T>();
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
|
|
||||||
T t;
|
T t;
|
||||||
if (convert<T>::decode(node, t))
|
if (convert<T>::decode(node, t))
|
||||||
return t;
|
return t;
|
||||||
throw TypedBadConversion<T>();
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -126,7 +133,7 @@ struct as_if<std::string, void> {
|
|||||||
|
|
||||||
const std::string operator()() const {
|
const std::string operator()() const {
|
||||||
if (node.Type() != NodeType::Scalar)
|
if (node.Type() != NodeType::Scalar)
|
||||||
throw TypedBadConversion<std::string>();
|
throw TypedBadConversion<std::string>(node.Mark());
|
||||||
return node.Scalar();
|
return node.Scalar();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/emitterstyle.h"
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
|
#include "yaml-cpp/mark.h"
|
||||||
#include "yaml-cpp/node/detail/bool_type.h"
|
#include "yaml-cpp/node/detail/bool_type.h"
|
||||||
#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"
|
||||||
@@ -48,6 +49,7 @@ class YAML_CPP_API Node {
|
|||||||
Node(const Node& rhs);
|
Node(const Node& rhs);
|
||||||
~Node();
|
~Node();
|
||||||
|
|
||||||
|
YAML::Mark Mark() const;
|
||||||
NodeType::value Type() const;
|
NodeType::value Type() const;
|
||||||
bool IsDefined() const;
|
bool IsDefined() const;
|
||||||
bool IsNull() const { return Type() == NodeType::Null; }
|
bool IsNull() const { return Type() == NodeType::Null; }
|
||||||
|
@@ -17,6 +17,7 @@ std::string node_data::empty_scalar;
|
|||||||
|
|
||||||
node_data::node_data()
|
node_data::node_data()
|
||||||
: m_isDefined(false),
|
: m_isDefined(false),
|
||||||
|
m_mark(Mark::null_mark()),
|
||||||
m_type(NodeType::Null),
|
m_type(NodeType::Null),
|
||||||
m_style(EmitterStyle::Default),
|
m_style(EmitterStyle::Default),
|
||||||
m_seqSize(0) {}
|
m_seqSize(0) {}
|
||||||
@@ -27,6 +28,10 @@ void node_data::mark_defined() {
|
|||||||
m_isDefined = true;
|
m_isDefined = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void node_data::set_mark(const Mark& mark) {
|
||||||
|
m_mark = mark;
|
||||||
|
}
|
||||||
|
|
||||||
void node_data::set_type(NodeType::value type) {
|
void node_data::set_type(NodeType::value type) {
|
||||||
if (type == NodeType::Undefined) {
|
if (type == NodeType::Undefined) {
|
||||||
m_type = type;
|
m_type = type;
|
||||||
|
@@ -28,8 +28,8 @@ void NodeBuilder::OnDocumentStart(const Mark&) {}
|
|||||||
|
|
||||||
void NodeBuilder::OnDocumentEnd() {}
|
void NodeBuilder::OnDocumentEnd() {}
|
||||||
|
|
||||||
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) {
|
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_null();
|
node.set_null();
|
||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
@@ -40,18 +40,18 @@ void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
|
|||||||
Pop();
|
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) {
|
anchor_t anchor, const std::string& value) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_scalar(value);
|
node.set_scalar(value);
|
||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
|
void NodeBuilder::OnSequenceStart(const Mark& mark,
|
||||||
const std::string& tag, anchor_t anchor,
|
const std::string& tag, anchor_t anchor,
|
||||||
EmitterStyle::value style) {
|
EmitterStyle::value style) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
node.set_type(NodeType::Sequence);
|
node.set_type(NodeType::Sequence);
|
||||||
node.set_style(style);
|
node.set_style(style);
|
||||||
@@ -59,9 +59,9 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
|
|||||||
|
|
||||||
void NodeBuilder::OnSequenceEnd() { Pop(); }
|
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) {
|
anchor_t anchor, EmitterStyle::value style) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_type(NodeType::Map);
|
node.set_type(NodeType::Map);
|
||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
node.set_style(style);
|
node.set_style(style);
|
||||||
@@ -74,8 +74,9 @@ void NodeBuilder::OnMapEnd() {
|
|||||||
Pop();
|
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();
|
detail::node& node = m_pMemory->create_node();
|
||||||
|
node.set_mark(mark);
|
||||||
RegisterAnchor(anchor, node);
|
RegisterAnchor(anchor, node);
|
||||||
Push(node);
|
Push(node);
|
||||||
return node;
|
return node;
|
||||||
|
@@ -48,7 +48,7 @@ class NodeBuilder : public EventHandler {
|
|||||||
virtual void OnMapEnd();
|
virtual void OnMapEnd();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::node& Push(anchor_t anchor);
|
detail::node& Push(const Mark& mark, anchor_t anchor);
|
||||||
void Push(detail::node& node);
|
void Push(detail::node& node);
|
||||||
void Pop();
|
void Pop();
|
||||||
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
||||||
|
Reference in New Issue
Block a user