meta/runtime/reflection.h
2024-03-04 18:21:58 +08:00

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, {&params...}));
}
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, {&params...}));
}
template<typename... Params>
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<void *> &params) 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