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

260 lines
7.0 KiB
C
Raw Normal View History

2024-04-03 17:58:02 +08:00
#pragma once
#include "type.h"
#include "field.h"
2024-04-06 23:50:17 +08:00
#include "view.h"
2024-04-03 17:58:02 +08:00
namespace refl {
2024-04-06 23:50:17 +08:00
enum ClassFlag :uint32_t {
CLASS_NONE_FLAG = 0,
CLASS_MEMBER_FLAG = 1 << 0,
CLASS_ATTRIBUTE_FLAG = 1 << 1,
CLASS_METHOD_FLAG = 1 << 2,
};
2024-04-03 17:58:02 +08:00
class UClass{
2024-04-05 16:03:58 +08:00
using enum FieldFlag;
2024-04-03 17:58:02 +08:00
public:
Name name;
uint32_t size;
2024-04-04 18:18:04 +08:00
UClass* parent;
2024-04-03 17:58:02 +08:00
public:
2024-04-04 18:18:04 +08:00
constexpr UClass(Name name, uint32_t size, UClass* parent = nullptr)
:name(name),size(size), parent(parent){}
ObjectView New(void* ptr = nullptr) const{
if (ptr == nullptr) {
ptr = malloc(size);
InitObject(ptr);
}
return { ptr , this };
2024-04-03 17:58:02 +08:00
}
template<typename T>
2024-04-04 18:18:04 +08:00
T* New(T* ptr = nullptr) const{
if (!IsChildOf<T>()) {
return nullptr;
}
if (ptr == nullptr) {
ptr = (T*)malloc(size);
}
InitObject(ptr);
return ptr;
}
template<typename T>
bool IsChildOf(bool bthis = false) const {
constexpr UClass* cls = &TypeInfo<T>::StaticClass;
if (bthis) {
return cls == this;
}
const UClass* _parent = this;
while (_parent != nullptr) {
if (_parent == cls) {
return true;
}
_parent = _parent->parent;
}
return false;
}
2024-04-06 23:50:17 +08:00
public:
2024-04-04 18:18:04 +08:00
//unsafe if called by other, need check class && size
virtual void InitObject(void* ptr)const {
memset(ptr, 0, size);
}
virtual const FieldPtr* GetField(const Name& name)const {
return nullptr;
2024-04-03 17:58:02 +08:00
}
2024-04-06 23:50:17 +08:00
virtual std::vector<UClass*> GetParams() const {
return{};
}
virtual void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const{}
virtual bool ConvertToValue(ArgsView& args)const{
return false;
}
2024-04-03 17:58:02 +08:00
protected:
2024-04-06 23:50:17 +08:00
template<typename T,Offset offset>
FieldPtr MakeMemberField(Name name) {
2024-04-03 17:58:02 +08:00
FieldPtr::Data member = { offset };
2024-04-05 16:03:58 +08:00
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
return { name, &TypeInfo<T>::StaticClass, {member}, flag };
2024-04-03 17:58:02 +08:00
}
2024-04-05 16:03:58 +08:00
template<typename R, typename ...Args>
FieldPtr MakeMethodField(R (* ptr)(Args...), Name name) {
2024-04-06 23:50:17 +08:00
FieldPtr::Data member = { *(Method*)&ptr};
2024-04-05 16:03:58 +08:00
constexpr uint32_t flag = FIELD_METHOD_FLAG;
2024-04-06 23:50:17 +08:00
return { name, &TypeInfo<R(*)(Args...)>::StaticClass, {member},flag };
2024-04-05 16:03:58 +08:00
}
template<typename T, typename R, typename ...Args>
FieldPtr MakeMethodField(R(T::* ptr)(Args...), Name name) {
2024-04-06 23:50:17 +08:00
FieldPtr::Data member = { *(Method*)&ptr };
2024-04-05 16:03:58 +08:00
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
2024-04-06 23:50:17 +08:00
return { name, &TypeInfo<R(*)(const void*, Args...)>::StaticClass, {member},flag };
2024-04-04 18:18:04 +08:00
}
2024-04-03 17:58:02 +08:00
};
2024-04-05 16:03:58 +08:00
template<_ReflCheck_Ctor T>
2024-04-04 18:18:04 +08:00
class UClass_Auto : public UClass{
public:
using UClass::UClass;
2024-04-06 23:50:17 +08:00
bool ConvertToValue(ArgsView& args)const override {
if constexpr (std::is_same<T, int*>::value) {
using RawT = std::remove_pointer_t<T>;
args.val = (void*)*(RawT*)args.val;
args.cls = &TypeInfo<RawT>::StaticClass;
return true;
}
return false;
}
2024-04-04 18:18:04 +08:00
protected:
void InitObject(void* ptr)const override {
constexpr bool is_shallow_copyable = std::is_trivially_copyable<T>::value;
if constexpr (!is_shallow_copyable){
2024-04-05 16:03:58 +08:00
T obj{};
2024-04-04 18:18:04 +08:00
std::construct_at((T*)ptr, obj);
}
else {
memset(ptr, 0, size);
}
}
public:
static UClass_Auto<T> BuildClass() {
auto cls = UClass_Auto<T>(type_name<T>().View(), sizeof(T));
return cls;
}
};
2024-04-06 23:50:17 +08:00
2024-04-05 16:03:58 +08:00
template<_ReflCheck_Ctor_NoUClass T>
2024-04-06 23:50:17 +08:00
struct TypeInfoImpl<T>{
2024-04-04 18:18:04 +08:00
using UClass = UClass_Auto<T>;
inline static UClass StaticClass = UClass::BuildClass();
2024-04-03 17:58:02 +08:00
};
2024-04-06 23:50:17 +08:00
2024-04-05 16:03:58 +08:00
template<typename R, typename... Args>
class UMethod_Auto : public UClass {
using UClass::UClass;
using MethodType = R(*)(Args...);
public:
std::array<UClass*, sizeof...(Args) + 1> UList;
2024-04-06 23:50:17 +08:00
std::vector<UClass*> GetParams()const override {
return { UList.data(), UList.data() + UList.size()};
}
void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const override {
Call<Args...>(field, ArgsList);
}
protected:
template<typename... Args>
inline void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const {
MethodType fptr = (MethodType)std::get<Method>(field.data);
int Indices = 0;
//fptr(ArgsList[1].val, Indices, Indices);
//fptr(std::forward<Args>((Args)Indices), ...);
int a = 1;
a = a + 1;
}
2024-04-05 16:03:58 +08:00
public:
static UMethod_Auto<R,Args...> BuildClass() {
auto cls = UMethod_Auto<R, Args...>(type_name<MethodType>().View(), sizeof(MethodType));
if constexpr(!std::is_same<R, void>::value) {
cls.UList[0] = &TypeInfo<R>::StaticClass;
}
if (sizeof...(Args) > 0) {
auto ptr = &cls.UList[1];
(...,(*ptr = &TypeInfo<Args>::StaticClass, ptr++));
}
return cls;
}
};
// 函数指针类型的偏特化
template<typename R, typename... Args>
2024-04-06 23:50:17 +08:00
struct TypeInfoImpl<R(*)(Args...)> {
2024-04-05 16:03:58 +08:00
using UClass = UMethod_Auto<R,Args...>;
inline static UClass StaticClass = UClass::BuildClass();
};
2024-04-04 18:18:04 +08:00
template<typename T>
inline bool ObjectView::Get(const Name& name, T& t)
{
if (cache && cache->name == name) {
_cache_get: bool isChild = cache->type->IsChildOf<T>(true);
if (isChild) {
t = *(T*)(ptr + std::get<uint32_t>(cache->data));
}
return isChild;
}
auto field = cls->GetField(name);
if (field) {
cache = field;
goto _cache_get;
}
return false;
}
template<typename T>
inline bool ObjectView::Set(const Name& name, const T& t)
{
if (cache && cache->name == name) {
_cache_set: bool isChild = cache->type->IsChildOf<T>(true);
if (isChild) {
*(T*)(ptr + std::get<uint32_t>(cache->data)) = t;
}
return isChild;
}
auto field = cls->GetField(name);
if (field) {
cache = field;
goto _cache_set;
}
return false;
}
template<typename ...Args>
2024-04-06 23:50:17 +08:00
bool ObjectView::Invoke(const Name& name, Args&&... args)
2024-04-04 18:18:04 +08:00
{
2024-04-05 16:03:58 +08:00
auto field = cls->GetField(name);
if (!field) {
return false;
}
2024-04-06 23:50:17 +08:00
constexpr int inputSize = sizeof...(Args);
auto params = field->type->GetParams();
int paramsSize = params.size();
bool member = field->flag & FIELD_MEMBER_FLAG;
if (inputSize + member >= paramsSize) {
return false;
2024-04-05 16:03:58 +08:00
}
2024-04-06 23:50:17 +08:00
std::vector<ArgsView> ArgsList;
ArgsList.reserve(paramsSize);
ArgsList.emplace_back();
if (member) {
ArgsList.emplace_back(ptr, cls );
2024-04-05 16:03:58 +08:00
}
2024-04-06 23:50:17 +08:00
(..., (ArgsList.emplace_back((void*)&args, &TypeInfo<Args>::StaticClass)));
for (int i = member + 1; i < paramsSize; i++) {
if (ArgsList[i].cls != params[i]) {
ArgsList[i].ConvertTo(params[i]);
}
}
field->type->Call(*field, ArgsList);
return false;
2024-04-05 16:03:58 +08:00
}
template<typename R, typename ...Args>
2024-04-06 23:50:17 +08:00
inline bool ObjectView::InvokeRet(const Name& name, R& ret, Args&& ...args)
2024-04-05 16:03:58 +08:00
{
auto field = cls->GetField(name);
if (!field) {
return false;
}
if (field->flag & FIELD_MEMBER_FLAG) {
using MemberMethodType = R(*)(const void*, Args...);
2024-04-06 23:50:17 +08:00
MemberMethodType fptr = (MemberMethodType)std::get<Method>(field->data);
ret = fptr(ptr, std::forward<Args>(args)...);
2024-04-05 16:03:58 +08:00
}
else {
using MethodType = R(*)(Args...);
2024-04-06 23:50:17 +08:00
MethodType fptr = (MethodType)std::get<Method>(field->data);
ret = fptr(std::forward<Args>(args)...);
2024-04-05 16:03:58 +08:00
}
return true;
2024-04-04 18:18:04 +08:00
}
2024-04-06 23:50:17 +08:00
bool ArgsView::ConvertTo(UClass* toClass) {
ArgsView args{val};
cls->ConvertToValue(args);
if (args.cls == toClass) {
*this = args;
return true;
}
return false;
}
2024-04-03 17:58:02 +08:00
}