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