diff --git a/parse/enum.hpp b/parse/enum.hpp index 0b39caba..f0aea983 100644 --- a/parse/enum.hpp +++ b/parse/enum.hpp @@ -18,6 +18,14 @@ namespace cruft::parse::enumeration { namespace detail { + /// Abstract base class for lookups from string names to typed + /// integers. + /// + /// An exception should be thrown if the type is incorrect. This + /// shouldn't be the case because the caller is expected to know the + /// type beforehand. + /// + /// Do not perform type casting - lossless or otherwise. struct lookup_base { virtual ~lookup_base () = default; @@ -33,6 +41,8 @@ namespace cruft::parse::enumeration { }; + /// A simple lookup from a supplied mapping of strings-to-underlying, + /// specialised on the EnumT that the lookup is targetting. template struct lookup_concrete : public lookup_base { static_assert (std::is_enum_v); @@ -44,11 +54,26 @@ namespace cruft::parse::enumeration { : m_cache (std::move (_cache)) { ; } + i08 as_i08 (cruft::view &str) const& override { return get (str); } + i16 as_i16 (cruft::view &str) const& override { return get (str); } + i32 as_i32 (cruft::view &str) const& override { return get (str); } + i64 as_i64 (cruft::view &str) const& override { return get (str); } + u08 as_u08 (cruft::view &str) const& override { return get (str); } + u16 as_u16 (cruft::view &str) const& override { return get (str); } + u32 as_u32 (cruft::view &str) const& override { return get (str); } + u64 as_u64 (cruft::view &str) const& override { return get (str); } + + private: + /// A common lookup helper for strings-to-some_value_type. + /// Provided so that we don't need to replicate the lookup and + /// error logic for each integer case. template ValueT get (cruft::view &str) const& { + static_assert (std::is_integral_v); + if constexpr (std::is_same_v) { for (auto const [key,val]: m_cache) { if (equal (key, str)) { @@ -65,26 +90,27 @@ namespace cruft::parse::enumeration { } } - i08 as_i08 (cruft::view &str) const& override { return get (str); } - i16 as_i16 (cruft::view &str) const& override { return get (str); } - i32 as_i32 (cruft::view &str) const& override { return get (str); } - i64 as_i64 (cruft::view &str) const& override { return get (str); } - - u08 as_u08 (cruft::view &str) const& override { return get (str); } - u16 as_u16 (cruft::view &str) const& override { return get (str); } - u32 as_u32 (cruft::view &str) const& override { return get (str); } - u64 as_u64 (cruft::view &str) const& override { return get (str); } - - private: cache_type m_cache; }; - std::map>& cache (void); + /// Resolves a global map from typeidx to lookup providers for the + /// enumeration type. + std::map< + int, + std::unique_ptr + >& + cache (void); + + /// Map a type to the underlying enum type if it is an enum, else + /// provided the identity mapping. Useful so simplify template logic + /// when dealing with types that aren't quite enums proper. template struct underlying_else_identity { using type = EnumT; }; + + // Specialise for the enum case. template struct underlying_else_identity< EnumT, @@ -93,8 +119,15 @@ namespace cruft::parse::enumeration { }; + /// Establish a mapping from strings-to-enums and return a cookie that + /// will deregister the mapping at destruction time. + /// + /// Results when calling multiple times for the same type are undefined + /// though some form of runtime warning will likely be emitted, and it's + /// unlikely to crash your application). template - cookie setup [[nodiscard]] (std::map mapping) + cookie + setup [[nodiscard]] (std::map mapping) { auto &cache = detail::cache (); @@ -109,6 +142,10 @@ namespace cruft::parse::enumeration { }; + /// Lookup an enumeration value given a string representation. + /// + /// The string view is taken by reference and will be modified so that it + /// points to the remainder of the string after the parsed value. template EnumT value (int const idx, cruft::view &str) @@ -157,6 +194,10 @@ namespace cruft::parse::enumeration { } + /// Lookup an enumeration value from the string representation given a + /// typeidx. + /// + /// If the entire string isn't consumed an exception will be thrown. template EnumT from_string (int const idx, cruft::view src) @@ -168,6 +209,9 @@ namespace cruft::parse::enumeration { } + /// Lookup an enumeration value from the string representation + /// + /// If the entire string isn't consumed an exception will be thrown. template EnumT from_string (cruft::view src)