zengine-old/engine/3rdparty/zlib/include/refl/detail/view.inl
2024-04-19 22:02:27 +08:00

146 lines
3.2 KiB
C++

#pragma once
#include "uclass.h"
#include "view.h"
namespace refl {
/*平凡对象的转化要支持吗
* 比如同大小的安全转化
* 对象从小到大
* 对象从大到小
*/
using enum ClassFlag;
Any* Any::ConvertTo(const UClass* toClass) {
if (cls == toClass) {
return this;
}
//子类转父类
if (cls->IsChildOf(toClass)) {
cls = toClass;
return this;
}
if (cls->flag & CLASS_TRIVIAL_FLAG && toClass->flag & CLASS_TRIVIAL_FLAG) {
cls = toClass;
return this;
}
return nullptr;
}
AnyValueList::AnyValueList(const sarray<AnyValue>& args, void* memory)
: data(memory), num(args.size())
{
if (!memory) {
isMemoryOwner = true;
data = malloc(GetArgsSize(args));
}
Any* any = (Any*)data;
assert(any != nullptr);
char* pData = ((char*)data) + num * sizeof(Any);
for (auto& arg : args) {
arg.type->InitObject(pData);
arg.type->CopyObject(pData, arg.ptr);
any->ptr = pData;
any->cls = arg.cls;
any++;
pData += arg.type->size;
}
}
inline AnyValueList::~AnyValueList()
{
if (num == 0 || !data) {
return;
}
Any* ptr = (Any*)data;
for (int i = 0; i < num; i++) {
ptr->cls->DestObject((void*)ptr->ptr);
ptr++;
}
if (isMemoryOwner) {
free(data);
}
num = 0;
data = nullptr;
}
inline void AnyValueList::ConvertArgs(sarray<const UClass*> params)
{
Any* ptr = (Any*)data;
int first = params.size() - num;
for (int i = 0; i < num; i++, ptr++) {
ptr->ConvertTo(*params.at(first + i));
}
}
inline const sarray<Any> AnyValueList::ToSArray()
{
return sarray<Any>((Any*)data, num);
}
inline constexpr int AnyValueList::GetArgsSize(const sarray<AnyValue>& args)
{
int size = args.size() * sizeof(Any);
for (auto& arg : args) {
size += arg.type->size;
}
return size;
}
template<typename T>
inline bool AnyView::Get(const Name& name, T& t)
{
if (cache && cache->name == name) {
_cache_get: bool isChild = cache->type->IsChildOf<T>(true);
if (isChild) {
t = *(T*)((const char*)ptr + cache->data.offset);
}
return isChild;
}
auto field = cls->GetField(name, 0);
if (field) {
cache = field;
goto _cache_get;
}
if (cls->parent) {
return Parent().Get(name, t);
}
return false;
}
template<typename T>
inline bool AnyView::Set(const Name& name, const T& t)
{
if (cache && cache->name == name) {
_cache_set: bool isChild = cache->type->IsChildOf<T>(true);
if (isChild) {
*(T*)((const char*)ptr + cache->data.offset) = t;
}
return isChild;
}
auto field = cls->GetField(name, 0);
if (field) {
cache = field;
goto _cache_set;
}
if (cls->parent) {
return Parent().Set(name, t);
}
return false;
}
bool AnyView::Invoke(const Name& name,const sarray<Any>& ArgsList)
{
auto field = cls->GetField(name, 0);
if (!field) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
return field->Invoke(ArgsList);
}
bool AnyView::Invoke(const Name& name, svector<Any>& ArgsList)
{
auto field = cls->GetField(name, 0);
if (!field) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
return field->Invoke(ArgsList);
}
AnyView AnyView::Parent() {
return { ptr, cls ? cls->parent : nullptr };
}
}