#pragma once #include "type.h" #include "field.h" #include "object.h" namespace refl { class UClass{ 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 }; return { name, &TypeInfo::StaticClass, {member} }; } template FieldPtr MakeMethodField(T U::* ptr, Name name) { FieldPtr::Data member = { offset }; return { name, &TypeInfo::StaticClass, {member} }; } }; template requires std::is_default_constructible_v 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){ constexpr 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 T, typename> struct TypeInfo { using UClass = UClass_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) { return false; } }