summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Goodliffe <dan.goodliffe@octal.co.uk>2022-10-24 09:21:07 +0100
committerDan Goodliffe <dan.goodliffe@octal.co.uk>2022-10-24 09:21:07 +0100
commita0c21b92e89bb39571c2159c037fc7168a7fbafe (patch)
treef65e4cb336ad7c34de2005c839f755036cac0f89 /lib
parentAdd explicit constructor to Mode to initialise target (diff)
downloadilt-a0c21b92e89bb39571c2159c037fc7168a7fbafe.tar.bz2
ilt-a0c21b92e89bb39571c2159c037fc7168a7fbafe.tar.xz
ilt-a0c21b92e89bb39571c2159c037fc7168a7fbafe.zip
Tidy and de-dupe enumDetails
Diffstat (limited to 'lib')
-rw-r--r--lib/enumDetails.hpp65
1 files changed, 36 insertions, 29 deletions
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 <optional>
#include <string_view>
+/// EnumDetailsBase
+// Shared helpers
+struct EnumDetailsBase {
+ template<size_t len>
+ constexpr static auto
+ strArr(auto input, auto start, auto end)
+ {
+ std::array<char, len> out;
+ input.copy(out.begin(), end - start, start);
+ return out;
+ }
+};
+
/// EnumTypeDetails
// Extracts the fully qualified name of the enumeration
-template<typename E> struct EnumTypeDetails {
+template<typename E> 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<char, typeNameLen> out;
- typeraw().copy(out.begin(), typeNameEnd - typeNameStart, typeNameStart);
- return out;
- }()};
+ constexpr static auto typeNameArr {strArr<typeNameLen>(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<char, nameLen> out;
- raw().copy(out.begin(), nameLen, nameStart);
- return out;
- }()};
+ constexpr static auto nameArr {EnumValueDetails::template strArr<nameLen>(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<typename E> struct EnumValueCollection {
using Vs = std::make_integer_sequence<int, 256>;
};
+/// EnumDetails
+// Interface for lookups/checks/etc at runtime
template<typename E> struct EnumDetails {
-public:
- using EVC = EnumValueCollection<E>;
-
#ifndef ENUM_PROBE
private:
#endif
@@ -88,21 +94,28 @@ private:
return std::array {EnumValueDetails<values[n]>::valueName...};
}
+ using EVC = EnumValueCollection<E>;
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<typename std::decay_t<decltype(out)>::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<E, valid_count> out;
- auto write = out.begin();
- for (auto v = values.begin(); const bool & valid : valid_flags) {
- if (valid) {
- *write++ = static_cast<E>(*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<int, valid_count> {})};
@@ -116,18 +129,12 @@ public:
constexpr static std::optional<E>
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<std::string_view>
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);
}
};