enable to show err msg for invalid insertion

like, with the following (invalid) toml file

> a.b = "value"
> a.b.c = 42

The error message becomes

> terminate called after throwing an instance of 'toml::syntax_error'
>   what():  [error] toml::insert_value: target (a.b) is neither table nor
> an array of tables
>  --> example.toml
>  1 | a.b = "value"
>    |       ~~~~~~~ actual type is string
>  ...
>  2 | a.b.c = 42
>    |         ~~ inserting this
This commit is contained in:
ToruNiina
2018-12-13 17:09:38 +09:00
parent f60e93c36f
commit e79069cc47

View File

@@ -1006,32 +1006,67 @@ insert_nested_key(table& root, const toml::value& v,
{ {
if(!(tab->at(k).is(value_t::Array))) if(!(tab->at(k).is(value_t::Array)))
{ {
throw syntax_error("toml::detail::insert_nested_key: " throw syntax_error(format_underline(concat_to_string(
"target is not an array of table: " + "[error] toml::insert_value: target value (\"",
format_dotted_keys(first, last)); format_dotted_keys(first, last), "\") is"
" not an array of tables"), get_region(tab->at(k)),
concat_to_string("actual type is ", tab->at(k).type()),
get_region(v), "this is an array of tables"));
} }
array& a = tab->at(k).template cast<toml::value_t::Array>(); array& a = tab->at(k).template cast<toml::value_t::Array>();
if(!(a.front().is(value_t::Table))) if(!(a.front().is(value_t::Table)))
{ {
throw syntax_error("toml::detail::insert_nested_key: " throw syntax_error(format_underline(concat_to_string(
"target is not an array of table: " + "[error] toml::insert_value: target value (\"",
format_dotted_keys(first, last)); format_dotted_keys(first, last), "\") is"
" not an array of tables"), get_region(tab->at(k)),
concat_to_string("actual type is ", tab->at(k).type()),
get_region(v), "this is an array of tables"));
} }
a.push_back(v); a.push_back(v);
return ok(true); return ok(true);
} }
else // if not, we need to create the array of table else // if not, we need to create the array of table
{ {
array aot(1, v); // array having one table toml::value aot(v); // copy region info from table to array
tab->insert(std::make_pair(k, value(aot))); // update content by an array with one element
detail::assign_keeping_region(aot,
::toml::value(toml::array(1, v)));
tab->insert(std::make_pair(k, aot));
return ok(true); return ok(true);
} }
} }
if(tab->count(k) == 1) if(tab->count(k) == 1)
{ {
throw syntax_error("[error] toml::detail::insert_nested_key: " if(tab->at(k).is(value_t::Table) && v.is(value_t::Table))
"while inserting value to table: value already exists. " + {
format_dotted_keys(first, last)); throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: table (\"",
format_dotted_keys(first, last), "\") already exists."),
get_region(tab->at(k)), "table already exists here",
get_region(v), "table defined twice"));
}
else if(v.is(value_t::Table) &&
tab->at(k).is(value_t::Array) &&
tab->at(k).cast<value_t::Array>().size() > 0 &&
tab->at(k).cast<value_t::Array>().front().is(value_t::Table))
{
throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: array of tables (\"",
format_dotted_keys(first, last), "\") already exists."),
get_region(tab->at(k)), "array of tables defined here",
get_region(v), "table conflicts with the previous array"
" of table"));
}
else
{
throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: value (\"",
format_dotted_keys(first, last), "\") already exists."),
get_region(tab->at(k)), "value already exists here",
get_region(v), "value inserted twice"));
}
} }
tab->insert(std::make_pair(k, v)); tab->insert(std::make_pair(k, v));
return ok(true); return ok(true);
@@ -1039,29 +1074,46 @@ insert_nested_key(table& root, const toml::value& v,
else else
{ {
// if there is no corresponding value, insert it first. // if there is no corresponding value, insert it first.
if(tab->count(k) == 0) {(*tab)[k] = table{};} // related: you don't need to write
// # [x]
// # [x.y]
// to write
// [x.y.z]
if(tab->count(k) == 0)
{
// the region of [x.y] is the same as [x.y.z].
(*tab)[k] = v; // copy region_info_
detail::assign_keeping_region((*tab)[k],
::toml::value(::toml::table{}));
}
// type checking... // type checking...
if(tab->at(k).is(value_t::Table)) if(tab->at(k).is(value_t::Table))
{ {
tab = std::addressof((*tab)[k].template cast<value_t::Table>()); tab = std::addressof((*tab)[k].template cast<value_t::Table>());
} }
else if(tab->at(k).is(value_t::Array)) // array-of-table case else if(tab->at(k).is(value_t::Array)) // inserting to array-of-tables?
{ {
array& a = (*tab)[k].template cast<value_t::Array>(); array& a = (*tab)[k].template cast<value_t::Array>();
if(!a.back().is(value_t::Table)) if(!a.back().is(value_t::Table))
{ {
throw syntax_error("toml::detail::insert_nested_key: value " throw syntax_error(format_underline(concat_to_string(
"is not a table but an array: " + "[error] toml::insert_value: target (",
format_dotted_keys(first, last)); format_dotted_keys(first, std::next(iter)),
") is neither table nor an array of tables"),
get_region(a.back()), concat_to_string("actual type is ",
a.back().type()), get_region(v), "inserting this"));
} }
tab = std::addressof(a.back().template cast<value_t::Table>()); tab = std::addressof(a.back().template cast<value_t::Table>());
} }
else else
{ {
throw syntax_error("toml::detail::insert_nested_key: value " throw syntax_error(format_underline(concat_to_string(
"is not a table but an array: " + "[error] toml::insert_value: target (",
format_dotted_keys(first, last)); format_dotted_keys(first, std::next(iter)),
") is neither table nor an array of tables"),
get_region(tab->at(k)), concat_to_string("actual type is ",
tab->at(k).type()), get_region(v), "inserting this"));
} }
} }
} }