zengine-old/engine/3rdparty/zlib/include/refl/detail/uclass.inl
2024-06-24 22:26:09 +08:00

404 lines
13 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;
}
};
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"
};
template<typename... Types>
class UClass_Tuple : public UClass {
using UClass::UClass;
using MyUClass = UClass_Tuple<Types...>;
using MyTuple = std::tuple<Types...>;
public:
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, std::size_t Index>
static FieldPtr field_in_tuple() {
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
const MyTuple* tuple_ptr = nullptr;
const auto& element = std::get<Index>(*tuple_ptr);
const std::ptrdiff_t offset = reinterpret_cast<const char*>(&element) - reinterpret_cast<const char*>(tuple_ptr);
MemberData member;
member.offset = offset;
return { IndexNames[Index], &TypeInfo<T>::StaticClass, member, flag};
}
template <std::size_t... Is>
void BuildFields(std::index_sequence<Is...>) {
auto ptr = &Fields[0];
(..., (*ptr = field_in_tuple<Types, Is>(), ptr++));
}
UClass_Tuple():UClass(type_name<MyTuple>().View(), sizeof(MyTuple)) {
assert(sizeof...(Types) < IndexNames.size());
BuildFields(std::index_sequence_for<Types...>{});
vtable.Construct = &MyUClass::construct;
vtable.Destruct = &MyUClass::destruct;
vtable.GetFields = &MyUClass::GetFields;
}
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);
}
};
template<typename First,typename Second>
class UClass_Pair : public UClass {
using UClass::UClass;
using MyUClass = UClass_Tuple<First, Second>;
using MyPair = std::pair<First, Second>;
public:
std::array<FieldPtr, 2> Fields;
static bool construct(void* ptr, const UClass* cls, const sarray<Any>& ArgsList) {
new(ptr)MyPair();
return true;
}
static void destruct(void* ptr) {
((MyPair*)ptr)->~MyPair();
}
template<typename T, int Index>
static FieldPtr field_in_pair() {
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
const MyPair* pair_ptr = nullptr;
MemberData member;
if constexpr (Index == 0) {
const auto& first = pair_ptr->first;
const std::ptrdiff_t offset = reinterpret_cast<const char*>(&first) - reinterpret_cast<const char*>(pair_ptr);
member.offset = offset;
}
else {
const auto& second = pair_ptr->second;
const std::ptrdiff_t offset = reinterpret_cast<const char*>(&second) - reinterpret_cast<const char*>(pair_ptr);
member.offset = offset;
}
return { IndexNames[Index], &TypeInfo<T>::StaticClass, member, flag };
}
UClass_Pair() :UClass(type_name<MyPair>().View(), sizeof(MyPair)) {
Fields[0] = field_in_pair<First, 0>();
Fields[1] = field_in_pair<Second, 1>();
vtable.Construct = &MyUClass::construct;
vtable.Destruct = &MyUClass::destruct;
vtable.GetFields = &MyUClass::GetFields;
}
const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
return sarray<const FieldPtr>(&Fields[0], 2);
}
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);
}
};
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 = 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_impl : public UClass_Container {
using UClass_Container::UClass_Container;
using MyUClass = UClass_Container_impl<T, value_type>;
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 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 = ++(*(T::iterator*)pit);
memcpy(pit, &it, sizeof(it));
pit->val = &*it;
}
static void sub(iterator* pit) {
auto it = --(*(T::iterator*)pit);
memcpy(pit, &it, sizeof(it));
pit->val = &*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>;
viterator_add = &MyUClass::add;
viterator_sub = &MyUClass::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 First, typename Second>
struct TypeInfoImpl<std::pair<First, Second>> {
using MyUClass = UClass_Pair<First, Second>;
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();
};
}