mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 00:30:31 +00:00
Attempts to flesh out Reflection::Enum.
This commit is contained in:
parent
ce80825abb
commit
7e8b86e9bb
@ -23,7 +23,7 @@ struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Targ
|
|||||||
// Boilerplate for declaring fields and potential values.
|
// Boilerplate for declaring fields and potential values.
|
||||||
if(needs_declare()) {
|
if(needs_declare()) {
|
||||||
declare(&model, "model");
|
declare(&model, "model");
|
||||||
declare_enum(&model, EnumDeclaration(Model));
|
Reflection::Enum::declare<Model>(EnumDeclaration(Model));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <typeindex>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Reflection {
|
namespace Reflection {
|
||||||
|
|
||||||
@ -20,39 +24,12 @@ namespace Reflection {
|
|||||||
|
|
||||||
#define EnumDeclaration(Name) __declaration##Name
|
#define EnumDeclaration(Name) __declaration##Name
|
||||||
|
|
||||||
|
class Enum {
|
||||||
template <typename EnumType> struct Enum {
|
public:
|
||||||
static size_t size() {
|
template <typename Type> static void declare(const char *declaration) {
|
||||||
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<std::string_view> members() {
|
|
||||||
EnumType m;
|
|
||||||
const char *const declaration = __declaration(m);
|
|
||||||
const char *d_ptr = declaration;
|
const char *d_ptr = declaration;
|
||||||
|
|
||||||
std::vector<std::string_view> result;
|
std::vector<std::string> result;
|
||||||
while(true) {
|
while(true) {
|
||||||
// Skip non-alphas, and exit if the terminator is found.
|
// Skip non-alphas, and exit if the terminator is found.
|
||||||
while(*d_ptr && !isalpha(*d_ptr)) ++d_ptr;
|
while(*d_ptr && !isalpha(*d_ptr)) ++d_ptr;
|
||||||
@ -63,30 +40,52 @@ template <typename EnumType> struct Enum {
|
|||||||
while(isalpha(*d_ptr) || isdigit(*d_ptr)) ++d_ptr;
|
while(isalpha(*d_ptr) || isdigit(*d_ptr)) ++d_ptr;
|
||||||
|
|
||||||
// Add a string view.
|
// 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 <typename Type> 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 <typename EnumType> 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 <typename Type> 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<const std::type_info *, std::vector<std::string>> 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 */
|
#endif /* Enum_h */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user