#pragma once #include "type.h" #include "field.h" #include "view.h" namespace refl { struct vtable_uclass { //object void (*InitObject)(void*); //class const FieldPtr* (*GetField)(const UClass*, const Name&, bool); //function std::vector(*GetParams)(const UClass*); //function void (*Call)(const FieldPtr&, std::vector&); }; class UClass{ using enum FieldFlag; public: Name name; uint32_t size; //uint32_t flag; const UClass* parent; vtable_uclass vtable{}; public: constexpr UClass(std::string_view name, uint32_t size, const 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; } bool IsChildOf(const UClass* cls) const { const UClass* _parent = parent; while (_parent != nullptr) { if (_parent == cls) { return true; } _parent = _parent->parent; } return false; } 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: template<_ReflCheck_Ctor T> static void InitObject(void* ptr) { T obj{}; std::construct_at((T*)ptr, obj); } //unsafe if called by other, need check class && size void InitObject(void* ptr)const { if (vtable.InitObject) { vtable.InitObject(ptr); } else { memset(ptr, 0, size); } } const FieldPtr* GetField(const Name& name, bool isMethod)const { if (vtable.GetField) { return vtable.GetField(this, name, isMethod); } return nullptr; } std::vector GetParams() const { if (vtable.GetParams) { return vtable.GetParams(this); } return{}; } void Call(const FieldPtr& field, std::vector& ArgsList)const{ if (vtable.Call) { return vtable.Call(field, ArgsList); } } public: template constexpr static FieldPtr MakeMemberField(Name name, const UClass* cls) { FieldPtr::Data member = { offset }; constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG; return { name, cls, {member}, flag }; } template static FieldPtr MakeMethodField(R (* ptr)(Args...), Name name) { FieldPtr::Data member = { *(Method*)&ptr}; constexpr uint32_t flag = FIELD_METHOD_FLAG; return { name, &TypeInfo::type...)>::StaticClass, {member},flag }; } template static 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::type...)>::StaticClass, {member},flag }; } }; }