#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& 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 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 AnyValueList::ToSArray() { return sarray((Any*)data, num); } inline constexpr int AnyValueList::GetArgsSize(const sarray& args) { int size = args.size() * sizeof(Any); for (auto& arg : args) { size += arg.type->size; } return size; } template inline bool AnyView::Get(const Name& name, T& t) { if (cache && cache->name == name) { _cache_get: bool isChild = cache->type->IsChildOf(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 inline bool AnyView::Set(const Name& name, const T& t) { if (cache && cache->name == name) { _cache_set: bool isChild = cache->type->IsChildOf(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& 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& 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 }; } }