Files
GacUI/Import/VlppReflection.cpp
2024-02-26 03:40:56 -08:00

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;
}
}
}
}