diff --git a/Analyser/Static/Macintosh/Target.hpp b/Analyser/Static/Macintosh/Target.hpp index 5e7d4913e..e9cbc82df 100644 --- a/Analyser/Static/Macintosh/Target.hpp +++ b/Analyser/Static/Macintosh/Target.hpp @@ -23,7 +23,7 @@ struct Target: public ::Analyser::Static::Target, public Reflection::Struct(EnumDeclaration(Model)); } } diff --git a/Reflection/Enum.h b/Reflection/Enum.h index 781c91468..9db6bb1a7 100644 --- a/Reflection/Enum.h +++ b/Reflection/Enum.h @@ -11,6 +11,10 @@ #include #include +#include +#include +#include +#include namespace Reflection { @@ -20,39 +24,12 @@ namespace Reflection { #define EnumDeclaration(Name) __declaration##Name - -template struct Enum { - static size_t size() { - return members().size(); - } - - /*! - @returns A @c string_view name for the enum value @c e. - */ - static std::string_view toString(EnumType e) { - return members()[size_t(e)]; - } - - /*! - @returns A value of @c EnumType name for the name @c str, or @c EnumType(-1) if - the string is not found. - */ - static EnumType fromString(const std::string_view &str) { - const auto member_list = members(); - auto position = std::find(member_list.begin(), member_list.end(), str); - if(position == member_list.end()) return EnumType(-1); - return EnumType(position - member_list.begin()); - } - - /*! - @returns A vector of string_views naming the members of this enum in value order. - */ - static std::vector members() { - EnumType m; - const char *const declaration = __declaration(m); +class Enum { + public: + template static void declare(const char *declaration) { const char *d_ptr = declaration; - std::vector result; + std::vector result; while(true) { // Skip non-alphas, and exit if the terminator is found. while(*d_ptr && !isalpha(*d_ptr)) ++d_ptr; @@ -63,30 +40,52 @@ template struct Enum { while(isalpha(*d_ptr) || isdigit(*d_ptr)) ++d_ptr; // Add a string view. - result.emplace_back(start, d_ptr - start); + result.emplace_back(std::string(start, size_t(d_ptr - start))); } - return result; + members_by_type_.emplace(std::make_pair(&typeid(Type), result)); } + + template size_t size() { + return size(typeid(Type)); + } + + size_t size(const std::type_info &type) { + const auto entry = members_by_type_.find(&type); + if(entry == members_by_type_.end()) return 0; + return entry->second.size(); + } + + /*! + @returns A @c string_view name for the enum value @c e. + */ + template static const std::string &toString(EnumType e) { + const auto entry = members_by_type_.find(&typeid(EnumType)); + if(entry == members_by_type_.end()) return empty_string_; + return entry->second[size_t(e)]; + } + + /*! + @returns A value of @c EnumType name for the name @c str, or @c EnumType(-1) if + the string is not found. + */ + template Type fromString(const std::string &str) { + return Type(fromString(typeid(Type), str)); + } + + size_t fromString(const std::type_info &type, const std::string &str) { + const auto entry = members_by_type_.find(&type); + if(entry == members_by_type_.end()) return 0; + const auto iterator = std::find(entry->second.begin(), entry->second.end(), str); + if(iterator == entry->second.end()) return 0; + return size_t(iterator - entry->second.begin()); + } + + private: + static inline std::unordered_map> members_by_type_; + static inline const std::string empty_string_; }; } -/*! - Provides a very limited subset of normal enums, with the addition of reflection. - - Enum members must take default values, and this enum must be in the global scope. -*/ -//#define DefX #define X - -//#define ForwardDeclareReflectiveEnum(Namespace, Name, ...) \ -// #define HAT - -// DeclName(m) m(__VA_ARGS__) - -// constexpr const char *__declaration(Namespace::Name) { return __VA_ARGS__; } - -//#define DefineReflectiveEnum(Name, Type) \ -// enum class Name: Type { Mac128k, Mac512k, Mac512ke, MacPlus }; - #endif /* Enum_h */