zengine-old/engine/3rdparty/zlib/include/refl/uclass.h
2024-04-04 18:18:04 +08:00

133 lines
3.1 KiB
C++

#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<typename T>
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;
}
//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<uint32_t offset, typename T,typename U>
FieldPtr MakeMemberField(T U::* ptr, Name name) {
FieldPtr::Data member = { offset };
return { name, &TypeInfo<T>::StaticClass, {member} };
}
template<uint32_t offset, typename T, typename U>
FieldPtr MakeMethodField(T U::* ptr, Name name) {
FieldPtr::Data member = { offset };
return { name, &TypeInfo<T>::StaticClass, {member} };
}
};
template<typename T>
requires std::is_default_constructible_v<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<T>::value;
if constexpr (!is_shallow_copyable){
constexpr T obj{};
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;
}
};
template<_ReflCheck T, typename>
struct TypeInfo {
using UClass = UClass_Auto<T>;
inline static UClass StaticClass = UClass::BuildClass();
};
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>
bool ObjectView::Invoke(const Name& name, Args... args)
{
return false;
}
}