parse/enum: add lookup-by-function
This commit is contained in:
parent
e4c224ceaa
commit
458654c9a3
@ -60,6 +60,47 @@ namespace cruft::parse::enumeration {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
struct lookup_callback : public lookup_base {
|
||||||
|
using function_t = std::function<EnumT(cruft::view<char const*>&)>;
|
||||||
|
|
||||||
|
lookup_callback (
|
||||||
|
function_t &&_callback
|
||||||
|
) : m_callback (std::move (_callback))
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
i08 as_i08 (cruft::view<char const*> &str) const& override { return get<i08> (str); }
|
||||||
|
i16 as_i16 (cruft::view<char const*> &str) const& override { return get<i16> (str); }
|
||||||
|
i32 as_i32 (cruft::view<char const*> &str) const& override { return get<i32> (str); }
|
||||||
|
i64 as_i64 (cruft::view<char const*> &str) const& override { return get<i64> (str); }
|
||||||
|
|
||||||
|
u08 as_u08 (cruft::view<char const*> &str) const& override { return get<u08> (str); }
|
||||||
|
u16 as_u16 (cruft::view<char const*> &str) const& override { return get<u16> (str); }
|
||||||
|
u32 as_u32 (cruft::view<char const*> &str) const& override { return get<u32> (str); }
|
||||||
|
u64 as_u64 (cruft::view<char const*> &str) const& override { return get<u64> (str); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename ValueT>
|
||||||
|
ValueT
|
||||||
|
get (cruft::view<char const*> &str) const&
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<ValueT, underlying_else_identity_t<EnumT>>) {
|
||||||
|
// Double check the callee changes the remaining string size.
|
||||||
|
auto const len = str.size ();
|
||||||
|
auto const res = m_callback (str);
|
||||||
|
if (len == str.size ())
|
||||||
|
throw std::invalid_argument ("Unknown enum value");
|
||||||
|
return static_cast<ValueT> (res);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error ("Invalid underlying type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function_t m_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// A simple lookup from a supplied mapping of strings-to-underlying,
|
/// A simple lookup from a supplied mapping of strings-to-underlying,
|
||||||
/// specialised on the EnumT that the lookup is targetting.
|
/// specialised on the EnumT that the lookup is targetting.
|
||||||
template <typename EnumT>
|
template <typename EnumT>
|
||||||
@ -118,6 +159,25 @@ namespace cruft::parse::enumeration {
|
|||||||
std::unique_ptr<lookup_base>
|
std::unique_ptr<lookup_base>
|
||||||
>&
|
>&
|
||||||
cache (void);
|
cache (void);
|
||||||
|
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
cookie
|
||||||
|
setup [[nodiscard]] (std::unique_ptr<lookup_base> &&lookup)
|
||||||
|
{
|
||||||
|
auto &cache = detail::cache ();
|
||||||
|
auto const index = cruft::typeidx<EnumT> ();
|
||||||
|
|
||||||
|
auto [pos, success] = cache.insert ({
|
||||||
|
index,
|
||||||
|
std::move (lookup)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
LOG_WARN ("duplicate parse setup for %! was ignored", cruft::type_name<EnumT> ());
|
||||||
|
|
||||||
|
return cookie {};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -131,19 +191,26 @@ namespace cruft::parse::enumeration {
|
|||||||
cookie
|
cookie
|
||||||
setup [[nodiscard]] (std::map<std::string_view, EnumT> mapping)
|
setup [[nodiscard]] (std::map<std::string_view, EnumT> mapping)
|
||||||
{
|
{
|
||||||
auto &cache = detail::cache ();
|
return detail::setup<EnumT> (
|
||||||
|
std::make_unique<
|
||||||
auto const index = cruft::typeidx<EnumT> ();
|
detail::lookup_concrete<EnumT>
|
||||||
auto lookup = std::make_unique<detail::lookup_concrete<EnumT>> (std::move (mapping));
|
> (std::move (mapping))
|
||||||
|
);
|
||||||
auto [pos, success] = cache.insert ({ index, std::move (lookup) });
|
|
||||||
if (!success)
|
|
||||||
LOG_WARN ("duplicate parse setup for %! was ignored", cruft::type_name<EnumT> ());
|
|
||||||
|
|
||||||
return cookie {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
cookie
|
||||||
|
setup [[nodiscard]] (std::function<EnumT(cruft::view<char const*>&)> &&func)
|
||||||
|
{
|
||||||
|
return detail::setup<EnumT> (
|
||||||
|
std::make_unique<
|
||||||
|
detail::lookup_callback<EnumT>
|
||||||
|
> (std::move (func))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Lookup an enumeration value given a string representation.
|
/// Lookup an enumeration value given a string representation.
|
||||||
///
|
///
|
||||||
/// The string view is taken by reference and will be modified so that it
|
/// The string view is taken by reference and will be modified so that it
|
||||||
|
@ -3,15 +3,13 @@
|
|||||||
#include "std.hpp"
|
#include "std.hpp"
|
||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
|
|
||||||
enum enumeration_t : u16 { FOO, BAR = 2, QUX = 257 };
|
|
||||||
|
|
||||||
enum class enum_class { VALUE };
|
|
||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
cruft::TAP::logger tap;
|
cruft::TAP::logger tap;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
enum enumeration_t : u16 { FOO, BAR = 2, QUX = 257 };
|
||||||
|
|
||||||
auto const cookie = cruft::parse::enumeration::setup<enumeration_t> ({
|
auto const cookie = cruft::parse::enumeration::setup<enumeration_t> ({
|
||||||
{ "FOO", FOO },
|
{ "FOO", FOO },
|
||||||
{ "BAR", BAR },
|
{ "BAR", BAR },
|
||||||
@ -34,6 +32,8 @@ int main ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
enum class enum_class { VALUE };
|
||||||
|
|
||||||
auto const cookie = cruft::parse::enumeration::setup<enum_class> ({
|
auto const cookie = cruft::parse::enumeration::setup<enum_class> ({
|
||||||
{ "VALUE", enum_class::VALUE },
|
{ "VALUE", enum_class::VALUE },
|
||||||
});
|
});
|
||||||
@ -45,5 +45,25 @@ int main ()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
enum class func_enum { ASDF };
|
||||||
|
|
||||||
|
auto const cookie = cruft::parse::enumeration::setup<func_enum> ([] (auto &str) {
|
||||||
|
if (equal (str, "ASDF")) {
|
||||||
|
str = str.consume (4);
|
||||||
|
return func_enum::ASDF;
|
||||||
|
}
|
||||||
|
throw std::runtime_error ("Invalid enum value");
|
||||||
|
});
|
||||||
|
|
||||||
|
(void)cookie;
|
||||||
|
|
||||||
|
tap.expect_eq (
|
||||||
|
func_enum::ASDF,
|
||||||
|
cruft::parse::from_string<func_enum> ("ASDF"),
|
||||||
|
"function enum lookup"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user