0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-02-18 17:50:16 +01:00

ircd: Add labeled-params tokenizer; fix bad lexical cast exception type.

This commit is contained in:
Jason Volk 2017-03-16 13:31:17 -07:00
parent 150583c711
commit 03cf816bb7
2 changed files with 94 additions and 0 deletions
include/ircd
ircd

View file

@ -28,6 +28,7 @@ namespace ircd {
//
// Lexical conversions
//
IRCD_EXCEPTION(ircd::error, bad_lex_cast)
template<class T> bool try_lex_cast(const string_view &);
template<> bool try_lex_cast<long double>(const string_view &);
@ -130,6 +131,29 @@ string_view token(const string_view &str, const char *const &sep, const size_t &
string_view token_last(const string_view &str, const char *const &sep);
string_view token_first(const string_view &str, const char *const &sep);
class params
{
string_view in;
const char *sep;
std::initializer_list<const char *> names;
const char *name(const size_t &i) const;
public:
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, missing)
IRCD_EXCEPTION(error, invalid)
string_view operator[](const size_t &i) const; // returns empty
template<class T> T at(const size_t &i, const T &def) const; // throws invalid
template<class T> T at(const size_t &i) const; // throws missing or invalid
string_view at(const size_t &i) const; // throws missing
params(const string_view &in,
const char *const &sep,
const std::initializer_list<const char *> &names = {});
};
//
// Misc utils
//
@ -256,6 +280,66 @@ ircd::chomp(const string_view &str,
return str.substr(0, pos + 1);
}
inline
ircd::params::params(const string_view &in,
const char *const &sep,
const std::initializer_list<const char *> &names)
:in{in}
,sep{sep}
,names{names}
{
}
template<class T>
T
ircd::params::at(const size_t &i,
const T &def)
const try
{
return tokens_count(in, sep) > i? at<T>(i) : def;
}
catch(const bad_lex_cast &e)
{
throw invalid("parameter #%zu \"%s\"", i, name(i));
}
template<class T>
T
ircd::params::at(const size_t &i)
const try
{
return lex_cast<T>(at(i));
}
catch(const bad_lex_cast &e)
{
throw invalid("parameter #%zu \"%s\"", i, name(i));
}
inline ircd::string_view
ircd::params::at(const size_t &i)
const try
{
return token(in, sep, i);
}
catch(const std::out_of_range &e)
{
throw missing("required parameter #%zu \"%s\"", i, name(i));
}
inline ircd::string_view
ircd::params::operator[](const size_t &i)
const
{
return tokens_count(in, sep) > i? token(in, sep, i) : string_view{};
}
inline const char *
ircd::params::name(const size_t &i)
const
{
return names.size() > i? *std::next(begin(names), i) : "<unlabeled>";
}
template<size_t N>
size_t
ircd::tokens(const string_view &str,

View file

@ -150,6 +150,7 @@ static string_view
_lex_cast(const T &i,
char *buf,
size_t max)
try
{
using array = std::array<char, N>;
@ -166,13 +167,22 @@ _lex_cast(const T &i,
a = boost::lexical_cast<array>(i);
return { buf, strnlen(buf, max) };
}
catch(const boost::bad_lexical_cast &e)
{
throw ircd::bad_lex_cast("%s", e.what());
}
template<class T>
static T
_lex_cast(const string_view &s)
try
{
return boost::lexical_cast<T>(s);
}
catch(const boost::bad_lexical_cast &e)
{
throw ircd::bad_lex_cast("%s", e.what());
}
} // namespace ircd