#pragma once #include "uclass.h" namespace refl { template inline bool ObjectView::Get(const Name& name, T& t) { if (cache && cache->name == name) { _cache_get: bool isChild = cache->type->IsChildOf(true); if (isChild) { t = *(T*)(ptr + cache->data.offset); } return isChild; } auto field = cls->GetField(name, false); if (field) { cache = field; goto _cache_get; } if (cls->parent) { return Parent().Get(name, t); } return false; } template inline bool ObjectView::Set(const Name& name, const T& t) { if (cache && cache->name == name) { _cache_set: bool isChild = cache->type->IsChildOf(true); if (isChild) { *(T*)(ptr + cache->data.offset) = t; } return isChild; } auto field = cls->GetField(name, false); if (field) { cache = field; goto _cache_set; } if (cls->parent) { return Parent().Set(name, t); } return false; } template bool ObjectView::Invoke(const Name& name, Args&&... args) { auto field = cls->GetField(name, true); if (!field) { if (cls->parent) { return Parent().Invoke(name, args...); } return false; } constexpr int inputSize = sizeof...(Args); auto params = field->type->GetParams(); int paramsSize = params.size(); std::vector ArgsList; ArgsList.reserve(paramsSize); ArgsList.emplace_back(); bool member = field->flag & FIELD_MEMBER_FLAG; if (member) { ArgsList.emplace_back(ptr, &TypeInfo::StaticClass); } (..., (ArgsList.emplace_back(args))); int argsSize = ArgsList.size(); if (argsSize < paramsSize && field->flag & FIELD_METHOD_VALUE_FLAG) { auto [argsPtr, valueSize] = field->value.method(); if (argsSize + valueSize >= paramsSize) { for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) { ArgsList.push_back(*(argsPtr + i)); } argsSize = paramsSize; } } if (argsSize < paramsSize) { return false; } for (int i = member + 1; i < paramsSize; i++) { if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) { return false; } } field->type->Call(*field, ArgsList); return true; } template R ObjectView::Invoke(const Name& name, Args&&... args) { //int x = 1; val = &x; *(int*)val = 2;//(x = 2) return *val; //val=>cast_to //int* x = nullptr; val = &x; *(int**)val = 0xff1234;//(x = 0xff1234) return *val; real_type_t data{}; ArgsView ret{ &data, &TypeInfo*>::StaticClass }; auto field = cls->GetField(name, true); if (!field) { if (cls->parent) { return Parent().Invoke(name, args...); } return ret.cast_ret(); } constexpr int inputSize = sizeof...(Args); auto params = field->type->GetParams(); int paramsSize = params.size(); std::vector ArgsList; ArgsList.reserve(paramsSize); ArgsList.emplace_back(ret); if (field->flag & FIELD_MEMBER_FLAG) { ArgsList.emplace_back(ptr, &TypeInfo::StaticClass); } (..., (ArgsList.emplace_back(args))); int argsSize = ArgsList.size(); if (argsSize < paramsSize && field->flag & FIELD_METHOD_VALUE_FLAG) { auto [argsPtr, valueSize] = field->value.method(); if (argsSize + valueSize >= paramsSize) { for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) { ArgsList.push_back(*(argsPtr + i)); } argsSize = paramsSize; } } if (argsSize < paramsSize) { return ret.cast_ret(); } for (int i = 0; i < paramsSize; i++) { if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) { return ret.cast_ret(); } } field->type->Call(*field, ArgsList); return ret.cast_ret(); } ObjectView ObjectView::Parent() { return { ptr, cls ? cls->parent : nullptr }; } /*平凡对象的转化要支持吗 * 比如同大小的安全转化 * 对象从小到大 * 对象从大到小 */ bool ArgsView::ConvertTo(const UClass* toClass) { //子类转父类 if (cls->IsChildOf(toClass)) { cls = toClass; return true; } return false; } ArgsValueList::ArgsValueList(const std::vector& args) { num = args.size(); int size = num * sizeof(ArgsView); for (auto& arg : args) { size += arg.cls->size; } data = (void*)malloc(size); ptr = (ArgsView*)data; char* pData = ((char*)data) + num * sizeof(ArgsView); for (auto& arg : args) { arg.type->InitObject(pData); arg.type->CopyObject(pData, arg.val); ptr->cls = arg.cls; ptr->val = pData; ptr++; pData += arg.cls->size; } ptr = (ArgsView*)data; } inline ArgsValueList::~ArgsValueList() { if (num == 0 || !data) { return; } for (int i = 0; i < num; i++) { ptr->cls->DestObject((void*)ptr->val); } free(data); num = 0; data = nullptr; } }