Merge origin/add-src-loc-to-exception #87

This commit is contained in:
ToruNiina
2019-10-31 23:11:53 +09:00
7 changed files with 57 additions and 37 deletions

View File

@@ -2,6 +2,7 @@
// Distributed under the MIT License. // Distributed under the MIT License.
#ifndef TOML11_EXCEPTION_HPP #ifndef TOML11_EXCEPTION_HPP
#define TOML11_EXCEPTION_HPP #define TOML11_EXCEPTION_HPP
#include "source_location.hpp"
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
@@ -18,32 +19,41 @@ struct exception : public std::exception
struct syntax_error : public toml::exception struct syntax_error : public toml::exception
{ {
public: public:
explicit syntax_error(const std::string& what_arg) : what_(what_arg){} explicit syntax_error(const std::string& what_arg, const source_location& loc)
explicit syntax_error(const char* what_arg) : what_(what_arg){} : what_(what_arg), loc_(loc)
{}
virtual ~syntax_error() noexcept override = default; virtual ~syntax_error() noexcept override = default;
virtual const char* what() const noexcept override {return what_.c_str();} virtual const char* what() const noexcept override {return what_.c_str();}
source_location const& location() const noexcept {return loc_;}
protected: protected:
std::string what_; std::string what_;
source_location loc_;
}; };
struct type_error : public toml::exception struct type_error : public toml::exception
{ {
public: public:
explicit type_error(const std::string& what_arg) : what_(what_arg){} explicit type_error(const std::string& what_arg, const source_location& loc)
explicit type_error(const char* what_arg) : what_(what_arg){} : what_(what_arg), loc_(loc)
{}
virtual ~type_error() noexcept override = default; virtual ~type_error() noexcept override = default;
virtual const char* what() const noexcept override {return what_.c_str();} virtual const char* what() const noexcept override {return what_.c_str();}
source_location const& location() const noexcept {return loc_;}
protected: protected:
std::string what_; std::string what_;
source_location loc_;
}; };
struct internal_error : public toml::exception struct internal_error : public toml::exception
{ {
public: public:
explicit internal_error(const std::string& what_arg) : what_(what_arg){} explicit internal_error(const std::string& what_arg)
explicit internal_error(const char* what_arg) : what_(what_arg){} : what_(what_arg)
{}
virtual ~internal_error() noexcept override = default; virtual ~internal_error() noexcept override = default;
virtual const char* what() const noexcept override {return what_.c_str();} virtual const char* what() const noexcept override {return what_.c_str();}
protected: protected:

View File

@@ -190,7 +190,7 @@ get(const basic_value<C, M, V>& v)
"bad_cast to std::chrono::system_clock::time_point", { "bad_cast to std::chrono::system_clock::time_point", {
{std::addressof(detail::get_region(v)), {std::addressof(detail::get_region(v)),
concat_to_string("the actual type is ", v.type())} concat_to_string("the actual type is ", v.type())}
})); }), v.location());
} }
} }
} }

View File

@@ -76,7 +76,8 @@ inline ::toml::value operator"" _toml(const char* str, std::size_t len)
} }
else // none of them. else // none of them.
{ {
throw ::toml::syntax_error(data.unwrap_err()); throw ::toml::syntax_error(data.unwrap_err(),
source_location(std::addressof(loc)));
} }
} }

View File

@@ -278,7 +278,7 @@ std::string read_utf8_codepoint(const region<Container>& reg,
"toml::read_utf8_codepoint: codepoints in the range " "toml::read_utf8_codepoint: codepoints in the range "
"[0xD800, 0xDFFF] are not valid UTF-8.", {{ "[0xD800, 0xDFFF] are not valid UTF-8.", {{
std::addressof(loc), "not a valid UTF-8 codepoint" std::addressof(loc), "not a valid UTF-8 codepoint"
}})); }}), source_location(std::addressof(loc)));
} }
assert(codepoint < 0xD800 || 0xDFFF < codepoint); assert(codepoint < 0xD800 || 0xDFFF < codepoint);
// 1110yyyy 10yxxxxx 10xxxxxx // 1110yyyy 10yxxxxx 10xxxxxx
@@ -298,7 +298,8 @@ std::string read_utf8_codepoint(const region<Container>& reg,
{ {
throw syntax_error(format_underline("[error] toml::read_utf8_codepoint:" throw syntax_error(format_underline("[error] toml::read_utf8_codepoint:"
" input codepoint is too large.", " input codepoint is too large.",
{{std::addressof(loc), "should be in [0x00..0x10FFFF]"}})); {{std::addressof(loc), "should be in [0x00..0x10FFFF]"}}),
source_location(std::addressof(loc)));
} }
return character; return character;
} }
@@ -929,7 +930,7 @@ parse_array(location<Container>& loc)
std::addressof(get_region(val.unwrap())), std::addressof(get_region(val.unwrap())),
"value has different type, " + stringize(val.unwrap().type()) "value has different type, " + stringize(val.unwrap().type())
} }
})); }), source_location(std::addressof(loc)));
} }
retval.push_back(std::move(val.unwrap())); retval.push_back(std::move(val.unwrap()));
} }
@@ -942,7 +943,7 @@ parse_array(location<Container>& loc)
"value having invalid format appeared in an array", { "value having invalid format appeared in an array", {
{std::addressof(array_start_loc), "array starts here"}, {std::addressof(array_start_loc), "array starts here"},
{std::addressof(loc), "it is not a valid value."} {std::addressof(loc), "it is not a valid value."}
})); }), source_location(std::addressof(loc)));
} }
using lex_array_separator = sequence<maybe<lex_ws>, character<','>>; using lex_array_separator = sequence<maybe<lex_ws>, character<','>>;
@@ -965,14 +966,15 @@ parse_array(location<Container>& loc)
" missing array separator `,` after a value", { " missing array separator `,` after a value", {
{std::addressof(array_start_loc), "array starts here"}, {std::addressof(array_start_loc), "array starts here"},
{std::addressof(loc), "should be `,`"} {std::addressof(loc), "should be `,`"}
})); }), source_location(std::addressof(loc)));
} }
} }
} }
loc.reset(first); loc.reset(first);
throw syntax_error(format_underline("[error] toml::parse_array: " throw syntax_error(format_underline("[error] toml::parse_array: "
"array did not closed by `]`", "array did not closed by `]`",
{{std::addressof(loc), "should be closed"}})); {{std::addressof(loc), "should be closed"}}),
source_location(std::addressof(loc)));
} }
template<typename Value, typename Container> template<typename Value, typename Container>
@@ -1175,7 +1177,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
"table already defined"}, "table already defined"},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"this conflicts with the previous table"} "this conflicts with the previous table"}
})); }), v.location());
} }
else if(!(tab->at(k).is_array())) else if(!(tab->at(k).is_array()))
{ {
@@ -1188,7 +1190,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
" value already exists")}, " value already exists")},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"while inserting this array-of-tables"} "while inserting this array-of-tables"}
})); }), v.location());
} }
// the above if-else-if checks tab->at(k) is an array // the above if-else-if checks tab->at(k) is an array
auto& a = tab->at(k).as_array(); auto& a = tab->at(k).as_array();
@@ -1203,7 +1205,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
" value already exists")}, " value already exists")},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"while inserting this array-of-tables"} "while inserting this array-of-tables"}
})); }), v.location());
} }
// avoid conflicting array of table like the following. // avoid conflicting array of table like the following.
// ```toml // ```toml
@@ -1231,7 +1233,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
" value has static size")}, " value has static size")},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"appending it to the statically sized array"} "appending it to the statically sized array"}
})); }), v.location());
} }
a.push_back(v); a.push_back(v);
return ok(true); return ok(true);
@@ -1259,7 +1261,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
"table already exists here"}, "table already exists here"},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"table defined twice"} "table defined twice"}
})); }), v.location());
} }
// to allow the following toml file. // to allow the following toml file.
// [a.b.c] // [a.b.c]
@@ -1286,7 +1288,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
"array of tables defined here"}, "array of tables defined here"},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"table conflicts with the previous array of table"} "table conflicts with the previous array of table"}
})); }), v.location());
} }
else else
{ {
@@ -1297,7 +1299,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
"value already exists here"}, "value already exists here"},
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
"value defined twice"} "value defined twice"}
})); }), v.location());
} }
} }
tab->insert(std::make_pair(k, v)); tab->insert(std::make_pair(k, v));
@@ -1333,7 +1335,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
{std::addressof(get_region(a.back())), {std::addressof(get_region(a.back())),
concat_to_string("actual type is ", a.back().type())}, concat_to_string("actual type is ", a.back().type())},
{std::addressof(get_region(v)), "inserting this"} {std::addressof(get_region(v)), "inserting this"}
})); }), v.location());
} }
tab = std::addressof(a.back().as_table()); tab = std::addressof(a.back().as_table());
} }
@@ -1346,7 +1348,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
{std::addressof(get_region(tab->at(k))), {std::addressof(get_region(tab->at(k))),
concat_to_string("actual type is ", tab->at(k).type())}, concat_to_string("actual type is ", tab->at(k).type())},
{std::addressof(get_region(v)), "inserting this"} {std::addressof(get_region(v)), "inserting this"}
})); }), v.location());
} }
} }
} }
@@ -1412,20 +1414,23 @@ parse_inline_table(location<Container>& loc)
{ {
throw syntax_error(format_underline("[error] " throw syntax_error(format_underline("[error] "
"toml::parse_inline_table: missing curly brace `}`", "toml::parse_inline_table: missing curly brace `}`",
{{std::addressof(loc), "should be `}`"}})); {{std::addressof(loc), "should be `}`"}}),
source_location(std::addressof(loc)));
} }
else else
{ {
throw syntax_error(format_underline("[error] " throw syntax_error(format_underline("[error] "
"toml::parse_inline_table: missing table separator `,` ", "toml::parse_inline_table: missing table separator `,` ",
{{std::addressof(loc), "should be `,`"}})); {{std::addressof(loc), "should be `,`"}}),
source_location(std::addressof(loc)));
} }
} }
} }
loc.reset(first); loc.reset(first);
throw syntax_error(format_underline("[error] toml::parse_inline_table: " throw syntax_error(format_underline("[error] toml::parse_inline_table: "
"inline table did not closed by `}`", "inline table did not closed by `}`",
{{std::addressof(loc), "should be closed"}})); {{std::addressof(loc), "should be closed"}}),
source_location(std::addressof(loc)));
} }
template<typename Container> template<typename Container>
@@ -1668,7 +1673,8 @@ parse_table_key(location<Container>& loc)
{ {
throw syntax_error(format_underline("[error] " throw syntax_error(format_underline("[error] "
"toml::parse_table_key: newline required after [table.key]", "toml::parse_table_key: newline required after [table.key]",
{{std::addressof(loc), "expected newline"}})); {{std::addressof(loc), "expected newline"}}),
source_location(std::addressof(loc)));
} }
} }
return ok(std::make_pair(keys.unwrap().first, token.unwrap())); return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
@@ -1722,7 +1728,8 @@ parse_array_table_key(location<Container>& loc)
{ {
throw syntax_error(format_underline("[error] toml::" throw syntax_error(format_underline("[error] toml::"
"parse_array_table_key: newline required after [[table.key]]", "parse_array_table_key: newline required after [[table.key]]",
{{std::addressof(loc), "expected newline"}})); {{std::addressof(loc), "expected newline"}}),
source_location(std::addressof(loc)));
} }
} }
return ok(std::make_pair(keys.unwrap().first, token.unwrap())); return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
@@ -1976,7 +1983,7 @@ parse(std::istream& is, const std::string& fname = "unknown file")
const auto data = detail::parse_toml_file<value_type>(loc); const auto data = detail::parse_toml_file<value_type>(loc);
if(!data) if(!data)
{ {
throw syntax_error(data.unwrap_err()); throw syntax_error(data.unwrap_err(), source_location(std::addressof(loc)));
} }
return data.unwrap(); return data.unwrap();
} }

View File

@@ -2,7 +2,6 @@
// Distributed under the MIT License. // Distributed under the MIT License.
#ifndef TOML11_REGION_HPP #ifndef TOML11_REGION_HPP
#define TOML11_REGION_HPP #define TOML11_REGION_HPP
#include "exception.hpp"
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
@@ -231,11 +230,10 @@ struct region final : public region_base
region& operator+=(const region& other) region& operator+=(const region& other)
{ {
if(this->begin() != other.begin() || this->end() != other.end() || // different regions cannot be concatenated
this->last_ != other.first_) assert(this->begin() == other.begin() && this->end() == other.end() &&
{ this->last_ == other.first_);
throw internal_error("invalid region concatenation");
}
this->last_ = other.last_; this->last_ = other.last_;
return *this; return *this;
} }

View File

@@ -48,7 +48,11 @@ struct source_location
{ {
if(reg) if(reg)
{ {
line_num_ = static_cast<std::uint_least32_t>(std::stoul(reg->line_num())); if(reg->line_num() != detail::region_base().line_num())
{
line_num_ = static_cast<std::uint_least32_t>(
std::stoul(reg->line_num()));
}
column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1); column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1);
region_size_ = static_cast<std::uint_least32_t>(reg->size()); region_size_ = static_cast<std::uint_least32_t>(reg->size());
file_name_ = reg->name(); file_name_ = reg->name();

View File

@@ -35,7 +35,7 @@ throw_bad_cast(value_t actual, const ::toml::basic_value<C, T, A>& v)
"[error] toml::value bad_cast to ", Expected), { "[error] toml::value bad_cast to ", Expected), {
{std::addressof(get_region(v)), {std::addressof(get_region(v)),
concat_to_string("the actual type is ", actual)} concat_to_string("the actual type is ", actual)}
})); }), v.location());
} }
// switch by `value_t` and call the corresponding `value::as_xxx()`. {{{ // switch by `value_t` and call the corresponding `value::as_xxx()`. {{{