#pragma once #include "type.h" #include "field.h" #include "object.h" namespace refl { 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; } //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; } protected: template FieldPtr MakeMemberField(T U::* ptr, 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 = { *(void**)&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 = { *(void**)&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; 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 TypeInfo { 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; 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 TypeInfo { 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; } if (field->flag & FIELD_MEMBER_FLAG) { using MemberMethodType = void(*)(const void*, Args...); MemberMethodType fptr = (MemberMethodType)std::get(field->data); fptr(ptr, args...); } else { using MethodType = void(*)(Args...); MethodType fptr = (MethodType)std::get(field->data); fptr(args...); } return true; } 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, args...); } else { using MethodType = R(*)(Args...); MethodType fptr = (MethodType)std::get(field->data); ret = fptr(args...); } return true; } }