zengine-old/engine/3rdparty/zlib/include/refl/detail/uclass.inl

349 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <array>
#include "uclass.h"
#include <iostream>
namespace refl {
template <class T>
concept _ReflCheck_Metas = requires(const Name & name) { MetaImpl<T>::MyMetas::GetMeta(name); };
template<typename T>
class UClass_Auto : public UClass {
public:
using UClass::UClass;
using MyUClass = UClass_Auto<T>;
public:
consteval static MyUClass BuildClass() {
MyUClass cls(type_name<T>().View(), sizeof(T));
if constexpr (std::is_pointer_v<T>){
using RT = std::remove_pointer_t<T>;
cls.flag = CLASS_POINTER_FLAG;
if constexpr (!std::is_same_v<RT, void>) {
cls.parent = &TypeInfo<RT>::StaticClass;
}
}
else if constexpr (is_array<T>::value) {
using RT = typename is_array<T>::type;
cls.flag = CLASS_ARRAY_FLAG;
if constexpr (std::is_pointer_v<RT>) {
cls.flag |= CLASS_POINTER_FLAG;
}
cls.parent = &TypeInfo<RT>::StaticClass;
}
else {
cls.vtable.Construct = &MyUClass::Construct<T>;
}
if constexpr (_ReflCheck_Metas<T>) {
cls.vtable.GetMeta = &MetaImpl<T>::MyMetas::GetMeta;
}
return cls;
}
void Set(void* ptr,const T& t) {
*(T*)ptr = t;
}
T& Get(void* ptr) {
return *(T*)ptr;
}
};
/*
* 模板优化
* 成员参数转化为const void*
* 引用参数转化为指针
* 返回引用转化为指针
*/
template<typename R, typename... Args>
class UMethod_Auto : public UClass {
using UClass::UClass;
using MethodType = R(*)(Args...);
using MyUClass = UMethod_Auto<R, Args...>;
public:
std::array<const UClass*, sizeof...(Args) + 1> UList{};
consteval sarray<const UClass*> GetParams()const {
return sarray<const UClass*>(&UList.front(), UList.size());
}
static sarray<const UClass*> GetParams(const UClass* cls) {
auto& UList = static_cast<const MyUClass*>(cls)->UList;
return sarray<const UClass*>(&UList.front(),UList.size());
}
//这里顺序似乎是不确定的,但是我实际运用是对的
//如果使用make_index_sequence,会多一次函数调用
//为什么包裹一层迭代器,就不会出现警告了
static void Call(const FieldPtr* field, const sarray<Any>& ArgsList) {
assert(sizeof...(Args) <= ArgsList.size());
if constexpr (std::is_same_v<R, void>) {
MethodType fptr = (MethodType)field->data.method.fptr;
auto param = ArgsList.end();
fptr((param--->CastTo<Args>())...);
}
else {
MethodType fptr = (MethodType)field->data.method.fptr;
auto param = ArgsList.end();
auto ret = ArgsList.front();
if (ret->cls == &TypeInfo<R>::StaticClass) {
*(R*)ret->ptr = fptr((param--->CastTo<Args>())...);
}
else {
fptr((param--->CastTo<Args>())...);
}
}
}
protected:
consteval void BuildUList() {
if constexpr (!std::is_same_v<R, void>) {
UList[0] = &TypeInfo<R>::StaticClass;
}
if constexpr (sizeof...(Args) > 0) {
auto ptr = &UList[1];
(..., (*ptr = &TypeInfo<args_type_t<Args>>::StaticClass, ptr++));
}
}
public:
//为了简化判断cls 对象 统统指向 T*
consteval static MyUClass BuildClass() {
MyUClass cls(type_name<MethodType>().View(), sizeof(MethodType));
cls.vtable.GetParams = &MyUClass::GetParams;
cls.vtable.Call = &MyUClass::Call;
cls.flag = CLASS_TRIVIAL_FLAG;
cls.BuildUList();
return cls;
}
};
template<typename... Types>
class UClass_Tuple : public UClass {
using UClass::UClass;
using MyUClass = UClass_Tuple<Types...>;
using MyTuple = std::tuple<Types...>;
public:
constexpr static std::array<std::string_view, 16> IndexNames = {
"1", "2", "3", "4", "5", "6", "7", "8",
"9", "10", "11", "12", "13", "14", "15", "16"
};
std::array<FieldPtr, sizeof...(Types)> Fields;
static bool construct(void* ptr, const UClass* cls, const sarray<Any>& ArgsList) {
new(ptr)MyTuple();
return true;
}
static void destruct(void* ptr) {
((MyTuple*)ptr)->~MyTuple();
}
template <typename T>
static FieldPtr field_in_tuple() {
MemberData member;
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
return { FName(""), &TypeInfo<T>::StaticClass, member, flag};
}
const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
return sarray<const FieldPtr>(&Fields[0], sizeof...(Types));
}
static const sarray<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, const Name& name) {
auto cls = static_cast<const MyUClass*>(_cls);
return cls->GetFields(find, name);
}
UClass_Tuple():UClass(type_name<MyTuple>().View(), sizeof(MyTuple)) {
vtable.Construct = &MyUClass::construct;
vtable.Destruct = &MyUClass::destruct;
vtable.GetFields = &MyUClass::GetFields;
auto ptr = &Fields[0];
(..., (*ptr = field_in_tuple<Types>(), ptr++));
Offset offset = 0;
constexpr int N = sizeof...(Types);
assert(N < IndexNames.size());
for (int i = 0; i < N; i++) {
Fields[i].name = IndexNames[i];
Fields[i].data.member.offset = offset;
offset += Fields[i].type->size;
}
}
};
class UClass_Container : public UClass {
public:
using UClass::UClass;
struct iterator {
void* ptr;
void* val;
};
//container
using size_impl = size_t(*)(const void*);
using to_iterator_impl = iterator(*)(const void*);
using insert_impl = void (*)(const void*, const void*);
//iterator
using iterator_impl = void* (*)(const void*);
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_impl : public UClass_Container {
using UClass_Container::UClass_Container;
using MyUClass = UClass_Container_impl<T, value_type>;
using ToIteratorFunc = T::iterator(T::*)();
using IteratorFunc = T::iterator& (T::iterator::*)();
public:
static bool construct(void* ptr, const UClass* cls, const sarray<Any>& ArgsList) {
new(ptr)T();
return true;
}
static void destruct(void* ptr) {
((T*)ptr)->~T();
}
static iterator begin(const void* ptr) {
auto it = ((T*)ptr)->begin();
return iterator{ *(void**)&it, &*it};
}
static iterator end(const void* ptr) {
auto it = ((T*)ptr)->end();
return iterator{ *(void**)&it, &*it };
}
UClass_Container_impl() : UClass_Container(type_name<T>().View(), sizeof(T)) {
parent = &TypeInfo<value_type>::StaticClass;
flag = CLASS_CONTAINER_FLAG;
vtable.Construct = &MyUClass::construct;
vtable.Destruct = &MyUClass::destruct;
if constexpr (is_sequence_v<T>) {
flag |= CLASS_SEQUENCE_FLAG;
}
else if constexpr (is_map_v<T>)
{
flag |= CLASS_MAP_FLAG;
}
auto __size = &T::size;
vsize = *(size_impl*)&__size;
vbegin = &MyUClass::begin;
vend = &MyUClass::end;
vinsert = &MyUClass::insert<T>;
IteratorFunc __it_add = &T::iterator::operator++;
viterator_add = *(iterator_impl*)&__it_add;
IteratorFunc __it_sub = &T::iterator::operator++;
viterator_sub = *(iterator_impl*)&__it_sub;
};
};
template<typename T, typename MyMeta>
class UClass_Meta : public UClass {
public:
using FieldsType = decltype(MyMeta::__MakeFields());
FieldsType Fields{ MyMeta::__MakeFields() };
UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)){
if constexpr (std::is_trivially_copyable_v<T>) {
flag = CLASS_TRIVIAL_FLAG;
}
if constexpr (_ReflCheck_Parent<MyMeta>) {
parent = &TypeInfo<typename MyMeta::Parent>::StaticClass;
}
if constexpr (_ReflCheck_Metas<T>) {
vtable.GetMeta = &MetaImpl<T>::MyMetas::GetMeta;
}
vtable.GetFields = &UClass_Meta::GetFields;
vtable.Construct = &UClass::Construct<T>;
}
const FieldPtr* GetField(int index) const {
return &Fields[index];
}
const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
constexpr int length = std::tuple_size<FieldsType>::value;
constexpr int MemberCount = MyMeta::MyStatic::MemberCount();
constexpr int CtorCount = MyMeta::MyStatic::CtorCount();
switch (find) {
case EFieldFind::FIND_ALL_FIELD:
return sarray<const FieldPtr>(&Fields[0], length);
case EFieldFind::FIND_ALL_MEMBER:
return sarray<const FieldPtr>(&Fields[0], MemberCount);
case EFieldFind::FIND_ALL_METHOD:
return sarray<const FieldPtr>(&Fields[MemberCount + CtorCount], length - MemberCount - CtorCount);
case EFieldFind::FIND_CTOR:
return sarray<const FieldPtr>(&Fields[MemberCount], CtorCount);
case EFieldFind::FIND_FIELD:
for (int i = 0; i < length; i++) {
if (name == Fields[i].name) {
return sarray<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_MEMBER:
for (int i = 0; i < MemberCount; i++) {
if (name == Fields[i].name) {
return sarray<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_METHOD:
for (int i = MemberCount + CtorCount; i < length; i++) {
if (name == Fields[i].name) {
return sarray<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_METHODS:
{
int first = 0,count = 0;
for (int i = MemberCount + CtorCount; i < length; i++) {
if (name == Fields[i].name) {
if (!count) {
first = i;
}
count++;
}
else if (count) {
return sarray<const FieldPtr>(&Fields[first], count);
}
}
return {};
}
default:
return {};
}
}
static const sarray<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, const Name& name) {
auto cls = static_cast<const UClass_Meta*>(_cls);
return cls->GetFields(find, name);
}
};
template<typename T>
struct TypeInfoImpl {
using MyUClass = UClass_Auto<T>;
inline constexpr static MyUClass StaticClass = MyUClass::BuildClass();
};
template<>
struct TypeInfoImpl<void> {
inline constexpr static UClass StaticClass = { type_name<void>().View(), 0 };
};
template<_ReflCheck_UClass T>
struct TypeInfoImpl<T> {
using MyUClass = UClass_Meta<T, typename MetaImpl<T>::MyMeta>;
inline static MyUClass StaticClass = MyUClass();
};
template<typename... Types>
struct TypeInfoImpl<std::tuple<Types...>> {
using MyUClass = UClass_Tuple<Types...>;
inline static MyUClass StaticClass = MyUClass();
};
template<typename... Types>
struct TypeInfoImpl<std::pair<Types...>> {
using MyUClass = UClass_Tuple<Types...>;
inline static MyUClass StaticClass = MyUClass();
};
template<is_container_v T>
struct TypeInfoImpl<T> {
using MyUClass = UClass_Container_impl<T, typename T::value_type>;
inline static MyUClass StaticClass = MyUClass();
};
// 函数指针类型的偏特化
template<typename R, typename... Args>
struct TypeInfoImpl<R(*)(Args...)> {
using MyUClass = UMethod_Auto<R, Args...>;
inline constexpr static MyUClass StaticClass = MyUClass::BuildClass();
};
}