Created
June 18, 2026 23:13
-
-
Save mistificator/2c40242841e88709af3917f406b73a09 to your computer and use it in GitHub Desktop.
enum_magic.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <string> | |
| #include <type_traits> | |
| struct StringRef { | |
| const char* data; | |
| size_t size; | |
| constexpr StringRef() : data(""), size(0) {} | |
| constexpr StringRef(const char* s, size_t len) : data(s), size(len) {} | |
| constexpr StringRef(const char* s) : data(s), size(0) { | |
| if (s) { | |
| while (s[size] != '\0') { | |
| size++; | |
| } | |
| } | |
| } | |
| operator std::string() const { | |
| return std::string(data, size); | |
| } | |
| constexpr bool operator==(StringRef other) const { | |
| if (size != other.size) return false; | |
| for (size_t i = 0; i < size; ++i) { | |
| if (data[i] != other.data[i]) return false; | |
| } | |
| return true; | |
| } | |
| constexpr bool empty() const { return size == 0; } | |
| }; | |
| namespace EnumMagic { | |
| template <typename T, T Value> | |
| constexpr StringRef GetValueNameRaw() { | |
| #if defined(__clang__) || defined(__GNUC__) | |
| const char* name = __PRETTY_FUNCTION__; | |
| size_t len = 0; while (name[len] != '\0') { len++; } | |
| size_t start = len; | |
| while (start > 0 && name[start] != ':' && name[start] != ' ') { start--; } | |
| if (name[start] == ':') start++; | |
| size_t end = len; | |
| while (end > start && name[end] != ']') { end--; } | |
| return StringRef(name + start, end - start); | |
| #elif defined(_MSC_VER) | |
| const char* name = __FUNCSIG__; | |
| size_t len = 0; while (name[len] != '\0') { len++; } | |
| size_t start = len; | |
| while (start > 0 && name[start] != ':' && name[start] != ' ') { start--; } | |
| if (name[start] == ':') start++; | |
| size_t end = len; | |
| while (end > start && name[end] != '>') { end--; } | |
| return StringRef(name + start, end - start); | |
| #else | |
| return StringRef(); | |
| #endif | |
| } | |
| template <typename T, T Value> | |
| constexpr bool IsValidEnum() { | |
| StringRef name = GetValueNameRaw<T, Value>(); | |
| if (name.empty()) return false; | |
| char first = name.data[0]; | |
| return !((first >= '0' && first <= '9') || first == '-' || first == '('); | |
| } | |
| constexpr int MinRange = 0; | |
| constexpr int MaxRange = 128; | |
| template <typename T, size_t... Is> | |
| struct Helper { | |
| static constexpr StringRef ToStr(T value) { | |
| StringRef result; | |
| int dummy[] = { 0, (static_cast<int>(value) == (MinRange + Is) && IsValidEnum<T, static_cast<T>(MinRange + Is)>() | |
| ? (result = GetValueNameRaw<T, static_cast<T>(MinRange + Is)>(), 0) : 0)... }; | |
| (void)dummy; | |
| return result.empty() ? StringRef("Unknown", 7) : result; | |
| } | |
| static constexpr bool FromStr(StringRef str, T& out_value) { | |
| bool found = false; | |
| int dummy[] = { 0, (!found && IsValidEnum<T, static_cast<T>(MinRange + Is)>() && GetValueNameRaw<T, static_cast<T>(MinRange + Is)>() == str | |
| ? (out_value = static_cast<T>(MinRange + Is), found = true, 0) : 0)... }; | |
| (void)dummy; | |
| return found; | |
| } | |
| }; | |
| template <size_t... Is> struct Seq {}; | |
| template <size_t N, size_t... Is> struct GenSeq : GenSeq<N - 1, N - 1, Is...> {}; | |
| template <size_t... Is> struct GenSeq<0, Is...> { typedef Seq<Is...> Type; }; | |
| template <typename T> | |
| constexpr StringRef ToStr(T value) { | |
| return ToStrImpl(value, typename GenSeq<MaxRange - MinRange>::Type()); | |
| } | |
| template <typename T, size_t... Is> | |
| constexpr StringRef ToStrImpl(T value, Seq<Is...>) { | |
| return Helper<T, Is...>::ToStr(value); | |
| } | |
| template <typename T> | |
| constexpr bool FromStr(StringRef str, T& out_value) { | |
| return FromStrImpl(str, out_value, typename GenSeq<MaxRange - MinRange>::Type()); | |
| } | |
| template <typename T, size_t... Is> | |
| constexpr bool FromStrImpl(StringRef str, T& out_value, Seq<Is...>) { | |
| return Helper<T, Is...>::FromStr(str, out_value); | |
| } | |
| } |
mistificator
commented
Jun 18, 2026
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment