refactor: add make_xxx_error funcs

This commit is contained in:
ToruNiina
2024-06-23 15:36:50 +09:00
parent 8c20067493
commit 7af0e66c25

View File

@@ -21,6 +21,8 @@
namespace toml namespace toml
{ {
template<typename TypeConfig>
class basic_value;
struct type_error final : public ::toml::exception struct type_error final : public ::toml::exception
{ {
@@ -42,6 +44,12 @@ struct type_error final : public ::toml::exception
// only for internal use // only for internal use
namespace detail namespace detail
{ {
template<typename TC>
error_info make_type_error(const basic_value<TC>&, const std::string&, const value_t);
template<typename TC>
error_info make_not_found_error(const basic_value<TC>&, const std::string&, const std::string&);
template<typename TC> template<typename TC>
void change_region_of_value(basic_value<TC>&, const basic_value<TC>&); void change_region_of_value(basic_value<TC>&, const basic_value<TC>&);
@@ -1192,7 +1200,7 @@ class basic_value
{ {
if(this->type_ != value_t::boolean) if(this->type_ != value_t::boolean)
{ {
this->throw_bad_cast("toml::value::as_boolean(): ", value_t::boolean); this->throw_bad_cast("toml::value::as_boolean()", value_t::boolean);
} }
return this->boolean_.value; return this->boolean_.value;
} }
@@ -1200,7 +1208,7 @@ class basic_value
{ {
if(this->type_ != value_t::integer) if(this->type_ != value_t::integer)
{ {
this->throw_bad_cast("toml::value::as_integer(): ", value_t::integer); this->throw_bad_cast("toml::value::as_integer()", value_t::integer);
} }
return this->integer_.value; return this->integer_.value;
} }
@@ -1208,7 +1216,7 @@ class basic_value
{ {
if(this->type_ != value_t::floating) if(this->type_ != value_t::floating)
{ {
this->throw_bad_cast("toml::value::as_floating(): ", value_t::floating); this->throw_bad_cast("toml::value::as_floating()", value_t::floating);
} }
return this->floating_.value; return this->floating_.value;
} }
@@ -1216,7 +1224,7 @@ class basic_value
{ {
if(this->type_ != value_t::string) if(this->type_ != value_t::string)
{ {
this->throw_bad_cast("toml::value::as_string(): ", value_t::string); this->throw_bad_cast("toml::value::as_string()", value_t::string);
} }
return this->string_.value; return this->string_.value;
} }
@@ -1224,7 +1232,7 @@ class basic_value
{ {
if(this->type_ != value_t::offset_datetime) if(this->type_ != value_t::offset_datetime)
{ {
this->throw_bad_cast("toml::value::as_offset_datetime(): ", value_t::offset_datetime); this->throw_bad_cast("toml::value::as_offset_datetime()", value_t::offset_datetime);
} }
return this->offset_datetime_.value; return this->offset_datetime_.value;
} }
@@ -1232,7 +1240,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_datetime) if(this->type_ != value_t::local_datetime)
{ {
this->throw_bad_cast("toml::value::as_local_datetime(): ", value_t::local_datetime); this->throw_bad_cast("toml::value::as_local_datetime()", value_t::local_datetime);
} }
return this->local_datetime_.value; return this->local_datetime_.value;
} }
@@ -1240,7 +1248,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_date) if(this->type_ != value_t::local_date)
{ {
this->throw_bad_cast("toml::value::as_local_date(): ", value_t::local_date); this->throw_bad_cast("toml::value::as_local_date()", value_t::local_date);
} }
return this->local_date_.value; return this->local_date_.value;
} }
@@ -1248,7 +1256,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_time) if(this->type_ != value_t::local_time)
{ {
this->throw_bad_cast("toml::value::as_local_time(): ", value_t::local_time); this->throw_bad_cast("toml::value::as_local_time()", value_t::local_time);
} }
return this->local_time_.value; return this->local_time_.value;
} }
@@ -1256,7 +1264,7 @@ class basic_value
{ {
if(this->type_ != value_t::array) if(this->type_ != value_t::array)
{ {
this->throw_bad_cast("toml::value::as_array(): ", value_t::array); this->throw_bad_cast("toml::value::as_array()", value_t::array);
} }
return this->array_.value.get(); return this->array_.value.get();
} }
@@ -1264,7 +1272,7 @@ class basic_value
{ {
if(this->type_ != value_t::table) if(this->type_ != value_t::table)
{ {
this->throw_bad_cast("toml::value::as_table(): ", value_t::table); this->throw_bad_cast("toml::value::as_table()", value_t::table);
} }
return this->table_.value.get(); return this->table_.value.get();
} }
@@ -1276,7 +1284,7 @@ class basic_value
{ {
if(this->type_ != value_t::boolean) if(this->type_ != value_t::boolean)
{ {
this->throw_bad_cast("toml::value::as_boolean(): ", value_t::boolean); this->throw_bad_cast("toml::value::as_boolean()", value_t::boolean);
} }
return this->boolean_.value; return this->boolean_.value;
} }
@@ -1284,7 +1292,7 @@ class basic_value
{ {
if(this->type_ != value_t::integer) if(this->type_ != value_t::integer)
{ {
this->throw_bad_cast("toml::value::as_integer(): ", value_t::integer); this->throw_bad_cast("toml::value::as_integer()", value_t::integer);
} }
return this->integer_.value; return this->integer_.value;
} }
@@ -1292,7 +1300,7 @@ class basic_value
{ {
if(this->type_ != value_t::floating) if(this->type_ != value_t::floating)
{ {
this->throw_bad_cast("toml::value::as_floating(): ", value_t::floating); this->throw_bad_cast("toml::value::as_floating()", value_t::floating);
} }
return this->floating_.value; return this->floating_.value;
} }
@@ -1300,7 +1308,7 @@ class basic_value
{ {
if(this->type_ != value_t::string) if(this->type_ != value_t::string)
{ {
this->throw_bad_cast("toml::value::as_string(): ", value_t::string); this->throw_bad_cast("toml::value::as_string()", value_t::string);
} }
return this->string_.value; return this->string_.value;
} }
@@ -1308,7 +1316,7 @@ class basic_value
{ {
if(this->type_ != value_t::offset_datetime) if(this->type_ != value_t::offset_datetime)
{ {
this->throw_bad_cast("toml::value::as_offset_datetime(): ", value_t::offset_datetime); this->throw_bad_cast("toml::value::as_offset_datetime()", value_t::offset_datetime);
} }
return this->offset_datetime_.value; return this->offset_datetime_.value;
} }
@@ -1316,7 +1324,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_datetime) if(this->type_ != value_t::local_datetime)
{ {
this->throw_bad_cast("toml::value::as_local_datetime(): ", value_t::local_datetime); this->throw_bad_cast("toml::value::as_local_datetime()", value_t::local_datetime);
} }
return this->local_datetime_.value; return this->local_datetime_.value;
} }
@@ -1324,7 +1332,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_date) if(this->type_ != value_t::local_date)
{ {
this->throw_bad_cast("toml::value::as_local_date(): ", value_t::local_date); this->throw_bad_cast("toml::value::as_local_date()", value_t::local_date);
} }
return this->local_date_.value; return this->local_date_.value;
} }
@@ -1332,7 +1340,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_time) if(this->type_ != value_t::local_time)
{ {
this->throw_bad_cast("toml::value::as_local_time(): ", value_t::local_time); this->throw_bad_cast("toml::value::as_local_time()", value_t::local_time);
} }
return this->local_time_.value; return this->local_time_.value;
} }
@@ -1340,7 +1348,7 @@ class basic_value
{ {
if(this->type_ != value_t::array) if(this->type_ != value_t::array)
{ {
this->throw_bad_cast("toml::value::as_array(): ", value_t::array); this->throw_bad_cast("toml::value::as_array()", value_t::array);
} }
return this->array_.value.get(); return this->array_.value.get();
} }
@@ -1348,7 +1356,7 @@ class basic_value
{ {
if(this->type_ != value_t::table) if(this->type_ != value_t::table)
{ {
this->throw_bad_cast("toml::value::as_table(): ", value_t::table); this->throw_bad_cast("toml::value::as_table()", value_t::table);
} }
return this->table_.value.get(); return this->table_.value.get();
} }
@@ -1411,7 +1419,7 @@ class basic_value
{ {
if(this->type_ != value_t::boolean) if(this->type_ != value_t::boolean)
{ {
this->throw_bad_cast("toml::value::as_boolean_fmt(): ", value_t::boolean); this->throw_bad_cast("toml::value::as_boolean_fmt()", value_t::boolean);
} }
return this->boolean_.format; return this->boolean_.format;
} }
@@ -1419,7 +1427,7 @@ class basic_value
{ {
if(this->type_ != value_t::integer) if(this->type_ != value_t::integer)
{ {
this->throw_bad_cast("toml::value::as_integer_fmt(): ", value_t::integer); this->throw_bad_cast("toml::value::as_integer_fmt()", value_t::integer);
} }
return this->integer_.format; return this->integer_.format;
} }
@@ -1427,7 +1435,7 @@ class basic_value
{ {
if(this->type_ != value_t::floating) if(this->type_ != value_t::floating)
{ {
this->throw_bad_cast("toml::value::as_floating_fmt(): ", value_t::floating); this->throw_bad_cast("toml::value::as_floating_fmt()", value_t::floating);
} }
return this->floating_.format; return this->floating_.format;
} }
@@ -1435,7 +1443,7 @@ class basic_value
{ {
if(this->type_ != value_t::string) if(this->type_ != value_t::string)
{ {
this->throw_bad_cast("toml::value::as_string_fmt(): ", value_t::string); this->throw_bad_cast("toml::value::as_string_fmt()", value_t::string);
} }
return this->string_.format; return this->string_.format;
} }
@@ -1443,7 +1451,7 @@ class basic_value
{ {
if(this->type_ != value_t::offset_datetime) if(this->type_ != value_t::offset_datetime)
{ {
this->throw_bad_cast("toml::value::as_offset_datetime_fmt(): ", value_t::offset_datetime); this->throw_bad_cast("toml::value::as_offset_datetime_fmt()", value_t::offset_datetime);
} }
return this->offset_datetime_.format; return this->offset_datetime_.format;
} }
@@ -1451,7 +1459,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_datetime) if(this->type_ != value_t::local_datetime)
{ {
this->throw_bad_cast("toml::value::as_local_datetime_fmt(): ", value_t::local_datetime); this->throw_bad_cast("toml::value::as_local_datetime_fmt()", value_t::local_datetime);
} }
return this->local_datetime_.format; return this->local_datetime_.format;
} }
@@ -1459,7 +1467,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_date) if(this->type_ != value_t::local_date)
{ {
this->throw_bad_cast("toml::value::as_local_date_fmt(): ", value_t::local_date); this->throw_bad_cast("toml::value::as_local_date_fmt()", value_t::local_date);
} }
return this->local_date_.format; return this->local_date_.format;
} }
@@ -1467,7 +1475,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_time) if(this->type_ != value_t::local_time)
{ {
this->throw_bad_cast("toml::value::as_local_time_fmt(): ", value_t::local_time); this->throw_bad_cast("toml::value::as_local_time_fmt()", value_t::local_time);
} }
return this->local_time_.format; return this->local_time_.format;
} }
@@ -1475,7 +1483,7 @@ class basic_value
{ {
if(this->type_ != value_t::array) if(this->type_ != value_t::array)
{ {
this->throw_bad_cast("toml::value::as_array_fmt(): ", value_t::array); this->throw_bad_cast("toml::value::as_array_fmt()", value_t::array);
} }
return this->array_.format; return this->array_.format;
} }
@@ -1483,7 +1491,7 @@ class basic_value
{ {
if(this->type_ != value_t::table) if(this->type_ != value_t::table)
{ {
this->throw_bad_cast("toml::value::as_table_fmt(): ", value_t::table); this->throw_bad_cast("toml::value::as_table_fmt()", value_t::table);
} }
return this->table_.format; return this->table_.format;
} }
@@ -1495,7 +1503,7 @@ class basic_value
{ {
if(this->type_ != value_t::boolean) if(this->type_ != value_t::boolean)
{ {
this->throw_bad_cast("toml::value::as_boolean_fmt(): ", value_t::boolean); this->throw_bad_cast("toml::value::as_boolean_fmt()", value_t::boolean);
} }
return this->boolean_.format; return this->boolean_.format;
} }
@@ -1503,7 +1511,7 @@ class basic_value
{ {
if(this->type_ != value_t::integer) if(this->type_ != value_t::integer)
{ {
this->throw_bad_cast("toml::value::as_integer_fmt(): ", value_t::integer); this->throw_bad_cast("toml::value::as_integer_fmt()", value_t::integer);
} }
return this->integer_.format; return this->integer_.format;
} }
@@ -1511,7 +1519,7 @@ class basic_value
{ {
if(this->type_ != value_t::floating) if(this->type_ != value_t::floating)
{ {
this->throw_bad_cast("toml::value::as_floating_fmt(): ", value_t::floating); this->throw_bad_cast("toml::value::as_floating_fmt()", value_t::floating);
} }
return this->floating_.format; return this->floating_.format;
} }
@@ -1519,7 +1527,7 @@ class basic_value
{ {
if(this->type_ != value_t::string) if(this->type_ != value_t::string)
{ {
this->throw_bad_cast("toml::value::as_string_fmt(): ", value_t::string); this->throw_bad_cast("toml::value::as_string_fmt()", value_t::string);
} }
return this->string_.format; return this->string_.format;
} }
@@ -1527,7 +1535,7 @@ class basic_value
{ {
if(this->type_ != value_t::offset_datetime) if(this->type_ != value_t::offset_datetime)
{ {
this->throw_bad_cast("toml::value::as_offset_datetime_fmt(): ", value_t::offset_datetime); this->throw_bad_cast("toml::value::as_offset_datetime_fmt()", value_t::offset_datetime);
} }
return this->offset_datetime_.format; return this->offset_datetime_.format;
} }
@@ -1535,7 +1543,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_datetime) if(this->type_ != value_t::local_datetime)
{ {
this->throw_bad_cast("toml::value::as_local_datetime_fmt(): ", value_t::local_datetime); this->throw_bad_cast("toml::value::as_local_datetime_fmt()", value_t::local_datetime);
} }
return this->local_datetime_.format; return this->local_datetime_.format;
} }
@@ -1543,7 +1551,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_date) if(this->type_ != value_t::local_date)
{ {
this->throw_bad_cast("toml::value::as_local_date_fmt(): ", value_t::local_date); this->throw_bad_cast("toml::value::as_local_date_fmt()", value_t::local_date);
} }
return this->local_date_.format; return this->local_date_.format;
} }
@@ -1551,7 +1559,7 @@ class basic_value
{ {
if(this->type_ != value_t::local_time) if(this->type_ != value_t::local_time)
{ {
this->throw_bad_cast("toml::value::as_local_time_fmt(): ", value_t::local_time); this->throw_bad_cast("toml::value::as_local_time_fmt()", value_t::local_time);
} }
return this->local_time_.format; return this->local_time_.format;
} }
@@ -1559,7 +1567,7 @@ class basic_value
{ {
if(this->type_ != value_t::array) if(this->type_ != value_t::array)
{ {
this->throw_bad_cast("toml::value::as_array_fmt(): ", value_t::array); this->throw_bad_cast("toml::value::as_array_fmt()", value_t::array);
} }
return this->array_.format; return this->array_.format;
} }
@@ -1567,7 +1575,7 @@ class basic_value
{ {
if(this->type_ != value_t::table) if(this->type_ != value_t::table)
{ {
this->throw_bad_cast("toml::value::as_table_fmt(): ", value_t::table); this->throw_bad_cast("toml::value::as_table_fmt()", value_t::table);
} }
return this->table_.format; return this->table_.format;
} }
@@ -1579,13 +1587,13 @@ class basic_value
{ {
if(!this->is_table()) if(!this->is_table())
{ {
this->throw_bad_cast("toml::value::at(key_type): ", value_t::table); this->throw_bad_cast("toml::value::at(key_type)", value_t::table);
} }
auto& table = this->as_table(std::nothrow); auto& table = this->as_table(std::nothrow);
const auto found = table.find(k); const auto found = table.find(k);
if(found == table.end()) if(found == table.end())
{ {
this->throw_key_not_found_error(k); this->throw_key_not_found_error("toml::value::at", k);
} }
assert(found->first == k); assert(found->first == k);
return found->second; return found->second;
@@ -1594,13 +1602,13 @@ class basic_value
{ {
if(!this->is_table()) if(!this->is_table())
{ {
this->throw_bad_cast("toml::value::at(key_type): ", value_t::table); this->throw_bad_cast("toml::value::at(key_type)", value_t::table);
} }
const auto& table = this->as_table(std::nothrow); const auto& table = this->as_table(std::nothrow);
const auto found = table.find(k); const auto found = table.find(k);
if(found == table.end()) if(found == table.end())
{ {
this->throw_key_not_found_error(k); this->throw_key_not_found_error("toml::value::at", k);
} }
assert(found->first == k); assert(found->first == k);
return found->second; return found->second;
@@ -1613,7 +1621,7 @@ class basic_value
} }
else if( ! this->is_table()) // initialized, but not a table else if( ! this->is_table()) // initialized, but not a table
{ {
this->throw_bad_cast("toml::value::operator[](key_type): ", value_t::table); this->throw_bad_cast("toml::value::operator[](key_type)", value_t::table);
} }
return (this->as_table(std::nothrow))[k]; return (this->as_table(std::nothrow))[k];
} }
@@ -1621,7 +1629,7 @@ class basic_value
{ {
if(!this->is_table()) if(!this->is_table())
{ {
this->throw_bad_cast("toml::value::count(key_type): ", value_t::table); this->throw_bad_cast("toml::value::count(key_type)", value_t::table);
} }
return this->as_table(std::nothrow).count(k); return this->as_table(std::nothrow).count(k);
} }
@@ -1629,7 +1637,7 @@ class basic_value
{ {
if(!this->is_table()) if(!this->is_table())
{ {
this->throw_bad_cast("toml::value::contains(key_type): ", value_t::table); this->throw_bad_cast("toml::value::contains(key_type)", value_t::table);
} }
const auto& table = this->as_table(std::nothrow); const auto& table = this->as_table(std::nothrow);
return table.find(k) != table.end(); return table.find(k) != table.end();
@@ -1642,7 +1650,7 @@ class basic_value
{ {
if(!this->is_array()) if(!this->is_array())
{ {
this->throw_bad_cast("toml::value::at(idx): ", value_t::array); this->throw_bad_cast("toml::value::at(idx)", value_t::array);
} }
auto& ar = this->as_array(std::nothrow); auto& ar = this->as_array(std::nothrow);
@@ -1662,7 +1670,7 @@ class basic_value
{ {
if(!this->is_array()) if(!this->is_array())
{ {
this->throw_bad_cast("toml::value::at(idx): ", value_t::array); this->throw_bad_cast("toml::value::at(idx)", value_t::array);
} }
const auto& ar = this->as_array(std::nothrow); const auto& ar = this->as_array(std::nothrow);
@@ -1695,7 +1703,7 @@ class basic_value
{ {
if(!this->is_array()) if(!this->is_array())
{ {
this->throw_bad_cast("toml::value::push_back(idx): ", value_t::array); this->throw_bad_cast("toml::value::push_back(idx)", value_t::array);
} }
this->as_array(std::nothrow).push_back(x); this->as_array(std::nothrow).push_back(x);
return; return;
@@ -1704,7 +1712,7 @@ class basic_value
{ {
if(!this->is_array()) if(!this->is_array())
{ {
this->throw_bad_cast("toml::value::push_back(idx): ", value_t::array); this->throw_bad_cast("toml::value::push_back(idx)", value_t::array);
} }
this->as_array(std::nothrow).push_back(std::move(x)); this->as_array(std::nothrow).push_back(std::move(x));
return; return;
@@ -1715,7 +1723,7 @@ class basic_value
{ {
if(!this->is_array()) if(!this->is_array())
{ {
this->throw_bad_cast("toml::value::emplace_back(idx): ", value_t::array); this->throw_bad_cast("toml::value::emplace_back(idx)", value_t::array);
} }
auto& ar = this->as_array(std::nothrow); auto& ar = this->as_array(std::nothrow);
ar.emplace_back(std::forward<Ts>(args) ...); ar.emplace_back(std::forward<Ts>(args) ...);
@@ -1793,52 +1801,15 @@ class basic_value
[[noreturn]] [[noreturn]]
void throw_bad_cast(const std::string& funcname, const value_t ty) const void throw_bad_cast(const std::string& funcname, const value_t ty) const
{ {
throw type_error(format_error(make_error_info( throw type_error(format_error(detail::make_type_error(*this, funcname, ty)),
funcname + "bad_cast to " + to_string(ty), this->location());
this->location(), "the actual type is " + to_string(this->type()))),
this->location());
} }
[[noreturn]] [[noreturn]]
void throw_key_not_found_error(const key_type& key) const void throw_key_not_found_error(const std::string& funcname, const key_type& key) const
{ {
const auto loc = this->location(); throw std::out_of_range(format_error(
detail::make_not_found_error(*this, funcname, key)));
std::ostringstream oss;
oss << color::red << "[error] " << color::reset
<< "key \"" << key << "\" not found";
// the value is not from a file. no information can be appended.
if( ! loc.is_ok())
{
throw std::out_of_range(oss.str());
}
// The top-level table has its region at the 0th character of the file.
// That means that, in the case when a key is not found in the top-level
// table, the error message points to the first character. If the file has
// the first table at the first line, the error message would be like this.
// ```console
// [error] key "a" not found
// --> example.toml
// |
// 1 | [table]
// | ^------ in this table
// ```
// It actually points to the top-level table at the first character, not
// `[table]`. But it is too confusing. To avoid the confusion, the error
// message should explicitly say "key not found in the top-level table".
if(loc.first_line_number() == 1 && loc.length() == 0)
{
oss << " at the top-level table in \"" << loc.file_name() << "\"";
throw std::out_of_range(oss.str());
}
else
{
// normal table.
oss << format_location(loc, "in this table");
throw std::out_of_range(oss.str());
}
} }
template<typename TC> template<typename TC>
@@ -2079,6 +2050,49 @@ std::string format_error(std::string title,
namespace detail namespace detail
{ {
template<typename TC>
error_info make_type_error(const basic_value<TC>& v, const std::string& fname, const value_t ty)
{
return make_error_info(fname + ": bad_cast to " + to_string(ty),
v.location(), "the actual type is " + to_string(v.type()));
}
template<typename TC>
error_info make_not_found_error(const basic_value<TC>& v, const std::string& fname, const std::string& key)
{
const auto loc = v.location();
const std::string title = fname + ": key \"" + key + "\" not found";
std::vector<std::pair<source_location, std::string>> locs;
if( ! loc.is_ok())
{
return error_info(title, locs);
}
if(loc.first_line_number() == 1 && loc.first_column_number() == 1 && loc.length() == 1)
{
// The top-level table has its region at the 0th character of the file.
// That means that, in the case when a key is not found in the top-level
// table, the error message points to the first character. If the file has
// the first table at the first line, the error message would be like this.
// ```console
// [error] key "a" not found
// --> example.toml
// |
// 1 | [table]
// | ^------ in this table
// ```
// It actually points to the top-level table at the first character, not
// `[table]`. But it is too confusing. To avoid the confusion, the error
// message should explicitly say "key not found in the top-level table".
locs.emplace_back(v.location(), "at the top-level table");
}
else
{
locs.emplace_back(v.location(), "in this table");
}
return error_info(title, locs);
}
#define TOML11_DETAIL_GENERATE_COMPTIME_GETTER(ty) \ #define TOML11_DETAIL_GENERATE_COMPTIME_GETTER(ty) \
template<typename TC> \ template<typename TC> \
struct getter<TC, value_t::ty> \ struct getter<TC, value_t::ty> \