188 lines
4.7 KiB
C++
188 lines
4.7 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<typename R, typename ...Args>
|
|
R ObjectView::Invoke(const Name& name, Args&&... args)
|
|
{
|
|
//int x = 1; val = &x; *(int*)val = 2;//(x = 2) return *val; //val=>cast_to<int>
|
|
//int* x = nullptr; val = &x; *(int**)val = 0xff1234;//(x = 0xff1234) return *val;
|
|
real_type_t<R> data{};
|
|
ArgsView ret{ &data, &TypeInfo<real_type_t<R>*>::StaticClass };
|
|
auto field = cls->GetField(name, true);
|
|
if (!field) {
|
|
if (cls->parent) {
|
|
return Parent().Invoke<R>(name, args...);
|
|
}
|
|
return ret.cast_ret<R>();
|
|
}
|
|
constexpr int inputSize = sizeof...(Args);
|
|
auto params = field->type->GetParams();
|
|
int paramsSize = params.size();
|
|
std::vector<ArgsView> ArgsList;
|
|
ArgsList.reserve(paramsSize);
|
|
ArgsList.emplace_back(ret);
|
|
|
|
if (field->flag & FIELD_MEMBER_FLAG) {
|
|
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 ret.cast_ret<R>();
|
|
}
|
|
|
|
for (int i = 0; i < paramsSize; i++) {
|
|
if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) {
|
|
return ret.cast_ret<R>();
|
|
}
|
|
}
|
|
field->type->Call(*field, ArgsList);
|
|
return ret.cast_ret<R>();
|
|
}
|
|
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;
|
|
}
|
|
} |