zengine-old/engine/3rdparty/zlib/include/refl/detail/view.inl
2024-06-14 22:24:52 +08:00

249 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "uclass.h"
#include "view.h"
#include "convert.h"
namespace refl {
using enum ClassFlag;
inline bool Any::Check(const UClass* toClass) const{
if (cls == toClass) {
return true;
}
if (!cls) {
return false;
}
return cls->IsChildOf(toClass);
}
inline constexpr int Any::Size()const
{
return cls->size;
}
inline constexpr const UClass* Any::Parent()const
{
return cls->parent;
}
inline Any Any::Member(const FieldPtr& field)const
{
if (field.flag & FIELD_MEMBER_FLAG) {
return { (const char*)ptr + field.data.member.offset, field.type };
}
return {};
}
inline Any Any::Member(int i) const
{
if (cls->flag & CLASS_ARRAY_FLAG) {
int offset = i * cls->parent->size;
if(offset < cls->size)
return { (const char*)ptr + offset, cls->parent };
}
return Any();
}
inline int Any::ArraySize()const
{
if (cls->flag & CLASS_ARRAY_FLAG) {
return cls->size / cls->parent->size;
}
return 0;
}
inline bool Any::IsArray() const
{
return cls->flag & CLASS_ARRAY_FLAG;
}
inline bool Any::IsObject() const
{
return !(cls->flag & CLASS_ARRAY_FLAG) && !(cls->flag & CLASS_POINTER_FLAG);
}
inline bool Any::Construct(const sarray<Any>& ArgsList) const
{
return cls->CtorObject((void*)ptr, ArgsList);
}
inline AnyArgs::AnyArgs(const sarray<Any>& args, const sarray<const UClass*>& params, void* memory)
: data(memory), num(args.size()), size(GetArgsSize(args, params))
{
assert(size > 0);
if (!memory) {
isMemoryOwner = true;
data = malloc(size);
}
Any* any = (Any*)data;
assert(any != nullptr);
char* pData = ((char*)data) + num * sizeof(Any);
auto uptr = params.at(params.size() - args.size());
for (auto& arg : args) {
any->cls = *uptr;
any->ptr = pData;
assert(Convert::Construct(*any, arg));
any++;
pData += (*uptr)->size;
}
}
inline AnyArgs::~AnyArgs()
{
if (num == 0 || !data) {
return;
}
if (isMemoryOwner) {
Any* any = (Any*)data;
for (int i = 0; i < num; i++) {
any->cls->DestObject((void*)any->ptr);
any++;
}
free(data);
}
num = 0;
data = nullptr;
}
inline int AnyArgs::Size()
{
return size;
}
inline const sarray<Any> AnyArgs::ToSArray()
{
return sarray<Any>((Any*)data, num);
}
inline constexpr Offset AnyArgs::GetArgsSize(const sarray<Any>& args,const sarray<const UClass*>& params)
{ //这里空间换时间Any多占用了一个数据指针
if (args.size() == 0 || params.size() < args.size() + 1) {
return 0;
}
Offset offset = args.size() * sizeof(Any);
auto uptr = params.at(params.size() - args.size());
for (auto uend = params.back(); uptr < uend; uptr++) {
offset += (*uptr)->size;//数据大小
}
return offset;
}
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>();
if (isChild) {
t = *(T*)((const char*)ptr + cache->data.member.offset);
}
return isChild;
}
auto& fieldList = cls->GetFields(EFieldFind::FIND_MEMBER, name);
if (fieldList.valid()) {
cache = fieldList.front();
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>();
if (isChild) {
*(T*)((const char*)ptr + cache->data.member.offset) = t;
}
return isChild;
}
auto& fieldList = cls->GetFields(EFieldFind::FIND_MEMBER, name);
if (fieldList.valid()) {
cache = fieldList.front();
goto _cache_set;
}
if (cls->parent) {
return Parent().Set(name, t);
}
return false;
}
inline bool AnyView::Invoke(const Name& name,const sarray<Any>& ArgsList)
{
auto& fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
return fieldList[0]->Invoke(ArgsList);
}
inline bool AnyView::Invoke(const Name& name, svector<Any>& ArgsList)
{
auto fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
return fieldList[0]->Invoke(ArgsList);
}
inline bool AnyView::Invokes(const Name& name, const sarray<Any>& ArgsList)
{
auto fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
if(fieldList.size() == 1)
return fieldList[0]->Invoke(ArgsList);
for (auto& field : fieldList) {
if (field.Invokes(ArgsList)) {
return true;
}
}
return false;
}
inline bool AnyView::Invokes(const Name& name, svector<Any>& ArgsList)
{
auto fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
if (fieldList.size() == 1)
return fieldList[0]->Invoke(ArgsList);
for (auto& field : fieldList) {
if (field.Invokes(ArgsList)) {
return true;
}
}
return false;
}
inline AnyView AnyView::Parent() {
return { ptr, cls ? cls->parent : nullptr };
}
inline bool UClass::CtorObject(void* ptr, const sarray<Any>& ArgsList) const
{
if (vtable.CtorObject) {
if (vtable.CtorObject(ptr, this, ArgsList)) {
return true;
}
auto& fieldList = GetFields(EFieldFind::FIND_CTOR, FName("Ctor"));
if (fieldList.empty()) {
return false;
}
std::array<Any, 10> ArgsArray = { Any{} , Any{ptr} };
int i = 2;
for (auto& arg : ArgsList) {
ArgsArray[i++] = arg;
}
sarray<Any> FieldArgs(&ArgsArray[0], 2 + ArgsList.size());
if (fieldList.size() == 1) {
return fieldList[0]->Invoke(FieldArgs);
}
for (auto& field : fieldList) {
if (field.Invokes(FieldArgs)) {
return true;
}
}
return false;
}
if (ArgsList.valid() && ArgsList[0]->Check(this)) {
memcpy(ptr, ArgsList[0]->ptr, size);
return true;
}
memset(ptr, 0, size);
return true;
}
}