mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
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.
This commit is contained in:
@@ -56,19 +56,19 @@ struct character
|
|||||||
static constexpr char target = C;
|
static constexpr char target = C;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return err('\0');}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
|
|
||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c != target)
|
if(c != target)
|
||||||
{
|
{
|
||||||
return err(c);
|
return none();
|
||||||
}
|
}
|
||||||
loc.advance(); // update location
|
loc.advance(); // update location
|
||||||
|
|
||||||
@@ -89,19 +89,19 @@ struct in_range
|
|||||||
static constexpr char lower = Low;
|
static constexpr char lower = Low;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return err('\0');}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
|
|
||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c < lower || upper < c)
|
if(c < lower || upper < c)
|
||||||
{
|
{
|
||||||
return err(c);
|
return none();
|
||||||
}
|
}
|
||||||
|
|
||||||
loc.advance();
|
loc.advance();
|
||||||
@@ -117,20 +117,20 @@ template<typename Combinator>
|
|||||||
struct exclude
|
struct exclude
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return err('\0');}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
auto first = loc.iter();
|
auto first = loc.iter();
|
||||||
|
|
||||||
auto rslt = Combinator::invoke(loc);
|
auto rslt = Combinator::invoke(loc);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(*first);
|
return none();
|
||||||
}
|
}
|
||||||
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
@@ -142,7 +142,7 @@ template<typename Combinator>
|
|||||||
struct maybe
|
struct maybe
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
@@ -164,7 +164,7 @@ template<typename Head, typename ... Tail>
|
|||||||
struct sequence<Head, Tail...>
|
struct sequence<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
@@ -175,21 +175,21 @@ struct sequence<Head, Tail...>
|
|||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from the above function only, recursively.
|
// called from the above function only, recursively.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
reg += rslt.unwrap(); // concat regions
|
reg += rslt.unwrap(); // concat regions
|
||||||
return sequence<Tail...>::invoke(loc, std::move(reg), first);
|
return sequence<Tail...>::invoke(loc, std::move(reg), first);
|
||||||
@@ -201,14 +201,14 @@ struct sequence<Head>
|
|||||||
{
|
{
|
||||||
// would be called from sequence<T ...>::invoke only.
|
// would be called from sequence<T ...>::invoke only.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
reg += rslt.unwrap(); // concat regions
|
reg += rslt.unwrap(); // concat regions
|
||||||
return ok(reg);
|
return ok(reg);
|
||||||
@@ -222,7 +222,7 @@ template<typename Head, typename ... Tail>
|
|||||||
struct either<Head, Tail...>
|
struct either<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
@@ -237,7 +237,7 @@ template<typename Head>
|
|||||||
struct either<Head>
|
struct either<Head>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
@@ -257,7 +257,7 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, exactly<N>>
|
struct repeat<T, exactly<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
@@ -268,7 +268,7 @@ struct repeat<T, exactly<N>>
|
|||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
retval += rslt.unwrap();
|
retval += rslt.unwrap();
|
||||||
}
|
}
|
||||||
@@ -280,7 +280,7 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, at_least<N>>
|
struct repeat<T, at_least<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
@@ -292,7 +292,7 @@ struct repeat<T, at_least<N>>
|
|||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
retval += rslt.unwrap();
|
retval += rslt.unwrap();
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ template<typename T>
|
|||||||
struct repeat<T, unlimited>
|
struct repeat<T, unlimited>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, char>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc)
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ parse_ml_basic_string(location<Container>& loc)
|
|||||||
// immediate newline is ignored (if exists)
|
// immediate newline is ignored (if exists)
|
||||||
/* discard return value */ lex_newline::invoke(inner_loc);
|
/* discard return value */ lex_newline::invoke(inner_loc);
|
||||||
|
|
||||||
delim = err('\0');
|
delim = none();
|
||||||
while(!delim)
|
while(!delim)
|
||||||
{
|
{
|
||||||
using lex_unescaped_seq = repeat<
|
using lex_unescaped_seq = repeat<
|
||||||
@@ -432,7 +432,7 @@ parse_basic_string(location<Container>& loc)
|
|||||||
std::string retval;
|
std::string retval;
|
||||||
retval.reserve(token.unwrap().size());
|
retval.reserve(token.unwrap().size());
|
||||||
|
|
||||||
quot = err('\0');
|
quot = none();
|
||||||
while(!quot)
|
while(!quot)
|
||||||
{
|
{
|
||||||
using lex_unescaped_seq = repeat<lex_basic_unescaped, unlimited>;
|
using lex_unescaped_seq = repeat<lex_basic_unescaped, unlimited>;
|
||||||
|
|||||||
@@ -692,5 +692,26 @@ void swap(result<T, E>& lhs, result<T, E>& rhs)
|
|||||||
// return lhs.is_ok() ? lhs : 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
|
} // toml11
|
||||||
#endif// TOML11_RESULT_H
|
#endif// TOML11_RESULT_H
|
||||||
|
|||||||
Reference in New Issue
Block a user