#include #include #include #include "Exceptions/NotReachableException.hpp" #include "MacroUtils.hpp" #define ENUM_CASE(x, name) \ case name::x: \ return #x; # #define ENUM_PARSE_CASE(x, name) \ case ConstHash(#x): \ return name::x; # #define ENUM_PARSE_CASE_INSENSITIVE(x, name) \ case ConstHashCI(#x): \ return name::x; # #define ARRAY_NAME(x, name) name::x, #define ENUM(name, type, values...) \ enum class name : type { values }; \ class name##Helper { \ inline static uint32_t constexpr ConstHash(char const* input) { \ return *input ? static_cast(*input) + 33 * ConstHash(input + 1) : 5381; \ } \ inline static constexpr char charToLower(const char c) { \ return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; \ } \ inline static uint32_t constexpr ConstHashCI(char const* input) { \ return charToLower(*input) ? static_cast(charToLower(*input)) + 33 * ConstHashCI(input + 1) \ : 5381; \ } \ \ public: \ static std::string ToString(name value) { \ switch (value) { FOR_EACH(ENUM_CASE, name, values) } \ throw NotReachableException(); \ } \ static name Parse(const std::string& input, bool caseInsensitive = false) { \ if (caseInsensitive) \ return ParseCaseInsensitive(input); \ switch (ConstHash(input.c_str())) { FOR_EACH(ENUM_PARSE_CASE, name, values) } \ throw CreatureException("String '" + input + "' could not be parsed as " #name); \ } \ static std::vector GetValues() { return {FOR_EACH(ARRAY_NAME, name, values)}; } \ \ private: \ static name ParseCaseInsensitive(const std::string& input) { \ switch (ConstHashCI(input.c_str())) { FOR_EACH(ENUM_PARSE_CASE_INSENSITIVE, name, values) } \ throw CreatureException("String '" + input + "' could not be parsed as " #name); \ } \ };