zengine/engine/modules/engine/zlib/include/refl/detail/uclass.inl

358 lines
10 KiB
C++

#include "uclass.h"
#include "name.h"
#include "type.h"
namespace refl {
template<typename T>
class UClass_Auto : public UClass {
public:
UClass_Auto() : UClass(meta_name<T>(), sizeof(T)) {
if constexpr (std::is_pointer_v<T>) {
using RT = std::remove_pointer_t<T>;
flag |= CLASS_POINTER_FLAG;
if constexpr (!std::is_same_v<RT, void>) {
parent = meta_info<RT>();
}
}
else if constexpr (is_array_v<T>) {
using RT = is_array_t<T>;
flag = CLASS_ARRAY_FLAG;
if constexpr (std::is_pointer_v<RT>) {
flag |= CLASS_POINTER_FLAG;
}
parent = meta_info<RT>();
}
else {
if constexpr (std::is_enum_v<T>) {
flag = CLASS_ENUM_FLAG;
parent = meta_info<std::underlying_type_t<T>>();
}
vtable.AddConstruct(&UClass::Construct<T>);
vtable.AddDestruct(&UClass::Destruct<T>);
}
}
};
/*
* 模板优化
* 成员参数转化为const void*
* 引用参数转化为指针
* 返回引用转化为指针
*/
template<typename R, typename... Args>
class UMethod_Auto : public UClass {
using MethodType = R(*)(Args...);
public:
std::array<const UClass*, sizeof...(Args) + 1> UList{};
UMethod_Auto() : UClass(meta_name<MethodType>(), sizeof(MethodType)) {
flag = CLASS_TRIVIAL_FLAG;
vtable.AddGetParams(&UMethod_Auto::GetParams);
vtable.AddCall(&UMethod_Auto::Call);
if constexpr (!std::is_same_v<R, void>) {
UList[0] = meta_info<R>();
}
if constexpr (sizeof...(Args) > 0) {
auto ptr = &UList[1];
(..., (*ptr = meta_info<Args>(), ptr++));
}
}
//这里顺序似乎是不确定的,但是我实际运用是对的
//如果使用make_index_sequence,会多一次函数调用
//为什么包裹一层迭代器,就不会出现警告了
static void Call(const FieldPtr* field, span<Any> ArgsList) {
assert(sizeof...(Args) < ArgsList.size());
auto param = ArgsList.end() - 1;
if constexpr (std::is_same_v<R, void>) {
MethodType fptr = (MethodType)field->data.method.fptr;
fptr((param--->CastTo<Args>())...);
}
else {
MethodType fptr = (MethodType)field->data.method.fptr;
auto& ret = ArgsList.front();
if (ret.cls == meta_info<R>()) {
*(R*)ret.ptr = fptr((param--->CastTo<Args>())...);
}
else {
fptr((param--->CastTo<Args>())...);
}
}
}
static span<const UClass*> GetParams(const UClass* cls) {
auto& UList = ((UMethod_Auto*)cls)->UList;
return span<const UClass*>{UList};
}
};
class UClass_Container_Impl : public UClass {
public:
using UClass::UClass;
struct iterator {
void* ptr;
void* val;
};
//container
using size_impl = size_t(*)(const void*);
using to_iterator_impl = void(*)(iterator&, const void*);
using insert_impl = void (*)(const void*, const void*);
//iterator
using iterator_impl = void (*)(iterator*);
public:
size_impl vsize;
to_iterator_impl vbegin;
to_iterator_impl vend;
insert_impl vinsert;
iterator_impl viterator_add;
iterator_impl viterator_sub;
template<typename T>
static void insert(const void* ptr, const void* obj) {
using value_type = typename T::value_type;
if constexpr (is_sequence_v<T>) {
((T*)ptr)->push_back(*(value_type*)obj);
}
else if constexpr (is_map_v<T>) {
((T*)ptr)->insert(*(value_type*)obj);
}
}
};
template<is_container_v T, typename value_type>
class UClass_Container : public UClass_Container_Impl {
public:
static bool construct(void* ptr, const UClass* cls, span<Any> ArgsList) {
new(ptr)T();
return true;
}
static void destruct(void* ptr) {
((T*)ptr)->~T();
}
static void begin(iterator& pit, const void* ptr) {
auto it = ((T*)ptr)->begin();
memcpy(&pit, &it, sizeof(it));
pit.val = &*it;
}
static void end(iterator& pit, const void* ptr) {
auto it = ((T*)ptr)->end();
memcpy(&pit, &it, sizeof(it));
pit.val = &*it;
}
static void add(iterator* pit) {
auto it = ++(*(typename T::iterator*)pit);
memcpy(pit, &it, sizeof(it));
pit->val = &*it;
}
static void sub(iterator* pit) {
auto it = --(*(typename T::iterator*)pit);
memcpy(pit, &it, sizeof(it));
pit->val = &*it;
}
UClass_Container() : UClass_Container_Impl(meta_name<T>(), sizeof(T)) {
parent = meta_info<value_type>();
flag = CLASS_CONTAINER_FLAG;
vtable.AddConstruct(&UClass_Container::construct);
vtable.AddDestruct(&UClass_Container::destruct);
if constexpr (is_sequence_v<T>) {
flag |= CLASS_SEQUENCE_FLAG;
}
else if constexpr (is_map_v<T>)
{
flag |= CLASS_MAP_FLAG;
}
auto p_size = &T::size;
vsize = *(size_impl*)&p_size;
vbegin = &UClass_Container::begin;
vend = &UClass_Container::end;
vinsert = &UClass_Container::insert<T>;
viterator_add = &UClass_Container::add;
viterator_sub = &UClass_Container::sub;
};
};
template<typename T, typename MetaImpl>
class UClass_Meta : public UClass {
using FieldsType = decltype(MetaImpl::MakeFields());
public:
FieldsType Fields{ MetaImpl::MakeFields() };
UClass_Meta() : UClass(meta_name<T>(), sizeof(T)) {
if constexpr (has_parent_v<T>) {
parent = meta_info<parent_t<T>>();
}
vtable.AddGetFields(&UClass_Meta::GetFields);
vtable.AddConstruct(&UClass::Construct<T>);
}
span<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
constexpr int length = std::tuple_size<FieldsType>::value;
constexpr int MemberCount = MetaImpl::MemberCount();
constexpr int AllMemberCount = MemberCount + MetaImpl::StaticMemberCount();
constexpr int CtorCount = MetaImpl::CtorCount();
switch (find) {
case EFieldFind::FIND_ALL_FIELD:
return span<const FieldPtr>(&Fields[0], length);
case EFieldFind::FIND_ALL_MEMBER:
return span<const FieldPtr>(&Fields[0], MemberCount);
case EFieldFind::FIND_ALL_MEMBER_WITH_STATIC:
return span<const FieldPtr>(&Fields[0], AllMemberCount);
case EFieldFind::FIND_ALL_METHOD:
return span<const FieldPtr>(&Fields[AllMemberCount + CtorCount], length - AllMemberCount - CtorCount);
case EFieldFind::FIND_CTOR:
return span<const FieldPtr>(&Fields[AllMemberCount], CtorCount);
case EFieldFind::FIND_FIELD:
for (int i = 0; i < length; i++) {
if (name == Fields[i].name) {
return span<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_MEMBER:
for (int i = 0; i < AllMemberCount; i++) {
if (name == Fields[i].name) {
return span<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_METHOD:
for (int i = AllMemberCount + CtorCount; i < length; i++) {
if (name == Fields[i].name) {
return span<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_METHODS:
{
int first = 0, count = 0;
for (int i = AllMemberCount + CtorCount; i < length; i++) {
if (name == Fields[i].name) {
if (!count) {
first = i;
}
count++;
}
else if (count) {
return span<const FieldPtr>(&Fields[first], count);
}
}
return {};
}
default:
return {};
}
}
static span<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, Name name) {
auto cls = static_cast<const UClass_Meta*>(_cls);
return cls->GetFields(find, name);
}
};
template<typename T>
struct meta_info_impl {
static UClass* create() {
return new(MetaGlobalPool()) UClass_Auto<T>{};
}
};
template<typename R, typename... Args>
struct meta_info_impl<R(*)(Args...)> {
static UClass* create() {
return new(MetaGlobalPool()) UMethod_Auto<R, Args...>{};
}
};
template<is_container_v T>
struct meta_info_impl<T> {
static UClass* create() {
return new(MetaGlobalPool()) UClass_Container<T, typename T::value_type>{};
}
};
struct MetaClasses {
size_t hash{ 0 };
const UClass* cls{nullptr};
MetaClasses* next{ nullptr };
};
using __tClassTable = table<Name, const UClass*>;
UNIQUER_INLINE(__tClassTable, ClassTable, "refl::ClassTable")
using __tMetaClassTable = table<Name, MetaClasses>;
UNIQUER_INLINE(__tMetaClassTable, MetaClassTable, "refl::MetaClassTable")
inline const UClass* find_info(Name name) {
auto& ClassTable = UNIQUER_VAL(ClassTable);
if (auto it = ClassTable.find(name); it != ClassTable.end()) {
return it->second;
}
return nullptr;
}
inline const UClass* find_info(Name name, size_t hash) {
auto& MetaClassTable = UNIQUER_VAL(MetaClassTable);
if (auto it = MetaClassTable.find(name); it != MetaClassTable.end()) {
auto meta = &it->second;
while (meta) {
if (meta->hash == hash) {
return meta->cls;
}
meta = meta->next;
}
}
return nullptr;
}
template<typename Type>
inline const UClass* meta_info()
{
using T = real_type_t<Type>;
auto name = meta_name<T>();
if (auto cls = find_info(name)) {
return cls;
}
UClass* cls;
if constexpr (is_meta_v<T>){
cls = new(MetaGlobalPool()) UClass_Meta<T, meta_t<T>>{};
}
else if constexpr (std::is_same_v<T, void>) {
cls = new(MetaGlobalPool()) UClass{ name, 0 };
}
else {
cls = meta_info_impl<T>::create();
}
auto& ClassTable = UNIQUER_VAL(ClassTable);
ClassTable[name] = cls;
return cls;
}
template<typename T, size_t hash>
inline const UClass* meta_info()
{
if constexpr (have_meta_impl_v<T, hash>) {
auto name = meta_name<T>();
const UClass* cls = find_info(name, hash);
if (cls) {
return cls;
}
cls = new(MetaGlobalPool()) UClass_Meta<T, gen::MetaImpl<T, hash>>{};
auto& MetaClassTable = UNIQUER_VAL(MetaClassTable);
if (auto it = MetaClassTable.find(name); it != MetaClassTable.end()) {
auto meta = &it->second;
while (meta) {
if (!meta->next) {
meta->next = new (MetaGlobalPool()) MetaClasses{ hash, cls };
break;
}
meta = meta->next;
}
}
else {
MetaClassTable.emplace(name, MetaClasses{hash, cls});
}
return cls;
}
else {
return meta_info<T>();
}
}
template<typename T, size_t index = 0>
inline void register_meta()
{
if constexpr (is_metas_v<T>) {
constexpr auto metaList = Meta<T>::MetaList();
meta_info<T, metaList[index]> ();
if constexpr (index + 1 < metaList.size()) {
register_meta<T, index + 1>();
}
}
meta_info<T>();
}
inline const UClass* find_meta(Name name, size_t hash) {
auto it = find_info(name);
if (it) {
return it->GetMeta(hash);
}
return nullptr;
}
}