mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-02-05 11:30:07 +08:00
5027 lines
136 KiB
C++
5027 lines
136 KiB
C++
/***********************************************************************
|
|
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
|
|
DEVELOPER: Zihan Chen(vczh)
|
|
***********************************************************************/
|
|
#include "VlppReflection.h"
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEINTERFACES.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace collections;
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
description::TypeManager
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
class TypeManager : public Object, public ITypeManager
|
|
{
|
|
public:
|
|
static vint typeVersion;
|
|
|
|
protected:
|
|
Dictionary<WString, Ptr<ITypeDescriptor>> typeDescriptors;
|
|
List<Ptr<ITypeLoader>> typeLoaders;
|
|
ITypeDescriptor* rootType = nullptr;
|
|
bool loaded = false;
|
|
|
|
public:
|
|
TypeManager()
|
|
{
|
|
}
|
|
|
|
~TypeManager()
|
|
{
|
|
Unload();
|
|
}
|
|
|
|
vint GetTypeDescriptorCount()override
|
|
{
|
|
return typeDescriptors.Values().Count();
|
|
}
|
|
|
|
ITypeDescriptor* GetTypeDescriptor(vint index)override
|
|
{
|
|
return typeDescriptors.Values().Get(index).Obj();
|
|
}
|
|
|
|
ITypeDescriptor* GetTypeDescriptor(const WString& name)override
|
|
{
|
|
vint index = typeDescriptors.Keys().IndexOf(name);
|
|
return index == -1 ? 0 : typeDescriptors.Values().Get(index).Obj();
|
|
}
|
|
|
|
bool SetTypeDescriptor(const WString& name, Ptr<ITypeDescriptor> typeDescriptor)override
|
|
{
|
|
if (typeDescriptor && name != typeDescriptor->GetTypeName())
|
|
{
|
|
return false;
|
|
}
|
|
if (!typeDescriptors.Keys().Contains(name))
|
|
{
|
|
if (typeDescriptor)
|
|
{
|
|
typeDescriptors.Add(name, typeDescriptor);
|
|
typeVersion++;
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!typeDescriptor)
|
|
{
|
|
typeDescriptors.Remove(name);
|
|
typeVersion++;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AddTypeLoader(Ptr<ITypeLoader> typeLoader)override
|
|
{
|
|
vint index = typeLoaders.IndexOf(typeLoader.Obj());
|
|
if (index == -1)
|
|
{
|
|
typeLoaders.Add(typeLoader);
|
|
if (loaded)
|
|
{
|
|
auto oldTypeVersion = typeVersion;
|
|
typeLoader->Load(this);
|
|
typeVersion = oldTypeVersion + 1;
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool RemoveTypeLoader(Ptr<ITypeLoader> typeLoader)override
|
|
{
|
|
vint index = typeLoaders.IndexOf(typeLoader.Obj());
|
|
if (index != -1)
|
|
{
|
|
if (loaded)
|
|
{
|
|
auto oldTypeVersion = typeVersion;
|
|
typeLoader->Unload(this);
|
|
typeVersion = oldTypeVersion + 1;
|
|
}
|
|
typeLoaders.RemoveAt(index);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Load()override
|
|
{
|
|
if (!loaded)
|
|
{
|
|
loaded = true;
|
|
auto oldTypeVersion = typeVersion;
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < typeLoaders.Count(); i++)
|
|
{
|
|
typeLoaders[i]->Load(this);
|
|
}
|
|
typeVersion = oldTypeVersion + 1;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Unload()override
|
|
{
|
|
if (loaded)
|
|
{
|
|
loaded = false;
|
|
rootType = 0;
|
|
auto oldTypeVersion = typeVersion;
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < typeLoaders.Count(); i++)
|
|
{
|
|
typeLoaders[i]->Unload(this);
|
|
}
|
|
typeVersion = oldTypeVersion + 1;
|
|
typeDescriptors.Clear();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Reload()override
|
|
{
|
|
Unload();
|
|
Load();
|
|
return true;
|
|
}
|
|
|
|
bool IsLoaded()override
|
|
{
|
|
return loaded;
|
|
}
|
|
|
|
ITypeDescriptor* GetRootType()override
|
|
{
|
|
if (!rootType)
|
|
{
|
|
rootType = description::GetTypeDescriptor<Value>();
|
|
}
|
|
return rootType;
|
|
}
|
|
|
|
vint GetTypeVersion() override
|
|
{
|
|
return typeVersion;
|
|
}
|
|
};
|
|
vint TypeManager::typeVersion = -1;
|
|
|
|
/***********************************************************************
|
|
description::TypeManager helper functions
|
|
***********************************************************************/
|
|
|
|
ITypeManager* globalTypeManager=0;
|
|
bool initializedGlobalTypeManager=false;
|
|
|
|
ITypeManager* GetGlobalTypeManager()
|
|
{
|
|
if (!initializedGlobalTypeManager)
|
|
{
|
|
initializedGlobalTypeManager = true;
|
|
globalTypeManager = new TypeManager;
|
|
}
|
|
return globalTypeManager;
|
|
}
|
|
|
|
bool DestroyGlobalTypeManager()
|
|
{
|
|
if (initializedGlobalTypeManager && globalTypeManager)
|
|
{
|
|
delete globalTypeManager;
|
|
globalTypeManager = nullptr;
|
|
TypeManager::typeVersion++;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool ResetGlobalTypeManager()
|
|
{
|
|
if (!DestroyGlobalTypeManager()) return false;
|
|
initializedGlobalTypeManager = false;
|
|
return true;
|
|
}
|
|
|
|
ITypeDescriptor* GetTypeDescriptor(const WString& name)
|
|
{
|
|
if (globalTypeManager)
|
|
{
|
|
if (!globalTypeManager->IsLoaded())
|
|
{
|
|
globalTypeManager->Load();
|
|
}
|
|
return globalTypeManager->GetTypeDescriptor(name);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Cpp Helper Functions
|
|
***********************************************************************/
|
|
|
|
WString CppGetFullName(ITypeDescriptor* type)
|
|
{
|
|
if (auto cpp = type->GetCpp())
|
|
{
|
|
if (cpp->GetFullName() == L"void" || cpp->GetFullName() == L"vl::reflection::description::VoidValue")
|
|
{
|
|
return L"void";
|
|
}
|
|
else if (cpp->GetFullName() == L"float")
|
|
{
|
|
return L"float";
|
|
}
|
|
else if (cpp->GetFullName() == L"double")
|
|
{
|
|
return L"double";
|
|
}
|
|
else if (cpp->GetFullName() == L"bool")
|
|
{
|
|
return L"bool";
|
|
}
|
|
else if (cpp->GetFullName() == L"wchar_t")
|
|
{
|
|
return L"wchar_t";
|
|
}
|
|
else
|
|
{
|
|
return L"::" + cpp->GetFullName();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return L"::vl::" + type->GetTypeName();
|
|
}
|
|
}
|
|
|
|
WString CppGetReferenceTemplate(IPropertyInfo* prop)
|
|
{
|
|
if (auto cpp = prop->GetCpp())
|
|
{
|
|
return cpp->GetReferenceTemplate();
|
|
}
|
|
else if ((prop->GetOwnerTypeDescriptor()->GetTypeDescriptorFlags() & TypeDescriptorFlags::ReferenceType) != TypeDescriptorFlags::Undefined)
|
|
{
|
|
return WString::Unmanaged(L"$This->$Name");
|
|
}
|
|
else
|
|
{
|
|
return WString::Unmanaged(L"$This.$Name");
|
|
}
|
|
}
|
|
|
|
WString CppGetClosureTemplate(IMethodInfo* method)
|
|
{
|
|
if (auto cpp = method->GetCpp())
|
|
{
|
|
return cpp->GetClosureTemplate();
|
|
}
|
|
|
|
if (method->IsStatic())
|
|
{
|
|
return WString::Unmanaged(L"::vl::Func<$Func>(&$Type::$Name)");
|
|
}
|
|
else
|
|
{
|
|
return WString::Unmanaged(L"::vl::Func<$Func>($This, &$Type::$Name)");
|
|
}
|
|
}
|
|
|
|
WString CppGetInvokeTemplate(IMethodInfo* method)
|
|
{
|
|
if (auto cpp = method->GetCpp())
|
|
{
|
|
return cpp->GetInvokeTemplate();
|
|
}
|
|
|
|
if (method->GetOwnerMethodGroup() == method->GetOwnerTypeDescriptor()->GetConstructorGroup())
|
|
{
|
|
return WString::Unmanaged(L"new $Type($Arguments)");
|
|
}
|
|
else if (method->IsStatic())
|
|
{
|
|
return WString::Unmanaged(L"$Type::$Name($Arguments)");
|
|
}
|
|
else
|
|
{
|
|
return WString::Unmanaged(L"$This->$Name($Arguments)");
|
|
}
|
|
}
|
|
|
|
WString CppGetAttachTemplate(IEventInfo* ev)
|
|
{
|
|
auto cpp = ev->GetCpp();
|
|
return cpp == nullptr ? WString::Unmanaged(L"::vl::__vwsn::EventAttach($This->$Name, $Handler)") : cpp->GetAttachTemplate();
|
|
}
|
|
|
|
WString CppGetDetachTemplate(IEventInfo* ev)
|
|
{
|
|
auto cpp = ev->GetCpp();
|
|
return cpp == nullptr ? WString::Unmanaged(L"::vl::__vwsn::EventDetach($This->$Name, $Handler)") : cpp->GetDetachTemplate();
|
|
}
|
|
|
|
WString CppGetInvokeTemplate(IEventInfo* ev)
|
|
{
|
|
auto cpp = ev->GetCpp();
|
|
return cpp == nullptr ? WString::Unmanaged(L"::vl::__vwsn::EventInvoke($This->$Name)($Arguments)") : cpp->GetInvokeTemplate();
|
|
}
|
|
|
|
bool CppExists(ITypeDescriptor* type)
|
|
{
|
|
auto cpp = type->GetCpp();
|
|
return cpp == nullptr || cpp->GetFullName() != L"*";
|
|
}
|
|
|
|
bool CppExists(IPropertyInfo* prop)
|
|
{
|
|
if (auto cpp = prop->GetCpp())
|
|
{
|
|
return cpp->GetReferenceTemplate() != L"*";
|
|
}
|
|
else if (auto method = prop->GetGetter())
|
|
{
|
|
return CppExists(method);
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CppExists(IMethodInfo* method)
|
|
{
|
|
auto cpp = method->GetCpp();
|
|
return cpp == nullptr || cpp->GetInvokeTemplate() != L"*";
|
|
}
|
|
|
|
bool CppExists(IEventInfo* ev)
|
|
{
|
|
auto cpp = ev->GetCpp();
|
|
return cpp == nullptr || cpp->GetInvokeTemplate() != L"*";
|
|
}
|
|
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEINTERFACES_LOG.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
using namespace collections;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
/***********************************************************************
|
|
LogTypeManager (enum)
|
|
***********************************************************************/
|
|
|
|
void LogTypeManager_Enum(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
if (type->GetTypeDescriptorFlags() == TypeDescriptorFlags::FlagEnum)
|
|
{
|
|
writer.WriteLine(L"@Flags");
|
|
}
|
|
writer.WriteLine(L"enum " + type->GetTypeName() + L" {");
|
|
|
|
auto enumType = type->GetEnumType();
|
|
for (vint j = 0; j < enumType->GetItemCount(); j++)
|
|
{
|
|
writer.WriteLine(L" " + enumType->GetItemName(j) + L" = " + u64tow(enumType->GetItemValue(j)) + L",");
|
|
}
|
|
|
|
writer.WriteLine(L"}");
|
|
}
|
|
|
|
/***********************************************************************
|
|
LogTypeManager (struct)
|
|
***********************************************************************/
|
|
|
|
void LogTypeManager_Property(stream::TextWriter& writer, IPropertyInfo* info)
|
|
{
|
|
if (auto cpp = info->GetCpp())
|
|
{
|
|
writer.WriteLine(L" @ReferenceTemplate:" + cpp->GetReferenceTemplate());
|
|
}
|
|
writer.WriteString(L" property " + info->GetName() + L" : " + info->GetReturn()->GetTypeFriendlyName());
|
|
if (info->IsReadable() && info->IsWritable() && !info->GetGetter() && !info->GetSetter() && !info->GetValueChangedEvent())
|
|
{
|
|
writer.WriteLine(L";");
|
|
}
|
|
else
|
|
{
|
|
writer.WriteString(L" { ");
|
|
if (info->IsReadable())
|
|
{
|
|
writer.WriteString(L"get");
|
|
if (auto mi = info->GetGetter())
|
|
{
|
|
writer.WriteString(L":" + mi->GetName());
|
|
}
|
|
writer.WriteString(L" ");
|
|
}
|
|
if (info->IsWritable())
|
|
{
|
|
writer.WriteString(L"set");
|
|
if (auto mi = info->GetSetter())
|
|
{
|
|
writer.WriteString(L":" + mi->GetName());
|
|
}
|
|
writer.WriteString(L" ");
|
|
}
|
|
if (auto ei = info->GetValueChangedEvent())
|
|
{
|
|
writer.WriteString(L"event:" + ei->GetName() + L" ");
|
|
}
|
|
writer.WriteLine(L"}");
|
|
}
|
|
}
|
|
|
|
void LogTypeManager_Struct(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
writer.WriteLine(L"struct " + type->GetTypeName() + L" {");
|
|
for (vint j = 0; j<type->GetPropertyCount(); j++)
|
|
{
|
|
IPropertyInfo* info = type->GetProperty(j);
|
|
LogTypeManager_Property(writer, info);
|
|
}
|
|
writer.WriteLine(L"}");
|
|
}
|
|
|
|
/***********************************************************************
|
|
LogTypeManager (data)
|
|
***********************************************************************/
|
|
|
|
void LogTypeManager_Data(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
writer.WriteLine(L"primitive " + type->GetTypeName() + L";");
|
|
}
|
|
|
|
/***********************************************************************
|
|
LogTypeManager (class)
|
|
***********************************************************************/
|
|
|
|
void LogTypeManager_PrintEvents(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
bool printed = false;
|
|
for (vint j = 0; j < type->GetEventCount(); j++)
|
|
{
|
|
printed = true;
|
|
IEventInfo* info = type->GetEvent(j);
|
|
if (auto cpp = info->GetCpp())
|
|
{
|
|
writer.WriteLine(L" @AttachTemplate:" + cpp->GetAttachTemplate());
|
|
writer.WriteLine(L" @DetachTemplate:" + cpp->GetDetachTemplate());
|
|
writer.WriteLine(L" @InvokeTemplate:" + cpp->GetInvokeTemplate());
|
|
}
|
|
|
|
writer.WriteString(L" event " + info->GetName() + L" : " + info->GetHandlerType()->GetTypeFriendlyName());
|
|
|
|
if (info->GetObservingPropertyCount() > 0)
|
|
{
|
|
writer.WriteLine(L" observing {");
|
|
vint count = info->GetObservingPropertyCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
writer.WriteLine(L" " + info->GetObservingProperty(i)->GetName() + L",");
|
|
}
|
|
writer.WriteLine(L" }");
|
|
}
|
|
else
|
|
{
|
|
writer.WriteLine(L";");
|
|
}
|
|
}
|
|
if (printed)
|
|
{
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
void LogTypeManager_PrintProperties(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
bool printed = false;
|
|
for (vint j = 0; j < type->GetPropertyCount(); j++)
|
|
{
|
|
printed = true;
|
|
IPropertyInfo* info = type->GetProperty(j);
|
|
LogTypeManager_Property(writer, info);
|
|
}
|
|
if (printed)
|
|
{
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
void LogTypeManager_Method(stream::TextWriter& writer, IMethodInfo* info, const wchar_t* title)
|
|
{
|
|
if (auto cpp = info->GetCpp())
|
|
{
|
|
writer.WriteLine(L" @InvokeTemplate:" + cpp->GetInvokeTemplate());
|
|
writer.WriteLine(L" @ClosureTemplate:" + cpp->GetClosureTemplate());
|
|
}
|
|
|
|
writer.WriteString(L" ");
|
|
writer.WriteString(title);
|
|
writer.WriteString(L" " + info->GetName() + L"(");
|
|
for (vint l = 0; l < info->GetParameterCount(); l++)
|
|
{
|
|
if (l > 0) writer.WriteString(L", ");
|
|
IParameterInfo* parameter = info->GetParameter(l);
|
|
writer.WriteString(parameter->GetName() + L" : " + parameter->GetType()->GetTypeFriendlyName());
|
|
}
|
|
writer.WriteLine(L") : " + info->GetReturn()->GetTypeFriendlyName() + L";");
|
|
}
|
|
|
|
void LogTypeManager_PrintMethods(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
bool printed = false;
|
|
for (vint j = 0; j < type->GetMethodGroupCount(); j++)
|
|
{
|
|
IMethodGroupInfo* group = type->GetMethodGroup(j);
|
|
for (vint k = 0; k < group->GetMethodCount(); k++)
|
|
{
|
|
printed = true;
|
|
IMethodInfo* info = group->GetMethod(k);
|
|
if (info->IsStatic())
|
|
{
|
|
LogTypeManager_Method(writer, info, L"static function");
|
|
}
|
|
else
|
|
{
|
|
LogTypeManager_Method(writer, info, L"function");
|
|
}
|
|
}
|
|
}
|
|
if (printed)
|
|
{
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
|
|
void LogTypeManager_PrintConstructors(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
if (IMethodGroupInfo* group = type->GetConstructorGroup())
|
|
{
|
|
for (vint k = 0; k < group->GetMethodCount(); k++)
|
|
{
|
|
IMethodInfo* info = group->GetMethod(k);
|
|
LogTypeManager_Method(writer, info, L"constructor");
|
|
}
|
|
}
|
|
}
|
|
|
|
void LogTypeManager_Class(stream::TextWriter& writer, ITypeDescriptor* type)
|
|
{
|
|
bool acceptProxy = false;
|
|
bool isInterface = (type->GetTypeDescriptorFlags() & TypeDescriptorFlags::InterfaceType) != TypeDescriptorFlags::Undefined;
|
|
writer.WriteString((isInterface ? L"interface " : L"class ") + type->GetTypeName());
|
|
for (vint j = 0; j<type->GetBaseTypeDescriptorCount(); j++)
|
|
{
|
|
writer.WriteString(j == 0 ? L" : " : L", ");
|
|
writer.WriteString(type->GetBaseTypeDescriptor(j)->GetTypeName());
|
|
}
|
|
writer.WriteLine(L" {");
|
|
|
|
LogTypeManager_PrintEvents(writer, type);
|
|
LogTypeManager_PrintProperties(writer, type);
|
|
LogTypeManager_PrintMethods(writer, type);
|
|
LogTypeManager_PrintConstructors(writer, type);
|
|
|
|
writer.WriteLine(L"}");
|
|
}
|
|
|
|
/***********************************************************************
|
|
LogTypeManager
|
|
***********************************************************************/
|
|
|
|
bool IsInterfaceType(ITypeDescriptor* typeDescriptor, bool& acceptProxy)
|
|
{
|
|
bool containsConstructor = false;
|
|
if (IMethodGroupInfo* group = typeDescriptor->GetConstructorGroup())
|
|
{
|
|
containsConstructor = group->GetMethodCount() > 0;
|
|
if (group->GetMethodCount() == 1)
|
|
{
|
|
if (IMethodInfo* info = group->GetMethod(0))
|
|
{
|
|
if (info->GetParameterCount() == 1 && info->GetParameter(0)->GetType()->GetTypeDescriptor()->GetTypeName() == TypeInfo<IValueInterfaceProxy>::content.typeName)
|
|
{
|
|
acceptProxy = true;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!containsConstructor)
|
|
{
|
|
if (typeDescriptor->GetTypeName() == TypeInfo<IDescriptable>::content.typeName)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
for (vint i = 0; i < typeDescriptor->GetBaseTypeDescriptorCount(); i++)
|
|
{
|
|
bool _acceptProxy = false;
|
|
if (!IsInterfaceType(typeDescriptor->GetBaseTypeDescriptor(i), _acceptProxy))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
const wchar_t* name = typeDescriptor->GetTypeName().Buffer();
|
|
while (const wchar_t* next = ::wcschr(name, L':'))
|
|
{
|
|
name = next + 1;
|
|
}
|
|
return name[0] == L'I' && (L'A' <= name[1] && name[1] <= L'Z');
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void LogTypeManager(stream::TextWriter& writer)
|
|
{
|
|
for (vint i = 0; i < GetGlobalTypeManager()->GetTypeDescriptorCount(); i++)
|
|
{
|
|
ITypeDescriptor* type = GetGlobalTypeManager()->GetTypeDescriptor(i);
|
|
if (auto cpp = type->GetCpp())
|
|
{
|
|
writer.WriteLine(L"@FullName:" + cpp->GetFullName());
|
|
}
|
|
if (type->GetValueType())
|
|
{
|
|
writer.WriteLine(L"@ValueType");
|
|
}
|
|
if (type->GetSerializableType())
|
|
{
|
|
writer.WriteLine(L"@Serializable");
|
|
}
|
|
|
|
switch (type->GetTypeDescriptorFlags())
|
|
{
|
|
case TypeDescriptorFlags::Object:
|
|
case TypeDescriptorFlags::IDescriptable:
|
|
case TypeDescriptorFlags::Class:
|
|
case TypeDescriptorFlags::Interface:
|
|
LogTypeManager_Class(writer, type);
|
|
break;
|
|
case TypeDescriptorFlags::FlagEnum:
|
|
case TypeDescriptorFlags::NormalEnum:
|
|
LogTypeManager_Enum(writer, type);
|
|
break;
|
|
case TypeDescriptorFlags::Primitive:
|
|
LogTypeManager_Data(writer, type);
|
|
break;
|
|
case TypeDescriptorFlags::Struct:
|
|
LogTypeManager_Struct(writer, type);
|
|
break;
|
|
default:;
|
|
}
|
|
writer.WriteLine(L"");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEINTERFACES_METAONLY.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
Context
|
|
***********************************************************************/
|
|
|
|
struct MetaonlyWriterContext
|
|
{
|
|
Dictionary<ITypeDescriptor*, vint> tdIndex;
|
|
Dictionary<IMethodInfo*, vint> miIndex;
|
|
Dictionary<IPropertyInfo*, vint> piIndex;
|
|
Dictionary<IEventInfo*, vint> eiIndex;
|
|
};
|
|
|
|
struct MetaonlyReaderContext
|
|
{
|
|
Dictionary<WString, Ptr<ISerializableType>> serializableTypes;
|
|
List<Ptr<ITypeDescriptor>> tds;
|
|
List<Ptr<IMethodInfo>> mis;
|
|
List<Ptr<IPropertyInfo>> pis;
|
|
List<Ptr<IEventInfo>> eis;
|
|
};
|
|
|
|
/***********************************************************************
|
|
MetaonlyTypeInfo
|
|
***********************************************************************/
|
|
|
|
class MetaonlyTypeInfo : public Object, public ITypeInfo
|
|
{
|
|
friend struct stream::internal::Serialization<MetaonlyTypeInfo>;
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Decorator decorator = TypeDescriptor;
|
|
TypeInfoHint hint = TypeInfoHint::Normal;
|
|
Ptr<MetaonlyTypeInfo> elementType;
|
|
vint typeDecriptor = -1;
|
|
List<Ptr<MetaonlyTypeInfo>> genericArguments;
|
|
|
|
public:
|
|
MetaonlyTypeInfo() = default;
|
|
|
|
MetaonlyTypeInfo(MetaonlyWriterContext& _context, ITypeInfo* typeInfo)
|
|
: decorator(typeInfo->GetDecorator())
|
|
, hint(typeInfo->GetHint())
|
|
, typeDecriptor(_context.tdIndex[typeInfo->GetTypeDescriptor()])
|
|
{
|
|
if (auto et = typeInfo->GetElementType())
|
|
{
|
|
elementType = Ptr(new MetaonlyTypeInfo(_context, et));
|
|
}
|
|
for (vint i = 0; i < typeInfo->GetGenericArgumentCount(); i++)
|
|
{
|
|
auto ga = typeInfo->GetGenericArgument(i);
|
|
genericArguments.Add(Ptr(new MetaonlyTypeInfo(_context, ga)));
|
|
}
|
|
}
|
|
|
|
void SetContext(MetaonlyReaderContext* _context)
|
|
{
|
|
context = _context;
|
|
if (elementType)
|
|
{
|
|
elementType->SetContext(_context);
|
|
}
|
|
for (vint i = 0; i < genericArguments.Count(); i++)
|
|
{
|
|
genericArguments[i]->SetContext(_context);
|
|
}
|
|
}
|
|
|
|
Decorator GetDecorator() override
|
|
{
|
|
return decorator;
|
|
}
|
|
|
|
TypeInfoHint GetHint() override
|
|
{
|
|
return hint;
|
|
}
|
|
|
|
ITypeInfo* GetElementType() override
|
|
{
|
|
return elementType.Obj();
|
|
}
|
|
|
|
ITypeDescriptor* GetTypeDescriptor() override
|
|
{
|
|
return context->tds[typeDecriptor].Obj();
|
|
}
|
|
|
|
vint GetGenericArgumentCount() override
|
|
{
|
|
return genericArguments.Count();
|
|
}
|
|
|
|
ITypeInfo* GetGenericArgument(vint index) override
|
|
{
|
|
return genericArguments[index].Obj();
|
|
}
|
|
|
|
WString GetTypeFriendlyName() override
|
|
{
|
|
switch (decorator)
|
|
{
|
|
case RawPtr: return elementType->GetTypeFriendlyName() + L"*";
|
|
case SharedPtr: return elementType->GetTypeFriendlyName() + L"^";
|
|
case Nullable: return elementType->GetTypeFriendlyName() + L"?";
|
|
case TypeDescriptor: return GetTypeDescriptor()->GetTypeName();
|
|
default:;
|
|
}
|
|
WString result = elementType->GetTypeFriendlyName() + L"<";
|
|
// TODO: (enumerable) Linq:Aggregate
|
|
for (auto [type, i] : indexed(genericArguments))
|
|
{
|
|
if (i > 0) result += L", ";
|
|
result += type->GetTypeFriendlyName();
|
|
}
|
|
result += L">";
|
|
return result;
|
|
}
|
|
};
|
|
|
|
ITypeInfo* EnsureSetContext(ITypeInfo* info, MetaonlyReaderContext* context)
|
|
{
|
|
if (auto minfo = dynamic_cast<MetaonlyTypeInfo*>(info))
|
|
{
|
|
minfo->SetContext(context);
|
|
}
|
|
return info;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Metadata
|
|
***********************************************************************/
|
|
|
|
struct IdRange
|
|
{
|
|
vint start = -1;
|
|
vint count = 0;
|
|
};
|
|
|
|
struct ParameterInfoMetadata
|
|
{
|
|
WString name;
|
|
Ptr<MetaonlyTypeInfo> type;
|
|
};
|
|
|
|
struct MethodInfoMetadata
|
|
{
|
|
WString invokeTemplate;
|
|
WString closureTemplate;
|
|
WString name;
|
|
vint ownerTypeDescriptor = -1;
|
|
vint ownerProperty = -1;
|
|
List<Ptr<ParameterInfoMetadata>> parameters;
|
|
Ptr<MetaonlyTypeInfo> returnType;
|
|
bool isStatic = false;
|
|
};
|
|
|
|
struct PropertyInfoMetadata
|
|
{
|
|
WString referenceTemplate;
|
|
WString name;
|
|
vint ownerTypeDescriptor = -1;
|
|
bool isReadable = false;
|
|
bool isWritable = false;
|
|
Ptr<MetaonlyTypeInfo> returnType;
|
|
vint getter = -1;
|
|
vint setter = -1;
|
|
vint valueChangedEvent = -1;
|
|
};
|
|
|
|
struct EventInfoMetadata
|
|
{
|
|
WString attachTemplate;
|
|
WString detachTemplate;
|
|
WString invokeTemplate;
|
|
WString name;
|
|
vint ownerTypeDescriptor = -1;
|
|
Ptr<MetaonlyTypeInfo> handlerType;
|
|
List<vint> observingProperties;
|
|
};
|
|
|
|
struct TypeDescriptorMetadata
|
|
{
|
|
WString fullName;
|
|
WString typeName;
|
|
TypeDescriptorFlags flags = TypeDescriptorFlags::Undefined;
|
|
bool isAggregatable = false;
|
|
bool isValueType = false;
|
|
bool isSerializable = false;
|
|
bool isEnumType = false;
|
|
bool isFlagEnum = false;
|
|
List<WString> enumItems;
|
|
List<vuint64_t> enumValues;
|
|
List<vint> baseTypeDescriptors;
|
|
List<vint> properties;
|
|
List<vint> events;
|
|
List<vint> methods;
|
|
List<IdRange> methodGroups;
|
|
IdRange constructorGroup;
|
|
};
|
|
}
|
|
}
|
|
|
|
namespace stream
|
|
{
|
|
namespace internal
|
|
{
|
|
|
|
/***********************************************************************
|
|
Serialization
|
|
***********************************************************************/
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::IdRange)
|
|
SERIALIZE(start)
|
|
SERIALIZE(count)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::MetaonlyTypeInfo)
|
|
SERIALIZE(decorator)
|
|
SERIALIZE(hint)
|
|
SERIALIZE(elementType)
|
|
SERIALIZE(typeDecriptor)
|
|
SERIALIZE(genericArguments)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::ParameterInfoMetadata)
|
|
SERIALIZE(name)
|
|
SERIALIZE(type)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::MethodInfoMetadata)
|
|
SERIALIZE(invokeTemplate)
|
|
SERIALIZE(closureTemplate)
|
|
SERIALIZE(name)
|
|
SERIALIZE(ownerTypeDescriptor)
|
|
SERIALIZE(ownerProperty)
|
|
SERIALIZE(parameters)
|
|
SERIALIZE(returnType)
|
|
SERIALIZE(isStatic)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::PropertyInfoMetadata)
|
|
SERIALIZE(referenceTemplate)
|
|
SERIALIZE(name)
|
|
SERIALIZE(ownerTypeDescriptor)
|
|
SERIALIZE(isReadable)
|
|
SERIALIZE(isWritable)
|
|
SERIALIZE(returnType)
|
|
SERIALIZE(getter)
|
|
SERIALIZE(setter)
|
|
SERIALIZE(valueChangedEvent)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::EventInfoMetadata)
|
|
SERIALIZE(attachTemplate)
|
|
SERIALIZE(detachTemplate)
|
|
SERIALIZE(invokeTemplate)
|
|
SERIALIZE(name)
|
|
SERIALIZE(ownerTypeDescriptor)
|
|
SERIALIZE(handlerType)
|
|
SERIALIZE(observingProperties)
|
|
END_SERIALIZATION
|
|
|
|
BEGIN_SERIALIZATION(reflection::description::TypeDescriptorMetadata)
|
|
SERIALIZE(fullName)
|
|
SERIALIZE(typeName)
|
|
SERIALIZE(flags)
|
|
SERIALIZE(isAggregatable)
|
|
SERIALIZE(isValueType)
|
|
SERIALIZE(isSerializable)
|
|
SERIALIZE(isEnumType)
|
|
SERIALIZE(isFlagEnum)
|
|
SERIALIZE(enumItems)
|
|
SERIALIZE(enumValues)
|
|
SERIALIZE(baseTypeDescriptors)
|
|
SERIALIZE(properties)
|
|
SERIALIZE(events)
|
|
SERIALIZE(methods)
|
|
SERIALIZE(methodGroups)
|
|
SERIALIZE(constructorGroup)
|
|
END_SERIALIZATION
|
|
}
|
|
}
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
using Reader = stream::internal::Reader<Ptr<MetaonlyReaderContext>>;
|
|
using Writer = stream::internal::Writer<Ptr<MetaonlyWriterContext>>;
|
|
|
|
/***********************************************************************
|
|
IMethodInfo
|
|
***********************************************************************/
|
|
|
|
class MetaonlyParameterInfo : public Object, public IParameterInfo
|
|
{
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Ptr<ParameterInfoMetadata> metadata;
|
|
vint ownerTypeDescriptor = -1;
|
|
IMethodInfo* ownerMethod = nullptr;
|
|
|
|
public:
|
|
MetaonlyParameterInfo(MetaonlyReaderContext* _context, Ptr<ParameterInfoMetadata> _metadata, vint _ownerTypeDescriptor, IMethodInfo* _ownerMethod)
|
|
: context(_context)
|
|
, metadata(_metadata)
|
|
, ownerTypeDescriptor(_ownerTypeDescriptor)
|
|
, ownerMethod(_ownerMethod)
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* GetOwnerTypeDescriptor() override
|
|
{
|
|
return context->tds[ownerTypeDescriptor].Obj();
|
|
}
|
|
|
|
const WString& GetName() override
|
|
{
|
|
return metadata->name;
|
|
}
|
|
|
|
ITypeInfo* GetType() override
|
|
{
|
|
return EnsureSetContext(metadata->type.Obj(), context);
|
|
}
|
|
|
|
IMethodInfo* GetOwnerMethod() override
|
|
{
|
|
return ownerMethod;
|
|
}
|
|
};
|
|
|
|
class MetaonlyMethodInfo : public Object, public IMethodInfo, protected IMethodInfo::ICpp
|
|
{
|
|
friend class MetaonlyMethodGroupInfo;
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Ptr<MethodInfoMetadata> metadata;
|
|
IMethodGroupInfo* methodGroup = nullptr;
|
|
List<Ptr<IParameterInfo>> parameters;
|
|
|
|
public:
|
|
MetaonlyMethodInfo(MetaonlyReaderContext* _context, Ptr<MethodInfoMetadata> _metadata)
|
|
: context(_context)
|
|
, metadata(_metadata)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < metadata->parameters.Count(); i++)
|
|
{
|
|
parameters.Add(Ptr(new MetaonlyParameterInfo(context, metadata->parameters[i], metadata->ownerTypeDescriptor, this)));
|
|
}
|
|
}
|
|
|
|
// ICpp
|
|
|
|
const WString& GetInvokeTemplate() override
|
|
{
|
|
return metadata->invokeTemplate;
|
|
}
|
|
|
|
const WString& GetClosureTemplate() override
|
|
{
|
|
return metadata->closureTemplate;
|
|
}
|
|
|
|
// IMemberInfo
|
|
|
|
ITypeDescriptor* GetOwnerTypeDescriptor() override
|
|
{
|
|
return context->tds[metadata->ownerTypeDescriptor].Obj();
|
|
}
|
|
|
|
const WString& GetName() override
|
|
{
|
|
return metadata->name;
|
|
}
|
|
|
|
// IMethodInfo
|
|
|
|
IMethodInfo::ICpp* GetCpp() override
|
|
{
|
|
if (metadata->invokeTemplate.Length() + metadata->closureTemplate.Length() > 0)
|
|
{
|
|
return this;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
IMethodGroupInfo* GetOwnerMethodGroup() override
|
|
{
|
|
return methodGroup;
|
|
}
|
|
|
|
IPropertyInfo* GetOwnerProperty() override
|
|
{
|
|
return metadata->ownerProperty == -1 ? nullptr : context->pis[metadata->ownerProperty].Obj();
|
|
}
|
|
|
|
vint GetParameterCount() override
|
|
{
|
|
return parameters.Count();
|
|
}
|
|
|
|
IParameterInfo* GetParameter(vint index) override
|
|
{
|
|
return parameters[index].Obj();
|
|
}
|
|
|
|
ITypeInfo* GetReturn() override
|
|
{
|
|
return EnsureSetContext(metadata->returnType.Obj(), context);
|
|
}
|
|
|
|
bool IsStatic() override
|
|
{
|
|
return metadata->isStatic;
|
|
}
|
|
|
|
void CheckArguments(collections::Array<Value>& arguments) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
Value Invoke(const Value& thisObject, collections::Array<Value>& arguments) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
Value CreateFunctionProxy(const Value& thisObject) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
};
|
|
|
|
class MetaonlyMethodGroupInfo : public Object, public IMethodGroupInfo
|
|
{
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Ptr<TypeDescriptorMetadata> metadata;
|
|
IdRange idRange;
|
|
public:
|
|
MetaonlyMethodGroupInfo(MetaonlyReaderContext* _context, Ptr<TypeDescriptorMetadata> _metadata, IdRange _idRange)
|
|
: context(_context)
|
|
, metadata(_metadata)
|
|
, idRange(_idRange)
|
|
{
|
|
}
|
|
|
|
// IMemberInfo
|
|
|
|
ITypeDescriptor* GetOwnerTypeDescriptor() override
|
|
{
|
|
return GetMethod(0)->GetOwnerTypeDescriptor();
|
|
}
|
|
|
|
const WString& GetName() override
|
|
{
|
|
return GetMethod(0)->GetName();
|
|
}
|
|
|
|
// IMethodGroupInfo
|
|
|
|
vint GetMethodCount() override
|
|
{
|
|
return idRange.count;
|
|
}
|
|
|
|
IMethodInfo* GetMethod(vint index) override
|
|
{
|
|
CHECK_ERROR(0 <= index && index < idRange.count, L"IMethodGroupInfo::GetMethod(vint)#Index out of range.");
|
|
auto info = dynamic_cast<MetaonlyMethodInfo*>(context->mis[metadata->methods[idRange.start + index]].Obj());
|
|
if (info->methodGroup == nullptr)
|
|
{
|
|
info->methodGroup = this;
|
|
}
|
|
return info;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
IPropertyInfo
|
|
***********************************************************************/
|
|
|
|
class MetaonlyPropertyInfo : public Object, public IPropertyInfo, protected IPropertyInfo::ICpp
|
|
{
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Ptr<PropertyInfoMetadata> metadata;
|
|
|
|
public:
|
|
MetaonlyPropertyInfo(MetaonlyReaderContext* _context, Ptr<PropertyInfoMetadata> _metadata)
|
|
: context(_context)
|
|
, metadata(_metadata)
|
|
{
|
|
}
|
|
|
|
// ICpp
|
|
|
|
const WString& GetReferenceTemplate() override
|
|
{
|
|
return metadata->referenceTemplate;
|
|
}
|
|
|
|
// IMemberInfo
|
|
|
|
ITypeDescriptor* GetOwnerTypeDescriptor() override
|
|
{
|
|
return context->tds[metadata->ownerTypeDescriptor].Obj();
|
|
}
|
|
|
|
const WString& GetName() override
|
|
{
|
|
return metadata->name;
|
|
}
|
|
|
|
// IPropertyInfo
|
|
|
|
IPropertyInfo::ICpp* GetCpp() override
|
|
{
|
|
if (metadata->referenceTemplate.Length() > 0)
|
|
{
|
|
return this;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool IsReadable() override
|
|
{
|
|
return metadata->isReadable;
|
|
}
|
|
|
|
bool IsWritable() override
|
|
{
|
|
return metadata->isWritable;
|
|
}
|
|
|
|
ITypeInfo* GetReturn() override
|
|
{
|
|
return EnsureSetContext(metadata->returnType.Obj(), context);
|
|
}
|
|
|
|
IMethodInfo* GetGetter() override
|
|
{
|
|
return metadata->getter == -1 ? nullptr : context->mis[metadata->getter].Obj();
|
|
}
|
|
|
|
IMethodInfo* GetSetter() override
|
|
{
|
|
return metadata->setter == -1 ? nullptr : context->mis[metadata->setter].Obj();
|
|
}
|
|
|
|
IEventInfo* GetValueChangedEvent() override
|
|
{
|
|
return metadata->valueChangedEvent == -1 ? nullptr : context->eis[metadata->valueChangedEvent].Obj();
|
|
}
|
|
|
|
Value GetValue(const Value& thisObject) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
void SetValue(Value& thisObject, const Value& newValue) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
IEventInfo
|
|
***********************************************************************/
|
|
|
|
class MetaonlyEventInfo : public Object, public IEventInfo, protected IEventInfo::ICpp
|
|
{
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Ptr<EventInfoMetadata> metadata;
|
|
|
|
public:
|
|
MetaonlyEventInfo(MetaonlyReaderContext* _context, Ptr<EventInfoMetadata> _metadata)
|
|
: context(_context)
|
|
, metadata(_metadata)
|
|
{
|
|
}
|
|
|
|
// ICpp
|
|
|
|
const WString& GetAttachTemplate() override
|
|
{
|
|
return metadata->attachTemplate;
|
|
}
|
|
|
|
const WString& GetDetachTemplate() override
|
|
{
|
|
return metadata->detachTemplate;
|
|
}
|
|
|
|
const WString& GetInvokeTemplate() override
|
|
{
|
|
return metadata->invokeTemplate;
|
|
}
|
|
|
|
// IMemberInfo
|
|
|
|
ITypeDescriptor* GetOwnerTypeDescriptor() override
|
|
{
|
|
return context->tds[metadata->ownerTypeDescriptor].Obj();
|
|
}
|
|
|
|
const WString& GetName() override
|
|
{
|
|
return metadata->name;
|
|
}
|
|
|
|
// IEventInfo
|
|
|
|
IEventInfo::ICpp* GetCpp() override
|
|
{
|
|
if (metadata->attachTemplate.Length() + metadata->detachTemplate.Length() + metadata->invokeTemplate.Length() > 0)
|
|
{
|
|
return this;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
ITypeInfo* GetHandlerType() override
|
|
{
|
|
return EnsureSetContext(metadata->handlerType.Obj(), context);
|
|
}
|
|
|
|
vint GetObservingPropertyCount() override
|
|
{
|
|
return metadata->observingProperties.Count();
|
|
}
|
|
|
|
IPropertyInfo* GetObservingProperty(vint index) override
|
|
{
|
|
return context->pis[metadata->observingProperties[index]].Obj();
|
|
}
|
|
|
|
Ptr<IEventHandler> Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
bool Detach(const Value& thisObject, Ptr<IEventHandler> handler) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
void Invoke(const Value& thisObject, Ptr<IValueReadonlyList> arguments) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ITypeDescriptor
|
|
***********************************************************************/
|
|
|
|
class MetaonlyTypeDescriptor
|
|
: public Object
|
|
, public ITypeDescriptor
|
|
, protected ITypeDescriptor::ICpp
|
|
, protected IValueType
|
|
, protected IEnumType
|
|
{
|
|
protected:
|
|
MetaonlyReaderContext* context = nullptr;
|
|
Ptr<TypeDescriptorMetadata> metadata;
|
|
ISerializableType* serializableType = nullptr;
|
|
List<Ptr<IMethodGroupInfo>> methodGroups;
|
|
Ptr<IMethodGroupInfo> constructorGroup;
|
|
|
|
public:
|
|
MetaonlyTypeDescriptor(MetaonlyReaderContext* _context, Ptr<TypeDescriptorMetadata> _metadata)
|
|
: context(_context)
|
|
, metadata(_metadata)
|
|
{
|
|
if (metadata->isSerializable)
|
|
{
|
|
serializableType = context->serializableTypes[metadata->typeName].Obj();
|
|
}
|
|
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < metadata->methodGroups.Count(); i++)
|
|
{
|
|
methodGroups.Add(Ptr(new MetaonlyMethodGroupInfo(context, metadata, metadata->methodGroups[i])));
|
|
}
|
|
if (metadata->constructorGroup.start != -1)
|
|
{
|
|
constructorGroup = Ptr(new MetaonlyMethodGroupInfo(context, metadata, metadata->constructorGroup));
|
|
}
|
|
}
|
|
|
|
// ICpp
|
|
|
|
const WString& GetFullName() override
|
|
{
|
|
return metadata->fullName;
|
|
}
|
|
|
|
// IValueType
|
|
|
|
Value CreateDefault() override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
// IEnumType
|
|
|
|
bool IsFlagEnum() override
|
|
{
|
|
return metadata->isFlagEnum;
|
|
}
|
|
|
|
vint GetItemCount() override
|
|
{
|
|
return metadata->enumItems.Count();
|
|
}
|
|
|
|
WString GetItemName(vint index) override
|
|
{
|
|
return metadata->enumItems[index];
|
|
}
|
|
|
|
vuint64_t GetItemValue(vint index) override
|
|
{
|
|
return metadata->enumValues[index];
|
|
}
|
|
|
|
vint IndexOfItem(WString name) override
|
|
{
|
|
return metadata->enumItems.IndexOf(name);
|
|
}
|
|
|
|
Value ToEnum(vuint64_t value) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
vuint64_t FromEnum(const Value& value) override
|
|
{
|
|
CHECK_FAIL(L"Not Supported!");
|
|
}
|
|
|
|
// ITypeDescriptor
|
|
|
|
ITypeDescriptor::ICpp* GetCpp() override
|
|
{
|
|
if (metadata->fullName.Length() > 0)
|
|
{
|
|
return this;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
TypeDescriptorFlags GetTypeDescriptorFlags() override
|
|
{
|
|
return metadata->flags;
|
|
}
|
|
|
|
bool IsAggregatable() override
|
|
{
|
|
return metadata->isAggregatable;
|
|
}
|
|
|
|
const WString& GetTypeName() override
|
|
{
|
|
return metadata->typeName;
|
|
}
|
|
|
|
IValueType* GetValueType() override
|
|
{
|
|
return metadata->isValueType ? this : nullptr;
|
|
}
|
|
|
|
IEnumType* GetEnumType() override
|
|
{
|
|
return metadata->isEnumType ? this : nullptr;
|
|
}
|
|
|
|
ISerializableType* GetSerializableType() override
|
|
{
|
|
return serializableType;
|
|
}
|
|
|
|
vint GetBaseTypeDescriptorCount() override
|
|
{
|
|
return metadata->baseTypeDescriptors.Count();
|
|
}
|
|
|
|
ITypeDescriptor* GetBaseTypeDescriptor(vint index) override
|
|
{
|
|
return context->tds[metadata->baseTypeDescriptors[index]].Obj();
|
|
}
|
|
|
|
bool CanConvertTo(ITypeDescriptor* targetType) override
|
|
{
|
|
if (this == targetType) return true;
|
|
vint count = GetBaseTypeDescriptorCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
if (GetBaseTypeDescriptor(i)->CanConvertTo(targetType)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
vint GetPropertyCount() override
|
|
{
|
|
return metadata->properties.Count();
|
|
}
|
|
|
|
IPropertyInfo* GetProperty(vint index) override
|
|
{
|
|
return context->pis[metadata->properties[index]].Obj();
|
|
}
|
|
|
|
bool IsPropertyExists(const WString& name, bool inheritable) override
|
|
{
|
|
return GetPropertyByName(name, inheritable);
|
|
}
|
|
|
|
IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable) override
|
|
{
|
|
for (vint i = 0; i < metadata->properties.Count(); i++)
|
|
{
|
|
auto info = GetProperty(i);
|
|
if (info->GetName() == name)
|
|
{
|
|
return info;
|
|
}
|
|
}
|
|
if (inheritable)
|
|
{
|
|
for (vint i = 0; i < metadata->baseTypeDescriptors.Count(); i++)
|
|
{
|
|
if (auto info = GetBaseTypeDescriptor(i)->GetPropertyByName(name, true))
|
|
{
|
|
return info;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
vint GetEventCount() override
|
|
{
|
|
return metadata->events.Count();
|
|
}
|
|
|
|
IEventInfo* GetEvent(vint index) override
|
|
{
|
|
return context->eis[metadata->events[index]].Obj();
|
|
}
|
|
|
|
bool IsEventExists(const WString& name, bool inheritable) override
|
|
{
|
|
return GetEventByName(name, inheritable);
|
|
}
|
|
|
|
IEventInfo* GetEventByName(const WString& name, bool inheritable) override
|
|
{
|
|
for (vint i = 0; i < metadata->events.Count(); i++)
|
|
{
|
|
auto info = GetEvent(i);
|
|
if (info->GetName() == name)
|
|
{
|
|
return info;
|
|
}
|
|
}
|
|
if (inheritable)
|
|
{
|
|
for (vint i = 0; i < metadata->baseTypeDescriptors.Count(); i++)
|
|
{
|
|
if (auto info = GetBaseTypeDescriptor(i)->GetEventByName(name, true))
|
|
{
|
|
return info;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
vint GetMethodGroupCount() override
|
|
{
|
|
return methodGroups.Count();
|
|
}
|
|
|
|
IMethodGroupInfo* GetMethodGroup(vint index) override
|
|
{
|
|
return methodGroups[index].Obj();
|
|
}
|
|
|
|
bool IsMethodGroupExists(const WString& name, bool inheritable) override
|
|
{
|
|
return GetMethodGroupByName(name, inheritable);
|
|
}
|
|
|
|
IMethodGroupInfo* GetMethodGroupByName(const WString& name, bool inheritable) override
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < methodGroups.Count(); i++)
|
|
{
|
|
auto info = methodGroups[i].Obj();
|
|
if (info->GetName() == name)
|
|
{
|
|
return info;
|
|
}
|
|
}
|
|
if (inheritable)
|
|
{
|
|
for (vint i = 0; i < metadata->baseTypeDescriptors.Count(); i++)
|
|
{
|
|
if (auto info = GetBaseTypeDescriptor(i)->GetMethodGroupByName(name, true))
|
|
{
|
|
return info;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
IMethodGroupInfo* GetConstructorGroup() override
|
|
{
|
|
return constructorGroup.Obj();
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GenerateMetaonlyTypes
|
|
***********************************************************************/
|
|
|
|
void GenerateMetaonlyTypeDescriptor(Writer& writer, ITypeDescriptor* td)
|
|
{
|
|
auto metadata = Ptr(new TypeDescriptorMetadata);
|
|
if (auto cpp = td->GetCpp())
|
|
{
|
|
metadata->fullName = cpp->GetFullName();
|
|
}
|
|
metadata->typeName = td->GetTypeName();
|
|
metadata->flags = td->GetTypeDescriptorFlags();
|
|
metadata->isAggregatable = td->IsAggregatable();
|
|
metadata->isValueType = td->GetValueType();
|
|
metadata->isSerializable = td->GetSerializableType();
|
|
if (auto enumType = td->GetEnumType())
|
|
{
|
|
metadata->isEnumType = true;
|
|
metadata->isFlagEnum = enumType->IsFlagEnum();
|
|
for (vint i = 0; i < enumType->GetItemCount(); i++)
|
|
{
|
|
metadata->enumItems.Add(enumType->GetItemName(i));
|
|
metadata->enumValues.Add(enumType->GetItemValue(i));
|
|
}
|
|
}
|
|
|
|
for (vint i = 0; i < td->GetBaseTypeDescriptorCount(); i++)
|
|
{
|
|
metadata->baseTypeDescriptors.Add(writer.context->tdIndex[td->GetBaseTypeDescriptor(i)]);
|
|
}
|
|
|
|
for (vint i = 0; i < td->GetPropertyCount(); i++)
|
|
{
|
|
metadata->properties.Add(writer.context->piIndex[td->GetProperty(i)]);
|
|
}
|
|
|
|
for (vint i = 0; i < td->GetEventCount(); i++)
|
|
{
|
|
metadata->events.Add(writer.context->eiIndex[td->GetEvent(i)]);
|
|
}
|
|
|
|
for (vint i = 0; i < td->GetMethodGroupCount(); i++)
|
|
{
|
|
auto mg = td->GetMethodGroup(i);
|
|
IdRange ir;
|
|
ir.start = metadata->methods.Count();
|
|
for (vint j = 0; j < mg->GetMethodCount(); j++)
|
|
{
|
|
metadata->methods.Add(writer.context->miIndex[mg->GetMethod(j)]);
|
|
}
|
|
ir.count = metadata->methods.Count() - ir.start;
|
|
metadata->methodGroups.Add(ir);
|
|
}
|
|
|
|
if (auto cg = td->GetConstructorGroup())
|
|
{
|
|
metadata->constructorGroup.start = metadata->methods.Count();
|
|
for (vint j = 0; j < cg->GetMethodCount(); j++)
|
|
{
|
|
metadata->methods.Add(writer.context->miIndex[cg->GetMethod(j)]);
|
|
}
|
|
metadata->constructorGroup.count = metadata->methods.Count() - metadata->constructorGroup.start;
|
|
}
|
|
|
|
writer << metadata;
|
|
}
|
|
|
|
void GenerateMetaonlyMethodInfo(Writer& writer, IMethodInfo* mi)
|
|
{
|
|
auto metadata = Ptr(new MethodInfoMetadata);
|
|
if (auto cpp = mi->GetCpp())
|
|
{
|
|
metadata->invokeTemplate = cpp->GetInvokeTemplate();
|
|
metadata->closureTemplate = cpp->GetClosureTemplate();
|
|
}
|
|
metadata->name = mi->GetName();
|
|
metadata->ownerTypeDescriptor = writer.context->tdIndex[mi->GetOwnerTypeDescriptor()];
|
|
if (auto pi = mi->GetOwnerProperty())
|
|
{
|
|
metadata->ownerProperty = writer.context->piIndex[pi];
|
|
}
|
|
for (vint i = 0; i < mi->GetParameterCount(); i++)
|
|
{
|
|
auto pi = mi->GetParameter(i);
|
|
auto piMetadata = Ptr(new ParameterInfoMetadata);
|
|
piMetadata->name = pi->GetName();
|
|
piMetadata->type = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), pi->GetType()));
|
|
metadata->parameters.Add(piMetadata);
|
|
}
|
|
metadata->returnType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), mi->GetReturn()));
|
|
metadata->isStatic = mi->IsStatic();
|
|
writer << metadata;
|
|
}
|
|
|
|
void GenerateMetaonlyPropertyInfo(Writer& writer, IPropertyInfo* pi)
|
|
{
|
|
auto metadata = Ptr(new PropertyInfoMetadata);;
|
|
if (auto cpp = pi->GetCpp())
|
|
{
|
|
metadata->referenceTemplate = cpp->GetReferenceTemplate();
|
|
}
|
|
metadata->name = pi->GetName();
|
|
metadata->ownerTypeDescriptor = writer.context->tdIndex[pi->GetOwnerTypeDescriptor()];
|
|
metadata->isReadable = pi->IsReadable();
|
|
metadata->isWritable = pi->IsWritable();
|
|
metadata->returnType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), pi->GetReturn()));
|
|
if (auto mi = pi->GetGetter())
|
|
{
|
|
metadata->getter = writer.context->miIndex[mi];
|
|
}
|
|
if (auto mi = pi->GetSetter())
|
|
{
|
|
metadata->setter = writer.context->miIndex[mi];
|
|
}
|
|
if (auto ei = pi->GetValueChangedEvent())
|
|
{
|
|
metadata->valueChangedEvent = writer.context->eiIndex[ei];
|
|
}
|
|
writer << metadata;
|
|
}
|
|
|
|
void GenerateMetaonlyEventInfo(Writer& writer, IEventInfo* ei)
|
|
{
|
|
auto metadata = Ptr(new EventInfoMetadata);;
|
|
if (auto cpp = ei->GetCpp())
|
|
{
|
|
metadata->attachTemplate = cpp->GetAttachTemplate();
|
|
metadata->detachTemplate = cpp->GetDetachTemplate();
|
|
metadata->invokeTemplate = cpp->GetInvokeTemplate();
|
|
}
|
|
metadata->name = ei->GetName();
|
|
metadata->ownerTypeDescriptor = writer.context->tdIndex[ei->GetOwnerTypeDescriptor()];
|
|
metadata->handlerType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), ei->GetHandlerType()));
|
|
for (vint i = 0; i < ei->GetObservingPropertyCount(); i++)
|
|
{
|
|
metadata->observingProperties.Add(writer.context->piIndex[ei->GetObservingProperty(i)]);
|
|
}
|
|
writer << metadata;
|
|
}
|
|
|
|
void GenerateMetaonlyTypes(stream::IStream& outputStream)
|
|
{
|
|
Writer writer(outputStream);
|
|
writer.context = Ptr(new MetaonlyWriterContext);
|
|
|
|
Dictionary<WString, ITypeDescriptor*> tds;
|
|
List<IMethodInfo*> mis;
|
|
List<IPropertyInfo*> pis;
|
|
List<IEventInfo*> eis;
|
|
|
|
{
|
|
auto tm = GetGlobalTypeManager();
|
|
vint count = tm->GetTypeDescriptorCount();
|
|
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto td = tm->GetTypeDescriptor(i);
|
|
tds.Add(td->GetTypeName(), td);
|
|
}
|
|
}
|
|
{
|
|
vint count = tds.Count();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto td = tds.Values()[i];
|
|
writer.context->tdIndex.Add(td, writer.context->tdIndex.Count());
|
|
|
|
vint mgCount = td->GetMethodGroupCount();
|
|
for (vint j = 0; j < mgCount; j++)
|
|
{
|
|
auto mg = td->GetMethodGroup(j);
|
|
vint miCount = mg->GetMethodCount();
|
|
for (vint k = 0; k < miCount; k++)
|
|
{
|
|
auto mi = mg->GetMethod(k);
|
|
writer.context->miIndex.Add(mi, mis.Count());
|
|
mis.Add(mi);
|
|
}
|
|
}
|
|
|
|
if (auto cg = td->GetConstructorGroup())
|
|
{
|
|
vint miCount = cg->GetMethodCount();
|
|
for (vint k = 0; k < miCount; k++)
|
|
{
|
|
auto mi = cg->GetMethod(k);
|
|
writer.context->miIndex.Add(mi, mis.Count());
|
|
mis.Add(mi);
|
|
}
|
|
}
|
|
|
|
vint piCount = td->GetPropertyCount();
|
|
for (vint j = 0; j < piCount; j++)
|
|
{
|
|
auto pi = td->GetProperty(j);
|
|
writer.context->piIndex.Add(pi, pis.Count());
|
|
pis.Add(pi);
|
|
}
|
|
|
|
vint eiCount = td->GetEventCount();
|
|
for (vint j = 0; j < eiCount; j++)
|
|
{
|
|
auto ei = td->GetEvent(j);
|
|
writer.context->eiIndex.Add(ei, eis.Count());
|
|
eis.Add(ei);
|
|
}
|
|
}
|
|
}
|
|
{
|
|
vint tdCount = tds.Count();
|
|
vint miCount = mis.Count();
|
|
vint piCount = pis.Count();
|
|
vint eiCount = eis.Count();
|
|
writer << tdCount << miCount << piCount << eiCount;
|
|
|
|
for (vint i = 0; i < tdCount; i++)
|
|
{
|
|
GenerateMetaonlyTypeDescriptor(writer, tds.Values()[i]);
|
|
}
|
|
for (vint i = 0; i < miCount; i++)
|
|
{
|
|
GenerateMetaonlyMethodInfo(writer, mis[i]);
|
|
}
|
|
for (vint i = 0; i < piCount; i++)
|
|
{
|
|
GenerateMetaonlyPropertyInfo(writer, pis[i]);
|
|
}
|
|
for (vint i = 0; i < eiCount; i++)
|
|
{
|
|
GenerateMetaonlyEventInfo(writer, eis[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
LoadMetaonlyTypes
|
|
***********************************************************************/
|
|
|
|
class MetaonlyTypeLoader : public Object, public ITypeLoader
|
|
{
|
|
public:
|
|
Ptr<MetaonlyReaderContext> context;
|
|
|
|
void Load(ITypeManager* manager) override
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < context->tds.Count(); i++)
|
|
{
|
|
auto td = context->tds[i];
|
|
manager->SetTypeDescriptor(td->GetTypeName(), td);
|
|
}
|
|
}
|
|
|
|
void Unload(ITypeManager* manager) override
|
|
{
|
|
}
|
|
};
|
|
|
|
Ptr<ITypeLoader> LoadMetaonlyTypes(stream::IStream& inputStream, const collections::Dictionary<WString, Ptr<ISerializableType>>& serializableTypes)
|
|
{
|
|
auto context = Ptr(new MetaonlyReaderContext);
|
|
CopyFrom(context->serializableTypes, serializableTypes);
|
|
auto loader = Ptr(new MetaonlyTypeLoader);
|
|
loader->context = context;
|
|
Reader reader(inputStream);
|
|
reader.context = context;
|
|
|
|
{
|
|
vint tdCount = 0;
|
|
vint miCount = 0;
|
|
vint piCount = 0;
|
|
vint eiCount = 0;
|
|
reader << tdCount << miCount << piCount << eiCount;
|
|
|
|
for (vint i = 0; i < tdCount; i++)
|
|
{
|
|
Ptr<TypeDescriptorMetadata> metadata;
|
|
reader << metadata;
|
|
context->tds.Add(Ptr(new MetaonlyTypeDescriptor(context.Obj(), metadata)));
|
|
}
|
|
for (vint i = 0; i < miCount; i++)
|
|
{
|
|
Ptr<MethodInfoMetadata> metadata;
|
|
reader << metadata;
|
|
context->mis.Add(Ptr(new MetaonlyMethodInfo(context.Obj(), metadata)));
|
|
}
|
|
for (vint i = 0; i < piCount; i++)
|
|
{
|
|
Ptr<PropertyInfoMetadata> metadata;
|
|
reader << metadata;
|
|
context->pis.Add(Ptr(new MetaonlyPropertyInfo(context.Obj(), metadata)));
|
|
}
|
|
for (vint i = 0; i < eiCount; i++)
|
|
{
|
|
Ptr<EventInfoMetadata> metadata;
|
|
reader << metadata;
|
|
context->eis.Add(Ptr(new MetaonlyEventInfo(context.Obj(), metadata)));
|
|
}
|
|
}
|
|
|
|
return loader;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEOBJECT.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
/***********************************************************************
|
|
DescriptableObject
|
|
***********************************************************************/
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
bool DescriptableObject::IsAggregated()
|
|
{
|
|
return aggregationInfo != nullptr;
|
|
}
|
|
|
|
vint DescriptableObject::GetAggregationSize()
|
|
{
|
|
CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::GetAggregationSize()#This function should not be called on non-aggregated objects.");
|
|
return aggregationSize;
|
|
}
|
|
|
|
DescriptableObject* DescriptableObject::GetAggregationRoot()
|
|
{
|
|
CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::GetAggregationRoot()#This function should not be called on non-aggregated objects.");
|
|
return aggregationInfo[aggregationSize];
|
|
}
|
|
|
|
void DescriptableObject::SetAggregationRoot(DescriptableObject* value)
|
|
{
|
|
CHECK_ERROR(value != nullptr, L"vl::reflection::DescriptableObject::SetAggregationRoot(Descriptable*)#The root object should not null.");
|
|
CHECK_ERROR(value->IsAggregated() && value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationRoot(Descriptable*)#The root object should not have an aggregation root.");
|
|
if (!IsAggregated())
|
|
{
|
|
InitializeAggregation(0);
|
|
}
|
|
aggregationInfo[aggregationSize] = value;
|
|
aggregationInfo[aggregationSize + 1] = value;
|
|
for (vint i = 0; i < aggregationSize; i++)
|
|
{
|
|
if (aggregationInfo[i])
|
|
{
|
|
aggregationInfo[i]->SetAggregationRoot(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
DescriptableObject* DescriptableObject::GetAggregationParent(vint index)
|
|
{
|
|
CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::GetAggregationParent(vint)#This function should not be called on non-aggregated objects.");
|
|
CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::GetAggregationParent(vint)#Index out of range.");
|
|
return aggregationInfo[index];
|
|
}
|
|
|
|
void DescriptableObject::SetAggregationParent(vint index, DescriptableObject* value)
|
|
{
|
|
CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#This function should not be called on non-aggregated objects.");
|
|
CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Index out of range.");
|
|
CHECK_ERROR(aggregationInfo[index] == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#This index has been used.");
|
|
CHECK_ERROR(value != nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Parent should not be null.");
|
|
CHECK_ERROR(!value->IsAggregated() || value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Parent already has a aggregation root.");
|
|
CHECK_ERROR(value->referenceCounter == 0, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Parent should not be contained in any smart pointer.");
|
|
value->SetAggregationRoot(this);
|
|
aggregationInfo[index] = value;
|
|
}
|
|
|
|
void DescriptableObject::SetAggregationParent(vint index, Ptr<DescriptableObject>& value)
|
|
{
|
|
CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#This function should not be called on non-aggregated objects.");
|
|
CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Index out of range.");
|
|
CHECK_ERROR(aggregationInfo[index] == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#This index has been used.");
|
|
CHECK_ERROR(value, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Parent should not be null");
|
|
CHECK_ERROR(!value->IsAggregated() || value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Parent already has a aggregation root.");
|
|
CHECK_ERROR(value->referenceCounter == 1, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Parent should not be contained in any other smart pointer.");
|
|
value->SetAggregationRoot(this);
|
|
|
|
auto parent = value.Detach();
|
|
aggregationInfo[index] = parent;
|
|
}
|
|
|
|
void DescriptableObject::InitializeAggregation(vint size)
|
|
{
|
|
CHECK_ERROR(!IsAggregated(), L"vl::reflection::DescriptableObject::InitializeAggregation(vint)#This function should not be called on aggregated objects.");
|
|
CHECK_ERROR(size >= 0, L"vl::reflection::DescriptableObject::InitializeAggregation(vint)#Size shout not be negative.");
|
|
aggregationSize = size;
|
|
aggregationInfo = new DescriptableObject * [size + 2];
|
|
memset(aggregationInfo, 0, sizeof(*aggregationInfo) * (size + 2));
|
|
}
|
|
#endif
|
|
|
|
void DescriptableObject::FinalizeAggregation()
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (IsAggregated())
|
|
{
|
|
if (auto root = GetAggregationRoot())
|
|
{
|
|
if (aggregationInfo[aggregationSize + 1] == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
aggregationInfo[aggregationSize + 1] = nullptr;
|
|
}
|
|
|
|
if (!root->destructing)
|
|
{
|
|
destructing = true;
|
|
delete root;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DescriptableObject::DescriptableObject()
|
|
:referenceCounter(0)
|
|
, sharedPtrDestructorProc(0)
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
, objectSize(0)
|
|
, typeDescriptor(0)
|
|
, destructing(false)
|
|
, aggregationInfo(nullptr)
|
|
, aggregationSize(-1)
|
|
#endif
|
|
{
|
|
}
|
|
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wexceptions"
|
|
#elif defined(__GNUC__)
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wterminate"
|
|
#endif
|
|
DescriptableObject::~DescriptableObject()
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
destructing = true;
|
|
if (IsAggregated())
|
|
{
|
|
if (auto root = GetAggregationRoot())
|
|
{
|
|
if (aggregationInfo[aggregationSize + 1] != nullptr)
|
|
{
|
|
#pragma warning (push)
|
|
#pragma warning (disable: 4297)
|
|
// Your class should call FinalizeAggregation in the destructor if it inherits from AggregatableDescription<T>.
|
|
CHECK_ERROR(!IsAggregated(), L"vl::reflection::DescriptableObject::~DescriptableObject0()#FinalizeAggregation function should be called.");
|
|
#pragma warning (pop)
|
|
}
|
|
}
|
|
for (vint i = 0; i < aggregationSize; i++)
|
|
{
|
|
if (auto parent = GetAggregationParent(i))
|
|
{
|
|
if (!parent->destructing)
|
|
{
|
|
delete parent;
|
|
}
|
|
}
|
|
}
|
|
delete[] aggregationInfo;
|
|
}
|
|
#endif
|
|
}
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic pop
|
|
#elif defined(__GNUC__)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
description::ITypeDescriptor* DescriptableObject::GetTypeDescriptor()
|
|
{
|
|
return typeDescriptor ? *typeDescriptor : 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
Ptr<Object> DescriptableObject::GetInternalProperty(const WString& name)
|
|
{
|
|
if (!internalProperties) return 0;
|
|
vint index = internalProperties->Keys().IndexOf(name);
|
|
if (index == -1) return 0;
|
|
return internalProperties->Values().Get(index);
|
|
}
|
|
|
|
void DescriptableObject::SetInternalProperty(const WString& name, Ptr<Object> value)
|
|
{
|
|
if (internalProperties)
|
|
{
|
|
vint index = internalProperties->Keys().IndexOf(name);
|
|
if (index == -1)
|
|
{
|
|
if (value)
|
|
{
|
|
internalProperties->Add(name, value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (value)
|
|
{
|
|
internalProperties->Set(name, value);
|
|
}
|
|
else
|
|
{
|
|
internalProperties->Remove(name);
|
|
if (internalProperties->Count() == 0)
|
|
{
|
|
internalProperties = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (value)
|
|
{
|
|
internalProperties = Ptr(new InternalPropertyMap);
|
|
internalProperties->Add(name, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool DescriptableObject::Dispose(bool forceDisposing)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (IsAggregated())
|
|
{
|
|
if (auto root = GetAggregationRoot())
|
|
{
|
|
return root->Dispose(forceDisposing);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (referenceCounter > 0 && forceDisposing)
|
|
{
|
|
throw description::ValueNotDisposableException();
|
|
}
|
|
|
|
if (sharedPtrDestructorProc)
|
|
{
|
|
return sharedPtrDestructorProc(this, forceDisposing);
|
|
}
|
|
else
|
|
{
|
|
delete this;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
DescriptableObject* DescriptableObject::SafeGetAggregationRoot()
|
|
{
|
|
if (IsAggregated())
|
|
{
|
|
if (auto root = GetAggregationRoot())
|
|
{
|
|
return root;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEVALUE.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace collections;
|
|
|
|
namespace reflection
|
|
{
|
|
|
|
/***********************************************************************
|
|
description::Value
|
|
***********************************************************************/
|
|
|
|
namespace description
|
|
{
|
|
Value::Value(DescriptableObject* value)
|
|
:valueType(value ? RawPtr :Null)
|
|
,rawPtr(nullptr)
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
,typeDescriptor(nullptr)
|
|
#endif
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (value)
|
|
{
|
|
rawPtr = value->SafeGetAggregationRoot();
|
|
}
|
|
#else
|
|
rawPtr = value;
|
|
#endif
|
|
}
|
|
|
|
Value::Value(Ptr<DescriptableObject> value)
|
|
:valueType(value ? SharedPtr : Null)
|
|
,rawPtr(nullptr)
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
,typeDescriptor(nullptr)
|
|
#endif
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (value)
|
|
{
|
|
rawPtr = value->SafeGetAggregationRoot();
|
|
sharedPtr = Ptr(rawPtr);
|
|
}
|
|
#else
|
|
rawPtr = value.Obj();
|
|
sharedPtr = value;
|
|
#endif
|
|
}
|
|
|
|
Value::Value(Ptr<IBoxedValue> value, ITypeDescriptor* associatedTypeDescriptor)
|
|
:valueType(value ? BoxedValue : Null)
|
|
, rawPtr(nullptr)
|
|
, boxedValue(value)
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
, typeDescriptor(associatedTypeDescriptor)
|
|
#endif
|
|
{
|
|
}
|
|
|
|
Value::Value()
|
|
:valueType(Null)
|
|
,rawPtr(0)
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
,typeDescriptor(nullptr)
|
|
#endif
|
|
{
|
|
}
|
|
|
|
Value::Value(const Value& value)
|
|
:valueType(value.valueType)
|
|
,rawPtr(value.rawPtr)
|
|
,sharedPtr(value.sharedPtr)
|
|
,boxedValue(value.boxedValue ? value.boxedValue->Copy() : nullptr)
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
,typeDescriptor(value.typeDescriptor)
|
|
#endif
|
|
{
|
|
}
|
|
|
|
Value& Value::operator=(const Value& value)
|
|
{
|
|
valueType = value.valueType;
|
|
rawPtr = value.rawPtr;
|
|
sharedPtr = value.sharedPtr;
|
|
boxedValue = value.boxedValue ? value.boxedValue->Copy() : nullptr;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
typeDescriptor = value.typeDescriptor;
|
|
#endif
|
|
return *this;
|
|
}
|
|
|
|
Value::ValueType Value::GetValueType()const
|
|
{
|
|
return valueType;
|
|
}
|
|
|
|
DescriptableObject* Value::GetRawPtr()const
|
|
{
|
|
return rawPtr;
|
|
}
|
|
|
|
Ptr<DescriptableObject> Value::GetSharedPtr()const
|
|
{
|
|
return sharedPtr;
|
|
}
|
|
|
|
Ptr<IBoxedValue> Value::GetBoxedValue()const
|
|
{
|
|
return boxedValue;
|
|
}
|
|
|
|
bool Value::IsNull()const
|
|
{
|
|
return valueType == Null;
|
|
}
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
ITypeDescriptor* Value::GetTypeDescriptor()const
|
|
{
|
|
switch(valueType)
|
|
{
|
|
case RawPtr:
|
|
case SharedPtr:
|
|
return rawPtr?rawPtr->GetTypeDescriptor():0;
|
|
case BoxedValue:
|
|
return typeDescriptor;
|
|
default:;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WString Value::GetTypeFriendlyName()const
|
|
{
|
|
switch(valueType)
|
|
{
|
|
case RawPtr:
|
|
return GetTypeDescriptor()->GetTypeName()+L"*";
|
|
case SharedPtr:
|
|
return L"Ptr<"+GetTypeDescriptor()->GetTypeName()+L">";
|
|
case BoxedValue:
|
|
return GetTypeDescriptor()->GetTypeName();
|
|
default:
|
|
return L"null";
|
|
}
|
|
}
|
|
|
|
bool Value::CanConvertTo(ITypeDescriptor* targetType, ValueType targetValueType)const
|
|
{
|
|
if(targetType==GetGlobalTypeManager()->GetRootType())
|
|
{
|
|
return true;
|
|
}
|
|
switch(valueType)
|
|
{
|
|
case Null:
|
|
return targetValueType != BoxedValue;
|
|
case RawPtr:
|
|
case SharedPtr:
|
|
if (targetValueType != RawPtr && targetValueType != SharedPtr) return false;
|
|
break;
|
|
case BoxedValue:
|
|
return targetValueType == BoxedValue;
|
|
}
|
|
return GetTypeDescriptor()->CanConvertTo(targetType);
|
|
}
|
|
|
|
bool Value::CanConvertTo(ITypeInfo* targetType)const
|
|
{
|
|
if(valueType==Null && targetType->GetDecorator()==ITypeInfo::Nullable)
|
|
{
|
|
return true;
|
|
}
|
|
ValueType targetValueType=ValueType::Null;
|
|
{
|
|
ITypeInfo* currentType=targetType;
|
|
while(currentType)
|
|
{
|
|
switch(targetType->GetDecorator())
|
|
{
|
|
case ITypeInfo::RawPtr:
|
|
targetValueType=RawPtr;
|
|
currentType=0;
|
|
break;
|
|
case ITypeInfo::SharedPtr:
|
|
targetValueType=SharedPtr;
|
|
currentType=0;
|
|
break;
|
|
case ITypeInfo::TypeDescriptor:
|
|
case ITypeInfo::Nullable:
|
|
targetValueType=BoxedValue;
|
|
currentType=0;
|
|
break;
|
|
default:
|
|
currentType=currentType->GetElementType();
|
|
}
|
|
}
|
|
}
|
|
return CanConvertTo(targetType->GetTypeDescriptor(), targetValueType);
|
|
}
|
|
|
|
#endif
|
|
|
|
Value Value::From(DescriptableObject* value)
|
|
{
|
|
return Value(value);
|
|
}
|
|
|
|
Value Value::From(Ptr<DescriptableObject> value)
|
|
{
|
|
return Value(value);
|
|
}
|
|
|
|
Value Value::From(Ptr<IBoxedValue> value, ITypeDescriptor* type)
|
|
{
|
|
return Value(value, type);
|
|
}
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
IMethodInfo* Value::SelectMethod(IMethodGroupInfo* methodGroup, collections::Array<Value>& arguments)
|
|
{
|
|
if(methodGroup->GetMethodCount()==1)
|
|
{
|
|
return methodGroup->GetMethod(0);
|
|
}
|
|
|
|
List<IMethodInfo*> methods;
|
|
for(vint i=0;i<methodGroup->GetMethodCount();i++)
|
|
{
|
|
IMethodInfo* method=methodGroup->GetMethod(i);
|
|
if(method->GetParameterCount()==arguments.Count())
|
|
{
|
|
methods.Add(method);
|
|
}
|
|
}
|
|
|
|
if(methods.Count()==0)
|
|
{
|
|
throw ArgumentCountMismtatchException(methodGroup);
|
|
}
|
|
else if(methods.Count()==1)
|
|
{
|
|
return methods[0];
|
|
}
|
|
else
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<methods.Count();i++)
|
|
{
|
|
IMethodInfo* method=methods[i];
|
|
try
|
|
{
|
|
method->CheckArguments(arguments);
|
|
return method;
|
|
}
|
|
catch(const TypeDescriptorException&)
|
|
{
|
|
}
|
|
}
|
|
return methods[0];
|
|
}
|
|
}
|
|
|
|
Value Value::Create(ITypeDescriptor* type)
|
|
{
|
|
Array<Value> arguments;
|
|
return Create(type, arguments);
|
|
}
|
|
|
|
Value Value::Create(ITypeDescriptor* type, collections::Array<Value>& arguments)
|
|
{
|
|
IMethodGroupInfo* methodGroup=type->GetConstructorGroup();
|
|
if(!methodGroup) throw ConstructorNotExistsException(type);
|
|
|
|
IMethodInfo* method=SelectMethod(methodGroup, arguments);
|
|
return method->Invoke(Value(), arguments);
|
|
}
|
|
|
|
Value Value::Create(const WString& typeName)
|
|
{
|
|
Array<Value> arguments;
|
|
return Create(typeName, arguments);
|
|
}
|
|
|
|
Value Value::Create(const WString& typeName, collections::Array<Value>& arguments)
|
|
{
|
|
ITypeDescriptor* type = vl::reflection::description::GetTypeDescriptor(typeName);
|
|
if(!type) throw TypeNotExistsException(typeName);
|
|
return Create(type, arguments);
|
|
}
|
|
|
|
Value Value::InvokeStatic(const WString& typeName, const WString& name)
|
|
{
|
|
Array<Value> arguments;
|
|
return InvokeStatic(typeName, name, arguments);
|
|
}
|
|
|
|
Value Value::InvokeStatic(const WString& typeName, const WString& name, collections::Array<Value>& arguments)
|
|
{
|
|
ITypeDescriptor* type=vl::reflection::description::GetTypeDescriptor(typeName);
|
|
if(!type) throw TypeNotExistsException(typeName);
|
|
|
|
IMethodGroupInfo* methodGroup=type->GetMethodGroupByName(name, true);
|
|
if(!methodGroup) throw MemberNotExistsException(name, type);
|
|
|
|
IMethodInfo* method=SelectMethod(methodGroup, arguments);
|
|
return method->Invoke(Value(), arguments);
|
|
}
|
|
|
|
Value Value::GetProperty(const WString& name)const
|
|
{
|
|
ITypeDescriptor* type=GetTypeDescriptor();
|
|
if(!type) throw ArgumentNullException(L"thisObject", name);
|
|
|
|
IPropertyInfo* prop=type->GetPropertyByName(name, true);
|
|
if(!prop) throw MemberNotExistsException(name, type);
|
|
|
|
return prop->GetValue(*this);
|
|
}
|
|
|
|
void Value::SetProperty(const WString& name, const Value& newValue)
|
|
{
|
|
ITypeDescriptor* type=GetTypeDescriptor();
|
|
if(!type) throw ArgumentNullException(L"thisObject", name);
|
|
|
|
IPropertyInfo* prop=type->GetPropertyByName(name, true);
|
|
if(!prop) throw MemberNotExistsException(name, type);
|
|
|
|
prop->SetValue(*this, newValue);
|
|
}
|
|
|
|
Value Value::Invoke(const WString& name)const
|
|
{
|
|
Array<Value> arguments;
|
|
return Invoke(name, arguments);
|
|
}
|
|
|
|
Value Value::Invoke(const WString& name, collections::Array<Value>& arguments)const
|
|
{
|
|
ITypeDescriptor* type=GetTypeDescriptor();
|
|
if(!type) throw ArgumentNullException(L"thisObject", name);
|
|
|
|
IMethodGroupInfo* methodGroup=type->GetMethodGroupByName(name, true);
|
|
if(!methodGroup) throw MemberNotExistsException(name, type);
|
|
|
|
IMethodInfo* method=SelectMethod(methodGroup, arguments);
|
|
return method->Invoke(*this, arguments);
|
|
}
|
|
|
|
Ptr<IEventHandler> Value::AttachEvent(const WString& name, const Value& function)const
|
|
{
|
|
ITypeDescriptor* type=GetTypeDescriptor();
|
|
if(!type) throw ArgumentNullException(L"thisObject", name);
|
|
|
|
IEventInfo* eventInfo=type->GetEventByName(name, true);
|
|
if(!eventInfo) throw MemberNotExistsException(name, type);
|
|
|
|
Ptr<IValueFunctionProxy> proxy=UnboxValue<Ptr<IValueFunctionProxy>>(function, description::GetTypeDescriptor<IValueFunctionProxy>(), L"function");
|
|
return eventInfo->Attach(*this, proxy);
|
|
}
|
|
|
|
bool Value::DetachEvent(const WString& name, Ptr<IEventHandler> handler)const
|
|
{
|
|
ITypeDescriptor* type = GetTypeDescriptor();
|
|
if (!type) throw ArgumentNullException(L"thisObject", name);
|
|
|
|
IEventInfo* eventInfo = type->GetEventByName(name, true);
|
|
if (!eventInfo) throw MemberNotExistsException(name, type);
|
|
|
|
return eventInfo->Detach(*this, handler);
|
|
}
|
|
|
|
#endif
|
|
|
|
bool Value::DeleteRawPtr()
|
|
{
|
|
if(valueType!=RawPtr) return false;
|
|
if(!rawPtr) return false;
|
|
rawPtr->Dispose(true);
|
|
*this=Value();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEVALUE_COMPARISON.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace collections;
|
|
|
|
namespace reflection
|
|
{
|
|
|
|
/***********************************************************************
|
|
description::Value
|
|
***********************************************************************/
|
|
|
|
namespace description
|
|
{
|
|
namespace pbt_selector
|
|
{
|
|
template<typename T>
|
|
struct UnboxTypeBase { using Type = T; };
|
|
|
|
template<PredefinedBoxableType> struct ExpectedUnboxType;
|
|
template<PredefinedBoxableType> struct RealUnboxType;
|
|
|
|
constexpr vint PBT_MIN = (vint)PredefinedBoxableType::PBT_S8;
|
|
constexpr vint PBT_MAX = (vint)PredefinedBoxableType::PBT_F64;
|
|
constexpr vint PBT_COUNT = PBT_MAX - PBT_MIN + 1;
|
|
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S8> : UnboxTypeBase<vint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S16> : UnboxTypeBase<vint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S32> : UnboxTypeBase<vint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S64> : UnboxTypeBase<vint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U8> : UnboxTypeBase<vuint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U16> : UnboxTypeBase<vuint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U32> : UnboxTypeBase<vuint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U64> : UnboxTypeBase<vuint64_t> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_F32> : UnboxTypeBase<double> {};
|
|
template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_F64> : UnboxTypeBase<double> {};
|
|
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_S8> : UnboxTypeBase<vint8_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_S16> : UnboxTypeBase<vint16_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_S32> : UnboxTypeBase<vint32_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_S64> : UnboxTypeBase<vint64_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_U8> : UnboxTypeBase<vuint8_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_U16> : UnboxTypeBase<vuint16_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_U32> : UnboxTypeBase<vuint32_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_U64> : UnboxTypeBase<vuint64_t> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_F32> : UnboxTypeBase<float> {};
|
|
template<> struct RealUnboxType<PredefinedBoxableType::PBT_F64> : UnboxTypeBase<double> {};
|
|
|
|
#define DEFINE_PBT_COMPARE(TYPE1, TYPE2)\
|
|
inline std::partial_ordering Compare(TYPE1& v1, TYPE2& v2)\
|
|
{\
|
|
return v1 <=> v2;\
|
|
}\
|
|
|
|
DEFINE_PBT_COMPARE(vint64_t, vint64_t)
|
|
DEFINE_PBT_COMPARE(vuint64_t, vuint64_t)
|
|
DEFINE_PBT_COMPARE(double, double)
|
|
DEFINE_PBT_COMPARE(vint64_t, double)
|
|
DEFINE_PBT_COMPARE(vuint64_t, double)
|
|
DEFINE_PBT_COMPARE(double, vint64_t)
|
|
DEFINE_PBT_COMPARE(double, vuint64_t)
|
|
|
|
inline std::partial_ordering Compare(vint64_t& v1, vuint64_t& v2)
|
|
{
|
|
if (v2 > _I64_MAX) return std::partial_ordering::less;
|
|
return v1 <=> (vint64_t)v2;
|
|
}
|
|
|
|
inline std::partial_ordering Compare(vuint64_t& v1, vint64_t& v2)
|
|
{
|
|
if (v1 > _I64_MAX) return std::partial_ordering::greater;
|
|
return (vint64_t)v1 <=> v2;
|
|
}
|
|
|
|
template<PredefinedBoxableType PBT1, PredefinedBoxableType PBT2>
|
|
std::partial_ordering PBT_Compare(const Value& v1, const Value& v2)
|
|
{
|
|
using E1 = typename ExpectedUnboxType<PBT1>::Type;
|
|
using E2 = typename ExpectedUnboxType<PBT2>::Type;
|
|
using R1 = typename RealUnboxType<PBT1>::Type;
|
|
using R2 = typename RealUnboxType<PBT2>::Type;
|
|
|
|
E1 e1 = (E1)v1.GetBoxedValue().Cast<IValueType::TypedBox<R1>>()->value;
|
|
E2 e2 = (E2)v2.GetBoxedValue().Cast<IValueType::TypedBox<R2>>()->value;
|
|
return Compare(e1, e2);
|
|
}
|
|
|
|
#undef DEFINE_PBT_COMPARE
|
|
}
|
|
|
|
std::partial_ordering operator<=>(const Value& a, const Value& b)
|
|
{
|
|
auto avt = a.GetValueType();
|
|
auto bvt = b.GetValueType();
|
|
|
|
if (avt == Value::RawPtr || avt == Value::SharedPtr)
|
|
{
|
|
if (bvt == Value::RawPtr || bvt == Value::SharedPtr)
|
|
{
|
|
auto pa = a.GetRawPtr();
|
|
auto pb = b.GetRawPtr();
|
|
return pa <=> pb;
|
|
}
|
|
}
|
|
|
|
if (avt != bvt)
|
|
{
|
|
return avt <=> bvt;
|
|
}
|
|
|
|
if (avt == Value::BoxedValue)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
auto adt = a.GetTypeDescriptor();
|
|
auto bdt = b.GetTypeDescriptor();
|
|
if (adt == bdt)
|
|
#endif
|
|
{
|
|
auto pa = a.GetBoxedValue();
|
|
auto pb = b.GetBoxedValue();
|
|
switch (pa->ComparePrimitive(pb))
|
|
{
|
|
case IBoxedValue::Smaller: return std::partial_ordering::less;
|
|
case IBoxedValue::Greater: return std::partial_ordering::greater;
|
|
case IBoxedValue::Equal: return std::partial_ordering::equivalent;
|
|
default: return std::partial_ordering::unordered;
|
|
}
|
|
}
|
|
|
|
|
|
#define DEFINE_PBT_MATRIX2(PBT1, PBT2) &pbt_selector::PBT_Compare<(PredefinedBoxableType)PBT1, (PredefinedBoxableType)PBT2>
|
|
|
|
#define DEFINE_PBT_MATRIX1(PBT1)\
|
|
DEFINE_PBT_MATRIX2(PBT1, 0),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 1),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 2),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 3),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 4),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 5),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 6),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 7),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 8),\
|
|
DEFINE_PBT_MATRIX2(PBT1, 9)
|
|
|
|
#define DEFINE_PBT_MATRIX\
|
|
DEFINE_PBT_MATRIX1(0),\
|
|
DEFINE_PBT_MATRIX1(1),\
|
|
DEFINE_PBT_MATRIX1(2),\
|
|
DEFINE_PBT_MATRIX1(3),\
|
|
DEFINE_PBT_MATRIX1(4),\
|
|
DEFINE_PBT_MATRIX1(5),\
|
|
DEFINE_PBT_MATRIX1(6),\
|
|
DEFINE_PBT_MATRIX1(7),\
|
|
DEFINE_PBT_MATRIX1(8),\
|
|
DEFINE_PBT_MATRIX1(9)
|
|
|
|
{
|
|
static std::partial_ordering(*PBT_CompareMatrix[pbt_selector::PBT_COUNT][pbt_selector::PBT_COUNT])(const Value & v1, const Value & v2) = { DEFINE_PBT_MATRIX };
|
|
auto apbt = (vint)a.GetBoxedValue()->GetBoxableType();
|
|
auto bpbt = (vint)b.GetBoxedValue()->GetBoxableType();
|
|
if (pbt_selector::PBT_MIN <= apbt && apbt <= pbt_selector::PBT_MAX)
|
|
{
|
|
if (pbt_selector::PBT_MIN <= bpbt && bpbt <= pbt_selector::PBT_MAX)
|
|
{
|
|
return PBT_CompareMatrix[apbt][bpbt](a, b);
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef DEFINE_PBT_MATRIX
|
|
#undef DEFINE_PBT_MATRIX1
|
|
#undef DEFINE_PBT_MATRI2
|
|
|
|
return std::partial_ordering::unordered;
|
|
}
|
|
|
|
return std::partial_ordering::equivalent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\METADATA\METADATA.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace collections;
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
/***********************************************************************
|
|
TypeDescriptorTypeInfo
|
|
***********************************************************************/
|
|
|
|
TypeDescriptorTypeInfo::TypeDescriptorTypeInfo(ITypeDescriptor* _typeDescriptor, TypeInfoHint _hint)
|
|
:typeDescriptor(_typeDescriptor)
|
|
, hint(_hint)
|
|
{
|
|
}
|
|
|
|
TypeDescriptorTypeInfo::~TypeDescriptorTypeInfo()
|
|
{
|
|
}
|
|
|
|
ITypeInfo::Decorator TypeDescriptorTypeInfo::GetDecorator()
|
|
{
|
|
return ITypeInfo::TypeDescriptor;
|
|
}
|
|
|
|
TypeInfoHint TypeDescriptorTypeInfo::GetHint()
|
|
{
|
|
return hint;
|
|
}
|
|
|
|
ITypeInfo* TypeDescriptorTypeInfo::GetElementType()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ITypeDescriptor* TypeDescriptorTypeInfo::GetTypeDescriptor()
|
|
{
|
|
return typeDescriptor;
|
|
}
|
|
|
|
vint TypeDescriptorTypeInfo::GetGenericArgumentCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ITypeInfo* TypeDescriptorTypeInfo::GetGenericArgument(vint index)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
WString TypeDescriptorTypeInfo::GetTypeFriendlyName()
|
|
{
|
|
return typeDescriptor->GetTypeName();
|
|
}
|
|
|
|
/***********************************************************************
|
|
DecoratedTypeInfo
|
|
***********************************************************************/
|
|
|
|
DecoratedTypeInfo::DecoratedTypeInfo(Ptr<ITypeInfo> _elementType)
|
|
:elementType(_elementType)
|
|
{
|
|
}
|
|
|
|
DecoratedTypeInfo::~DecoratedTypeInfo()
|
|
{
|
|
}
|
|
|
|
TypeInfoHint DecoratedTypeInfo::GetHint()
|
|
{
|
|
return elementType->GetHint();
|
|
}
|
|
|
|
ITypeInfo* DecoratedTypeInfo::GetElementType()
|
|
{
|
|
return elementType.Obj();
|
|
}
|
|
|
|
ITypeDescriptor* DecoratedTypeInfo::GetTypeDescriptor()
|
|
{
|
|
return elementType->GetTypeDescriptor();
|
|
}
|
|
|
|
vint DecoratedTypeInfo::GetGenericArgumentCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ITypeInfo* DecoratedTypeInfo::GetGenericArgument(vint index)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/***********************************************************************
|
|
RawPtrTypeInfo
|
|
***********************************************************************/
|
|
|
|
RawPtrTypeInfo::RawPtrTypeInfo(Ptr<ITypeInfo> _elementType)
|
|
:DecoratedTypeInfo(_elementType)
|
|
{
|
|
}
|
|
|
|
RawPtrTypeInfo::~RawPtrTypeInfo()
|
|
{
|
|
}
|
|
|
|
ITypeInfo::Decorator RawPtrTypeInfo::GetDecorator()
|
|
{
|
|
return ITypeInfo::RawPtr;
|
|
}
|
|
|
|
WString RawPtrTypeInfo::GetTypeFriendlyName()
|
|
{
|
|
return elementType->GetTypeFriendlyName() + L"*";
|
|
}
|
|
|
|
/***********************************************************************
|
|
SharedPtrTypeInfo
|
|
***********************************************************************/
|
|
|
|
SharedPtrTypeInfo::SharedPtrTypeInfo(Ptr<ITypeInfo> _elementType)
|
|
:DecoratedTypeInfo(_elementType)
|
|
{
|
|
}
|
|
|
|
SharedPtrTypeInfo::~SharedPtrTypeInfo()
|
|
{
|
|
}
|
|
|
|
ITypeInfo::Decorator SharedPtrTypeInfo::GetDecorator()
|
|
{
|
|
return ITypeInfo::SharedPtr;
|
|
}
|
|
|
|
WString SharedPtrTypeInfo::GetTypeFriendlyName()
|
|
{
|
|
return elementType->GetTypeFriendlyName() + L"^";
|
|
}
|
|
|
|
/***********************************************************************
|
|
NullableTypeInfo
|
|
***********************************************************************/
|
|
|
|
NullableTypeInfo::NullableTypeInfo(Ptr<ITypeInfo> _elementType)
|
|
:DecoratedTypeInfo(_elementType)
|
|
{
|
|
}
|
|
|
|
NullableTypeInfo::~NullableTypeInfo()
|
|
{
|
|
}
|
|
|
|
ITypeInfo::Decorator NullableTypeInfo::GetDecorator()
|
|
{
|
|
return ITypeInfo::Nullable;
|
|
}
|
|
|
|
WString NullableTypeInfo::GetTypeFriendlyName()
|
|
{
|
|
return elementType->GetTypeFriendlyName() + L"?";
|
|
}
|
|
|
|
/***********************************************************************
|
|
GenericTypeInfo
|
|
***********************************************************************/
|
|
|
|
GenericTypeInfo::GenericTypeInfo(Ptr<ITypeInfo> _elementType)
|
|
:DecoratedTypeInfo(_elementType)
|
|
{
|
|
}
|
|
|
|
GenericTypeInfo::~GenericTypeInfo()
|
|
{
|
|
}
|
|
|
|
ITypeInfo::Decorator GenericTypeInfo::GetDecorator()
|
|
{
|
|
return ITypeInfo::Generic;
|
|
}
|
|
|
|
vint GenericTypeInfo::GetGenericArgumentCount()
|
|
{
|
|
return genericArguments.Count();
|
|
}
|
|
|
|
ITypeInfo* GenericTypeInfo::GetGenericArgument(vint index)
|
|
{
|
|
return genericArguments[index].Obj();
|
|
}
|
|
|
|
WString GenericTypeInfo::GetTypeFriendlyName()
|
|
{
|
|
WString result = elementType->GetTypeFriendlyName() + L"<";
|
|
for (auto [type, i] : indexed(genericArguments))
|
|
{
|
|
if (i>0) result += L", ";
|
|
result += type->GetTypeFriendlyName();
|
|
}
|
|
result += L">";
|
|
return result;
|
|
}
|
|
|
|
void GenericTypeInfo::AddGenericArgument(Ptr<ITypeInfo> value)
|
|
{
|
|
genericArguments.Add(value);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
/***********************************************************************
|
|
TypeDescriptorImplBase
|
|
***********************************************************************/
|
|
|
|
const WString& TypeDescriptorImplBase::GetFullName()
|
|
{
|
|
return cppFullTypeName;
|
|
}
|
|
|
|
const TypeInfoContent* TypeDescriptorImplBase::GetTypeInfoContentInternal()
|
|
{
|
|
return typeInfoContent;
|
|
}
|
|
|
|
TypeDescriptorImplBase::TypeDescriptorImplBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent)
|
|
:typeDescriptorFlags(_typeDescriptorFlags)
|
|
, typeInfoContent(_typeInfoContent)
|
|
, typeName(WString::Unmanaged(_typeInfoContent->typeName))
|
|
{
|
|
switch (typeInfoContent->cppName)
|
|
{
|
|
case TypeInfoContent::VlppType:
|
|
break;
|
|
case TypeInfoContent::CppType:
|
|
cppFullTypeName = WString::Unmanaged(typeInfoContent->typeName);
|
|
break;
|
|
case TypeInfoContent::Renamed:
|
|
cppFullTypeName = WString::Unmanaged(typeInfoContent->cppFullTypeName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
TypeDescriptorImplBase::~TypeDescriptorImplBase()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor::ICpp* TypeDescriptorImplBase::GetCpp()
|
|
{
|
|
return typeInfoContent->cppName == TypeInfoContent::VlppType ? nullptr : this;
|
|
}
|
|
|
|
TypeDescriptorFlags TypeDescriptorImplBase::GetTypeDescriptorFlags()
|
|
{
|
|
return typeDescriptorFlags;
|
|
}
|
|
|
|
const WString& TypeDescriptorImplBase::GetTypeName()
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
/***********************************************************************
|
|
ValueTypeDescriptorBase
|
|
***********************************************************************/
|
|
|
|
void ValueTypeDescriptorBase::LoadInternal()
|
|
{
|
|
}
|
|
|
|
void ValueTypeDescriptorBase::Load()
|
|
{
|
|
if (!loaded)
|
|
{
|
|
loaded = true;
|
|
LoadInternal();
|
|
}
|
|
}
|
|
|
|
ValueTypeDescriptorBase::ValueTypeDescriptorBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent)
|
|
:TypeDescriptorImplBase(_typeDescriptorFlags, _typeInfoContent)
|
|
, loaded(false)
|
|
{
|
|
}
|
|
|
|
ValueTypeDescriptorBase::~ValueTypeDescriptorBase()
|
|
{
|
|
}
|
|
|
|
bool ValueTypeDescriptorBase::IsAggregatable()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
IValueType* ValueTypeDescriptorBase::GetValueType()
|
|
{
|
|
Load();
|
|
return valueType.Obj();
|
|
}
|
|
|
|
IEnumType* ValueTypeDescriptorBase::GetEnumType()
|
|
{
|
|
Load();
|
|
return enumType.Obj();
|
|
}
|
|
|
|
ISerializableType* ValueTypeDescriptorBase::GetSerializableType()
|
|
{
|
|
Load();
|
|
return serializableType.Obj();
|
|
}
|
|
|
|
vint ValueTypeDescriptorBase::GetBaseTypeDescriptorCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ITypeDescriptor* ValueTypeDescriptorBase::GetBaseTypeDescriptor(vint index)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool ValueTypeDescriptorBase::CanConvertTo(ITypeDescriptor* targetType)
|
|
{
|
|
return this == targetType;
|
|
}
|
|
|
|
vint ValueTypeDescriptorBase::GetPropertyCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IPropertyInfo* ValueTypeDescriptorBase::GetProperty(vint index)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool ValueTypeDescriptorBase::IsPropertyExists(const WString& name, bool inheritable)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
IPropertyInfo* ValueTypeDescriptorBase::GetPropertyByName(const WString& name, bool inheritable)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
vint ValueTypeDescriptorBase::GetEventCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IEventInfo* ValueTypeDescriptorBase::GetEvent(vint index)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool ValueTypeDescriptorBase::IsEventExists(const WString& name, bool inheritable)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
IEventInfo* ValueTypeDescriptorBase::GetEventByName(const WString& name, bool inheritable)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
vint ValueTypeDescriptorBase::GetMethodGroupCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IMethodGroupInfo* ValueTypeDescriptorBase::GetMethodGroup(vint index)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool ValueTypeDescriptorBase::IsMethodGroupExists(const WString& name, bool inheritable)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
IMethodGroupInfo* ValueTypeDescriptorBase::GetMethodGroupByName(const WString& name, bool inheritable)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IMethodGroupInfo* ValueTypeDescriptorBase::GetConstructorGroup()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
ParameterInfoImpl
|
|
***********************************************************************/
|
|
|
|
ParameterInfoImpl::ParameterInfoImpl(IMethodInfo* _ownerMethod, const WString& _name, Ptr<ITypeInfo> _type)
|
|
:ownerMethod(_ownerMethod)
|
|
,name(_name)
|
|
,type(_type)
|
|
{
|
|
}
|
|
|
|
ParameterInfoImpl::~ParameterInfoImpl()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* ParameterInfoImpl::GetOwnerTypeDescriptor()
|
|
{
|
|
return ownerMethod->GetOwnerTypeDescriptor();
|
|
}
|
|
|
|
const WString& ParameterInfoImpl::GetName()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
ITypeInfo* ParameterInfoImpl::GetType()
|
|
{
|
|
return type.Obj();
|
|
}
|
|
|
|
IMethodInfo* ParameterInfoImpl::GetOwnerMethod()
|
|
{
|
|
return ownerMethod;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MethodInfoImpl
|
|
***********************************************************************/
|
|
|
|
MethodInfoImpl::MethodInfoImpl(IMethodGroupInfo* _ownerMethodGroup, Ptr<ITypeInfo> _return, bool _isStatic)
|
|
:ownerMethodGroup(_ownerMethodGroup)
|
|
,ownerProperty(0)
|
|
,returnInfo(_return)
|
|
,isStatic(_isStatic)
|
|
{
|
|
}
|
|
|
|
MethodInfoImpl::~MethodInfoImpl()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* MethodInfoImpl::GetOwnerTypeDescriptor()
|
|
{
|
|
return ownerMethodGroup->GetOwnerTypeDescriptor();
|
|
}
|
|
|
|
IPropertyInfo* MethodInfoImpl::GetOwnerProperty()
|
|
{
|
|
return ownerProperty;
|
|
}
|
|
|
|
const WString& MethodInfoImpl::GetName()
|
|
{
|
|
return ownerMethodGroup->GetName();
|
|
}
|
|
|
|
IMethodGroupInfo* MethodInfoImpl::GetOwnerMethodGroup()
|
|
{
|
|
return ownerMethodGroup;
|
|
}
|
|
|
|
vint MethodInfoImpl::GetParameterCount()
|
|
{
|
|
return parameters.Count();
|
|
}
|
|
|
|
IParameterInfo* MethodInfoImpl::GetParameter(vint index)
|
|
{
|
|
if(0<=index && index<parameters.Count())
|
|
{
|
|
return parameters[index].Obj();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ITypeInfo* MethodInfoImpl::GetReturn()
|
|
{
|
|
return returnInfo.Obj();
|
|
}
|
|
|
|
bool MethodInfoImpl::IsStatic()
|
|
{
|
|
return isStatic;
|
|
}
|
|
|
|
void MethodInfoImpl::CheckArguments(collections::Array<Value>& arguments)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(arguments.Count()!=parameters.Count())
|
|
{
|
|
throw ArgumentCountMismtatchException(ownerMethodGroup);
|
|
}
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<parameters.Count();i++)
|
|
{
|
|
if(!arguments[i].CanConvertTo(parameters[i]->GetType()))
|
|
{
|
|
throw ArgumentTypeMismtatchException(parameters[i]->GetName(), parameters[i]->GetType(), arguments[i]);
|
|
}
|
|
}
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
Value MethodInfoImpl::Invoke(const Value& thisObject, collections::Array<Value>& arguments)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(thisObject.IsNull())
|
|
{
|
|
if(!isStatic)
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
}
|
|
else if(!thisObject.CanConvertTo(ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr, thisObject);
|
|
}
|
|
CheckArguments(arguments);
|
|
return InvokeInternal(thisObject, arguments);
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
Value MethodInfoImpl::CreateFunctionProxy(const Value& thisObject)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(thisObject.IsNull())
|
|
{
|
|
if(!isStatic)
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
}
|
|
else if(!thisObject.CanConvertTo(ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr, thisObject);
|
|
}
|
|
return CreateFunctionProxyInternal(thisObject);
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
bool MethodInfoImpl::AddParameter(Ptr<IParameterInfo> parameter)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<parameters.Count();i++)
|
|
{
|
|
if(parameters[i]->GetName()==parameter->GetName())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
parameters.Add(parameter);
|
|
return true;
|
|
}
|
|
|
|
bool MethodInfoImpl::SetOwnerMethodgroup(IMethodGroupInfo* _ownerMethodGroup)
|
|
{
|
|
if(ownerMethodGroup) return false;
|
|
ownerMethodGroup=_ownerMethodGroup;
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
MethodGroupInfoImpl
|
|
***********************************************************************/
|
|
|
|
MethodGroupInfoImpl::MethodGroupInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name)
|
|
:ownerTypeDescriptor(_ownerTypeDescriptor)
|
|
,name(_name)
|
|
{
|
|
}
|
|
|
|
MethodGroupInfoImpl::~MethodGroupInfoImpl()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* MethodGroupInfoImpl::GetOwnerTypeDescriptor()
|
|
{
|
|
return ownerTypeDescriptor;
|
|
}
|
|
|
|
const WString& MethodGroupInfoImpl::GetName()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
vint MethodGroupInfoImpl::GetMethodCount()
|
|
{
|
|
return methods.Count();
|
|
}
|
|
|
|
IMethodInfo* MethodGroupInfoImpl::GetMethod(vint index)
|
|
{
|
|
if(0<=index && index<methods.Count())
|
|
{
|
|
return methods[index].Obj();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool MethodGroupInfoImpl::AddMethod(Ptr<IMethodInfo> _method)
|
|
{
|
|
methods.Add(_method);
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
EventInfoImpl
|
|
***********************************************************************/
|
|
|
|
EventInfoImpl::EventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name)
|
|
:ownerTypeDescriptor(_ownerTypeDescriptor)
|
|
,name(_name)
|
|
{
|
|
}
|
|
|
|
EventInfoImpl::~EventInfoImpl()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* EventInfoImpl::GetOwnerTypeDescriptor()
|
|
{
|
|
return ownerTypeDescriptor;
|
|
}
|
|
|
|
ITypeInfo* EventInfoImpl::GetHandlerType()
|
|
{
|
|
if(!handlerType)
|
|
{
|
|
handlerType=GetHandlerTypeInternal();
|
|
}
|
|
return handlerType.Obj();
|
|
}
|
|
|
|
vint EventInfoImpl::GetObservingPropertyCount()
|
|
{
|
|
return observingProperties.Count();
|
|
}
|
|
|
|
IPropertyInfo* EventInfoImpl::GetObservingProperty(vint index)
|
|
{
|
|
return observingProperties[index];
|
|
}
|
|
|
|
const WString& EventInfoImpl::GetName()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
Ptr<IEventHandler> EventInfoImpl::Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(thisObject.IsNull())
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
else if(!thisObject.CanConvertTo(ownerTypeDescriptor, Value::RawPtr))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, Value::RawPtr, thisObject);
|
|
}
|
|
|
|
DescriptableObject* rawThisObject=thisObject.GetRawPtr();
|
|
if(rawThisObject)
|
|
{
|
|
return AttachInternal(rawThisObject, handler);
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
bool EventInfoImpl::Detach(const Value& thisObject, Ptr<IEventHandler> handler)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (thisObject.IsNull())
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
else if (!thisObject.CanConvertTo(ownerTypeDescriptor, Value::RawPtr))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, Value::RawPtr, thisObject);
|
|
}
|
|
|
|
DescriptableObject* rawThisObject = thisObject.GetRawPtr();
|
|
if (rawThisObject)
|
|
{
|
|
return DetachInternal(rawThisObject, handler);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
void EventInfoImpl::Invoke(const Value& thisObject, Ptr<IValueReadonlyList> arguments)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(thisObject.IsNull())
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
else if(!thisObject.CanConvertTo(ownerTypeDescriptor, Value::RawPtr))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, Value::RawPtr, thisObject);
|
|
}
|
|
|
|
DescriptableObject* rawThisObject=thisObject.GetRawPtr();
|
|
if(rawThisObject)
|
|
{
|
|
InvokeInternal(rawThisObject, arguments);
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************
|
|
PropertyInfoImpl
|
|
***********************************************************************/
|
|
|
|
PropertyInfoImpl::PropertyInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent)
|
|
:ownerTypeDescriptor(_ownerTypeDescriptor)
|
|
,name(_name)
|
|
,getter(_getter)
|
|
,setter(_setter)
|
|
,valueChangedEvent(_valueChangedEvent)
|
|
{
|
|
if(getter) getter->ownerProperty=this;
|
|
if(setter) setter->ownerProperty=this;
|
|
if(valueChangedEvent)
|
|
{
|
|
valueChangedEvent->observingProperties.Add(this);
|
|
}
|
|
}
|
|
|
|
PropertyInfoImpl::~PropertyInfoImpl()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* PropertyInfoImpl::GetOwnerTypeDescriptor()
|
|
{
|
|
return ownerTypeDescriptor;
|
|
}
|
|
|
|
const WString& PropertyInfoImpl::GetName()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
IPropertyInfo::ICpp* PropertyInfoImpl::GetCpp()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
bool PropertyInfoImpl::IsReadable()
|
|
{
|
|
return getter!=0;
|
|
}
|
|
|
|
bool PropertyInfoImpl::IsWritable()
|
|
{
|
|
return setter!=0;
|
|
}
|
|
|
|
ITypeInfo* PropertyInfoImpl::GetReturn()
|
|
{
|
|
return getter?getter->GetReturn():0;
|
|
}
|
|
|
|
IMethodInfo* PropertyInfoImpl::GetGetter()
|
|
{
|
|
return getter;
|
|
}
|
|
|
|
IMethodInfo* PropertyInfoImpl::GetSetter()
|
|
{
|
|
return setter;
|
|
}
|
|
|
|
IEventInfo* PropertyInfoImpl::GetValueChangedEvent()
|
|
{
|
|
return valueChangedEvent;
|
|
}
|
|
|
|
Value PropertyInfoImpl::GetValue(const Value& thisObject)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(getter)
|
|
{
|
|
Array<Value> arguments;
|
|
return getter->Invoke(thisObject, arguments);
|
|
}
|
|
else
|
|
{
|
|
throw PropertyIsNotReadableException(this);
|
|
}
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
void PropertyInfoImpl::SetValue(Value& thisObject, const Value& newValue)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(setter)
|
|
{
|
|
Array<Value> arguments(1);
|
|
arguments[0]=newValue;
|
|
setter->Invoke(thisObject, arguments);
|
|
}
|
|
else
|
|
{
|
|
throw PropertyIsNotWritableException(this);
|
|
}
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************
|
|
PropertyInfoImpl_StaticCpp
|
|
***********************************************************************/
|
|
|
|
const WString& PropertyInfoImpl_StaticCpp::GetReferenceTemplate()
|
|
{
|
|
return referenceTemplate;
|
|
}
|
|
|
|
PropertyInfoImpl_StaticCpp::PropertyInfoImpl_StaticCpp(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent, const WString& _referenceTemplate)
|
|
:PropertyInfoImpl(_ownerTypeDescriptor, _name, _getter, _setter, _valueChangedEvent)
|
|
, referenceTemplate(_referenceTemplate)
|
|
{
|
|
}
|
|
|
|
PropertyInfoImpl_StaticCpp::~PropertyInfoImpl_StaticCpp()
|
|
{
|
|
}
|
|
|
|
IPropertyInfo::ICpp* PropertyInfoImpl_StaticCpp::GetCpp()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
/***********************************************************************
|
|
FieldInfoImpl
|
|
***********************************************************************/
|
|
|
|
FieldInfoImpl::FieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Ptr<ITypeInfo> _returnInfo)
|
|
:ownerTypeDescriptor(_ownerTypeDescriptor)
|
|
,name(_name)
|
|
,returnInfo(_returnInfo)
|
|
{
|
|
}
|
|
|
|
FieldInfoImpl::~FieldInfoImpl()
|
|
{
|
|
}
|
|
|
|
ITypeDescriptor* FieldInfoImpl::GetOwnerTypeDescriptor()
|
|
{
|
|
return ownerTypeDescriptor;
|
|
}
|
|
|
|
const WString& FieldInfoImpl::GetName()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
bool FieldInfoImpl::IsReadable()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool FieldInfoImpl::IsWritable()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
ITypeInfo* FieldInfoImpl::GetReturn()
|
|
{
|
|
return returnInfo.Obj();
|
|
}
|
|
|
|
IMethodInfo* FieldInfoImpl::GetGetter()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IMethodInfo* FieldInfoImpl::GetSetter()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IEventInfo* FieldInfoImpl::GetValueChangedEvent()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Value FieldInfoImpl::GetValue(const Value& thisObject)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(thisObject.IsNull())
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
else
|
|
{
|
|
auto td = thisObject.GetTypeDescriptor();
|
|
auto valueType = td->GetValueType() ? Value::BoxedValue : Value::RawPtr;
|
|
if(!thisObject.CanConvertTo(ownerTypeDescriptor, valueType))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, valueType, thisObject);
|
|
}
|
|
}
|
|
return GetValueInternal(thisObject);
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
void FieldInfoImpl::SetValue(Value& thisObject, const Value& newValue)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(thisObject.IsNull())
|
|
{
|
|
throw ArgumentNullException(L"thisObject", this);
|
|
}
|
|
else
|
|
{
|
|
auto td = thisObject.GetTypeDescriptor();
|
|
auto valueType = td->GetValueType() ? Value::BoxedValue : Value::RawPtr;
|
|
if(!thisObject.CanConvertTo(ownerTypeDescriptor, valueType))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, valueType, thisObject);
|
|
}
|
|
}
|
|
if(!newValue.CanConvertTo(returnInfo.Obj()))
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"newValue", returnInfo.Obj(), newValue);
|
|
}
|
|
SetValueInternal(thisObject, newValue);
|
|
#else
|
|
CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!");
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************
|
|
TypeDescriptorImpl
|
|
***********************************************************************/
|
|
|
|
MethodGroupInfoImpl* TypeDescriptorImpl::PrepareMethodGroup(const WString& name)
|
|
{
|
|
vint index=methodGroups.Keys().IndexOf(name);
|
|
if(index==-1)
|
|
{
|
|
auto methodGroup=Ptr(new MethodGroupInfoImpl(this, name));
|
|
methodGroups.Add(name, methodGroup);
|
|
return methodGroup.Obj();
|
|
}
|
|
else
|
|
{
|
|
return methodGroups.Values().Get(index).Obj();
|
|
}
|
|
}
|
|
|
|
MethodGroupInfoImpl* TypeDescriptorImpl::PrepareConstructorGroup()
|
|
{
|
|
if(!constructorGroup)
|
|
{
|
|
constructorGroup=Ptr(new MethodGroupInfoImpl(this, L""));
|
|
}
|
|
return constructorGroup.Obj();
|
|
}
|
|
|
|
IPropertyInfo* TypeDescriptorImpl::AddProperty(Ptr<IPropertyInfo> value)
|
|
{
|
|
properties.Add(value->GetName(), value);
|
|
return value.Obj();
|
|
}
|
|
|
|
IEventInfo* TypeDescriptorImpl::AddEvent(Ptr<IEventInfo> value)
|
|
{
|
|
events.Add(value->GetName(), value);
|
|
return value.Obj();
|
|
}
|
|
|
|
IMethodInfo* TypeDescriptorImpl::AddMethod(const WString& name, Ptr<MethodInfoImpl> value)
|
|
{
|
|
MethodGroupInfoImpl* methodGroup=PrepareMethodGroup(name);
|
|
value->SetOwnerMethodgroup(methodGroup);
|
|
methodGroup->AddMethod(value);
|
|
return value.Obj();
|
|
}
|
|
|
|
IMethodInfo* TypeDescriptorImpl::AddConstructor(Ptr<MethodInfoImpl> value)
|
|
{
|
|
MethodGroupInfoImpl* methodGroup=PrepareConstructorGroup();
|
|
value->SetOwnerMethodgroup(methodGroup);
|
|
methodGroup->AddMethod(value);
|
|
return value.Obj();
|
|
}
|
|
|
|
void TypeDescriptorImpl::AddBaseType(ITypeDescriptor* value)
|
|
{
|
|
baseTypeDescriptors.Add(value);
|
|
}
|
|
|
|
void TypeDescriptorImpl::Load()
|
|
{
|
|
if(!loaded)
|
|
{
|
|
loaded=true;
|
|
LoadInternal();
|
|
}
|
|
}
|
|
|
|
TypeDescriptorImpl::TypeDescriptorImpl(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent)
|
|
:TypeDescriptorImplBase(_typeDescriptorFlags, _typeInfoContent)
|
|
,loaded(false)
|
|
{
|
|
}
|
|
|
|
TypeDescriptorImpl::~TypeDescriptorImpl()
|
|
{
|
|
}
|
|
|
|
bool TypeDescriptorImpl::IsAggregatable()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
IValueType* TypeDescriptorImpl::GetValueType()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
IEnumType* TypeDescriptorImpl::GetEnumType()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ISerializableType* TypeDescriptorImpl::GetSerializableType()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
vint TypeDescriptorImpl::GetBaseTypeDescriptorCount()
|
|
{
|
|
Load();
|
|
return baseTypeDescriptors.Count();
|
|
}
|
|
|
|
ITypeDescriptor* TypeDescriptorImpl::GetBaseTypeDescriptor(vint index)
|
|
{
|
|
Load();
|
|
if(0<=index && index<baseTypeDescriptors.Count())
|
|
{
|
|
return baseTypeDescriptors[index];
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool TypeDescriptorImpl::CanConvertTo(ITypeDescriptor* targetType)
|
|
{
|
|
Load();
|
|
if (this == targetType) return true;
|
|
// TODO: (enumerable) foreach
|
|
for (vint i = 0; i < baseTypeDescriptors.Count(); i++)
|
|
{
|
|
if (baseTypeDescriptors[i]->CanConvertTo(targetType)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
vint TypeDescriptorImpl::GetPropertyCount()
|
|
{
|
|
Load();
|
|
return properties.Count();
|
|
}
|
|
|
|
IPropertyInfo* TypeDescriptorImpl::GetProperty(vint index)
|
|
{
|
|
Load();
|
|
if(0<=index && index<properties.Count())
|
|
{
|
|
return properties.Values().Get(index).Obj();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool TypeDescriptorImpl::IsPropertyExists(const WString& name, bool inheritable)
|
|
{
|
|
Load();
|
|
if(properties.Keys().Contains(name))
|
|
{
|
|
return true;
|
|
}
|
|
if(inheritable)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<baseTypeDescriptors.Count();i++)
|
|
{
|
|
if(baseTypeDescriptors[i]->IsPropertyExists(name, true))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IPropertyInfo* TypeDescriptorImpl::GetPropertyByName(const WString& name, bool inheritable)
|
|
{
|
|
Load();
|
|
vint index=properties.Keys().IndexOf(name);
|
|
if(index!=-1)
|
|
{
|
|
return properties.Values().Get(index).Obj();
|
|
}
|
|
if(inheritable)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<baseTypeDescriptors.Count();i++)
|
|
{
|
|
IPropertyInfo* result=baseTypeDescriptors[i]->GetPropertyByName(name, true);
|
|
if(result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
vint TypeDescriptorImpl::GetEventCount()
|
|
{
|
|
Load();
|
|
return events.Count();
|
|
}
|
|
|
|
IEventInfo* TypeDescriptorImpl::GetEvent(vint index)
|
|
{
|
|
Load();
|
|
if(0<=index && index<events.Count())
|
|
{
|
|
return events.Values().Get(index).Obj();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool TypeDescriptorImpl::IsEventExists(const WString& name, bool inheritable)
|
|
{
|
|
Load();
|
|
if(events.Keys().Contains(name))
|
|
{
|
|
return true;
|
|
}
|
|
if(inheritable)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<baseTypeDescriptors.Count();i++)
|
|
{
|
|
if(baseTypeDescriptors[i]->IsEventExists(name, true))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IEventInfo* TypeDescriptorImpl::GetEventByName(const WString& name, bool inheritable)
|
|
{
|
|
Load();
|
|
vint index=events.Keys().IndexOf(name);
|
|
if(index!=-1)
|
|
{
|
|
return events.Values().Get(index).Obj();
|
|
}
|
|
if(inheritable)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<baseTypeDescriptors.Count();i++)
|
|
{
|
|
IEventInfo* result=baseTypeDescriptors[i]->GetEventByName(name, true);
|
|
if(result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
vint TypeDescriptorImpl::GetMethodGroupCount()
|
|
{
|
|
Load();
|
|
return methodGroups.Count();
|
|
}
|
|
|
|
IMethodGroupInfo* TypeDescriptorImpl::GetMethodGroup(vint index)
|
|
{
|
|
Load();
|
|
if(0<=index && index<methodGroups.Count())
|
|
{
|
|
return methodGroups.Values().Get(index).Obj();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool TypeDescriptorImpl::IsMethodGroupExists(const WString& name, bool inheritable)
|
|
{
|
|
Load();
|
|
if(methodGroups.Keys().Contains(name))
|
|
{
|
|
return true;
|
|
}
|
|
if(inheritable)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<baseTypeDescriptors.Count();i++)
|
|
{
|
|
if(baseTypeDescriptors[i]->IsMethodGroupExists(name, true))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IMethodGroupInfo* TypeDescriptorImpl::GetMethodGroupByName(const WString& name, bool inheritable)
|
|
{
|
|
Load();
|
|
vint index=methodGroups.Keys().IndexOf(name);
|
|
if(index!=-1)
|
|
{
|
|
return methodGroups.Values().Get(index).Obj();
|
|
}
|
|
if(inheritable)
|
|
{
|
|
// TODO: (enumerable) foreach
|
|
for(vint i=0;i<baseTypeDescriptors.Count();i++)
|
|
{
|
|
IMethodGroupInfo* result=baseTypeDescriptors[i]->GetMethodGroupByName(name, true);
|
|
if(result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
IMethodGroupInfo* TypeDescriptorImpl::GetConstructorGroup()
|
|
{
|
|
Load();
|
|
return constructorGroup.Obj();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\PREDEFINED\PREDEFINEDTYPES.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace collections;
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
/***********************************************************************
|
|
IValueEnumerable
|
|
***********************************************************************/
|
|
|
|
Ptr<IValueEnumerable> IValueEnumerable::Create(collections::LazyList<Value> values)
|
|
{
|
|
Ptr<IEnumerable<Value>> enumerable(new LazyList<Value>(values));
|
|
return Ptr(new ValueEnumerableWrapper<Ptr<IEnumerable<Value>>>(enumerable));
|
|
}
|
|
|
|
/***********************************************************************
|
|
IValueArray
|
|
***********************************************************************/
|
|
|
|
Ptr<IValueArray> IValueArray::Create()
|
|
{
|
|
return Create(LazyList<Value>());
|
|
}
|
|
|
|
Ptr<IValueArray> IValueArray::Create(Ptr<IValueReadonlyList> values)
|
|
{
|
|
return Create(GetLazyList<Value>(values));
|
|
}
|
|
|
|
Ptr<IValueArray> IValueArray::Create(collections::LazyList<Value> values)
|
|
{
|
|
auto list = Ptr(new Array<Value>);
|
|
CopyFrom(*list.Obj(), values);
|
|
return Ptr(new ValueArrayWrapper<Ptr<Array<Value>>>(list));
|
|
}
|
|
|
|
/***********************************************************************
|
|
IValueList
|
|
***********************************************************************/
|
|
|
|
Ptr<IValueList> IValueList::Create()
|
|
{
|
|
return Create(LazyList<Value>());
|
|
}
|
|
|
|
Ptr<IValueList> IValueList::Create(Ptr<IValueReadonlyList> values)
|
|
{
|
|
return Create(GetLazyList<Value>(values));
|
|
}
|
|
|
|
Ptr<IValueList> IValueList::Create(collections::LazyList<Value> values)
|
|
{
|
|
auto list = Ptr(new List<Value>);
|
|
CopyFrom(*list.Obj(), values);
|
|
return Ptr(new ValueListWrapper<Ptr<List<Value>>>(list));
|
|
}
|
|
|
|
/***********************************************************************
|
|
IObservableList
|
|
***********************************************************************/
|
|
|
|
class ReversedObservableList : public ObservableListBase<Value>
|
|
{
|
|
protected:
|
|
|
|
void NotifyUpdateInternal(vint start, vint count, vint newCount)override
|
|
{
|
|
if (observableList)
|
|
{
|
|
observableList->ItemChanged(start, count, newCount);
|
|
}
|
|
}
|
|
public:
|
|
IValueObservableList* observableList = nullptr;
|
|
};
|
|
|
|
Ptr<IValueObservableList> IValueObservableList::Create()
|
|
{
|
|
return Create(LazyList<Value>());
|
|
}
|
|
|
|
Ptr<IValueObservableList> IValueObservableList::Create(Ptr<IValueReadonlyList> values)
|
|
{
|
|
return Create(GetLazyList<Value>(values));
|
|
}
|
|
|
|
Ptr<IValueObservableList> IValueObservableList::Create(collections::LazyList<Value> values)
|
|
{
|
|
auto list = Ptr(new ReversedObservableList);
|
|
CopyFrom(*list.Obj(), values);
|
|
auto wrapper = Ptr(new ValueObservableListWrapper<Ptr<ReversedObservableList>>(list));
|
|
list->observableList = wrapper.Obj();
|
|
return wrapper;
|
|
}
|
|
|
|
/***********************************************************************
|
|
IValueDictionary
|
|
***********************************************************************/
|
|
|
|
Ptr<IValueDictionary> IValueDictionary::Create()
|
|
{
|
|
auto dictionary = Ptr(new Dictionary<Value, Value>);
|
|
return Ptr(new ValueDictionaryWrapper<Ptr<Dictionary<Value, Value>>>(dictionary));
|
|
}
|
|
|
|
Ptr<IValueDictionary> IValueDictionary::Create(Ptr<IValueReadonlyDictionary> values)
|
|
{
|
|
auto dictionary = Ptr(new Dictionary<Value, Value>);
|
|
CopyFrom(*dictionary.Obj(), GetLazyList<Value, Value>(values));
|
|
return Ptr(new ValueDictionaryWrapper<Ptr<Dictionary<Value, Value>>>(dictionary));
|
|
}
|
|
|
|
Ptr<IValueDictionary> IValueDictionary::Create(collections::LazyList<collections::Pair<Value, Value>> values)
|
|
{
|
|
auto dictionary = Ptr(new Dictionary<Value, Value>);
|
|
CopyFrom(*dictionary.Obj(), values);
|
|
return Ptr(new ValueDictionaryWrapper<Ptr<Dictionary<Value, Value>>>(dictionary));
|
|
}
|
|
|
|
/***********************************************************************
|
|
IValueException
|
|
***********************************************************************/
|
|
|
|
class DefaultValueException : public Object, public IValueException
|
|
{
|
|
protected:
|
|
WString message;
|
|
|
|
public:
|
|
DefaultValueException(const WString& _message)
|
|
:message(_message)
|
|
{
|
|
}
|
|
|
|
#pragma push_macro("GetMessage")
|
|
#if defined GetMessage
|
|
#undef GetMessage
|
|
#endif
|
|
WString GetMessage()override
|
|
{
|
|
return message;
|
|
}
|
|
#pragma pop_macro("GetMessage")
|
|
|
|
bool GetFatal()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Ptr<IValueReadonlyList> GetCallStack()override
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
Ptr<IValueException> IValueException::Create(const WString& message)
|
|
{
|
|
return Ptr(new DefaultValueException(message));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\PREDEFINED\TYPEDVALUESERIALIZERPROVIDER.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace regex;
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
/***********************************************************************
|
|
bool
|
|
***********************************************************************/
|
|
|
|
bool TypedValueSerializerProvider<bool>::GetDefaultValue()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<bool>::Serialize(const bool& input, WString& output)
|
|
{
|
|
output = input ? L"true" : L"false";
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<bool>::Deserialize(const WString& input, bool& output)
|
|
{
|
|
output = input == L"true";
|
|
return input == L"true" || input == L"false";
|
|
}
|
|
|
|
/***********************************************************************
|
|
wchar_t
|
|
***********************************************************************/
|
|
|
|
wchar_t TypedValueSerializerProvider<wchar_t>::GetDefaultValue()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<wchar_t>::Serialize(const wchar_t& input, WString& output)
|
|
{
|
|
output = input ? WString::FromChar(input) : L"";
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<wchar_t>::Deserialize(const WString& input, wchar_t& output)
|
|
{
|
|
if (input.Length() > 1) return false;
|
|
output = input.Length() == 0 ? 0 : input[0];
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
WString
|
|
***********************************************************************/
|
|
|
|
WString TypedValueSerializerProvider<WString>::GetDefaultValue()
|
|
{
|
|
return L"";
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<WString>::Serialize(const WString& input, WString& output)
|
|
{
|
|
output = input;
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<WString>::Deserialize(const WString& input, WString& output)
|
|
{
|
|
output = input;
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Locale
|
|
***********************************************************************/
|
|
|
|
Locale TypedValueSerializerProvider<Locale>::GetDefaultValue()
|
|
{
|
|
return Locale();
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<Locale>::Serialize(const Locale& input, WString& output)
|
|
{
|
|
output = input.GetName();
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<Locale>::Deserialize(const WString& input, Locale& output)
|
|
{
|
|
output = Locale(input);
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
DateTime
|
|
***********************************************************************/
|
|
|
|
BEGIN_GLOBAL_STORAGE_CLASS(DateTimeSerializerStorage)
|
|
Regex* regexDateTime = nullptr;
|
|
vint _Y, _M, _D, _h, _m, _s, _ms;
|
|
|
|
INITIALIZE_GLOBAL_STORAGE_CLASS
|
|
regexDateTime = new Regex(L"(<Y>/d/d/d/d)-(<M>/d/d)-(<D>/d/d) (<h>/d/d):(<m>/d/d):(<s>/d/d).(<ms>/d/d/d)");
|
|
_Y = regexDateTime->CaptureNames().IndexOf(L"Y");
|
|
_M = regexDateTime->CaptureNames().IndexOf(L"M");
|
|
_D = regexDateTime->CaptureNames().IndexOf(L"D");
|
|
_h = regexDateTime->CaptureNames().IndexOf(L"h");
|
|
_m = regexDateTime->CaptureNames().IndexOf(L"m");
|
|
_s = regexDateTime->CaptureNames().IndexOf(L"s");
|
|
_ms = regexDateTime->CaptureNames().IndexOf(L"ms");
|
|
|
|
FINALIZE_GLOBAL_STORAGE_CLASS
|
|
delete regexDateTime;
|
|
regexDateTime = nullptr;
|
|
|
|
END_GLOBAL_STORAGE_CLASS(DateTimeSerializerStorage)
|
|
|
|
DateTime TypedValueSerializerProvider<DateTime>::GetDefaultValue()
|
|
{
|
|
return DateTime();
|
|
}
|
|
|
|
WString FormatDigits(vint number, vint length)
|
|
{
|
|
WString result = itow(number);
|
|
while (result.Length() < length)
|
|
{
|
|
result = L"0" + result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
vint ParseDigits(const WString& text)
|
|
{
|
|
const wchar_t* reading = text.Buffer();
|
|
while (*reading == '0') reading++;
|
|
if (!*reading) return 0;
|
|
return wtoi(WString::Unmanaged(reading));
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<DateTime>::Serialize(const DateTime& input, WString& output)
|
|
{
|
|
output =
|
|
FormatDigits(input.year, 4) + L"-" + FormatDigits(input.month, 2) + L"-" + FormatDigits(input.day, 2) + L" " +
|
|
FormatDigits(input.hour, 2) + L":" + FormatDigits(input.minute, 2) + L":" + FormatDigits(input.second, 2) + L"." +
|
|
FormatDigits(input.milliseconds, 3);
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<DateTime>::Deserialize(const WString& input, DateTime& output)
|
|
{
|
|
auto& dts = GetDateTimeSerializerStorage();
|
|
Ptr<RegexMatch> match = dts.regexDateTime->Match(input);
|
|
if (!match) return false;
|
|
if (!match->Success()) return false;
|
|
if (match->Result().Start() != 0) return false;
|
|
if (match->Result().Length() != input.Length()) return false;
|
|
|
|
vint year = ParseDigits(match->Groups()[dts._Y].Get(0).Value());
|
|
vint month = ParseDigits(match->Groups()[dts._M].Get(0).Value());
|
|
vint day = ParseDigits(match->Groups()[dts._D].Get(0).Value());
|
|
vint hour = ParseDigits(match->Groups()[dts._h].Get(0).Value());
|
|
vint minute = ParseDigits(match->Groups()[dts._m].Get(0).Value());
|
|
vint second = ParseDigits(match->Groups()[dts._s].Get(0).Value());
|
|
vint milliseconds = ParseDigits(match->Groups()[dts._ms].Get(0).Value());
|
|
|
|
output = DateTime::FromDateTime(year, month, day, hour, minute, second, milliseconds);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\REFLECTION\REFLECTION.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
using namespace collections;
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
/***********************************************************************
|
|
TypeName
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
IMPL_TYPE_INFO_RENAME(void, system::Void)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::VoidValue, system::Void)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::IDescriptable, system::Interface)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::DescriptableObject, system::ReferenceType)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::Value, system::Object)
|
|
IMPL_TYPE_INFO_RENAME(vl::vuint8_t, system::UInt8)
|
|
IMPL_TYPE_INFO_RENAME(vl::vuint16_t, system::UInt16)
|
|
IMPL_TYPE_INFO_RENAME(vl::vuint32_t, system::UInt32)
|
|
IMPL_TYPE_INFO_RENAME(vl::vuint64_t, system::UInt64)
|
|
IMPL_TYPE_INFO_RENAME(vl::vint8_t, system::Int8)
|
|
IMPL_TYPE_INFO_RENAME(vl::vint16_t, system::Int16)
|
|
IMPL_TYPE_INFO_RENAME(vl::vint32_t, system::Int32)
|
|
IMPL_TYPE_INFO_RENAME(vl::vint64_t, system::Int64)
|
|
IMPL_TYPE_INFO_RENAME(float, system::Single)
|
|
IMPL_TYPE_INFO_RENAME(double, system::Double)
|
|
IMPL_TYPE_INFO_RENAME(bool, system::Boolean)
|
|
IMPL_TYPE_INFO_RENAME(wchar_t, system::Char)
|
|
IMPL_TYPE_INFO_RENAME(vl::WString, system::String)
|
|
IMPL_TYPE_INFO_RENAME(vl::DateTime, system::DateTime)
|
|
IMPL_TYPE_INFO_RENAME(vl::Locale, system::Locale)
|
|
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueEnumerator, system::Enumerator)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueEnumerable, system::Enumerable)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueReadonlyList, system::ReadonlyList)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueArray, system::Array)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueList, system::List)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueObservableList, system::ObservableList)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueReadonlyDictionary, system::ReadonlyDictionary)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueDictionary, system::Dictionary)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueInterfaceProxy, system::InterfaceProxy)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueFunctionProxy, system::Function)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueSubscription, system::Subscription)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueCallStack, system::CallStack)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueException, system::Exception)
|
|
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IBoxedValue, system::reflection::BoxedValue)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IBoxedValue::CompareResult, system::reflection::ValueType::CompareResult)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueType, system::reflection::ValueType)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IEnumType, system::reflection::EnumType)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::ISerializableType, system::reflection::SerializableType)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::ITypeInfo, system::reflection::TypeInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::ITypeInfo::Decorator, system::reflection::TypeInfo::Decorator)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IMemberInfo, system::reflection::MemberInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IEventHandler, system::reflection::EventHandler)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IEventInfo, system::reflection::EventInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IPropertyInfo, system::reflection::PropertyInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IParameterInfo, system::reflection::ParameterInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IMethodInfo, system::reflection::MethodInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::IMethodGroupInfo, system::reflection::MethodGroupInfo)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::TypeDescriptorFlags, system::reflection::TypeDescriptorFlags)
|
|
IMPL_TYPE_INFO_RENAME(vl::reflection::description::ITypeDescriptor, system::reflection::TypeDescriptor)
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
vint ITypeDescriptor_GetTypeDescriptorCount()
|
|
{
|
|
return GetGlobalTypeManager()->GetTypeDescriptorCount();
|
|
}
|
|
|
|
ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(vint index)
|
|
{
|
|
return GetGlobalTypeManager()->GetTypeDescriptor(index);
|
|
}
|
|
|
|
ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const WString& name)
|
|
{
|
|
return GetGlobalTypeManager()->GetTypeDescriptor(name);
|
|
}
|
|
|
|
#else
|
|
|
|
vint ITypeDescriptor_GetTypeDescriptorCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(vint index)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const WString& name)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const Value& value)
|
|
{
|
|
return value.GetTypeDescriptor();
|
|
}
|
|
|
|
#else
|
|
|
|
ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const Value& value)
|
|
{
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
LoadPredefinedTypes
|
|
***********************************************************************/
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
#define _ ,
|
|
|
|
template<>
|
|
struct CustomTypeDescriptorSelector<DescriptableObject>
|
|
{
|
|
public:
|
|
class CustomTypeDescriptorImpl : public TypeDescriptorImpl
|
|
{
|
|
public:
|
|
CustomTypeDescriptorImpl()
|
|
:TypeDescriptorImpl(TypeDescriptorFlags::Class, &TypeInfo<DescriptableObject>::content)
|
|
{
|
|
Description<DescriptableObject>::SetAssociatedTypeDescriptor(this);
|
|
}
|
|
~CustomTypeDescriptorImpl()
|
|
{
|
|
Description<DescriptableObject>::SetAssociatedTypeDescriptor(0);
|
|
}
|
|
protected:
|
|
void LoadInternal()override
|
|
{
|
|
}
|
|
};
|
|
};
|
|
|
|
BEGIN_STRUCT_MEMBER_FLAG(VoidValue, TypeDescriptorFlags::Primitive)
|
|
END_STRUCT_MEMBER(VoidValue)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(IDescriptable, TypeDescriptorFlags::IDescriptable)
|
|
END_INTERFACE_MEMBER(IDescriptable)
|
|
|
|
BEGIN_STRUCT_MEMBER(DateTime)
|
|
valueType = Ptr(new SerializableValueType<DateTime>());
|
|
serializableType = Ptr(new SerializableType<DateTime>());
|
|
STRUCT_MEMBER(year)
|
|
STRUCT_MEMBER(month)
|
|
STRUCT_MEMBER(dayOfWeek)
|
|
STRUCT_MEMBER(day)
|
|
STRUCT_MEMBER(hour)
|
|
STRUCT_MEMBER(minute)
|
|
STRUCT_MEMBER(second)
|
|
STRUCT_MEMBER(milliseconds)
|
|
STRUCT_MEMBER(osMilliseconds)
|
|
STRUCT_MEMBER(osInternal)
|
|
END_STRUCT_MEMBER(DateTime)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueEnumerator)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Current)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Index)
|
|
CLASS_MEMBER_METHOD(Next, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IValueEnumerator)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueEnumerable)
|
|
CLASS_MEMBER_METHOD(CreateEnumerator, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IValueEnumerable)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueReadonlyList)
|
|
CLASS_MEMBER_BASE(IValueEnumerable)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Count)
|
|
CLASS_MEMBER_METHOD(Get, { L"index" })
|
|
CLASS_MEMBER_METHOD(Contains, { L"value" })
|
|
CLASS_MEMBER_METHOD(IndexOf, { L"value" })
|
|
END_INTERFACE_MEMBER(IValueReadonlyList)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueArray)
|
|
CLASS_MEMBER_BASE(IValueReadonlyList)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueArray>(), NO_PARAMETER, vl::reflection::description::IValueArray::Create)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueArray>(Ptr<IValueReadonlyList>), { L"values" }, vl::reflection::description::IValueArray::Create)
|
|
|
|
CLASS_MEMBER_METHOD(Set, { L"index" _ L"value" })
|
|
CLASS_MEMBER_METHOD(Resize, { L"size" })
|
|
END_INTERFACE_MEMBER(IValueArray)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueList)
|
|
CLASS_MEMBER_BASE(IValueReadonlyList)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueList>(), NO_PARAMETER, vl::reflection::description::IValueList::Create)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueList>(Ptr<IValueReadonlyList>), { L"values" }, vl::reflection::description::IValueList::Create)
|
|
|
|
CLASS_MEMBER_METHOD(Set, { L"index" _ L"value" })
|
|
CLASS_MEMBER_METHOD(Add, { L"value" })
|
|
CLASS_MEMBER_METHOD(Insert, { L"index" _ L"value" })
|
|
CLASS_MEMBER_METHOD(Remove, { L"value" })
|
|
CLASS_MEMBER_METHOD(RemoveAt, { L"index" })
|
|
CLASS_MEMBER_METHOD(Clear, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IValueList)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueObservableList)
|
|
CLASS_MEMBER_BASE(IValueList)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueObservableList>(), NO_PARAMETER, vl::reflection::description::IValueObservableList::Create)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueObservableList>(Ptr<IValueReadonlyList>), { L"values" }, vl::reflection::description::IValueObservableList::Create)
|
|
|
|
CLASS_MEMBER_EVENT(ItemChanged)
|
|
END_INTERFACE_MEMBER(IValueObservableList)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueReadonlyDictionary)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Keys)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Values)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Count)
|
|
CLASS_MEMBER_METHOD(Get, { L"key" })
|
|
END_INTERFACE_MEMBER(IValueReadonlyDictionary)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueDictionary)
|
|
CLASS_MEMBER_BASE(IValueReadonlyDictionary)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueDictionary>(), NO_PARAMETER, vl::reflection::description::IValueDictionary::Create)
|
|
CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueDictionary>(Ptr<IValueReadonlyDictionary>), { L"values" }, vl::reflection::description::IValueDictionary::Create)
|
|
CLASS_MEMBER_METHOD(Set, { L"key" _ L"value" })
|
|
CLASS_MEMBER_METHOD(Remove, { L"key" })
|
|
CLASS_MEMBER_METHOD(Clear, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IValueDictionary)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IValueInterfaceProxy)
|
|
CLASS_MEMBER_METHOD(Invoke, { L"methodInfo" _ L"arguments" })
|
|
END_INTERFACE_MEMBER(IValueInterfaceProxy)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IValueFunctionProxy)
|
|
CLASS_MEMBER_METHOD(Invoke, { L"arguments" })
|
|
END_INTERFACE_MEMBER(IValueFunctionProxy)
|
|
|
|
BEGIN_INTERFACE_MEMBER(IValueSubscription)
|
|
CLASS_MEMBER_EVENT(ValueChanged)
|
|
CLASS_MEMBER_METHOD(Open, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(Update, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(Close, NO_PARAMETER)
|
|
END_CLASS_MEMBER(IValueSubscription)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IValueCallStack)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(LocalVariables)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(LocalArguments)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(CapturedVariables)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(GlobalVariables)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(FunctionName)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(SourceCodeBeforeCodegen)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(SourceCodeAfterCodegen)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(RowBeforeCodegen)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(RowAfterCodegen)
|
|
END_INTERFACE_MEMBER(IValueCallStack)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IValueException)
|
|
#pragma push_macro("GetMessage")
|
|
#if defined GetMessage
|
|
#undef GetMessage
|
|
#endif
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Message)
|
|
#pragma pop_macro("GetMessage")
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Fatal)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(CallStack)
|
|
END_INTERFACE_MEMBER(IValueException)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IBoxedValue)
|
|
CLASS_MEMBER_METHOD(Copy, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IBoxedValue)
|
|
|
|
BEGIN_ENUM_ITEM(IBoxedValue::CompareResult)
|
|
ENUM_ITEM_NAMESPACE(IBoxedValue)
|
|
|
|
ENUM_NAMESPACE_ITEM(Smaller)
|
|
ENUM_NAMESPACE_ITEM(Greater)
|
|
ENUM_NAMESPACE_ITEM(Equal)
|
|
ENUM_NAMESPACE_ITEM(NotComparable)
|
|
END_ENUM_ITEM(ITypeInfo::Decorator)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IValueType)
|
|
CLASS_MEMBER_METHOD(CreateDefault, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IValueType)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IEnumType)
|
|
CLASS_MEMBER_METHOD(IsFlagEnum, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(GetItemCount, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(GetItemName, { L"index" })
|
|
CLASS_MEMBER_METHOD(GetItemValue, { L"index" })
|
|
CLASS_MEMBER_METHOD(IndexOfItem, { L"name" })
|
|
CLASS_MEMBER_METHOD(ToEnum, { L"value" })
|
|
CLASS_MEMBER_METHOD(FromEnum, { L"value" })
|
|
END_INTERFACE_MEMBER(IEnumType)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(ISerializableType)
|
|
CLASS_MEMBER_METHOD(Serialize, { L"input" _ L"output" })
|
|
CLASS_MEMBER_METHOD(Deserialize, { L"input" _ L"output" })
|
|
END_INTERFACE_MEMBER(ISerializableType)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(ITypeInfo)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Decorator)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(ElementType)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeDescriptor)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(GenericArgumentCount)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeFriendlyName)
|
|
|
|
CLASS_MEMBER_METHOD(GetGenericArgument, { L"index" })
|
|
END_INTERFACE_MEMBER(ITypeInfo)
|
|
|
|
BEGIN_ENUM_ITEM(ITypeInfo::Decorator)
|
|
ENUM_ITEM_NAMESPACE(ITypeInfo)
|
|
|
|
ENUM_NAMESPACE_ITEM(RawPtr)
|
|
ENUM_NAMESPACE_ITEM(SharedPtr)
|
|
ENUM_NAMESPACE_ITEM(Nullable)
|
|
ENUM_NAMESPACE_ITEM(TypeDescriptor)
|
|
ENUM_NAMESPACE_ITEM(Generic)
|
|
END_ENUM_ITEM(ITypeInfo::Decorator)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IMemberInfo)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerTypeDescriptor)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Name)
|
|
END_INTERFACE_MEMBER(IMemberInfo)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IEventHandler)
|
|
CLASS_MEMBER_METHOD(IsAttached, NO_PARAMETER)
|
|
END_INTERFACE_MEMBER(IEventHandler)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IEventInfo)
|
|
CLASS_MEMBER_BASE(IMemberInfo)
|
|
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(HandlerType)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(ObservingPropertyCount)
|
|
|
|
CLASS_MEMBER_METHOD(GetObservingProperty, { L"index" })
|
|
CLASS_MEMBER_METHOD(Attach, { L"thisObject" _ L"handler" })
|
|
CLASS_MEMBER_METHOD(Invoke, { L"thisObject" _ L"arguments" })
|
|
END_INTERFACE_MEMBER(IEventInfo)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IPropertyInfo)
|
|
CLASS_MEMBER_BASE(IMemberInfo)
|
|
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Return)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Getter)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Setter)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(ValueChangedEvent)
|
|
|
|
CLASS_MEMBER_METHOD(IsReadable, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(IsWritable, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(GetValue, { L"thisObject" })
|
|
CLASS_MEMBER_METHOD(SetValue, { L"thisObject" _ L"newValue" })
|
|
END_INTERFACE_MEMBER(IPropertyInfo)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IParameterInfo)
|
|
CLASS_MEMBER_BASE(IMemberInfo)
|
|
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Type)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerMethod)
|
|
END_CLASS_MEMBER(IParameterInfo)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IMethodInfo)
|
|
CLASS_MEMBER_BASE(IMemberInfo)
|
|
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerMethodGroup)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerProperty)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(ParameterCount)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(Return)
|
|
|
|
CLASS_MEMBER_METHOD(GetParameter, { L"index" })
|
|
CLASS_MEMBER_METHOD(IsStatic, NO_PARAMETER)
|
|
CLASS_MEMBER_METHOD(CheckArguments, { L"arguments" })
|
|
CLASS_MEMBER_METHOD(Invoke, { L"thisObject" _ L"arguments" })
|
|
CLASS_MEMBER_BASE(IMemberInfo)
|
|
END_INTERFACE_MEMBER(IMethodInfo)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(IMethodGroupInfo)
|
|
CLASS_MEMBER_BASE(IMemberInfo)
|
|
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(MethodCount)
|
|
|
|
CLASS_MEMBER_METHOD(GetMethod, { L"index" })
|
|
END_INTERFACE_MEMBER(IMethodGroupInfo)
|
|
|
|
BEGIN_ENUM_ITEM_MERGABLE(TypeDescriptorFlags)
|
|
ENUM_CLASS_ITEM(Undefined)
|
|
ENUM_CLASS_ITEM(Object)
|
|
ENUM_CLASS_ITEM(IDescriptable)
|
|
ENUM_CLASS_ITEM(Class)
|
|
ENUM_CLASS_ITEM(Interface)
|
|
ENUM_CLASS_ITEM(Primitive)
|
|
ENUM_CLASS_ITEM(Struct)
|
|
ENUM_CLASS_ITEM(FlagEnum)
|
|
ENUM_CLASS_ITEM(NormalEnum)
|
|
END_ENUM_ITEM(TypeDescriptorFlags)
|
|
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(ITypeDescriptor)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeDescriptorFlags)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeName)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(ValueType)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(EnumType)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(SerializableType)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(BaseTypeDescriptorCount)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(PropertyCount)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(EventCount)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(MethodGroupCount)
|
|
CLASS_MEMBER_PROPERTY_READONLY_FAST(ConstructorGroup)
|
|
|
|
CLASS_MEMBER_METHOD(GetBaseTypeDescriptor, { L"index" })
|
|
CLASS_MEMBER_METHOD(CanConvertTo, { L"targetType" })
|
|
CLASS_MEMBER_METHOD(GetProperty, { L"index" })
|
|
CLASS_MEMBER_METHOD(IsPropertyExists, { L"name" _ L"inheritable" })
|
|
CLASS_MEMBER_METHOD(GetPropertyByName, { L"name" _ L"inheritable" })
|
|
CLASS_MEMBER_METHOD(GetEvent, { L"index" })
|
|
CLASS_MEMBER_METHOD(IsEventExists, { L"name" _ L"inheritable" })
|
|
CLASS_MEMBER_METHOD(GetEventByName, { L"name" _ L"inheritable" })
|
|
CLASS_MEMBER_METHOD(GetMethodGroup, { L"index" })
|
|
CLASS_MEMBER_METHOD(IsMethodGroupExists, { L"name" _ L"inheritable" })
|
|
CLASS_MEMBER_METHOD(GetMethodGroupByName, { L"name" _ L"inheritable" })
|
|
|
|
CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptorCount, NO_PARAMETER, vint(*)(), vl::reflection::description::ITypeDescriptor_GetTypeDescriptorCount)
|
|
CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptor, { L"index" }, ITypeDescriptor*(*)(vint), vl::reflection::description::ITypeDescriptor_GetTypeDescriptor)
|
|
CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptor, { L"name" }, ITypeDescriptor*(*)(const WString&), vl::reflection::description::ITypeDescriptor_GetTypeDescriptor)
|
|
CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptor, { L"value" }, ITypeDescriptor*(*)(const Value&), vl::reflection::description::ITypeDescriptor_GetTypeDescriptor)
|
|
END_INTERFACE_MEMBER(ITypeDescriptor)
|
|
#undef _
|
|
|
|
class PredefinedTypeLoader : public Object, public ITypeLoader
|
|
{
|
|
public:
|
|
void Load(ITypeManager* manager)override
|
|
{
|
|
manager->SetTypeDescriptor(TypeInfo<Value>::content.typeName, Ptr(new TypedValueTypeDescriptorBase<Value, TypeDescriptorFlags::Object>));
|
|
#define ADD_PRIMITIVE_TYPE(TYPE) manager->SetTypeDescriptor(TypeInfo<TYPE>::content.typeName, Ptr(new PrimitiveTypeDescriptor<TYPE>()));
|
|
REFLECTION_PREDEFINED_PRIMITIVE_TYPES(ADD_PRIMITIVE_TYPE)
|
|
#undef ADD_PRIMITIVE_TYPE
|
|
REFLECTION_PREDEFINED_COMPLEX_TYPES(ADD_TYPE_INFO, VoidValue)
|
|
}
|
|
|
|
void Unload(ITypeManager* manager)override
|
|
{
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
bool LoadPredefinedTypes()
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
ITypeManager* manager = GetGlobalTypeManager();
|
|
if (manager)
|
|
{
|
|
auto loader = Ptr(new PredefinedTypeLoader);
|
|
return manager->AddTypeLoader(loader);
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|