zengine-old/engine/3rdparty/zlib/include/refl/detail/view.inl

172 lines
4.1 KiB
C++

#pragma once
#include "uclass.h"
namespace refl {
template<typename T>
inline bool ObjectView::Get(const Name& name, T& t)
{
if (cache && cache->name == name) {
_cache_get: bool isChild = cache->type->IsChildOf<T>(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<typename T>
inline bool ObjectView::Set(const Name& name, const T& t)
{
if (cache && cache->name == name) {
_cache_set: bool isChild = cache->type->IsChildOf<T>(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<typename ...Args>
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<ArgsView> ArgsList;
ArgsList.reserve(paramsSize);
ArgsList.emplace_back();
bool member = field->flag & FIELD_MEMBER_FLAG;
if (member) {
ArgsList.emplace_back(ptr, &TypeInfo<const void*>::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<_ReflCheck_Ctor R, typename ...Args>
R ObjectView::Invoke(const Name& name, Args&&... args)
{
auto field = cls->GetField(name, true);
if (!field) {
if (cls->parent) {
return Parent().Invoke<R>(name, args...);
}
return {};
}
R ret{};
constexpr int inputSize = sizeof...(Args);
auto params = field->type->GetParams();
int paramsSize = params.size();
bool member = field->flag & FIELD_MEMBER_FLAG;
if (inputSize + member >= paramsSize) {
return false;
}
std::vector<ArgsView> ArgsList;
ArgsList.reserve(paramsSize);
ArgsList.emplace_back(ret);
if (member) {
ArgsList.emplace_back(ptr, &TypeInfo<const void*>::StaticClass);
}
(..., (ArgsList.emplace_back(args)));
for (int i = 0; i < paramsSize; i++) {
if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) {
return ret;
}
}
field->type->Call(*field, ArgsList);
return 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<ArgsValue>& 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;
}
}