parse/enum: allow translation of enum string to integer with typeidx
This commit is contained in:
parent
5e3af7f8fb
commit
cc7d4eb0a9
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace cruft::parse::detail::enumeration {
|
namespace cruft::parse::enumeration::detail {
|
||||||
std::map<int, std::unique_ptr<lookup_base>>&
|
std::map<int, std::unique_ptr<lookup_base>>&
|
||||||
cache (void)
|
cache (void)
|
||||||
{
|
{
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace cruft::parse {
|
namespace cruft::parse::enumeration {
|
||||||
namespace detail::enumeration {
|
namespace detail {
|
||||||
struct lookup_base {
|
struct lookup_base {
|
||||||
virtual ~lookup_base () = default;
|
virtual ~lookup_base () = default;
|
||||||
|
|
||||||
@ -77,16 +77,25 @@ namespace cruft::parse {
|
|||||||
|
|
||||||
|
|
||||||
std::map<int, std::unique_ptr<lookup_base>>& cache (void);
|
std::map<int, std::unique_ptr<lookup_base>>& cache (void);
|
||||||
}
|
|
||||||
|
template <typename EnumT, typename = void>
|
||||||
|
struct underlying_else_identity { using type = EnumT; };
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
struct underlying_else_identity<
|
||||||
|
EnumT,
|
||||||
|
std::enable_if_t<std::is_enum_v<EnumT>>
|
||||||
|
> { using type = std::underlying_type_t<EnumT>; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename EnumT>
|
template <typename EnumT>
|
||||||
void setup (std::map<std::string_view, EnumT> mapping)
|
void setup (std::map<std::string_view, EnumT> mapping)
|
||||||
{
|
{
|
||||||
auto &cache = detail::enumeration::cache ();
|
auto &cache = detail::cache ();
|
||||||
|
|
||||||
auto const index = cruft::typeidx<EnumT> ();
|
auto const index = cruft::typeidx<EnumT> ();
|
||||||
auto lookup = std::make_unique<detail::enumeration::lookup_concrete<EnumT>> (std::move (mapping));
|
auto lookup = std::make_unique<detail::lookup_concrete<EnumT>> (std::move (mapping));
|
||||||
|
|
||||||
auto [pos, success] = cache.insert ({ index, std::move (lookup) });
|
auto [pos, success] = cache.insert ({ index, std::move (lookup) });
|
||||||
if (!success)
|
if (!success)
|
||||||
@ -96,10 +105,9 @@ namespace cruft::parse {
|
|||||||
|
|
||||||
template <typename EnumT>
|
template <typename EnumT>
|
||||||
EnumT
|
EnumT
|
||||||
enumeration (cruft::view<char const*> &str)
|
value (int const idx, cruft::view<char const*> &str)
|
||||||
{
|
{
|
||||||
auto const idx = cruft::typeidx<EnumT> ();
|
auto const ® = detail::cache ();
|
||||||
auto const ® = detail::enumeration::cache ();
|
|
||||||
auto const pos = reg.find (idx);
|
auto const pos = reg.find (idx);
|
||||||
|
|
||||||
if (pos == reg.cend ())
|
if (pos == reg.cend ())
|
||||||
@ -114,7 +122,10 @@ namespace cruft::parse {
|
|||||||
sizeof (EnumT) == 8
|
sizeof (EnumT) == 8
|
||||||
);
|
);
|
||||||
|
|
||||||
if constexpr (std::is_signed_v<std::underlying_type_t<EnumT>>) {
|
using underlying_type = typename detail::underlying_else_identity<EnumT>::type;
|
||||||
|
static_assert (std::is_integral_v<underlying_type>);
|
||||||
|
|
||||||
|
if constexpr (std::is_signed_v<underlying_type>) {
|
||||||
if constexpr (sizeof (EnumT) == 1) return static_cast<EnumT> (obj.as_i08 (str));
|
if constexpr (sizeof (EnumT) == 1) return static_cast<EnumT> (obj.as_i08 (str));
|
||||||
if constexpr (sizeof (EnumT) == 2) return static_cast<EnumT> (obj.as_i16 (str));
|
if constexpr (sizeof (EnumT) == 2) return static_cast<EnumT> (obj.as_i16 (str));
|
||||||
if constexpr (sizeof (EnumT) == 4) return static_cast<EnumT> (obj.as_i32 (str));
|
if constexpr (sizeof (EnumT) == 4) return static_cast<EnumT> (obj.as_i32 (str));
|
||||||
@ -130,4 +141,31 @@ namespace cruft::parse {
|
|||||||
unreachable ();
|
unreachable ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
EnumT
|
||||||
|
value (cruft::view<char const*> &str)
|
||||||
|
{
|
||||||
|
return value<EnumT> (typeidx<EnumT> (), str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
EnumT
|
||||||
|
from_string (int const idx, cruft::view<char const*> src)
|
||||||
|
{
|
||||||
|
auto const res = value<EnumT> (idx, src);
|
||||||
|
if (!src.empty ())
|
||||||
|
throw std::runtime_error ("Invalid conversion");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
EnumT
|
||||||
|
from_string (cruft::view<char const*> src)
|
||||||
|
{
|
||||||
|
return from_string<EnumT> (typeidx<EnumT> (), src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,18 +31,15 @@ namespace cruft::parse {
|
|||||||
T
|
T
|
||||||
from_string (cruft::view<const char*> data)
|
from_string (cruft::view<const char*> data)
|
||||||
{
|
{
|
||||||
T res = [&] () {
|
|
||||||
if constexpr (std::is_enum_v<T>) {
|
if constexpr (std::is_enum_v<T>) {
|
||||||
return enumeration<T> (data);
|
return enumeration::from_string<T> (data);
|
||||||
} else {
|
} else {
|
||||||
return value<T> (data);
|
T res = value<T> (data);
|
||||||
}
|
|
||||||
} ();
|
|
||||||
|
|
||||||
if (!data.empty ())
|
if (!data.empty ())
|
||||||
throw std::invalid_argument ("unable to parse");
|
throw std::invalid_argument ("unable to parse");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> T from_string (const char *data) { return from_string<T> (cruft::view (data)); }
|
template <typename T> T from_string (const char *data) { return from_string<T> (cruft::view (data)); }
|
||||||
template <typename T> T from_string (std::string const &data) { return from_string<T> (cruft::view (data)); }
|
template <typename T> T from_string (std::string const &data) { return from_string<T> (cruft::view (data)); }
|
||||||
|
@ -7,7 +7,7 @@ enum enumeration_t : u16 { FOO, BAR = 2, QUX = 257 };
|
|||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
cruft::parse::setup<enumeration_t> ({
|
cruft::parse::enumeration::setup<enumeration_t> ({
|
||||||
{ "FOO", FOO },
|
{ "FOO", FOO },
|
||||||
{ "BAR", BAR },
|
{ "BAR", BAR },
|
||||||
{ "QUX", QUX },
|
{ "QUX", QUX },
|
||||||
@ -17,5 +17,14 @@ int main ()
|
|||||||
tap.expect_eq (FOO, cruft::parse::from_string<enumeration_t> ("FOO"), "enumeration, FOO");
|
tap.expect_eq (FOO, cruft::parse::from_string<enumeration_t> ("FOO"), "enumeration, FOO");
|
||||||
tap.expect_eq (BAR, cruft::parse::from_string<enumeration_t> ("BAR"), "enumeration, BAR");
|
tap.expect_eq (BAR, cruft::parse::from_string<enumeration_t> ("BAR"), "enumeration, BAR");
|
||||||
tap.expect_eq (QUX, cruft::parse::from_string<enumeration_t> ("QUX"), "enumeration, QUX");
|
tap.expect_eq (QUX, cruft::parse::from_string<enumeration_t> ("QUX"), "enumeration, QUX");
|
||||||
|
|
||||||
|
tap.expect_eq (
|
||||||
|
u16 {QUX},
|
||||||
|
cruft::parse::enumeration::from_string<u16> (
|
||||||
|
cruft::typeidx<enumeration_t> (),
|
||||||
|
"QUX"
|
||||||
|
),
|
||||||
|
"u16, QUX"
|
||||||
|
);
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user