From 7af0e66c25b01c8ebf52de901d936481e3440e73 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Sun, 23 Jun 2024 15:36:50 +0900 Subject: [PATCH] refactor: add make_xxx_error funcs --- include/toml11/value.hpp | 202 +++++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 94 deletions(-) diff --git a/include/toml11/value.hpp b/include/toml11/value.hpp index 284a0b80..fe1720df 100644 --- a/include/toml11/value.hpp +++ b/include/toml11/value.hpp @@ -21,6 +21,8 @@ namespace toml { +template +class basic_value; struct type_error final : public ::toml::exception { @@ -42,6 +44,12 @@ struct type_error final : public ::toml::exception // only for internal use namespace detail { +template +error_info make_type_error(const basic_value&, const std::string&, const value_t); + +template +error_info make_not_found_error(const basic_value&, const std::string&, const std::string&); + template void change_region_of_value(basic_value&, const basic_value&); @@ -1192,7 +1200,7 @@ class basic_value { 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; } @@ -1200,7 +1208,7 @@ class basic_value { 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; } @@ -1208,7 +1216,7 @@ class basic_value { 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; } @@ -1216,7 +1224,7 @@ class basic_value { 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; } @@ -1224,7 +1232,7 @@ class basic_value { 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; } @@ -1232,7 +1240,7 @@ class basic_value { 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; } @@ -1240,7 +1248,7 @@ class basic_value { 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; } @@ -1248,7 +1256,7 @@ class basic_value { 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; } @@ -1256,7 +1264,7 @@ class basic_value { 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(); } @@ -1264,7 +1272,7 @@ class basic_value { 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(); } @@ -1276,7 +1284,7 @@ class basic_value { 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; } @@ -1284,7 +1292,7 @@ class basic_value { 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; } @@ -1292,7 +1300,7 @@ class basic_value { 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; } @@ -1300,7 +1308,7 @@ class basic_value { 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; } @@ -1308,7 +1316,7 @@ class basic_value { 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; } @@ -1316,7 +1324,7 @@ class basic_value { 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; } @@ -1324,7 +1332,7 @@ class basic_value { 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; } @@ -1332,7 +1340,7 @@ class basic_value { 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; } @@ -1340,7 +1348,7 @@ class basic_value { 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(); } @@ -1348,7 +1356,7 @@ class basic_value { 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(); } @@ -1411,7 +1419,7 @@ class basic_value { 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; } @@ -1419,7 +1427,7 @@ class basic_value { 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; } @@ -1427,7 +1435,7 @@ class basic_value { 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; } @@ -1435,7 +1443,7 @@ class basic_value { 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; } @@ -1443,7 +1451,7 @@ class basic_value { 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; } @@ -1451,7 +1459,7 @@ class basic_value { 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; } @@ -1459,7 +1467,7 @@ class basic_value { 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; } @@ -1467,7 +1475,7 @@ class basic_value { 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; } @@ -1475,7 +1483,7 @@ class basic_value { 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; } @@ -1483,7 +1491,7 @@ class basic_value { 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; } @@ -1495,7 +1503,7 @@ class basic_value { 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; } @@ -1503,7 +1511,7 @@ class basic_value { 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; } @@ -1511,7 +1519,7 @@ class basic_value { 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; } @@ -1519,7 +1527,7 @@ class basic_value { 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; } @@ -1527,7 +1535,7 @@ class basic_value { 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; } @@ -1535,7 +1543,7 @@ class basic_value { 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; } @@ -1543,7 +1551,7 @@ class basic_value { 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; } @@ -1551,7 +1559,7 @@ class basic_value { 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; } @@ -1559,7 +1567,7 @@ class basic_value { 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; } @@ -1567,7 +1575,7 @@ class basic_value { 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; } @@ -1579,13 +1587,13 @@ class basic_value { 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); const auto found = table.find(k); 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); return found->second; @@ -1594,13 +1602,13 @@ class basic_value { 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 found = table.find(k); 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); return found->second; @@ -1613,7 +1621,7 @@ class basic_value } 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]; } @@ -1621,7 +1629,7 @@ class basic_value { 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); } @@ -1629,7 +1637,7 @@ class basic_value { 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); return table.find(k) != table.end(); @@ -1642,7 +1650,7 @@ class basic_value { 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); @@ -1662,7 +1670,7 @@ class basic_value { 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); @@ -1695,7 +1703,7 @@ class basic_value { 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); return; @@ -1704,7 +1712,7 @@ class basic_value { 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)); return; @@ -1715,7 +1723,7 @@ class basic_value { 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); ar.emplace_back(std::forward(args) ...); @@ -1793,52 +1801,15 @@ class basic_value [[noreturn]] void throw_bad_cast(const std::string& funcname, const value_t ty) const { - throw type_error(format_error(make_error_info( - funcname + "bad_cast to " + to_string(ty), - this->location(), "the actual type is " + to_string(this->type()))), - this->location()); + throw type_error(format_error(detail::make_type_error(*this, funcname, ty)), + this->location()); } [[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(); - - 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()); - } + throw std::out_of_range(format_error( + detail::make_not_found_error(*this, funcname, key))); } template @@ -2079,6 +2050,49 @@ std::string format_error(std::string title, namespace detail { +template +error_info make_type_error(const basic_value& 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 +error_info make_not_found_error(const basic_value& 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> 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) \ template \ struct getter \