#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::IsContainer() const { return cls->flag & CLASS_CONTAINER_FLAG; } inline bool Any::IsSequence() const { return cls->flag & CLASS_SEQUENCE_FLAG; } inline bool Any::IsMap() const { return cls->flag & CLASS_MAP_FLAG; } inline bool Any::Construct(const sarray& ArgsList) const { return cls->Construct((void*)ptr, ArgsList); } inline void Any::Destruct() const { cls->Destruct((void*)ptr); } inline AnyArgs::AnyArgs(const sarray& args, const sarray& 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->Destruct((void*)any->ptr); any++; } free(data); } num = 0; data = nullptr; } inline int AnyArgs::Size() { return size; } inline const sarray AnyArgs::ToSArray() { return sarray((Any*)data, num); } inline constexpr Offset AnyArgs::GetArgsSize(const sarray& args,const sarray& 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 inline consteval Offset AnyArgs::GetArgsSize(const sarray& args) { constexpr int N = sizeof...(Args); if (args.size() == 0 || N < args.size() + 1) { return 0; } int first = N - args.size(); Offset offset = args.size() * sizeof(Any); offset += fetch_tuple_size>(std::index_sequence_for{}, first); return 0; } template inline bool AnyView::Get(const Name& name, T& t) { if (cache && cache->name == name) { _cache_get: bool isChild = cache->type->IsChildOf(); 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 inline bool AnyView::Set(const Name& name, const T& t) { if (cache && cache->name == name) { _cache_set: bool isChild = cache->type->IsChildOf(); 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& 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& 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& 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& 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::Construct(void* ptr, const sarray& ArgsList) const { if (vtable.Construct) { if (vtable.Construct(ptr, this, ArgsList)) { return true; } auto& fieldList = GetFields(EFieldFind::FIND_CTOR, FName("Ctor")); if (fieldList.empty()) { return false; } std::array ArgsArray = { Any{} , Any{ptr} }; int i = 2; for (auto& arg : ArgsList) { ArgsArray[i++] = arg; } sarray 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; } }