From a0c21b92e89bb39571c2159c037fc7168a7fbafe Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 24 Oct 2022 09:21:07 +0100 Subject: Tidy and de-dupe enumDetails --- lib/enumDetails.hpp | 65 +++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 29 deletions(-) (limited to 'lib/enumDetails.hpp') diff --git a/lib/enumDetails.hpp b/lib/enumDetails.hpp index ace6252..7234c6d 100644 --- a/lib/enumDetails.hpp +++ b/lib/enumDetails.hpp @@ -6,9 +6,22 @@ #include #include +/// EnumDetailsBase +// Shared helpers +struct EnumDetailsBase { + template + constexpr static auto + strArr(auto input, auto start, auto end) + { + std::array out; + input.copy(out.begin(), end - start, start); + return out; + } +}; + /// EnumTypeDetails // Extracts the fully qualified name of the enumeration -template struct EnumTypeDetails { +template struct EnumTypeDetails : EnumDetailsBase { #ifndef ENUM_PROBE protected: #endif @@ -21,11 +34,7 @@ protected: constexpr static auto typeNameStart {typeraw().find(SEARCH_TYPE) + SEARCH_TYPE.length()}; constexpr static auto typeNameEnd {typeraw().find_first_of("];", typeNameStart)}; constexpr static auto typeNameLen {typeNameEnd - typeNameStart}; - constexpr static auto typeNameArr {[]() { - std::array out; - typeraw().copy(out.begin(), typeNameEnd - typeNameStart, typeNameStart); - return out; - }()}; + constexpr static auto typeNameArr {strArr(typeraw(), typeNameStart, typeNameEnd)}; public: constexpr static std::string_view typeName {typeNameArr.data(), typeNameArr.size()}; @@ -46,11 +55,7 @@ private: constexpr static auto nameStart {raw().find_last_of(": ") + 1}; constexpr static auto nameEnd {raw().find_first_of("];", nameStart)}; constexpr static auto nameLen {nameEnd - nameStart}; - constexpr static auto nameArr {[]() { - std::array out; - raw().copy(out.begin(), nameLen, nameStart); - return out; - }()}; + constexpr static auto nameArr {EnumValueDetails::template strArr(raw(), nameStart, nameEnd)}; public: constexpr static std::string_view valueName {nameArr.data(), nameArr.size()}; @@ -58,14 +63,15 @@ public: constexpr static auto raw_value {value}; }; +/// EnumValueCollection +// Customisation point for specifying the range of underlying values your enum can have template struct EnumValueCollection { using Vs = std::make_integer_sequence; }; +/// EnumDetails +// Interface for lookups/checks/etc at runtime template struct EnumDetails { -public: - using EVC = EnumValueCollection; - #ifndef ENUM_PROBE private: #endif @@ -88,21 +94,28 @@ private: return std::array {EnumValueDetails::valueName...}; } + using EVC = EnumValueCollection; constexpr static auto valid_flags {get_valids(typename EVC::Vs {})}; constexpr static auto valid_count {std::count_if(valid_flags.begin(), valid_flags.end(), std::identity {})}; + constexpr static auto + lookup(const auto key, const auto & search, const auto & out) + -> std::optional::value_type> + { + if (const auto itr = std::find(search.begin(), search.end(), key); itr != search.end()) { + return out[std::distance(search.begin(), itr)]; + } + return std::nullopt; + } + public: constexpr static auto values {[]() { constexpr auto values {get_values(typename EVC::Vs {})}; static_assert(std::is_sorted(values.begin(), values.end()), "Candidate values must be sorted"); std::array out; - auto write = out.begin(); - for (auto v = values.begin(); const bool & valid : valid_flags) { - if (valid) { - *write++ = static_cast(*v); - } - ++v; - } + std::copy_if(values.begin(), values.end(), out.begin(), [valid = valid_flags.begin()](auto) mutable { + return *valid++; + }); return out; }()}; constexpr static auto names {get_valueNames(std::make_integer_sequence {})}; @@ -116,18 +129,12 @@ public: constexpr static std::optional parse(std::string_view name) noexcept { - if (const auto itr = std::find(names.begin(), names.end(), name); itr != names.end()) { - return values[std::distance(names.begin(), itr)]; - } - return std::nullopt; + return lookup(name, names, values); } constexpr static std::optional to_string(E value) noexcept { - if (const auto itr = std::find(values.begin(), values.end(), value); itr != values.end()) { - return names[std::distance(values.begin(), itr)]; - } - return std::nullopt; + return lookup(value, values, names); } }; -- cgit v1.2.3