Compare commits

..

16 Commits

Author SHA1 Message Date
ToruNiina
717f5929c2 feat: use detail::none_t instead of char
Although the error value from combinators currently does not have any
information, it can have an information because it is a char value. It
is better to use no-information-type explicitly to make it clear that
it does not have any information. So I added none_t in toml::detai and
use it in combinators and parsers as an error value from combinators.
2019-05-31 17:07:52 +09:00
ToruNiina
81abb6c9d7 perf: remove err-msg from combinator
Generate error message in `parse_something()`, not in `lex_something`.
Since the error message generated by `lex_something` is too difficult to
read for humans, I've disabled the error message generation for the sake
of efficiency (it takes time to generate error message that will never
be read). I think now the error message generation itself safely can be
removed from combinators. At this stage, `lex_something` does not need
to return `result<T, E>` because all the error type would be discarded.
Now it is turned out that returing `optional<T>` from lex_* is enough.
Maybe later I would change the return type itself, but currently I
changed the error type from std::string to char because implementing
optional takes time and effort. It makes the parsing process a bit
faster.
2019-05-30 20:08:37 +09:00
ToruNiina
8bba3c8a14 refactor: use literal instead of empty string
so far, the error value of the lexer is just ignored because they are
not readable (results from all the nested combinator are concatenated,
so they are too redundant). those ones are replaced by a simple literal.
2019-05-30 19:33:25 +09:00
ToruNiina
b13e727b90 refactor: remove unused func, combinator::pattern
because it is not human-readable (too long and redundant)
2019-05-30 18:05:47 +09:00
ToruNiina
d352c9e66f perf: suppress unused error message generation 2019-05-30 17:47:06 +09:00
ToruNiina
c0aaba06d0 Merge branch 'refactoring' 2019-05-30 16:25:10 +09:00
ToruNiina
1633268d57 refactor: use snake_case typename only 2019-05-30 14:39:15 +09:00
ToruNiina
3bf1c2b820 Merge branch 'refactoring' to master 2019-05-30 00:18:07 +09:00
ToruNiina
4dbd2cb9fe refactor: use as_* to avoid needless checking 2019-05-29 21:22:32 +09:00
ToruNiina
65124a8d2e refactor: use is_something instead of is(...)
to reduce the code size a bit
2019-05-29 21:20:22 +09:00
ToruNiina
1b78f161f5 refactor: use is_something/as_something in parser
this reduces the size of the code. And also it skips needless
double-checking, so we can expect it makes parsing a bit faster.
2019-05-29 21:18:17 +09:00
ToruNiina
0ce259ada0 refactor: split throw_bad_cast from value::cast 2019-05-29 21:06:25 +09:00
ToruNiina
74da49f87f refactor: move switch_cast from inside of value
use as_something() instead of it. To realize this, the implementation of
as_something() is also changed. Now as_something does not depends on
`cast`. This reduces complexity around casting toml::value to other types.
2019-05-29 20:18:15 +09:00
ToruNiina
d5d697639c docs: add contributor to README 2019-05-10 23:02:23 +09:00
Toru Niina
0b365ca7d3 Merge pull request #63 from chronoxor/master
Fix Visual Studio 2019 warnings in pedantic compilation mode (/W4 /WX)
2019-05-10 22:58:17 +09:00
Ivan Shynkarenka
db6f3d5d11 Fix Visual Studio 2019 warnings in pedantic compilation mode (/W4 /WX) 2019-05-10 14:58:22 +03:00
11 changed files with 366 additions and 330 deletions

View File

@@ -1068,6 +1068,8 @@ I appreciate the help of the contributors who introduced the great feature to th
- Improved error messages for invaild keys to show the location where the parser fails
- Petr Beneš (@wbenny)
- Fixed warnings on MSVC
- Ivan Shynkarenka (@chronoxor)
- Fixed Visual Studio 2019 warnings
## Licensing terms

View File

@@ -18,7 +18,7 @@ do { \
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \
loc.begin(), loc.iter())), region.size()); \
} else { \
std::cerr << "lexer " << lxr::pattern() << " failed with input `"; \
std::cerr << "lexer failed with input `"; \
std::cerr << token << "`. expected `" << expected << "`\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \

View File

@@ -56,31 +56,24 @@ struct character
static constexpr char target = C;
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
if(loc.iter() == loc.end()) {return none();}
const auto first = loc.iter();
const char c = *(loc.iter());
if(c != target)
{
if(msg)
{
return err(concat_to_string("expected '", show_char(target),
"' but got '", show_char(c), "'."));
}
return err("");
return none();
}
loc.advance(); // update location
return ok(region<Cont>(loc, first, loc.iter()));
}
static std::string pattern() {return show_char(target);}
};
template<char C>
constexpr char character<C>::target;
@@ -96,35 +89,24 @@ struct in_range
static constexpr char lower = Low;
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
if(loc.iter() == loc.end()) {return none();}
const auto first = loc.iter();
const char c = *(loc.iter());
if(c < lower || upper < c)
{
if(msg)
{
return err(concat_to_string("expected character in range "
"[", show_char(lower), ", ", show_char(upper), "] but got ",
"'", show_char(c), "'."));
}
return err("");
return none();
}
loc.advance();
return ok(region<Cont>(loc, first, loc.iter()));
}
static std::string pattern()
{
return concat_to_string("[",show_char(lower),"-",show_char(upper),"]");
}
};
template<char L, char U> constexpr char in_range<L, U>::upper;
template<char L, char U> constexpr char in_range<L, U>::lower;
@@ -135,34 +117,24 @@ template<typename Combinator>
struct exclude
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
if(loc.iter() == loc.end()) {return none();}
auto first = loc.iter();
auto rslt = Combinator::invoke(loc, msg);
auto rslt = Combinator::invoke(loc);
if(rslt.is_ok())
{
loc.reset(first);
if(msg)
{
return err(concat_to_string("invalid pattern (",
Combinator::pattern(), ") appeared ", rslt.unwrap().str()));
}
return err("");
return none();
}
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
return ok(region<Cont>(loc, first, loc.iter()));
}
static std::string pattern()
{
return concat_to_string("^(", Combinator::pattern(), ')');
}
};
// increment `iter`, if matches. otherwise, just return empty string.
@@ -170,24 +142,19 @@ template<typename Combinator>
struct maybe
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
const auto rslt = Combinator::invoke(loc, msg);
const auto rslt = Combinator::invoke(loc);
if(rslt.is_ok())
{
return rslt;
}
return ok(region<Cont>(loc));
}
static std::string pattern()
{
return concat_to_string('(', Combinator::pattern(), ")?");
}
};
template<typename ... Ts>
@@ -197,41 +164,35 @@ template<typename Head, typename ... Tail>
struct sequence<Head, Tail...>
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
const auto first = loc.iter();
const auto rslt = Head::invoke(loc, msg);
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first, msg);
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
}
// called from the above function only, recursively.
template<typename Cont, typename Iterator>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first,
const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
{
const auto rslt = Head::invoke(loc, msg);
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
reg += rslt.unwrap(); // concat regions
return sequence<Tail...>::invoke(loc, std::move(reg), first, msg);
}
static std::string pattern()
{
return concat_to_string(Head::pattern(), sequence<Tail...>::pattern());
return sequence<Tail...>::invoke(loc, std::move(reg), first);
}
};
@@ -240,20 +201,18 @@ struct sequence<Head>
{
// would be called from sequence<T ...>::invoke only.
template<typename Cont, typename Iterator>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first,
const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
{
const auto rslt = Head::invoke(loc, msg);
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
reg += rslt.unwrap(); // concat regions
return ok(reg);
}
static std::string pattern() {return Head::pattern();}
};
template<typename ... Ts>
@@ -263,36 +222,27 @@ template<typename Head, typename ... Tail>
struct either<Head, Tail...>
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
const auto rslt = Head::invoke(loc, msg);
const auto rslt = Head::invoke(loc);
if(rslt.is_ok()) {return rslt;}
return either<Tail...>::invoke(loc, msg);
}
static std::string pattern()
{
return concat_to_string('(', Head::pattern(), ")|", either<Tail...>::pattern());
return either<Tail...>::invoke(loc);
}
};
template<typename Head>
struct either<Head>
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
return Head::invoke(loc, msg);
}
static std::string pattern()
{
return concat_to_string('(', Head::pattern(), ')');
return Head::invoke(loc);
}
};
@@ -307,52 +257,48 @@ template<typename T, std::size_t N>
struct repeat<T, exactly<N>>
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
const auto first = loc.iter();
for(std::size_t i=0; i<N; ++i)
{
auto rslt = T::invoke(loc, msg);
auto rslt = T::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
retval += rslt.unwrap();
}
return ok(std::move(retval));
}
static std::string pattern()
{
return concat_to_string('(', T::pattern(), "){", N, '}');
}
};
template<typename T, std::size_t N>
struct repeat<T, at_least<N>>
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
const auto first = loc.iter();
for(std::size_t i=0; i<N; ++i)
{
auto rslt = T::invoke(loc, msg);
auto rslt = T::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
retval += rslt.unwrap();
}
while(true)
{
auto rslt = T::invoke(loc, msg);
auto rslt = T::invoke(loc);
if(rslt.is_err())
{
return ok(std::move(retval));
@@ -360,23 +306,19 @@ struct repeat<T, at_least<N>>
retval += rslt.unwrap();
}
}
static std::string pattern()
{
return concat_to_string('(',T::pattern(), "){", N, ",}");
}
};
template<typename T>
struct repeat<T, unlimited>
{
template<typename Cont>
static result<region<Cont>, std::string>
invoke(location<Cont>& loc, const bool msg = false)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
while(true)
{
auto rslt = T::invoke(loc, msg);
auto rslt = T::invoke(loc);
if(rslt.is_err())
{
return ok(std::move(retval));
@@ -384,7 +326,6 @@ struct repeat<T, unlimited>
retval += rslt.unwrap();
}
}
static std::string pattern() {return concat_to_string('(', T::pattern(), ")*");}
};
} // detail

View File

@@ -353,15 +353,15 @@ struct local_datetime
explicit local_datetime(const std::chrono::system_clock::time_point& tp)
{
const auto t = std::chrono::system_clock::to_time_t(tp);
std::tm time = detail::localtime_s(&t);
std::tm ltime = detail::localtime_s(&t);
this->date = local_date(time);
this->time = local_time(time);
this->date = local_date(ltime);
this->time = local_time(ltime);
// std::tm lacks subsecond information, so diff between tp and tm
// can be used to get millisecond & microsecond information.
const auto t_diff = tp -
std::chrono::system_clock::from_time_t(std::mktime(&time));
std::chrono::system_clock::from_time_t(std::mktime(&ltime));
this->time.millisecond = static_cast<std::uint16_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
this->time.microsecond = static_cast<std::uint16_t>(

View File

@@ -276,7 +276,7 @@ namespace detail
{
template<typename T, std::size_t ...I>
T get_tuple_impl(const toml::Array& a, index_sequence<I...>)
T get_tuple_impl(const toml::array& a, index_sequence<I...>)
{
return std::make_tuple(
::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);

View File

@@ -376,7 +376,7 @@ parse_ml_basic_string(location<Container>& loc)
// immediate newline is ignored (if exists)
/* discard return value */ lex_newline::invoke(inner_loc);
delim = err("tmp");
delim = none();
while(!delim)
{
using lex_unescaped_seq = repeat<
@@ -432,7 +432,7 @@ parse_basic_string(location<Container>& loc)
std::string retval;
retval.reserve(token.unwrap().size());
quot = err("tmp");
quot = none();
while(!quot)
{
using lex_unescaped_seq = repeat<lex_basic_unescaped, unlimited>;
@@ -587,23 +587,17 @@ parse_local_date(location<Container>& loc)
const auto y = lex_date_fullyear::invoke(inner_loc);
if(!y || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
{
const std::string msg = y.map_err_or_else(
[](const std::string& msg) {return msg;}, "should be `-`");
throw internal_error(format_underline("[error]: "
"toml::parse_inner_local_date: invalid year format",
{{std::addressof(inner_loc), msg}}));
{{std::addressof(inner_loc), "should be `-`"}}));
}
inner_loc.advance();
const auto m = lex_date_month::invoke(inner_loc);
if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
{
const std::string msg = m.map_err_or_else(
[](const std::string& msg) {return msg;}, "should be `-`");
throw internal_error(format_underline("[error]: "
"toml::parse_local_date: invalid month format",
{{std::addressof(inner_loc), msg}}));
{{std::addressof(inner_loc), "should be `-`"}}));
}
inner_loc.advance();
const auto d = lex_date_mday::invoke(inner_loc);
@@ -611,7 +605,7 @@ parse_local_date(location<Container>& loc)
{
throw internal_error(format_underline("[error]: "
"toml::parse_local_date: invalid day format",
{{std::addressof(inner_loc), d.unwrap_err()}}));
{{std::addressof(inner_loc), "here"}}));
}
return ok(std::make_pair(local_date(
static_cast<std::int16_t>(from_string<int>(y.unwrap().str(), 0)),
@@ -640,23 +634,17 @@ parse_local_time(location<Container>& loc)
const auto h = lex_time_hour::invoke(inner_loc);
if(!h || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
{
const std::string msg = h.map_err_or_else(
[](const std::string& msg) {return msg;}, "should be `:`");
throw internal_error(format_underline("[error]: "
"toml::parse_local_time: invalid year format",
{{std::addressof(inner_loc), msg}}));
{{std::addressof(inner_loc), "should be `:`"}}));
}
inner_loc.advance();
const auto m = lex_time_minute::invoke(inner_loc);
if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
{
const std::string msg = m.map_err_or_else(
[](const std::string& msg) {return msg;}, "should be `:`");
throw internal_error(format_underline("[error]: "
"toml::parse_local_time: invalid month format",
{{std::addressof(inner_loc), msg}}));
{{std::addressof(inner_loc), "should be `:`"}}));
}
inner_loc.advance();
const auto s = lex_time_second::invoke(inner_loc);
@@ -664,7 +652,7 @@ parse_local_time(location<Container>& loc)
{
throw internal_error(format_underline("[error]: "
"toml::parse_local_time: invalid second format",
{{std::addressof(inner_loc), s.unwrap_err()}}));
{{std::addressof(inner_loc), "here"}}));
}
local_time time(
static_cast<std::int8_t>(from_string<int>(h.unwrap().str(), 0)),
@@ -700,7 +688,7 @@ parse_local_time(location<Container>& loc)
{
throw internal_error(format_underline("[error]: "
"toml::parse_local_time: invalid subsecond format",
{{std::addressof(inner_loc), secfrac.unwrap_err()}}));
{{std::addressof(inner_loc), "here"}}));
}
}
return ok(std::make_pair(time, token.unwrap()));
@@ -724,12 +712,9 @@ parse_local_datetime(location<Container>& loc)
const auto date = parse_local_date(inner_loc);
if(!date || inner_loc.iter() == inner_loc.end())
{
const std::string msg = date.map_err_or_else(
[](const std::string& msg) {return msg;}, "date, not datetime");
throw internal_error(format_underline("[error]: "
"toml::parse_local_datetime: invalid datetime format",
{{std::addressof(inner_loc), msg}}));
{{std::addressof(inner_loc), "date, not datetime"}}));
}
const char delim = *(inner_loc.iter());
if(delim != 'T' && delim != 't' && delim != ' ')
@@ -769,12 +754,9 @@ parse_offset_datetime(location<Container>& loc)
const auto datetime = parse_local_datetime(inner_loc);
if(!datetime || inner_loc.iter() == inner_loc.end())
{
const std::string msg = datetime.map_err_or_else(
[](const std::string& msg){return msg;}, "date, not datetime");
throw internal_error(format_underline("[error]: "
"toml::parse_offset_datetime: invalid datetime format",
{{std::addressof(inner_loc), msg}}));
{{std::addressof(inner_loc), "date, not datetime"}}));
}
time_offset offset(0, 0);
if(const auto ofs = lex_time_numoffset::invoke(inner_loc))
@@ -1167,7 +1149,7 @@ insert_nested_key(table& root, const toml::value& v,
{
if(tab->count(k) == 1) // there is already an array of table
{
if(tab->at(k).is(value_t::Table))
if(tab->at(k).is_table())
{
// show special err msg for conflicting table
throw syntax_error(format_underline(concat_to_string(
@@ -1180,7 +1162,7 @@ insert_nested_key(table& root, const toml::value& v,
"this conflicts with the previous table"}
}));
}
else if(!(tab->at(k).is(value_t::Array)))
else if(!(tab->at(k).is_array()))
{
throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: array of table (\"",
@@ -1193,8 +1175,9 @@ insert_nested_key(table& root, const toml::value& v,
"while inserting this array-of-tables"}
}));
}
array& a = tab->at(k).template cast<toml::value_t::Array>();
if(!(a.front().is(value_t::Table)))
// the above if-else-if checks tab->at(k) is an array
array& a = tab->at(k).as_array();
if(!(a.front().is_table()))
{
throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: array of table (\"",
@@ -1248,7 +1231,7 @@ insert_nested_key(table& root, const toml::value& v,
if(tab->count(k) == 1)
{
if(tab->at(k).is(value_t::Table) && v.is(value_t::Table))
if(tab->at(k).is_table() && v.is_table())
{
if(!is_valid_forward_table_definition(
tab->at(k), first, iter, last))
@@ -1268,18 +1251,18 @@ insert_nested_key(table& root, const toml::value& v,
// d = 42
// [a]
// e = 2.71
auto& t = tab->at(k).cast<value_t::Table>();
for(const auto& kv : v.cast<value_t::Table>())
auto& t = tab->at(k).as_table();
for(const auto& kv : v.as_table())
{
t[kv.first] = kv.second;
}
detail::change_region(tab->at(k), key_reg);
return ok(true);
}
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))
else if(v.is_table() &&
tab->at(k).is_array() &&
tab->at(k).as_array().size() > 0 &&
tab->at(k).as_array().front().is_table())
{
throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: array of tables (\"",
@@ -1319,14 +1302,14 @@ insert_nested_key(table& root, const toml::value& v,
}
// type checking...
if(tab->at(k).is(value_t::Table))
if(tab->at(k).is_table())
{
tab = std::addressof((*tab)[k].template cast<value_t::Table>());
tab = std::addressof((*tab)[k].as_table());
}
else if(tab->at(k).is(value_t::Array)) // inserting to array-of-tables?
else if(tab->at(k).is_array()) // inserting to array-of-tables?
{
array& a = (*tab)[k].template cast<value_t::Array>();
if(!a.back().is(value_t::Table))
array& a = (*tab)[k].as_array();
if(!a.back().is_table())
{
throw syntax_error(format_underline(concat_to_string(
"[error] toml::insert_value: target (",
@@ -1337,7 +1320,7 @@ insert_nested_key(table& root, const toml::value& v,
{std::addressof(get_region(v)), "inserting this"}
}));
}
tab = std::addressof(a.back().template cast<value_t::Table>());
tab = std::addressof(a.back().as_table());
}
else
{
@@ -1363,7 +1346,7 @@ parse_inline_table(location<Container>& loc)
table retval;
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
{
return err(format_underline("[error] toml::parse_inline_table: ",
return err(format_underline("[error] toml::parse_inline_table: ",
{{std::addressof(loc), "the next token is not an inline table"}}));
}
loc.advance();
@@ -1560,7 +1543,7 @@ template<typename Container>
result<std::pair<std::vector<key>, region<Container>>, std::string>
parse_array_table_key(location<Container>& loc)
{
if(auto token = lex_array_table::invoke(loc, true))
if(auto token = lex_array_table::invoke(loc))
{
location<std::string> inner_loc(loc.name(), token.unwrap().str());
@@ -1672,12 +1655,12 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
const auto newline = skip_line::invoke(loc);
if(!newline && loc.iter() != loc.end())
{
const auto before = loc.iter();
const auto before2 = loc.iter();
lex_ws::invoke(loc); // skip whitespace
const auto msg = format_underline("[error] toml::parse_table: "
"invalid line format", {{std::addressof(loc), concat_to_string(
"expected newline, but got '", show_char(*loc.iter()), "'.")}});
loc.reset(before);
loc.reset(before2);
return err(msg);
}

View File

@@ -113,21 +113,25 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
result(const failure_type& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
result(success_type&& s): is_ok_(true)
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
result(failure_type&& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
template<typename U>
@@ -135,24 +139,28 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
template<typename U>
result(const failure<U>& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
template<typename U>
result(success<U>&& s): is_ok_(true)
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
template<typename U>
result(failure<U>&& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
result& operator=(const success_type& s)
@@ -161,6 +169,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
result& operator=(const failure_type& f)
@@ -169,6 +178,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
result& operator=(success_type&& s)
@@ -177,6 +187,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
result& operator=(failure_type&& f)
@@ -185,6 +196,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
@@ -195,6 +207,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
template<typename U>
@@ -204,6 +217,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
template<typename U>
@@ -213,6 +227,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
template<typename U>
@@ -222,6 +237,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
@@ -233,11 +249,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
result(result&& other): is_ok_(other.is_ok())
@@ -246,11 +264,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
@@ -261,11 +281,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
template<typename U, typename F>
@@ -275,11 +297,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
@@ -290,11 +314,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -306,11 +332,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -324,11 +352,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -341,11 +371,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -660,5 +692,26 @@ void swap(result<T, E>& lhs, result<T, E>& rhs)
// return lhs.is_ok() ? lhs : rhs;
// }
// ----------------------------------------------------------------------------
// re-use result<T, E> as a optional<T> with none_t
namespace detail
{
struct none_t {};
inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
{
os << "none";
return os;
}
inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
} // detail
} // toml11
#endif// TOML11_RESULT_H

View File

@@ -157,7 +157,7 @@ struct serializer
std::string operator()(const array& v) const
{
if(!v.empty() && v.front().is(value_t::Table))// v is an array of tables
if(!v.empty() && v.front().is_table())// v is an array of tables
{
// if it's not inlined, we need to add `[[table.key]]`.
// but if it can be inlined, we need `table.key = [...]`.
@@ -411,7 +411,7 @@ struct serializer
// remaining non-table values will be assigned into [foo.bar], not [foo]
for(const auto kv : v)
{
if(kv.second.is(value_t::Table) || is_array_of_tables(kv.second))
if(kv.second.is_table() || is_array_of_tables(kv.second))
{
continue;
}
@@ -438,7 +438,7 @@ struct serializer
bool multiline_table_printed = false;
for(const auto& kv : v)
{
if(!kv.second.is(value_t::Table) && !is_array_of_tables(kv.second))
if(!kv.second.is_table() && !is_array_of_tables(kv.second))
{
continue; // other stuff are already serialized. skip them.
}
@@ -467,10 +467,9 @@ struct serializer
bool is_array_of_tables(const value& v) const
{
if(!v.is(value_t::Array)) {return false;}
const auto& a = v.cast<value_t::Array>();
return !a.empty() && a.front().is(value_t::Table);
if(!v.is_array()) {return false;}
const auto& a = v.as_array();
return !a.empty() && a.front().is_table();
}
private:

View File

@@ -131,30 +131,30 @@ template<> struct toml_default_type<value_t::Table > {typedef table
template<> struct toml_default_type<value_t::Empty > {typedef void type;};
template<> struct toml_default_type<value_t::Unknown > {typedef void type;};
template<typename T> struct toml_value_t {static constexpr value_t value = value_t::Unknown ;};
template<> struct toml_value_t<Boolean >{static constexpr value_t value = value_t::Boolean ;};
template<> struct toml_value_t<Integer >{static constexpr value_t value = value_t::Integer ;};
template<> struct toml_value_t<Float >{static constexpr value_t value = value_t::Float ;};
template<> struct toml_value_t<String >{static constexpr value_t value = value_t::String ;};
template<> struct toml_value_t<OffsetDatetime>{static constexpr value_t value = value_t::OffsetDatetime;};
template<> struct toml_value_t<LocalDatetime >{static constexpr value_t value = value_t::LocalDatetime ;};
template<> struct toml_value_t<LocalDate >{static constexpr value_t value = value_t::LocalDate ;};
template<> struct toml_value_t<LocalTime >{static constexpr value_t value = value_t::LocalTime ;};
template<> struct toml_value_t<Array >{static constexpr value_t value = value_t::Array ;};
template<> struct toml_value_t<Table >{static constexpr value_t value = value_t::Table ;};
template<typename T> struct toml_value_t {static constexpr value_t value = value_t::Unknown ;};
template<> struct toml_value_t<boolean >{static constexpr value_t value = value_t::Boolean ;};
template<> struct toml_value_t<integer >{static constexpr value_t value = value_t::Integer ;};
template<> struct toml_value_t<floating >{static constexpr value_t value = value_t::Float ;};
template<> struct toml_value_t<string >{static constexpr value_t value = value_t::String ;};
template<> struct toml_value_t<offset_datetime>{static constexpr value_t value = value_t::OffsetDatetime;};
template<> struct toml_value_t<local_datetime >{static constexpr value_t value = value_t::LocalDatetime ;};
template<> struct toml_value_t<local_date >{static constexpr value_t value = value_t::LocalDate ;};
template<> struct toml_value_t<local_time >{static constexpr value_t value = value_t::LocalTime ;};
template<> struct toml_value_t<array >{static constexpr value_t value = value_t::Array ;};
template<> struct toml_value_t<table >{static constexpr value_t value = value_t::Table ;};
template<typename T>
struct is_exact_toml_type : disjunction<
std::is_same<T, Boolean >,
std::is_same<T, Integer >,
std::is_same<T, Float >,
std::is_same<T, String >,
std::is_same<T, boolean >,
std::is_same<T, integer >,
std::is_same<T, floating >,
std::is_same<T, string >,
std::is_same<T, offset_datetime>,
std::is_same<T, local_datetime>,
std::is_same<T, local_date>,
std::is_same<T, local_time>,
std::is_same<T, Array >,
std::is_same<T, Table >
std::is_same<T, local_datetime >,
std::is_same<T, local_date >,
std::is_same<T, local_time >,
std::is_same<T, array >,
std::is_same<T, table >
>{};
template<typename T> struct is_exact_toml_type<T&> : is_exact_toml_type<T>{};
template<typename T> struct is_exact_toml_type<T const&> : is_exact_toml_type<T>{};

View File

@@ -79,7 +79,7 @@ std::string concat_to_string(Ts&& ... args)
template<typename T, typename U>
T from_string(const std::string& str, U&& opt)
{
T v(std::forward<U>(opt));
T v(static_cast<T>(std::forward<U>(opt)));
std::istringstream iss(str);
iss >> v;
return v;

View File

@@ -48,6 +48,7 @@ class value
{
const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
assert(tmp == std::addressof(dst));
(void)tmp;
}
using region_base = detail::region_base;
@@ -633,27 +634,38 @@ class value
template<value_t T>
typename detail::toml_default_type<T>::type&& cast() &&;
boolean const& as_boolean() const {return this->cast<value_t::Boolean >();}
integer const& as_integer() const {return this->cast<value_t::Integer >();}
floating const& as_float() const {return this->cast<value_t::Float >();}
string const& as_string() const {return this->cast<value_t::String >();}
offset_datetime const& as_offset_datetime() const {return this->cast<value_t::OffsetDatetime>();}
local_datetime const& as_local_datetime() const {return this->cast<value_t::LocalDatetime >();}
local_date const& as_local_date() const {return this->cast<value_t::LocalDate >();}
local_time const& as_local_time() const {return this->cast<value_t::LocalTime >();}
array const& as_array() const {return this->cast<value_t::Array >();}
table const& as_table() const {return this->cast<value_t::Table >();}
boolean const& as_boolean() const& noexcept {return this->boolean_;}
integer const& as_integer() const& noexcept {return this->integer_;}
floating const& as_float() const& noexcept {return this->floating_;}
string const& as_string() const& noexcept {return this->string_;}
offset_datetime const& as_offset_datetime() const& noexcept {return this->offset_datetime_;}
local_datetime const& as_local_datetime() const& noexcept {return this->local_datetime_;}
local_date const& as_local_date() const& noexcept {return this->local_date_;}
local_time const& as_local_time() const& noexcept {return this->local_time_;}
array const& as_array() const& noexcept {return this->array_.value();}
table const& as_table() const& noexcept {return this->table_.value();}
boolean& as_boolean() {return this->cast<value_t::Boolean >();}
integer& as_integer() {return this->cast<value_t::Integer >();}
floating& as_float() {return this->cast<value_t::Float >();}
string& as_string() {return this->cast<value_t::String >();}
offset_datetime& as_offset_datetime() {return this->cast<value_t::OffsetDatetime>();}
local_datetime& as_local_datetime() {return this->cast<value_t::LocalDatetime >();}
local_date& as_local_date() {return this->cast<value_t::LocalDate >();}
local_time& as_local_time() {return this->cast<value_t::LocalTime >();}
array& as_array() {return this->cast<value_t::Array >();}
table& as_table() {return this->cast<value_t::Table >();}
boolean & as_boolean() & noexcept {return this->boolean_;}
integer & as_integer() & noexcept {return this->integer_;}
floating & as_float() & noexcept {return this->floating_;}
string & as_string() & noexcept {return this->string_;}
offset_datetime& as_offset_datetime() & noexcept {return this->offset_datetime_;}
local_datetime & as_local_datetime() & noexcept {return this->local_datetime_;}
local_date & as_local_date() & noexcept {return this->local_date_;}
local_time & as_local_time() & noexcept {return this->local_time_;}
array & as_array() & noexcept {return this->array_.value();}
table & as_table() & noexcept {return this->table_.value();}
boolean && as_boolean() && noexcept {return std::move(this->boolean_);}
integer && as_integer() && noexcept {return std::move(this->integer_);}
floating && as_float() && noexcept {return std::move(this->floating_);}
string && as_string() && noexcept {return std::move(this->string_);}
offset_datetime&& as_offset_datetime() && noexcept {return std::move(this->offset_datetime_);}
local_datetime && as_local_datetime() && noexcept {return std::move(this->local_datetime_);}
local_date && as_local_date() && noexcept {return std::move(this->local_date_);}
local_time && as_local_time() && noexcept {return std::move(this->local_time_);}
array && as_array() && noexcept {return std::move(this->array_.value());}
table && as_table() && noexcept {return std::move(this->table_.value());}
std::string comment() const
{
@@ -687,9 +699,6 @@ class value
template<typename Region>
friend void detail::change_region(value&, Region&&);
template<value_t T>
struct switch_cast;
private:
using array_storage = detail::storage<array>;
@@ -735,107 +744,116 @@ void change_region(value& v, Region&& reg)
return;
}
}// detail
template<value_t Expected>
[[noreturn]] inline void throw_bad_cast(value_t actual, const ::toml::value& v)
{
throw type_error(detail::format_underline(concat_to_string(
"[error] toml::value bad_cast to ", Expected), {
{std::addressof(get_region(v)),
concat_to_string("the actual type is ", actual)}
}));
}
template<> struct value::switch_cast<value_t::Boolean>
template<value_t T>
struct switch_cast;
template<>
struct switch_cast<value_t::Boolean>
{
static Boolean& invoke(value& v) {return v.boolean_;}
static Boolean const& invoke(value const& v) {return v.boolean_;}
static Boolean&& invoke(value&& v) {return std::move(v.boolean_);}
static ::toml::boolean& invoke(value& v) {return v.as_boolean();}
static ::toml::boolean const& invoke(value const& v) {return v.as_boolean();}
static ::toml::boolean&& invoke(value&& v) {return std::move(v).as_boolean();}
};
template<> struct value::switch_cast<value_t::Integer>
template<>
struct switch_cast<value_t::Integer>
{
static Integer& invoke(value& v) {return v.integer_;}
static Integer const& invoke(value const& v) {return v.integer_;}
static Integer&& invoke(value&& v) {return std::move(v.integer_);}
static ::toml::integer& invoke(value& v) {return v.as_integer();}
static ::toml::integer const& invoke(value const& v) {return v.as_integer();}
static ::toml::integer&& invoke(value&& v) {return std::move(v).as_integer();}
};
template<> struct value::switch_cast<value_t::Float>
template<>
struct switch_cast<value_t::Float>
{
static Float& invoke(value& v) {return v.floating_;}
static Float const& invoke(value const& v) {return v.floating_;}
static Float&& invoke(value&& v) {return std::move(v.floating_);}
static ::toml::floating& invoke(value& v) {return v.as_float();}
static ::toml::floating const& invoke(value const& v) {return v.as_float();}
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_float();}
};
template<> struct value::switch_cast<value_t::String>
template<>
struct switch_cast<value_t::String>
{
static String& invoke(value& v) {return v.string_;}
static String const& invoke(value const& v) {return v.string_;}
static String&& invoke(value&& v) {return std::move(v.string_);}
static ::toml::string& invoke(value& v) {return v.as_string();}
static ::toml::string const& invoke(value const& v) {return v.as_string();}
static ::toml::string&& invoke(value&& v) {return std::move(v).as_string();}
};
template<> struct value::switch_cast<value_t::OffsetDatetime>
template<>
struct switch_cast<value_t::OffsetDatetime>
{
static OffsetDatetime& invoke(value& v) {return v.offset_datetime_;}
static OffsetDatetime const& invoke(value const& v) {return v.offset_datetime_;}
static OffsetDatetime&& invoke(value&& v) {return std::move(v.offset_datetime_);}
static ::toml::offset_datetime& invoke(value& v) {return v.as_offset_datetime();}
static ::toml::offset_datetime const& invoke(value const& v) {return v.as_offset_datetime();}
static ::toml::offset_datetime&& invoke(value&& v) {return std::move(v).as_offset_datetime();}
};
template<> struct value::switch_cast<value_t::LocalDatetime>
template<>
struct switch_cast<value_t::LocalDatetime>
{
static LocalDatetime& invoke(value& v) {return v.local_datetime_;}
static LocalDatetime const& invoke(value const& v) {return v.local_datetime_;}
static LocalDatetime&& invoke(value&& v) {return std::move(v.local_datetime_);}
static ::toml::local_datetime& invoke(value& v) {return v.as_local_datetime();}
static ::toml::local_datetime const& invoke(value const& v) {return v.as_local_datetime();}
static ::toml::local_datetime&& invoke(value&& v) {return std::move(v).as_local_datetime();}
};
template<> struct value::switch_cast<value_t::LocalDate>
template<>
struct switch_cast<value_t::LocalDate>
{
static LocalDate& invoke(value& v) {return v.local_date_;}
static LocalDate const& invoke(value const& v) {return v.local_date_;}
static LocalDate&& invoke(value&& v) {return std::move(v.local_date_);}
static ::toml::local_date& invoke(value& v) {return v.as_local_date();}
static ::toml::local_date const& invoke(value const& v) {return v.as_local_date();}
static ::toml::local_date&& invoke(value&& v) {return std::move(v).as_local_date();}
};
template<> struct value::switch_cast<value_t::LocalTime>
template<>
struct switch_cast<value_t::LocalTime>
{
static LocalTime& invoke(value& v) {return v.local_time_;}
static LocalTime const& invoke(value const& v) {return v.local_time_;}
static LocalTime&& invoke(value&& v) {return std::move(v.local_time_);}
static ::toml::local_time& invoke(value& v) {return v.as_local_time();}
static ::toml::local_time const& invoke(value const& v) {return v.as_local_time();}
static ::toml::local_time&& invoke(value&& v) {return std::move(v).as_local_time();}
};
template<> struct value::switch_cast<value_t::Array>
template<>
struct switch_cast<value_t::Array>
{
static Array& invoke(value& v) {return v.array_.value();}
static Array const& invoke(value const& v) {return v.array_.value();}
static Array&& invoke(value&& v) {return std::move(v.array_.value());}
static ::toml::array& invoke(value& v) {return v.as_array();}
static ::toml::array const& invoke(value const& v) {return v.as_array();}
static ::toml::array&& invoke(value&& v) {return std::move(v).as_array();}
};
template<> struct value::switch_cast<value_t::Table>
template<>
struct switch_cast<value_t::Table>
{
static Table& invoke(value& v) {return v.table_.value();}
static Table const& invoke(value const& v) {return v.table_.value();}
static Table&& invoke(value&& v) {return std::move(v.table_.value());}
static ::toml::table& invoke(value& v) {return v.as_table();}
static ::toml::table const& invoke(value const& v) {return v.as_table();}
static ::toml::table&& invoke(value&& v) {return std::move(v).as_table();}
};
}// detail
template<value_t T>
typename detail::toml_default_type<T>::type& value::cast() &
{
if(T != this->type_)
{
throw type_error(detail::format_underline(concat_to_string(
"[error] toml::value bad_cast to ", T), {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}));
detail::throw_bad_cast<T>(this->type_, *this);
}
return switch_cast<T>::invoke(*this);
return detail::switch_cast<T>::invoke(*this);
}
template<value_t T>
typename detail::toml_default_type<T>::type const& value::cast() const&
{
if(T != this->type_)
{
throw type_error(detail::format_underline(concat_to_string(
"[error] toml::value bad_cast to ", T), {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}));
detail::throw_bad_cast<T>(this->type_, *this);
}
return switch_cast<T>::invoke(*this);
return detail::switch_cast<T>::invoke(*this);
}
template<value_t T>
typename detail::toml_default_type<T>::type&& value::cast() &&
{
if(T != this->type_)
{
throw type_error(detail::format_underline(concat_to_string(
"[error] toml::value bad_cast to ", T), {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}));
detail::throw_bad_cast<T>(this->type_, *this);
}
return switch_cast<T>::invoke(std::move(*this));
return detail::switch_cast<T>::invoke(std::move(*this));
}
inline bool operator==(const toml::value& lhs, const toml::value& rhs)
@@ -844,28 +862,48 @@ inline bool operator==(const toml::value& lhs, const toml::value& rhs)
switch(lhs.type())
{
case value_t::Boolean :
return lhs.cast<value_t::Boolean >() == rhs.cast<value_t::Boolean >();
{
return lhs.as_boolean() == rhs.as_boolean();
}
case value_t::Integer :
return lhs.cast<value_t::Integer >() == rhs.cast<value_t::Integer >();
{
return lhs.as_integer() == rhs.as_integer();
}
case value_t::Float :
return lhs.cast<value_t::Float >() == rhs.cast<value_t::Float >();
{
return lhs.as_float() == rhs.as_float();
}
case value_t::String :
return lhs.cast<value_t::String >() == rhs.cast<value_t::String >();
{
return lhs.as_string() == rhs.as_string();
}
case value_t::OffsetDatetime:
return lhs.cast<value_t::OffsetDatetime>() == rhs.cast<value_t::OffsetDatetime>();
{
return lhs.as_offset_datetime() == rhs.as_offset_datetime();
}
case value_t::LocalDatetime:
return lhs.cast<value_t::LocalDatetime>() == rhs.cast<value_t::LocalDatetime>();
{
return lhs.as_local_datetime() == rhs.as_local_datetime();
}
case value_t::LocalDate:
return lhs.cast<value_t::LocalDate>() == rhs.cast<value_t::LocalDate>();
{
return lhs.as_local_date() == rhs.as_local_date();
}
case value_t::LocalTime:
return lhs.cast<value_t::LocalTime>() == rhs.cast<value_t::LocalTime>();
{
return lhs.as_local_time() == rhs.as_local_time();
}
case value_t::Array :
return lhs.cast<value_t::Array >() == rhs.cast<value_t::Array >();
{
return lhs.as_array() == rhs.as_array();
}
case value_t::Table :
return lhs.cast<value_t::Table >() == rhs.cast<value_t::Table >();
case value_t::Empty : return true;
case value_t::Unknown : return false;
default: return false;
{
return lhs.as_table() == rhs.as_table();
}
case value_t::Empty : {return true; }
case value_t::Unknown : {return false;}
default: {return false;}
}
}
inline bool operator<(const toml::value& lhs, const toml::value& rhs)
@@ -874,28 +912,48 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
switch(lhs.type())
{
case value_t::Boolean :
return lhs.cast<value_t::Boolean >() < rhs.cast<value_t::Boolean >();
{
return lhs.as_boolean() < rhs.as_boolean();
}
case value_t::Integer :
return lhs.cast<value_t::Integer >() < rhs.cast<value_t::Integer >();
{
return lhs.as_integer() < rhs.as_integer();
}
case value_t::Float :
return lhs.cast<value_t::Float >() < rhs.cast<value_t::Float >();
{
return lhs.as_float() < rhs.as_float();
}
case value_t::String :
return lhs.cast<value_t::String >() < rhs.cast<value_t::String >();
{
return lhs.as_string() < rhs.as_string();
}
case value_t::OffsetDatetime:
return lhs.cast<value_t::OffsetDatetime>() < rhs.cast<value_t::OffsetDatetime>();
{
return lhs.as_offset_datetime() < rhs.as_offset_datetime();
}
case value_t::LocalDatetime:
return lhs.cast<value_t::LocalDatetime>() < rhs.cast<value_t::LocalDatetime>();
{
return lhs.as_local_datetime() < rhs.as_local_datetime();
}
case value_t::LocalDate:
return lhs.cast<value_t::LocalDate>() < rhs.cast<value_t::LocalDate>();
{
return lhs.as_local_date() < rhs.as_local_date();
}
case value_t::LocalTime:
return lhs.cast<value_t::LocalTime>() < rhs.cast<value_t::LocalTime>();
{
return lhs.as_local_time() < rhs.as_local_time();
}
case value_t::Array :
return lhs.cast<value_t::Array >() < rhs.cast<value_t::Array >();
{
return lhs.as_array() < rhs.as_array();
}
case value_t::Table :
return lhs.cast<value_t::Table >() < rhs.cast<value_t::Table >();
case value_t::Empty : return false;
case value_t::Unknown : return false;
default: return false;
{
return lhs.as_table() < rhs.as_table();
}
case value_t::Empty : {return false;}
case value_t::Unknown : {return false;}
default: {return false;}
}
}
@@ -958,16 +1016,16 @@ visit(Visitor&& visitor, const toml::value& v)
{
switch(v.type())
{
case value_t::Boolean : {return visitor(v.cast<value_t::Boolean >());}
case value_t::Integer : {return visitor(v.cast<value_t::Integer >());}
case value_t::Float : {return visitor(v.cast<value_t::Float >());}
case value_t::String : {return visitor(v.cast<value_t::String >());}
case value_t::OffsetDatetime: {return visitor(v.cast<value_t::OffsetDatetime>());}
case value_t::LocalDatetime : {return visitor(v.cast<value_t::LocalDatetime >());}
case value_t::LocalDate : {return visitor(v.cast<value_t::LocalDate >());}
case value_t::LocalTime : {return visitor(v.cast<value_t::LocalTime >());}
case value_t::Array : {return visitor(v.cast<value_t::Array >());}
case value_t::Table : {return visitor(v.cast<value_t::Table >());}
case value_t::Boolean : {return visitor(v.as_boolean ());}
case value_t::Integer : {return visitor(v.as_integer ());}
case value_t::Float : {return visitor(v.as_float ());}
case value_t::String : {return visitor(v.as_string ());}
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
case value_t::LocalDate : {return visitor(v.as_local_date ());}
case value_t::LocalTime : {return visitor(v.as_local_time ());}
case value_t::Array : {return visitor(v.as_array ());}
case value_t::Table : {return visitor(v.as_table ());}
case value_t::Empty : break;
case value_t::Unknown : break;
default: break;
@@ -982,16 +1040,16 @@ visit(Visitor&& visitor, toml::value& v)
{
switch(v.type())
{
case value_t::Boolean : {return visitor(v.cast<value_t::Boolean >());}
case value_t::Integer : {return visitor(v.cast<value_t::Integer >());}
case value_t::Float : {return visitor(v.cast<value_t::Float >());}
case value_t::String : {return visitor(v.cast<value_t::String >());}
case value_t::OffsetDatetime: {return visitor(v.cast<value_t::OffsetDatetime>());}
case value_t::LocalDatetime : {return visitor(v.cast<value_t::LocalDatetime >());}
case value_t::LocalDate : {return visitor(v.cast<value_t::LocalDate >());}
case value_t::LocalTime : {return visitor(v.cast<value_t::LocalTime >());}
case value_t::Array : {return visitor(v.cast<value_t::Array >());}
case value_t::Table : {return visitor(v.cast<value_t::Table >());}
case value_t::Boolean : {return visitor(v.as_boolean ());}
case value_t::Integer : {return visitor(v.as_integer ());}
case value_t::Float : {return visitor(v.as_float ());}
case value_t::String : {return visitor(v.as_string ());}
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
case value_t::LocalDate : {return visitor(v.as_local_date ());}
case value_t::LocalTime : {return visitor(v.as_local_time ());}
case value_t::Array : {return visitor(v.as_array ());}
case value_t::Table : {return visitor(v.as_table ());}
case value_t::Empty : break;
case value_t::Unknown : break;
default: break;
@@ -1006,16 +1064,16 @@ visit(Visitor&& visitor, toml::value&& v)
{
switch(v.type())
{
case value_t::Boolean : {return visitor(std::move(v.cast<value_t::Boolean >()));}
case value_t::Integer : {return visitor(std::move(v.cast<value_t::Integer >()));}
case value_t::Float : {return visitor(std::move(v.cast<value_t::Float >()));}
case value_t::String : {return visitor(std::move(v.cast<value_t::String >()));}
case value_t::OffsetDatetime: {return visitor(std::move(v.cast<value_t::OffsetDatetime>()));}
case value_t::LocalDatetime : {return visitor(std::move(v.cast<value_t::LocalDatetime >()));}
case value_t::LocalDate : {return visitor(std::move(v.cast<value_t::LocalDate >()));}
case value_t::LocalTime : {return visitor(std::move(v.cast<value_t::LocalTime >()));}
case value_t::Array : {return visitor(std::move(v.cast<value_t::Array >()));}
case value_t::Table : {return visitor(std::move(v.cast<value_t::Table >()));}
case value_t::Boolean : {return visitor(std::move(v.as_boolean ()));}
case value_t::Integer : {return visitor(std::move(v.as_integer ()));}
case value_t::Float : {return visitor(std::move(v.as_float ()));}
case value_t::String : {return visitor(std::move(v.as_string ()));}
case value_t::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));}
case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));}
case value_t::LocalDate : {return visitor(std::move(v.as_local_date ()));}
case value_t::LocalTime : {return visitor(std::move(v.as_local_time ()));}
case value_t::Array : {return visitor(std::move(v.as_array ()));}
case value_t::Table : {return visitor(std::move(v.as_table ()));}
case value_t::Empty : break;
case value_t::Unknown : break;
default: break;