193 lines
6.0 KiB
C++
193 lines
6.0 KiB
C++
#pragma once
|
|
#ifndef META_RUNTIME_REFLECTION_H
|
|
#define META_RUNTIME_REFLECTION_H
|
|
#include "any.h"
|
|
#include "apply.h"
|
|
#include <cstdlib>
|
|
#include <cxxabi.h>
|
|
#include <sled/log/log.h>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
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<typename T, typename U = typename std::decay<T>::type>
|
|
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<typename T>
|
|
inline const std::string &
|
|
PrettyName()
|
|
{
|
|
static std::string pretty_name = detail::PrettyNameImpl<T>();
|
|
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) \
|
|
friend class meta::reflection::##class_name##_Method; \
|
|
friend class meta::reflection::##class_name##_Field; \
|
|
friend class meta::reflection::##class_name##_Constructor; \
|
|
friend class meta::reflection::##class_name##_Serializer;
|
|
|
|
class Constructor;
|
|
class Method;
|
|
class Field;
|
|
class Class;
|
|
|
|
class BaseType {
|
|
public:
|
|
BaseType(const std::string &name, std::shared_ptr<Class> parent) : name_(name), parent_(parent)
|
|
{}
|
|
|
|
virtual ~BaseType() = default;
|
|
|
|
std::string Name() const { return name_; }
|
|
|
|
std::shared_ptr<Class> Parent() const { return parent_; }
|
|
|
|
private:
|
|
const std::string name_;
|
|
std::shared_ptr<Class> parent_;
|
|
};
|
|
|
|
class Method : public BaseType {
|
|
public:
|
|
Method(const std::string &name, std::shared_ptr<Class> parent) : BaseType(name, parent) {}
|
|
|
|
~Method() override = default;
|
|
|
|
std::shared_ptr<Class> Parent() const { return parent_; }
|
|
|
|
template<typename ReturnT,
|
|
typename std::enable_if<!std::is_void<ReturnT>::value, ReturnT>::type * = nullptr,
|
|
typename... Params>
|
|
inline ReturnT InvokeAndCast(void *instance, Params &&...params) const
|
|
{
|
|
return ::meta::reflection::any_cast<ReturnT>(InvokeImpl(instance, {¶ms...}));
|
|
}
|
|
|
|
template<typename ReturnT,
|
|
typename std::enable_if<std::is_void<ReturnT>::value, int>::type * = nullptr,
|
|
typename... Params>
|
|
inline void InvokeAndCast(void *instance, Params &&...params) const
|
|
{
|
|
::meta::reflection::any_cast<ReturnT>(InvokeImpl(instance, {¶ms...}));
|
|
}
|
|
|
|
template<typename... Params>
|
|
inline ::meta::reflection::any Invoke(void *instance, Params &&...params) const
|
|
{
|
|
return InvokeImpl(instance, {¶ms...});
|
|
}
|
|
|
|
protected:
|
|
virtual ::meta::reflection::any InvokeImpl(void *instance,
|
|
const std::vector<void *> ¶ms) const
|
|
= 0;
|
|
|
|
private:
|
|
std::shared_ptr<Class> parent_;
|
|
};
|
|
|
|
class Field : public BaseType {
|
|
public:
|
|
Field(const std::string &name, std::shared_ptr<Class> parent) : BaseType(name, parent) {}
|
|
|
|
template<typename T, typename std::enable_if<!std::is_void<T>::value, T>::type * = nullptr>
|
|
inline T GetAndCast(void *instance) const
|
|
{
|
|
return ::meta::reflection::any_cast<T>(GetImpl(instance));
|
|
}
|
|
|
|
::meta::reflection::any Get(void *instance) const { return GetImpl(instance); }
|
|
|
|
template<typename T>
|
|
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<Class> base_class = nullptr)
|
|
: BaseType(name, base_class)
|
|
{}
|
|
};
|
|
|
|
#define REFLECTION_BODY() \
|
|
friend class meta::Serializer; \
|
|
friend class meta::Class; \
|
|
friend class meta::Method; \
|
|
friend class meta::Field; \
|
|
friend class meta::Constructor;
|
|
|
|
class Reflectioin {
|
|
public:
|
|
static Reflectioin *Instance();
|
|
~Reflectioin();
|
|
std::shared_ptr<Class> GetClass();
|
|
// std::shared_ptr<Constructor> GetConstructor(std::shared_ptr<Class> clz);
|
|
std::shared_ptr<Method> GetMethod(std::shared_ptr<Class> clz);
|
|
std::shared_ptr<Field> GetField(std::shared_ptr<Class> clz);
|
|
};
|
|
}// namespace reflection
|
|
|
|
}// namespace meta
|
|
|
|
#endif// META_RUNTIME_REFLECTION_H
|