#pragma once #ifndef META_RUNTIME_REFLECTION_H #define META_RUNTIME_REFLECTION_H #include "any.h" #include #include #include #include #include #include #include namespace meta { namespace reflection { namespace detail { inline std::string RemoveTypeSpace(const std::string &str, const std::string &chars = "[]()<>*&:") { std::string result; // trim { result = str.substr(str.find_first_not_of(' ')); result = result.substr(0, result.find_last_not_of(' ') + 1); } // remove right space for (size_t i = 0; i < result.size();) { if (result[i] == ' ') { bool left_is_chars = i > 0 && chars.find(result[i - 1]) != std::string::npos; bool right_is_chars = (i + 1 < str.size()) && chars.find(result[i + 1]) != std::string::npos; if (left_is_chars || right_is_chars) { result.erase(i, 1); } else { ++i; } } else { ++i; } } return result; } template::type> inline std::string PrettyNameImpl() { const std::string name = typeid(U).name(); std::string pretty_name = name; int status = -4; char *res = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status); if (status == 0) { pretty_name = std::string(res); } free(res); return RemoveTypeSpace(pretty_name); } }// namespace detail template inline const std::string & PrettyName() { static std::string pretty_name = detail::PrettyNameImpl(); return pretty_name; } #if defined(__REFLECTION_PARSER__) #define META(...) __attribute__((annotate(#__VA_ARGS__))) #define CLASS(class_name, ...) class __attribute__((annotate(#__VA_ARGS__))) class_name #define STRUCT(struct_name, ...) struct __attribute__((annotate(#__VA_ARGS__))) struct_name #else #define META(...) #define CLASS(class_name, ...) class class_name #define STRUCT(struct_name, ...) struct struct_name #endif// __REFLECTION_PARSER_ \ #define META_REFLECTION_BODY(class_name) \ class class_name##_Class; \ class class_name##_Constructor; \ class class_name##_Method; \ class class_name##_Field; \ class class_name##_Serializer; \ friend class class_name##_Class; \ friend class class_name##_Constructor; \ friend class class_name##_Method; \ friend class class_name##_Field; \ friend class class_name##_Serializer; \ friend class ::meta::reflection::Registry; class Constructor; class Method; class Field; class Class; class BaseType { public: BaseType(const std::string &name, std::shared_ptr parent) : name_(name), parent_(parent) {} virtual ~BaseType() = default; std::string Name() const { return name_; } std::shared_ptr Parent() const { return parent_; } private: const std::string name_; std::shared_ptr parent_; }; class Method : public BaseType { public: Method(const std::string &name, std::shared_ptr parent) : BaseType(name, parent) {} ~Method() override = default; std::shared_ptr Parent() const { return parent_; } template::value, ReturnT>::type * = nullptr, typename... Params> inline ReturnT InvokeAndCast(void *instance, Params &&...params) const { return ::meta::reflection::any_cast(InvokeImpl(instance, {params...})); } template::value, int>::type * = nullptr, typename... Params> inline void InvokeAndCast(void *instance, Params &&...params) const { ::meta::reflection::any_cast(InvokeImpl(instance, {params...})); } template inline ::meta::reflection::any Invoke(void *instance, Params &&...params) const { return InvokeImpl(instance, {params...}); } protected: virtual ::meta::reflection::any InvokeImpl(void *instance, const std::vector<::meta::reflection::any> ¶ms) const = 0; private: std::shared_ptr parent_; }; class Field : public BaseType { public: Field(const std::string &name, std::shared_ptr parent) : BaseType(name, parent) {} template::value, T>::type * = nullptr> inline T GetAndCast(void *instance) const { return ::meta::reflection::any_cast(GetImpl(instance)); } ::meta::reflection::any Get(void *instance) const { return GetImpl(instance); } template inline void Set(void *instance, const T &value) const { SetImpl(instance, ::meta::reflection::any(value)); } protected: virtual ::meta::reflection::any GetImpl(void *instance) const = 0; virtual void SetImpl(void *instance, const ::meta::reflection::any &value) const = 0; }; class Class : public BaseType { public: Class(const std::string &name, std::shared_ptr base_class = nullptr) : BaseType(name, base_class) {} inline std::vector> GetBaseClasses() const { return base_classes_; } inline std::shared_ptr GetBaseClass(const std::string &name) const { auto iter = base_class_by_name_.find(name); if (iter != base_class_by_name_.end()) { return iter->second; } return nullptr; } inline std::vector> GetMethods() const { return methods_; } inline std::shared_ptr GetMethod(const std::string &name) const { auto iter = method_by_name_.find(name); if (iter != method_by_name_.end()) { return iter->second; } return nullptr; } inline std::vector> GetFields() const { return fields_; } inline std::shared_ptr GetField(const std::string &name) const { auto iter = field_by_name_.find(name); if (iter != field_by_name_.end()) { return iter->second; } return nullptr; } protected: void AddBaseClass(std::shared_ptr clz) { if (base_class_by_name_.find(clz->Name()) != base_class_by_name_.end()) { return; } base_classes_.push_back(clz); base_class_by_name_[clz->Name()] = clz; } void AddMethod(std::shared_ptr method) { if (method_by_name_.find(method->Name()) != method_by_name_.end()) { return; } methods_.push_back(method); method_by_name_[method->Name()] = method; } void AddField(std::shared_ptr field) { fields_.push_back(field); field_by_name_[field->Name()] = field; } private: std::unordered_map> base_class_by_name_; std::unordered_map> method_by_name_; std::unordered_map> field_by_name_; std::vector> base_classes_; std::vector> methods_; std::vector> fields_; }; class Registry { public: static Registry *Instance() { static Registry instance; return &instance; } ~Registry() {} static void RegisterAll(); static void UnregisterAll(); static std::shared_ptr GetClass(const std::string &name) { return Instance()->GetClassInner(name); } static void RegisterClass(std::shared_ptr clz) { Instance()->RegisterClassInner(clz); } static std::vector> GetClasses() { return Instance()->classes(); } private: std::shared_ptr GetClassInner(const std::string &name) const { auto iter = class_by_name_.find(name); if (iter != class_by_name_.end()) { return iter->second; } return nullptr; } inline void RegisterClassInner(std::shared_ptr clz) { if (class_by_name_.find(clz->Name()) != class_by_name_.end()) { return; } classes_.push_back(clz); class_by_name_[clz->Name()] = clz; } inline std::vector> classes() const { return classes_; } std::unordered_map> class_by_name_; std::vector> classes_; }; }// namespace reflection }// namespace meta #endif// META_RUNTIME_REFLECTION_H