Files
GacUI/Import/Vlpp.h
T
2018-07-26 22:56:28 -07:00

19863 lines
629 KiB
C++

/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
/***********************************************************************
.\BASIC.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Basic
Classes:
NotCopyable : Object inherits from this type cannot be copied
Error : Error, unlike exception, is not encouraged to catch
Object : Base class of all classes
Macros:
CHECK_ERROR(CONDITION,DESCRIPTION) : Assert, throws an Error if failed
CHECK_FAIL(DESCRIPTION) : Force an assert failure
SCOPE_VARIABLE(TYPE,VARIABLE,VALUE){ ... } : Scoped variable
***********************************************************************/
#ifndef VCZH_BASIC
#define VCZH_BASIC
#ifdef VCZH_CHECK_MEMORY_LEAKS
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define VCZH_CHECK_MEMORY_LEAKS_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new VCZH_CHECK_MEMORY_LEAKS_NEW
#endif
#if defined _WIN64 || __x86_64 || __LP64__
#define VCZH_64
#endif
#if defined _MSC_VER
#define VCZH_MSVC
#else
#define VCZH_GCC
#if defined(__APPLE__)
#define VCZH_APPLE
#endif
#endif
#if defined VCZH_MSVC
#include <intrin.h>
#elif defined VCZH_GCC
#include <x86intrin.h>
#include <stdint.h>
#include <stddef.h>
#include <wchar.h>
#define abstract
#define __thiscall
#define __forceinline inline
#define _I8_MIN ((vint8_t)0x80)
#define _I8_MAX ((vint8_t)0x7F)
#define _UI8_MAX ((vuint8_t)0xFF)
#define _I16_MIN ((vint16_t)0x8000)
#define _I16_MAX ((vint16_t)0x7FFF)
#define _UI16_MAX ((vuint16_t)0xFFFF)
#define _I32_MIN ((vint32_t)0x80000000)
#define _I32_MAX ((vint32_t)0x7FFFFFFF)
#define _UI32_MAX ((vuint32_t)0xFFFFFFFF)
#define _I64_MIN ((vint64_t)0x8000000000000000L)
#define _I64_MAX ((vint64_t)0x7FFFFFFFFFFFFFFFL)
#define _UI64_MAX ((vuint64_t)0xFFFFFFFFFFFFFFFFL)
#endif
#define L_(x) L__(x)
#define L__(x) L ## x
namespace vl
{
/***********************************************************************
x86 and x64 Compatbility
***********************************************************************/
#if defined VCZH_MSVC
/// <summary>1-byte signed integer.</summary>
typedef signed __int8 vint8_t;
/// <summary>1-byte unsigned integer.</summary>
typedef unsigned __int8 vuint8_t;
/// <summary>2-bytes signed integer.</summary>
typedef signed __int16 vint16_t;
/// <summary>2-bytes unsigned integer.</summary>
typedef unsigned __int16 vuint16_t;
/// <summary>4-bytes signed integer.</summary>
typedef signed __int32 vint32_t;
/// <summary>4-bytes unsigned integer.</summary>
typedef unsigned __int32 vuint32_t;
/// <summary>8-bytes signed integer.</summary>
typedef signed __int64 vint64_t;
/// <summary>8-bytes unsigned integer.</summary>
typedef unsigned __int64 vuint64_t;
#elif defined VCZH_GCC
typedef int8_t vint8_t;
typedef uint8_t vuint8_t;
typedef int16_t vint16_t;
typedef uint16_t vuint16_t;
typedef int32_t vint32_t;
typedef uint32_t vuint32_t;
typedef int64_t vint64_t;
typedef uint64_t vuint64_t;
#endif
#ifdef VCZH_64
/// <summary>Signed interface whose size is equal to sizeof(void*).</summary>
typedef vint64_t vint;
/// <summary>Signed interface whose size is equal to sizeof(void*).</summary>
typedef vint64_t vsint;
/// <summary>Unsigned interface whose size is equal to sizeof(void*).</summary>
typedef vuint64_t vuint;
#else
/// <summary>Signed interface whose size is equal to sizeof(void*).</summary>
typedef vint32_t vint;
/// <summary>Signed interface whose size is equal to sizeof(void*).</summary>
typedef vint32_t vsint;
/// <summary>Unsigned interface whose size is equal to sizeof(void*).</summary>
typedef vuint32_t vuint;
#endif
/// <summary>Signed interger representing position.</summary>
typedef vint64_t pos_t;
#ifdef VCZH_64
#define ITOA_S _i64toa_s
#define ITOW_S _i64tow_s
#define I64TOA_S _i64toa_s
#define I64TOW_S _i64tow_s
#define UITOA_S _ui64toa_s
#define UITOW_S _ui64tow_s
#define UI64TOA_S _ui64toa_s
#define UI64TOW_S _ui64tow_s
#if defined VCZH_MSVC
#define INCRC(x) (_InterlockedIncrement64(x))
#define DECRC(x) (_InterlockedDecrement64(x))
#elif defined VCZH_GCC
#define INCRC(x) (__sync_add_and_fetch(x, 1))
#define DECRC(x) (__sync_sub_and_fetch(x, 1))
#endif
#else
#define ITOA_S _itoa_s
#define ITOW_S _itow_s
#define I64TOA_S _i64toa_s
#define I64TOW_S _i64tow_s
#define UITOA_S _ui64toa_s
#define UITOW_S _ui64tow_s
#define UI64TOA_S _ui64toa_s
#define UI64TOW_S _ui64tow_s
#if defined VCZH_MSVC
#define INCRC(x) (_InterlockedIncrement((volatile long*)(x)))
#define DECRC(x) (_InterlockedDecrement((volatile long*)(x)))
#elif defined VCZH_GCC
#define INCRC(x) (__sync_add_and_fetch(x, 1))
#define DECRC(x) (__sync_sub_and_fetch(x, 1))
#endif
#endif
/***********************************************************************
Basic Types
***********************************************************************/
class NotCopyable
{
private:
NotCopyable(const NotCopyable&);
NotCopyable& operator=(const NotCopyable&);
public:
NotCopyable();
};
/// <summary>Base type of all errors. An error is an exception that you are not allowed to catch. Raising it means there is a fatal error in the code.</summary>
class Error
{
private:
const wchar_t* description;
public:
Error(const wchar_t* _description);
const wchar_t* Description()const;
};
#if defined VCZH_MSVC || defined VCZH_GCC || defined _DEBUG
#define CHECK_ERROR(CONDITION,DESCRIPTION) do{if(!(CONDITION))throw Error(DESCRIPTION);}while(0)
#elif defined NDEBUG
#define CHECK_ERROR(CONDITION,DESCRIPTION)
#endif
#define CHECK_FAIL(DESCRIPTION) do{throw Error(DESCRIPTION);}while(0)
#define SCOPE_VARIABLE(TYPE, VARIABLE, VALUE)\
if(bool __scope_variable_flag__=true)\
for(TYPE VARIABLE = VALUE;__scope_variable_flag__;__scope_variable_flag__=false)
/***********************************************************************
Type Traits
***********************************************************************/
template<typename T>
struct RemoveReference
{
typedef T Type;
};
template<typename T>
struct RemoveReference<T&>
{
typedef T Type;
};
template<typename T>
struct RemoveReference<T&&>
{
typedef T Type;
};
template<typename T>
struct RemoveConst
{
typedef T Type;
};
template<typename T>
struct RemoveConst<const T>
{
typedef T Type;
};
template<typename T>
struct RemoveVolatile
{
typedef T Type;
};
template<typename T>
struct RemoveVolatile<volatile T>
{
typedef T Type;
};
template<typename T>
struct RemoveCVR
{
typedef T Type;
};
template<typename T>
struct RemoveCVR<T&>
{
typedef typename RemoveCVR<T>::Type Type;
};
template<typename T>
struct RemoveCVR<T&&>
{
typedef typename RemoveCVR<T>::Type Type;
};
template<typename T>
struct RemoveCVR<const T>
{
typedef typename RemoveCVR<T>::Type Type;
};
template<typename T>
struct RemoveCVR<volatile T>
{
typedef typename RemoveCVR<T>::Type Type;
};
template<typename T>
typename RemoveReference<T>::Type&& MoveValue(T&& value)
{
return (typename RemoveReference<T>::Type&&)value;
}
template<typename T>
T&& ForwardValue(typename RemoveReference<T>::Type&& value)
{
return (T&&)value;
}
template<typename T>
T&& ForwardValue(typename RemoveReference<T>::Type& value)
{
return (T&&)value;
}
template<typename ...TArgs>
struct TypeTuple
{
};
/***********************************************************************
Basic Types
***********************************************************************/
/// <summary>Base type of all classes.</summary>
class Object
{
public:
virtual ~Object();
};
/// <summary>Type for storing a value to wherever requiring a [T:vl.Ptr`1] to [T:vl.Object].</summary>
/// <typeparam name="T">Type of the value.</typeparam>
template<typename T>
class ObjectBox : public Object
{
private:
T object;
public:
/// <summary>Box a value.</summary>
/// <param name="_object">The value to box.</param>
ObjectBox(const T& _object)
:object(_object)
{
}
/// <summary>Box a movable value.</summary>
/// <param name="_object">The value to box.</param>
ObjectBox(T&& _object)
:object(MoveValue(_object))
{
}
/// <summary>Copy a box.</summary>
/// <param name="value">The box.</param>
ObjectBox(const ObjectBox<T>& value)
:object(value.object)
{
}
/// <summary>Move a box.</summary>
/// <param name="value">The box.</param>
ObjectBox(ObjectBox<T>&& value)
:object(MoveValue(value.object))
{
}
/// <summary>Box a value.</summary>
/// <returns>The boxed value.</returns>
/// <param name="_object">The value to box.</param>
ObjectBox<T>& operator=(const T& _object)
{
object=_object;
return *this;
}
/// <summary>Copy a box.</summary>
/// <returns>The boxed value.</returns>
/// <param name="value">The box.</param>
ObjectBox<T>& operator=(const ObjectBox<T>& value)
{
object=value.object;
return *this;
}
/// <summary>Move a box.</summary>
/// <returns>The boxed value.</returns>
/// <param name="value">The box.</param>
ObjectBox<T>& operator=(ObjectBox<T>&& value)
{
object=MoveValue(value.object);
return *this;
}
/// <summary>Unbox the value.</summary>
/// <returns>The original value.</returns>
const T& Unbox()
{
return object;
}
};
/// <summary>Type for optionally storing a value.</summary>
/// <typeparam name="T">Type of the value.</typeparam>
template<typename T>
class Nullable
{
private:
T* object;
public:
/// <summary>Create a null value.</summary>
Nullable()
:object(0)
{
}
/// <summary>Create a non-null value.</summary>
/// <param name="value">The value to copy.</param>
Nullable(const T& value)
:object(new T(value))
{
}
/// <summary>Create a non-null value.</summary>
/// <param name="value">The value to move.</param>
Nullable(T&& value)
:object(new T(MoveValue(value)))
{
}
/// <summary>Copy a nullable value.</summary>
/// <param name="nullable">The nullable value to copy.</param>
Nullable(const Nullable<T>& nullable)
:object(nullable.object?new T(*nullable.object):0)
{
}
/// <summary>Move a nullable value.</summary>
/// <param name="nullable">The nullable value to move.</param>
Nullable(Nullable<T>&& nullable)
:object(nullable.object)
{
nullable.object=0;
}
~Nullable()
{
if(object)
{
delete object;
object=0;
}
}
/// <summary>Create a non-null value.</summary>
/// <returns>The created nullable value.</returns>
/// <param name="value">The value to copy.</param>
Nullable<T>& operator=(const T& value)
{
if(object)
{
delete object;
object=0;
}
object=new T(value);
return *this;
}
/// <summary>Copy a nullable value.</summary>
/// <returns>The created nullable value.</returns>
/// <param name="nullable">The nullable value to copy.</param>
Nullable<T>& operator=(const Nullable<T>& nullable)
{
if(this!=&nullable)
{
if(object)
{
delete object;
object=0;
}
if(nullable.object)
{
object=new T(*nullable.object);
}
}
return *this;
}
/// <summary>Move a nullable value.</summary>
/// <returns>The created nullable value.</returns>
/// <param name="nullable">The nullable value to move.</param>
Nullable<T>& operator=(Nullable<T>&& nullable)
{
if(this!=&nullable)
{
if(object)
{
delete object;
object=0;
}
object=nullable.object;
nullable.object=0;
}
return *this;
}
static bool Equals(const Nullable<T>& a, const Nullable<T>& b)
{
return
a.object
?b.object
?*a.object==*b.object
:false
:b.object
?false
:true;
}
static vint Compare(const Nullable<T>& a, const Nullable<T>& b)
{
return
a.object
?b.object
?(*a.object==*b.object?0:*a.object<*b.object?-1:1)
:1
:b.object
?-1
:0;
}
bool operator==(const Nullable<T>& nullable)const
{
return Equals(*this, nullable);
}
bool operator!=(const Nullable<T>& nullable)const
{
return !Equals(*this, nullable);
}
bool operator<(const Nullable<T>& nullable)const
{
return Compare(*this, nullable)<0;
}
bool operator<=(const Nullable<T>& nullable)const
{
return Compare(*this, nullable)<=0;
}
bool operator>(const Nullable<T>& nullable)const
{
return Compare(*this, nullable)>0;
}
bool operator>=(const Nullable<T>& nullable)const
{
return Compare(*this, nullable)>=0;
}
/// <summary>Convert the nullable value to a bool value.</summary>
/// <returns>Returns true if it is not null.</returns>
operator bool()const
{
return object!=0;
}
/// <summary>Unbox the value. This operation will cause an access violation of it is null.</summary>
/// <returns>The original value.</returns>
const T& Value()const
{
return *object;
}
};
template<typename T, size_t minSize>
union BinaryRetriver
{
T t;
char binary[sizeof(T)>minSize?sizeof(T):minSize];
};
/***********************************************************************
Type Traits
***********************************************************************/
/// <summary>Get the index type of a value for containers.</summary>
/// <typeparam name="T">Type of the value.</typeparam>
template<typename T>
struct KeyType
{
public:
/// <summary>The index type of a value for containers.</summary>
typedef T Type;
/// <summary>Convert a value to its index type.</summary>
/// <returns>The corresponding index value.</returns>
/// <param name="value">The value.</param>
static const T& GetKeyValue(const T& value)
{
return value;
}
};
/// <summary>Test is a type a Plain-Old-Data type for containers.</summary>
/// <typeparam name="T">The type to test.</typeparam>
template<typename T>
struct POD
{
/// <summary>Returns true if the type is a Plain-Old-Data type.</summary>
static const bool Result=false;
};
template<>struct POD<bool>{static const bool Result=true;};
template<>struct POD<vint8_t>{static const bool Result=true;};
template<>struct POD<vuint8_t>{static const bool Result=true;};
template<>struct POD<vint16_t>{static const bool Result=true;};
template<>struct POD<vuint16_t>{static const bool Result=true;};
template<>struct POD<vint32_t>{static const bool Result=true;};
template<>struct POD<vuint32_t>{static const bool Result=true;};
template<>struct POD<vint64_t>{static const bool Result=true;};
template<>struct POD<vuint64_t>{static const bool Result=true;};
template<>struct POD<char>{static const bool Result=true;};
template<>struct POD<wchar_t>{static const bool Result=true;};
template<typename T>struct POD<T*>{static const bool Result=true;};
template<typename T>struct POD<T&>{static const bool Result=true;};
template<typename T, typename C>struct POD<T C::*>{static const bool Result=true;};
template<typename T, vint _Size>struct POD<T[_Size]>{static const bool Result=POD<T>::Result;};
template<typename T>struct POD<const T>{static const bool Result=POD<T>::Result;};
template<typename T>struct POD<volatile T>{static const bool Result=POD<T>::Result;};
template<typename T>struct POD<const volatile T>{static const bool Result=POD<T>::Result;};
/***********************************************************************
Date and Time
***********************************************************************/
/// <summary>A type representing the combination of date and time.</summary>
struct DateTime
{
vint year;
vint month;
vint dayOfWeek;
vint day;
vint hour;
vint minute;
vint second;
vint milliseconds;
vuint64_t totalMilliseconds;
// in gcc, this will be mktime(t) * 1000 + gettimeofday().tv_usec / 1000
vuint64_t filetime;
/// <summary>Get the current local time.</summary>
/// <returns>The current local time.</returns>
static DateTime LocalTime();
/// <summary>Get the current UTC time.</summary>
/// <returns>The current UTC time.</returns>
static DateTime UtcTime();
/// <summary>Create a date time value.</summary>
/// <returns>The created date time value.</returns>
/// <param name="_year">The year.</param>
/// <param name="_month">The month.</param>
/// <param name="_day">The day.</param>
/// <param name="_hour">The hour.</param>
/// <param name="_minute">The minute.</param>
/// <param name="_second">The second.</param>
/// <param name="_milliseconds">The millisecond.</param>
static DateTime FromDateTime(vint _year, vint _month, vint _day, vint _hour=0, vint _minute=0, vint _second=0, vint _milliseconds=0);
static DateTime FromFileTime(vuint64_t filetime);
/// <summary>Create an empty date time value.</summary>
DateTime();
/// <summary>Convert the UTC time to the local time.</summary>
/// <returns>The UTC time.</returns>
DateTime ToLocalTime();
/// <summary>Convert the local time to the UTC time.</summary>
/// <returns>The local time.</returns>
DateTime ToUtcTime();
/// <summary>Move forward.</summary>
/// <returns>The moved time.</returns>
/// <param name="milliseconds">The delta in milliseconds.</param>
DateTime Forward(vuint64_t milliseconds);
/// <summary>Move Backward.</summary>
/// <returns>The moved time.</returns>
/// <param name="milliseconds">The delta in milliseconds.</param>
DateTime Backward(vuint64_t milliseconds);
bool operator==(const DateTime& value)const { return filetime==value.filetime; }
bool operator!=(const DateTime& value)const { return filetime!=value.filetime; }
bool operator<(const DateTime& value)const { return filetime<value.filetime; }
bool operator<=(const DateTime& value)const { return filetime<=value.filetime; }
bool operator>(const DateTime& value)const { return filetime>value.filetime; }
bool operator>=(const DateTime& value)const { return filetime>=value.filetime; }
};
/***********************************************************************
Interface
***********************************************************************/
/// <summary>Base type of all interfaces. All interface types are encouraged to be virtual inherited.</summary>
class Interface : private NotCopyable
{
public:
virtual ~Interface();
};
/***********************************************************************
Type Traits
***********************************************************************/
struct YesType{};
struct NoType{};
template<typename T, typename YesOrNo>
struct AcceptType
{
};
template<typename T>
struct AcceptType<T, YesType>
{
typedef T Type;
};
template<typename YesOrNo>
struct AcceptValue
{
static const bool Result=false;
};
template<>
struct AcceptValue<YesType>
{
static const bool Result=true;
};
template<typename TFrom, typename TTo>
struct RequiresConvertable
{
static YesType Test(TTo* value);
static NoType Test(void* value);
typedef decltype(Test((TFrom*)0)) YesNoType;
};
template<typename T, typename U>
struct AcceptAlways
{
typedef T Type;
};
}
#endif
/***********************************************************************
.\STRING.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::String
Classes:
AString : Mbcs using the code page of the current locale
WString : UTF-16 (for Windows), or UTF-32 (for Linux and macOS)
***********************************************************************/
#ifndef VCZH_STRING
#define VCZH_STRING
#include <memory.h>
namespace vl
{
/// <summary>A type representing a string.</summary>
/// <typeparam name="T">Type of a character.</typeparam>
template<typename T>
class ObjectString : public Object
{
private:
static const T zero;
mutable T* buffer;
mutable volatile vint* counter;
mutable vint start;
mutable vint length;
mutable vint realLength;
static vint CalculateLength(const T* buffer)
{
vint result=0;
while(*buffer++)result++;
return result;
}
static vint Compare(const T* bufA, const ObjectString<T>& strB)
{
const T* bufB=strB.buffer+strB.start;
const T* bufAOld=bufA;
vint length=strB.length;
while(length-- && *bufA)
{
vint diff=*bufA++-*bufB++;
if(diff!=0)
{
return diff;
}
};
return CalculateLength(bufAOld)-strB.length;
}
public:
static vint Compare(const ObjectString<T>& strA, const ObjectString<T>& strB)
{
const T* bufA=strA.buffer+strA.start;
const T* bufB=strB.buffer+strB.start;
vint length=strA.length<strB.length?strA.length:strB.length;
while(length--)
{
vint diff=*bufA++-*bufB++;
if(diff!=0)
{
return diff;
}
};
return strA.length-strB.length;
}
private:
void Inc()const
{
if(counter)
{
INCRC(counter);
}
}
void Dec()const
{
if(counter)
{
if(DECRC(counter)==0)
{
delete[] buffer;
delete counter;
}
}
}
ObjectString(const ObjectString<T>& string, vint _start, vint _length)
{
if(_length<=0)
{
buffer=(T*)&zero;
counter=0;
start=0;
length=0;
realLength=0;
}
else
{
buffer=string.buffer;
counter=string.counter;
start=string.start+_start;
length=_length;
realLength=string.realLength;
Inc();
}
}
ObjectString(const ObjectString<T>& dest, const ObjectString<T>& source, vint index, vint count)
{
if(index==0 && count==dest.length && source.length==0)
{
buffer=(T*)&zero;
counter=0;
start=0;
length=0;
realLength=0;
}
else
{
counter=new vint(1);
start=0;
length=dest.length-count+source.length;
realLength=length;
buffer=new T[length+1];
memcpy(buffer, dest.buffer+dest.start, sizeof(T)*index);
memcpy(buffer+index, source.buffer+source.start, sizeof(T)*source.length);
memcpy(buffer+index+source.length, (dest.buffer+dest.start+index+count), sizeof(T)*(dest.length-index-count));
buffer[length]=0;
}
}
public:
static ObjectString<T> Empty;
/// <summary>Create an empty string.</summary>
ObjectString()
{
buffer=(T*)&zero;
counter=0;
start=0;
length=0;
realLength=0;
}
/// <summary>Create a string continaing one character.</summary>
/// <param name="_char">The character.</param>
ObjectString(const T& _char)
{
counter=new vint(1);
start=0;
length=1;
buffer=new T[2];
buffer[0]=_char;
buffer[1]=0;
realLength=length;
}
/// <summary>Copy a string.</summary>
/// <param name="_buffer">Memory to copy. It does not have to contain the zero terminator.</param>
/// <param name="_length">Size of the content in characters.</param>
ObjectString(const T* _buffer, vint _length)
{
if(_length<=0)
{
buffer=(T*)&zero;
counter=0;
start=0;
length=0;
realLength=0;
}
else
{
buffer=new T[_length+1];
memcpy(buffer, _buffer, _length*sizeof(T));
buffer[_length]=0;
counter=new vint(1);
start=0;
length=_length;
realLength=_length;
}
}
/// <summary>Copy a string.</summary>
/// <param name="_buffer">Memory to copy. It should have to contain the zero terminator.</param>
/// <param name="copy">Set to true to copy the memory. Set to false to use the memory directly.</param>
ObjectString(const T* _buffer, bool copy = true)
{
CHECK_ERROR(_buffer!=0, L"ObjectString<T>::ObjectString(const T*, bool)#Cannot construct a string from nullptr.");
if(copy)
{
counter=new vint(1);
start=0;
length=CalculateLength(_buffer);
buffer=new T[length+1];
memcpy(buffer, _buffer, sizeof(T)*(length+1));
realLength=length;
}
else
{
buffer=(T*)_buffer;
counter=0;
start=0;
length=CalculateLength(_buffer);
realLength=length;
}
}
/// <summary>Copy a string.</summary>
/// <param name="string">The string to copy.</param>
ObjectString(const ObjectString<T>& string)
{
buffer=string.buffer;
counter=string.counter;
start=string.start;
length=string.length;
realLength=string.realLength;
Inc();
}
/// <summary>Move a string.</summary>
/// <param name="string">The string to move.</param>
ObjectString(ObjectString<T>&& string)
{
buffer=string.buffer;
counter=string.counter;
start=string.start;
length=string.length;
realLength=string.realLength;
string.buffer=(T*)&zero;
string.counter=0;
string.start=0;
string.length=0;
string.realLength=0;
}
~ObjectString()
{
Dec();
}
/// <summary>Get the zero-terminated buffer in the string. Copying parts of a string does not necessarily create a new buffer, so in some situation the string will not actually points to a zero-terminated buffer. In this case, this function will copy the content to a new buffer with a zero terminator and return.</summary>
/// <returns>Returns the buffer.</returns>
const T* Buffer()const
{
if(start+length!=realLength)
{
T* newBuffer=new T[length+1];
memcpy(newBuffer, buffer+start, sizeof(T)*length);
newBuffer[length]=0;
Dec();
buffer=newBuffer;
counter=new vint(1);
start=0;
realLength=length;
}
return buffer+start;
}
ObjectString<T>& operator=(const ObjectString<T>& string)
{
if(this!=&string)
{
Dec();
buffer=string.buffer;
counter=string.counter;
start=string.start;
length=string.length;
realLength=string.realLength;
Inc();
}
return *this;
}
ObjectString<T>& operator=(ObjectString<T>&& string)
{
if(this!=&string)
{
Dec();
buffer=string.buffer;
counter=string.counter;
start=string.start;
length=string.length;
realLength=string.realLength;
string.buffer=(T*)&zero;
string.counter=0;
string.start=0;
string.length=0;
string.realLength=0;
}
return *this;
}
ObjectString<T>& operator+=(const ObjectString<T>& string)
{
return *this=*this+string;
}
ObjectString<T> operator+(const ObjectString<T>& string)const
{
return ObjectString<T>(*this, string, length, 0);
}
bool operator==(const ObjectString<T>& string)const
{
return Compare(*this, string)==0;
}
bool operator!=(const ObjectString<T>& string)const
{
return Compare(*this, string)!=0;
}
bool operator>(const ObjectString<T>& string)const
{
return Compare(*this, string)>0;
}
bool operator>=(const ObjectString<T>& string)const
{
return Compare(*this, string)>=0;
}
bool operator<(const ObjectString<T>& string)const
{
return Compare(*this, string)<0;
}
bool operator<=(const ObjectString<T>& string)const
{
return Compare(*this, string)<=0;
}
bool operator==(const T* buffer)const
{
return Compare(buffer, *this)==0;
}
bool operator!=(const T* buffer)const
{
return Compare(buffer, *this)!=0;
}
bool operator>(const T* buffer)const
{
return Compare(buffer, *this)<0;
}
bool operator>=(const T* buffer)const
{
return Compare(buffer, *this)<=0;
}
bool operator<(const T* buffer)const
{
return Compare(buffer, *this)>0;
}
bool operator<=(const T* buffer)const
{
return Compare(buffer, *this)>=0;
}
T operator[](vint index)const
{
CHECK_ERROR(index>=0 && index<length, L"ObjectString:<T>:operator[](vint)#Argument index not in range.");
return buffer[start+index];
}
/// <summary>Get the size of the string in characters.</summary>
/// <returns>The size.</returns>
vint Length()const
{
return length;
}
/// <summary>Find a character.</summary>
/// <returns>The position of the character. Returns -1 if it doesn not exist.</returns>
/// <param name="c">The character to find.</param>
vint IndexOf(T c)const
{
const T* reading=buffer+start;
for(vint i=0;i<length;i++)
{
if(reading[i]==c)
return i;
}
return -1;
}
/// <summary>Copy the beginning of the string.</summary>
/// <returns>The copied string.</returns>
/// <param name="count">Size of characters to copy.</param>
ObjectString<T> Left(vint count)const
{
CHECK_ERROR(count>=0 && count<=length, L"ObjectString<T>::Left(vint)#Argument count not in range.");
return ObjectString<T>(*this, 0, count);
}
/// <summary>Copy the ending of the string.</summary>
/// <returns>The copied string.</returns>
/// <param name="count">Size of characters to copy.</param>
ObjectString<T> Right(vint count)const
{
CHECK_ERROR(count>=0 && count<=length, L"ObjectString<T>::Right(vint)#Argument count not in range.");
return ObjectString<T>(*this, length-count, count);
}
/// <summary>Copy the middle of the string.</summary>
/// <returns>The copied string.</returns>
/// <param name="index">Position of characters to copy.</param>
/// <param name="count">Size of characters to copy.</param>
ObjectString<T> Sub(vint index, vint count)const
{
CHECK_ERROR(index>=0 && index<=length, L"ObjectString<T>::Sub(vint, vint)#Argument index not in range.");
CHECK_ERROR(index+count>=0 && index+count<=length, L"ObjectString<T>::Sub(vint, vint)#Argument count not in range.");
return ObjectString<T>(*this, index, count);
}
/// <summary>Copy the beginning and the end of the string.</summary>
/// <returns>The copied string.</returns>
/// <param name="index">Position of characters NOT to copy.</param>
/// <param name="count">Size of characters NOT to copy.</param>
ObjectString<T> Remove(vint index, vint count)const
{
CHECK_ERROR(index>=0 && index<length, L"ObjectString<T>::Remove(vint, vint)#Argument index not in range.");
CHECK_ERROR(index+count>=0 && index+count<=length, L"ObjectString<T>::Remove(vint, vint)#Argument count not in range.");
return ObjectString<T>(*this, ObjectString<T>(), index, count);
}
/// <summary>Make a new string by inserting a string in this string.</summary>
/// <returns>The copied string.</returns>
/// <param name="index">Position of characters to insert.</param>
/// <param name="string">The string to be inserted in this string.</param>
ObjectString<T> Insert(vint index, const ObjectString<T>& string)const
{
CHECK_ERROR(index>=0 && index<=length, L"ObjectString<T>::Insert(vint)#Argument count not in range.");
return ObjectString<T>(*this, string, index, 0);
}
friend bool operator<(const T* left, const ObjectString<T>& right)
{
return Compare(left, right)<0;
}
friend bool operator<=(const T* left, const ObjectString<T>& right)
{
return Compare(left, right)<=0;
}
friend bool operator>(const T* left, const ObjectString<T>& right)
{
return Compare(left, right)>0;
}
friend bool operator>=(const T* left, const ObjectString<T>& right)
{
return Compare(left, right)>=0;
}
friend bool operator==(const T* left, const ObjectString<T>& right)
{
return Compare(left, right)==0;
}
friend bool operator!=(const T* left, const ObjectString<T>& right)
{
return Compare(left, right)!=0;
}
friend ObjectString<T> operator+(const T* left, const ObjectString<T>& right)
{
return ObjectString<T>(left, false)+right;
}
};
template<typename T>
ObjectString<T> ObjectString<T>::Empty=ObjectString<T>();
template<typename T>
const T ObjectString<T>::zero=0;
/// <summary>Ansi string.</summary>
typedef ObjectString<char> AString;
/// <summary>Unicode string.</summary>
typedef ObjectString<wchar_t> WString;
/// <summary>Convert a string to an signed integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vint atoi_test(const AString& string, bool& success);
/// <summary>Convert a string to an signed integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vint wtoi_test(const WString& string, bool& success);
/// <summary>Convert a string to an signed 64-bits integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vint64_t atoi64_test(const AString& string, bool& success);
/// <summary>Convert a string to an signed 64-bits integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vint64_t wtoi64_test(const WString& string, bool& success);
/// <summary>Convert a string to an unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vuint atou_test(const AString& string, bool& success);
/// <summary>Convert a string to an unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vuint wtou_test(const WString& string, bool& success);
/// <summary>Convert a string to a 64-bits unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vuint64_t atou64_test(const AString& string, bool& success);
/// <summary>Convert a string to a 64-bits unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern vuint64_t wtou64_test(const WString& string, bool& success);
/// <summary>Convert a string to 64-bits floating point number.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern double atof_test(const AString& string, bool& success);
/// <summary>Convert a string to 64-bits floating point number.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
/// <param name="success">Returns true if this operation succeeded.</param>
extern double wtof_test(const WString& string, bool& success);
/// <summary>Convert a string to an signed integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vint atoi(const AString& string);
/// <summary>Convert a string to an signed integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vint wtoi(const WString& string);
/// <summary>Convert a string to an signed 64-bits integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vint64_t atoi64(const AString& string);
/// <summary>Convert a string to an signed 64-bits integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vint64_t wtoi64(const WString& string);
/// <summary>Convert a string to an unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vuint atou(const AString& string);
/// <summary>Convert a string to an unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vuint wtou(const WString& string);
/// <summary>Convert a string to a 64-bits unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vuint64_t atou64(const AString& string);
/// <summary>Convert a string to a 64-bits unsigned integer.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern vuint64_t wtou64(const WString& string);
/// <summary>Convert a string to a 64-bits floating point number.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern double atof(const AString& string);
/// <summary>Convert a string to a 64-bits floating point number.</summary>
/// <returns>The converted number. If the convert failed, the result is undefined.</returns>
/// <param name="string">The string to convert.</param>
extern double wtof(const WString& string);
/// <summary>Convert a signed interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern AString itoa(vint number);
/// <summary>Convert a signed interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern WString itow(vint number);
/// <summary>Convert a 64-bits signed interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern AString i64toa(vint64_t number);
/// <summary>Convert a 64-bits signed interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern WString i64tow(vint64_t number);
/// <summary>Convert an unsigned interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern AString utoa(vuint number);
/// <summary>Convert an unsigned interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern WString utow(vuint number);
/// <summary>Convert a 64-bits unsigned interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern AString u64toa(vuint64_t number);
/// <summary>Convert a 64-bits unsigned interger to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern WString u64tow(vuint64_t number);
/// <summary>Convert a 64-bits floating pointer number to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern AString ftoa(double number);
/// <summary>Convert a 64-bits floating pointer number to a string.</summary>
/// <returns>The converted string.</returns>
/// <param name="number">The number to convert.</param>
extern WString ftow(double number);
extern vint _wtoa(const wchar_t* w, char* a, vint chars);
/// <summary>Convert an Unicode string to an Ansi string.</summary>
/// <returns>The converted string.</returns>
/// <param name="string">The string to convert.</param>
extern AString wtoa(const WString& string);
extern vint _atow(const char* a, wchar_t* w, vint chars);
/// <summary>Convert an Ansi string to an Unicode string.</summary>
/// <returns>The converted string.</returns>
/// <param name="string">The string to convert.</param>
extern WString atow(const AString& string);
/// <summary>Convert all letters to lower case letters.</summary>
/// <returns>The converted string.</returns>
/// <param name="string">The string to convert.</param>
extern AString alower(const AString& string);
/// <summary>Convert all letters to lower case letters.</summary>
/// <returns>The converted string.</returns>
/// <param name="string">The string to convert.</param>
extern WString wlower(const WString& string);
/// <summary>Convert all letters to upper case letters.</summary>
/// <returns>The converted string.</returns>
/// <param name="string">The string to convert.</param>
extern AString aupper(const AString& string);
/// <summary>Convert all letters to upper case letters.</summary>
/// <returns>The converted string.</returns>
/// <param name="string">The string to convert.</param>
extern WString wupper(const WString& string);
#if defined VCZH_GCC
extern void _itoa_s(vint32_t value, char* buffer, size_t size, vint radix);
extern void _itow_s(vint32_t value, wchar_t* buffer, size_t size, vint radix);
extern void _i64toa_s(vint64_t value, char* buffer, size_t size, vint radix);
extern void _i64tow_s(vint64_t value, wchar_t* buffer, size_t size, vint radix);
extern void _uitoa_s(vuint32_t value, char* buffer, size_t size, vint radix);
extern void _uitow_s(vuint32_t value, wchar_t* buffer, size_t size, vint radix);
extern void _ui64toa_s(vuint64_t value, char* buffer, size_t size, vint radix);
extern void _ui64tow_s(vuint64_t value, wchar_t* buffer, size_t size, vint radix);
extern void _gcvt_s(char* buffer, size_t size, double value, vint numberOfDigits);
extern void _strlwr_s(char* buffer, size_t size);
extern void _strupr_s(char* buffer, size_t size);
extern void _wcslwr_s(wchar_t* buffer, size_t size);
extern void _wcsupr_s(wchar_t* buffer, size_t size);
extern void wcscpy_s(wchar_t* buffer, size_t size, const wchar_t* text);
#endif
enum class LoremIpsumCasing
{
AllWordsLowerCase,
FirstWordUpperCase,
AllWordsUpperCase,
};
extern WString LoremIpsum(vint bestLength, LoremIpsumCasing casing);
extern WString LoremIpsumTitle(vint bestLength);
extern WString LoremIpsumSentence(vint bestLength);
extern WString LoremIpsumParagraph(vint bestLength);
}
#endif
/***********************************************************************
.\POINTER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Smart Pointer
Classes:
Ptr<T> : Shared Pointer
***********************************************************************/
#ifndef VCZH_POINTER
#define VCZH_POINTER
namespace vl
{
/***********************************************************************
ReferenceCounterOperator
***********************************************************************/
/// <summary>The strategy to get the pointer to the reference counter from an object. If you get the same pointer multiple times from the same object by calling [M:vl.ReferenceCounterOperator`2.CreateCounter], than it is safe to convert a object pointer to a [T:vl.Ptr`1]. Currently for reflectable C++ types which inherit from [T:vl.reflection.DescriptableObject] it is yet. For others it is no.</summary>
/// <typeparam name="T">The type of the object.</typeparam>
/// <typeparam name="Enabled">[T:vl.Ptr`1] will always use [T:vl.YesType] as the second type parameter. This parameter is useful when you want to do partial specialization in the SFINAE way.</typeparam>
template<typename T, typename Enabled=YesType>
struct ReferenceCounterOperator
{
/// <summary>Create a pointer to the reference counter from an object.</summary>
/// <returns>The pointer to the reference counter.</returns>
/// <param name="reference">The object.</param>
static __forceinline volatile vint* CreateCounter(T* reference)
{
return new vint(0);
}
/// <summary>Destroy a pointer to the reference counter from an object.</summary>
/// <param name="counter">The pointer to the reference counter.</param>
/// <param name="reference">The object.</param>
static __forceinline void DeleteReference(volatile vint* counter, void* reference)
{
delete counter;
delete (T*)reference;
}
};
/***********************************************************************
Ptr
***********************************************************************/
/// <summary>A smart pointer. It is always safe to convert a pointer to an object to a smart pointer once. If you do it multiple times, it may be wrong due to different implementation of [T:vl.ReferenceCounterOperator`2]. In case of wrong, disposing the smart pointer will cause an access violation.</summary>
/// <typeparam name="T">The type of the object.</typeparam>
template<typename T>
class Ptr
{
template<typename X>
friend class Ptr;
protected:
typedef void (*Destructor)(volatile vint*, void*);
volatile vint* counter;
T* reference;
void* originalReference;
Destructor originalDestructor;
void Inc()
{
if(counter)
{
INCRC(counter);
}
}
void Dec(bool deleteIfZero = true)
{
if(counter)
{
if(DECRC(counter)==0)
{
if (deleteIfZero)
{
originalDestructor(counter, originalReference);
}
counter=nullptr;
reference=nullptr;
originalReference=nullptr;
originalDestructor=nullptr;
}
}
}
volatile vint* Counter()const
{
return counter;
}
Ptr(volatile vint* _counter, T* _reference, void* _originalReference, Destructor _originalDestructor)
:counter(_counter)
,reference(_reference)
,originalReference(_originalReference)
,originalDestructor(_originalDestructor)
{
Inc();
}
public:
/// <summary>Create a null pointer.</summary>
Ptr()
:counter(0)
,reference(0)
,originalReference(0)
,originalDestructor(0)
{
}
/// <summary>Convert a pointer to an object to a smart pointer.</summary>
/// <param name="pointer">The pointer to the object.</param>
Ptr(T* pointer)
:counter(0)
,reference(0)
,originalReference(0)
,originalDestructor(0)
{
if(pointer)
{
counter=ReferenceCounterOperator<T>::CreateCounter(pointer);
reference=pointer;
originalReference=pointer;
originalDestructor=&ReferenceCounterOperator<T>::DeleteReference;
Inc();
}
}
/// <summary>Copy a smart pointer.</summary>
/// <param name="pointer">The smart pointer to copy.</param>
Ptr(const Ptr<T>& pointer)
:counter(pointer.counter)
,reference(pointer.reference)
,originalReference(pointer.originalReference)
,originalDestructor(pointer.originalDestructor)
{
Inc();
}
/// <summary>Move a smart pointer.</summary>
/// <param name="pointer">The smart pointer to Move.</param>
Ptr(Ptr<T>&& pointer)
:counter(pointer.counter)
,reference(pointer.reference)
,originalReference(pointer.originalReference)
,originalDestructor(pointer.originalDestructor)
{
pointer.counter=0;
pointer.reference=0;
pointer.originalReference=0;
pointer.originalDestructor=0;
}
/// <summary>Cast a smart pointer.</summary>
/// <typeparam name="C">The type of the object before casting.</typeparam>
/// <param name="pointer">The smart pointer to cast.</param>
template<typename C>
Ptr(const Ptr<C>& pointer)
:counter(0)
,reference(0)
,originalReference(0)
,originalDestructor(0)
{
T* converted=pointer.Obj();
if(converted)
{
counter=pointer.Counter();
reference=converted;
originalReference=pointer.originalReference;
originalDestructor=pointer.originalDestructor;
Inc();
}
}
~Ptr()
{
Dec();
}
/// <summary>Detach the contained object from this smart pointer.</summary>
/// <returns>The detached object. Returns null if this smart pointer is empty.</returns>
T* Detach()
{
auto detached = reference;
Dec(false);
return detached;
}
/// <summary>Cast a smart pointer.</summary>
/// <typeparam name="C">The type of the object after casting.</typeparam>
/// <returns>The casted smart pointer. Returns null if failed.</returns>
template<typename C>
Ptr<C> Cast()const
{
C* converted=dynamic_cast<C*>(reference);
return Ptr<C>((converted?counter:0), converted, originalReference, originalDestructor);
}
/// <summary>Convert a pointer to an object to a smart pointer.</summary>
/// <returns>The converted smart pointer.</returns>
/// <param name="pointer">The pointer to the object.</param>
Ptr<T>& operator=(T* pointer)
{
Dec();
if(pointer)
{
counter=ReferenceCounterOperator<T>::CreateCounter(pointer);
reference=pointer;
originalReference=pointer;
originalDestructor=&ReferenceCounterOperator<T>::DeleteReference;
Inc();
}
else
{
counter=0;
reference=0;
originalReference=0;
originalDestructor=0;
}
return *this;
}
/// <summary>Copy a smart pointer.</summary>
/// <returns>The copied smart pointer.</returns>
/// <param name="pointer">The smart pointer to copy.</param>
Ptr<T>& operator=(const Ptr<T>& pointer)
{
if(this!=&pointer)
{
Dec();
counter=pointer.counter;
reference=pointer.reference;
originalReference=pointer.originalReference;
originalDestructor=pointer.originalDestructor;
Inc();
}
return *this;
}
/// <summary>Move a smart pointer.</summary>
/// <returns>The moved smart pointer.</returns>
/// <param name="pointer">The smart pointer to Move.</param>
Ptr<T>& operator=(Ptr<T>&& pointer)
{
if(this!=&pointer)
{
Dec();
counter=pointer.counter;
reference=pointer.reference;
originalReference=pointer.originalReference;
originalDestructor=pointer.originalDestructor;
pointer.counter=0;
pointer.reference=0;
pointer.originalReference=0;
pointer.originalDestructor=0;
}
return *this;
}
/// <summary>Cast a smart pointer.</summary>
/// <typeparam name="C">The type of the object before casting.</typeparam>
/// <returns>The smart pointer after casting.</returns>
/// <param name="pointer">The smart pointer to cast.</param>
template<typename C>
Ptr<T>& operator=(const Ptr<C>& pointer)
{
T* converted=pointer.Obj();
Dec();
if(converted)
{
counter=pointer.counter;
reference=converted;
originalReference=pointer.originalReference;
originalDestructor=pointer.originalDestructor;
Inc();
}
else
{
counter=0;
reference=0;
originalReference=0;
originalDestructor=0;
}
return *this;
}
bool operator==(const T* pointer)const
{
return reference==pointer;
}
bool operator!=(const T* pointer)const
{
return reference!=pointer;
}
bool operator>(const T* pointer)const
{
return reference>pointer;
}
bool operator>=(const T* pointer)const
{
return reference>=pointer;
}
bool operator<(const T* pointer)const
{
return reference<pointer;
}
bool operator<=(const T* pointer)const
{
return reference<=pointer;
}
bool operator==(const Ptr<T>& pointer)const
{
return reference==pointer.reference;
}
bool operator!=(const Ptr<T>& pointer)const
{
return reference!=pointer.reference;
}
bool operator>(const Ptr<T>& pointer)const
{
return reference>pointer.reference;
}
bool operator>=(const Ptr<T>& pointer)const
{
return reference>=pointer.reference;
}
bool operator<(const Ptr<T>& pointer)const
{
return reference<pointer.reference;
}
bool operator<=(const Ptr<T>& pointer)const
{
return reference<=pointer.reference;
}
/// <summary>Test if it is a null pointer.</summary>
/// <returns>Returns true if it is not null.</returns>
operator bool()const
{
return reference!=0;
}
/// <summary>Get the pointer to the object.</summary>
/// <returns>The pointer to the object.</returns>
T* Obj()const
{
return reference;
}
/// <summary>Get the pointer to the object.</summary>
/// <returns>The pointer to the object.</returns>
T* operator->()const
{
return reference;
}
};
/***********************************************************************
ComPtr
***********************************************************************/
template<typename T>
class ComPtr
{
protected:
volatile vint* counter;
T* reference;
void Inc()
{
if(counter)
{
INCRC(counter);
}
}
void Dec()
{
if(counter)
{
if(DECRC(counter)==0)
{
delete counter;
reference->Release();
counter=0;
reference=0;
}
}
}
volatile vint* Counter()const
{
return counter;
}
ComPtr(volatile vint* _counter, T* _reference)
:counter(_counter)
,reference(_reference)
{
Inc();
}
public:
ComPtr()
{
counter=0;
reference=0;
}
ComPtr(T* pointer)
{
if(pointer)
{
counter=new volatile vint(1);
reference=pointer;
}
else
{
counter=0;
reference=0;
}
}
ComPtr(const ComPtr<T>& pointer)
{
counter=pointer.counter;
reference=pointer.reference;
Inc();
}
ComPtr(ComPtr<T>&& pointer)
{
counter=pointer.counter;
reference=pointer.reference;
pointer.counter=0;
pointer.reference=0;
}
~ComPtr()
{
Dec();
}
ComPtr<T>& operator=(T* pointer)
{
Dec();
if(pointer)
{
counter=new vint(1);
reference=pointer;
}
else
{
counter=0;
reference=0;
}
return *this;
}
ComPtr<T>& operator=(const ComPtr<T>& pointer)
{
if(this!=&pointer)
{
Dec();
counter=pointer.counter;
reference=pointer.reference;
Inc();
}
return *this;
}
ComPtr<T>& operator=(ComPtr<T>&& pointer)
{
if(this!=&pointer)
{
Dec();
counter=pointer.counter;
reference=pointer.reference;
pointer.counter=0;
pointer.reference=0;
}
return *this;
}
bool operator==(const T* pointer)const
{
return reference==pointer;
}
bool operator!=(const T* pointer)const
{
return reference!=pointer;
}
bool operator>(const T* pointer)const
{
return reference>pointer;
}
bool operator>=(const T* pointer)const
{
return reference>=pointer;
}
bool operator<(const T* pointer)const
{
return reference<pointer;
}
bool operator<=(const T* pointer)const
{
return reference<=pointer;
}
bool operator==(const ComPtr<T>& pointer)const
{
return reference==pointer.reference;
}
bool operator!=(const ComPtr<T>& pointer)const
{
return reference!=pointer.reference;
}
bool operator>(const ComPtr<T>& pointer)const
{
return reference>pointer.reference;
}
bool operator>=(const ComPtr<T>& pointer)const
{
return reference>=pointer.reference;
}
bool operator<(const ComPtr<T>& pointer)const
{
return reference<pointer.reference;
}
bool operator<=(const ComPtr<T>& pointer)const
{
return reference<=pointer.reference;
}
operator bool()const
{
return reference!=0;
}
T* Obj()const
{
return reference;
}
T* operator->()const
{
return reference;
}
};
template<typename T, typename ...TArgs>
Ptr<T> MakePtr(TArgs ...args)
{
return new T(args...);
}
/***********************************************************************
Traits
***********************************************************************/
template<typename T>
struct KeyType<Ptr<T>>
{
typedef T* Type;
static T* GetKeyValue(const Ptr<T>& key)
{
return key.Obj();
}
};
template<typename T>
struct POD<Ptr<T>>
{
static const bool Result=false;
};
template<typename T>
struct KeyType<ComPtr<T>>
{
typedef T* Type;
static T* GetKeyValue(const ComPtr<T>& key)
{
return key.Obj();
}
};
template<typename T>
struct POD<ComPtr<T>>
{
static const bool Result=false;
};
}
#endif
/***********************************************************************
.\FUNCTION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Function
Classes:
Func<function-type> : Functor
Functions:
Curry :: (A->B) -> A -> B : Currying
Combine :: (A->B) -> (A->C) -> (B->C->D) -> (A->D) : Combine multiple functors using an operator
***********************************************************************/
#ifndef VCZH_FUNCTION
#define VCZH_FUNCTION
namespace vl
{
/***********************************************************************
vl::Func<R(TArgs...)>
***********************************************************************/
template<typename T>
class Func
{
};
namespace internal_invokers
{
template<typename R, typename ...TArgs>
class Invoker : public Object
{
public:
virtual R Invoke(TArgs&& ...args) = 0;
};
//------------------------------------------------------
template<typename R, typename ...TArgs>
class StaticInvoker : public Invoker<R, TArgs...>
{
protected:
R(*function)(TArgs ...args);
public:
StaticInvoker(R(*_function)(TArgs...))
:function(_function)
{
}
R Invoke(TArgs&& ...args)override
{
return function(ForwardValue<TArgs>(args)...);
}
};
//------------------------------------------------------
template<typename C, typename R, typename ...TArgs>
class MemberInvoker : public Invoker<R, TArgs...>
{
protected:
C* sender;
R(C::*function)(TArgs ...args);
public:
MemberInvoker(C* _sender, R(C::*_function)(TArgs ...args))
:sender(_sender)
,function(_function)
{
}
R Invoke(TArgs&& ...args)override
{
return (sender->*function)(ForwardValue<TArgs>(args)...);
}
};
//------------------------------------------------------
template<typename C, typename R, typename ...TArgs>
class ObjectInvoker : public Invoker<R, TArgs...>
{
protected:
C function;
public:
ObjectInvoker(const C& _function)
:function(_function)
{
}
R Invoke(TArgs&& ...args)override
{
return function(ForwardValue<TArgs>(args)...);
}
};
//------------------------------------------------------
template<typename C, typename ...TArgs>
class ObjectInvoker<C, void, TArgs...> : public Invoker<void, TArgs...>
{
protected:
C function;
public:
ObjectInvoker(const C& _function)
:function(_function)
{
}
void Invoke(TArgs&& ...args)override
{
function(ForwardValue<TArgs>(args)...);
}
};
}
/// <summary>A type representing a function reference.</summary>
/// <typeparam name="R">The return type.</typeparam>
/// <typeparam name="TArgs">Types of parameters.</typeparam>
template<typename R, typename ...TArgs>
class Func<R(TArgs...)> : public Object
{
protected:
Ptr<internal_invokers::Invoker<R, TArgs...>> invoker;
public:
typedef R FunctionType(TArgs...);
typedef R ResultType;
/// <summary>Create a null function reference.</summary>
Func()
{
}
/// <summary>Copy a function reference.</summary>
/// <param name="function">The function reference to copy.</param>
Func(const Func<R(TArgs...)>& function)
{
invoker=function.invoker;
}
/// <summary>Create a reference using a function pointer.</summary>
/// <param name="function">The function pointer.</param>
Func(R(*function)(TArgs...))
{
invoker=new internal_invokers::StaticInvoker<R, TArgs...>(function);
}
/// <summary>Create a reference using a method.</summary>
/// <typeparam name="C">Type of the class that has the method.</typeparam>
/// <param name="sender">The object that has the method.</param>
/// <param name="function">The function pointer.</param>
template<typename C>
Func(C* sender, R(C::*function)(TArgs...))
{
invoker=new internal_invokers::MemberInvoker<C, R, TArgs...>(sender, function);
}
/// <summary>Create a reference using a function object.</summary>
/// <typeparam name="R2">Return type of the function object.</typeparam>
/// <typeparam name="TArgs2">Argument types of the function object.</typeparam>
/// <param name="function">The function object.</param>
template<typename R2, typename ...TArgs2>
Func(const Func<R2(TArgs2...)>& function)
{
if (function)
{
invoker = new internal_invokers::ObjectInvoker<Func<R2(TArgs2...)>, R, TArgs...>(function);
}
}
/// <summary>Create a reference using a function object.</summary>
/// <typeparam name="C">Type of the function object.</typeparam>
/// <param name="function">The function object. It could be a lambda expression.</param>
template<typename C>
Func(const C& function)
{
invoker = new internal_invokers::ObjectInvoker<C, R, TArgs...>(function);
}
/// <summary>Invoke the function.</summary>
/// <returns>Returns the function result.</returns>
/// <param name="args">Arguments to invoke the function.</param>
R operator()(TArgs ...args)const
{
return invoker->Invoke(ForwardValue<TArgs>(args)...);
}
bool operator==(const Func<R(TArgs...)>& function)const
{
return invoker == function.invoker;
}
bool operator!=(const Func<R(TArgs...)>& function)const
{
return invoker != function.invoker;
}
/// <summary>Test is the reference a null reference.</summary>
/// <returns>Returns true if it is not a null reference.</returns>
operator bool()const
{
return invoker;
}
};
/***********************************************************************
vl::function_lambda::LambdaRetriveType<R(TArgs...)>
***********************************************************************/
namespace function_lambda
{
template<typename T>
struct LambdaRetriveType
{
typedef vint Type;
typedef vint FunctionType;
typedef vint ResultType;
};
template<typename T>
struct FunctionObjectRetriveType
{
typedef typename LambdaRetriveType<decltype(&T::operator())>::Type Type;
typedef typename LambdaRetriveType<decltype(&T::operator())>::FunctionType FunctionType;
typedef typename LambdaRetriveType<decltype(&T::operator())>::ResultType ResultType;
};
template<typename TObject, typename R, typename ...TArgs>
struct LambdaRetriveType<R (__thiscall TObject::*)(TArgs...)const>
{
typedef Func<R(TArgs...)> Type;
typedef R(FunctionType)(TArgs...);
typedef R ResultType;
};
template<typename TObject, typename R, typename ...TArgs>
struct LambdaRetriveType<R (__thiscall TObject::*)(TArgs...)>
{
typedef Func<R(TArgs...)> Type;
typedef R(FunctionType)(TArgs...);
typedef R ResultType;
};
template<typename R, typename ...TArgs>
struct FunctionObjectRetriveType<R(*)(TArgs...)>
{
typedef Func<R(TArgs...)> Type;
typedef R(FunctionType)(TArgs...);
typedef R ResultType;
};
/// <summary>Create a function reference to a function object or a lambda expression, with all type information autotimatically inferred. You can use the macro called "LAMBDA" to refer to this function.</summary>
/// <typeparam name="T">Type of the function object or the lambda expression.</typeparam>
/// <returns>The function reference.</returns>
/// <param name="functionObject">The function object or the lambda expression.</param>
template<typename T>
typename LambdaRetriveType<decltype(&T::operator())>::Type Lambda(T functionObject)
{
return functionObject;
}
/// <summary>Create a function reference to a function pointer, with all type information autotimatically inferred. You can use the macro called "FUNCTION" to refer to this function.</summary>
/// <typeparam name="T">Type of the function pointer.</typeparam>
/// <returns>The function reference.</returns>
/// <param name="functionObject">The function pointer.</param>
template<typename T>
typename FunctionObjectRetriveType<T>::Type ConvertToFunction(T functionObject)
{
return functionObject;
}
#define LAMBDA vl::function_lambda::Lambda
#define FUNCTION vl::function_lambda::ConvertToFunction
#define FUNCTION_TYPE(T) typename vl::function_lambda::FunctionObjectRetriveType<T>::Type
#define FUNCTION_RESULT_TYPE(T) typename vl::function_lambda::FunctionObjectRetriveType<T>::ResultType
}
/***********************************************************************
vl::function_binding::Binding<R(TArgs...)>
***********************************************************************/
namespace function_binding
{
template<typename T>
struct Binding
{
};
template<typename T>
struct CR{typedef const T& Type;};
template<typename T>
struct CR<T&>{typedef T& Type;};
template<typename T>
struct CR<const T>{typedef const T& Type;};
template<typename T>
struct CR<const T&>{typedef const T& Type;};
template<typename R, typename T0, typename ...TArgs>
struct Binding<R(T0, TArgs...)>
{
typedef R FunctionType(T0, TArgs...);
typedef R CurriedType(TArgs...);
typedef T0 FirstParameterType;
class Binder : public Object
{
protected:
Func<FunctionType> target;
T0 firstArgument;
public:
Binder(const Func<FunctionType>& _target, T0 _firstArgument)
:target(_target)
,firstArgument(ForwardValue<T0>(_firstArgument))
{
}
R operator()(TArgs ...args)const
{
return target(firstArgument, args...);
}
};
class Currier : public Object
{
protected:
Func<FunctionType> target;
public:
Currier(const Func<FunctionType>& _target)
:target(_target)
{
}
Func<CurriedType> operator()(T0 firstArgument)const
{
return Binder(target, firstArgument);
}
};
};
}
/// <summary>Currize a function. Currizing means to create a new function whose argument is the first argument of the original function. Calling this function will return another function reference whose arguments is all remain arguments of the original function. Calling the returned function will call the original function.</summary>
/// <typeparam name="T">Type of the function.</typeparam>
/// <returns>The currized function.</returns>
/// <param name="function">The function pointer to currize.</param>
template<typename T>
Func<Func<typename function_binding::Binding<T>::CurriedType>(typename function_binding::Binding<T>::FirstParameterType)>
Curry(T* function)
{
return typename function_binding::Binding<T>::Currier(function);
}
/// <summary>Currize a function. Currizing means to create a new function whose argument is the first argument of the original function. Calling this function will return another function reference whose arguments is all remain arguments of the original function. Calling the returned function will call the original function.</summary>
/// <typeparam name="T">Type of the function.</typeparam>
/// <returns>The currized function.</returns>
/// <param name="function">The function reference to currize.</param>
template<typename T>
Func<Func<typename function_binding::Binding<T>::CurriedType>(typename function_binding::Binding<T>::FirstParameterType)>
Curry(const Func<T>& function)
{
return typename function_binding::Binding<T>::Currier(function);
}
/***********************************************************************
vl::function_combining::Combining<R1(TArgs...), R2(TArgs...), R(R1,R2)>
***********************************************************************/
namespace function_combining
{
template<typename A, typename B, typename C>
class Combining
{
};
template<typename R1, typename R2, typename R, typename ...TArgs>
class Combining<R1(TArgs...), R2(TArgs...), R(R1,R2)> : public Object
{
protected:
Func<R1(TArgs...)> function1;
Func<R2(TArgs...)> function2;
Func<R(R1, R2)> converter;
public:
typedef R1 FirstFunctionType(TArgs...);
typedef R2 SecondFunctionType(TArgs...);
typedef R ConverterFunctionType(R1, R2);
typedef R FinalFunctionType(TArgs...);
Combining(const Func<R1(TArgs...)>& _function1, const Func<R2(TArgs...)>& _function2, const Func<R(R1,R2)>& _converter)
:function1(_function1)
,function2(_function2)
,converter(_converter)
{
}
R operator()(TArgs&& ...args)const
{
return converter(function1(ForwardValue<TArgs>(args)...), function2(ForwardValue<TArgs>(args)...));
}
};
}
/// <summary>Combine two functions with a converter function. The two functions to combine should have the same argument types. The converter function will use the return values of the two function to calculate the final value.</summary>
/// <typeparam name="F1">Type of the first function.</typeparam>
/// <typeparam name="F2">Type of the second function.</typeparam>
/// <typeparam name="C">Type of the converter function.</typeparam>
/// <returns>A new function whose argument list are the same of the two functions to provide. Calling this function will call function1, function2 and converter in order to calculate the final value.</returns>
/// <param name="converter">The converter function.</param>
/// <param name="function1">The first function.</param>
/// <param name="function2">The second function.</param>
template<typename F1, typename F2, typename C>
Func<typename function_combining::Combining<F1, F2, C>::FinalFunctionType>
Combine(Func<C> converter, Func<F1> function1, Func<F2> function2)
{
return function_combining::Combining<F1, F2, C>(function1, function2, converter);
}
/// <summary>Use the converter function to create a combiner, who will receive two function and use <see cref="Combine"/> to create a combined function. This function assumes the result types of the two provided function in the future are the same, and the converter function will not change the result type.</summary>
/// <typeparam name="T">Type of the two functions to combine.</typeparam>
/// <returns>The combiner.</returns>
/// <param name="converter">The converter function.</param>
template<typename T>
Func<Func<T>(Func<T>,Func<T>)> Combiner(const Func<typename Func<T>::ResultType(typename Func<T>::ResultType,typename Func<T>::ResultType)>& converter)
{
typedef typename Func<T>::ResultType R;
return Curry<Func<T>(Func<R(R,R)>,Func<T>,Func<T>)>(Combine)(converter);
}
}
#endif
/***********************************************************************
.\COLLECTIONS\PAIR.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Pair
Classes:
Pair<K, V> : Pair
***********************************************************************/
#ifndef VCZH_COLLECTIONS_PAIR
#define VCZH_COLLECTIONS_PAIR
namespace vl
{
namespace collections
{
/// <summary>A type representing a pair of key and value.</summary>
/// <typeparam name="K">Type of the key.</typeparam>
/// <typeparam name="V">Type of the value.</typeparam>
template<typename K, typename V>
class Pair
{
public:
/// <summary>The key.</summary>
K key;
/// <summary>The value.</summary>
V value;
Pair()
{
}
Pair(const K& _key, const V& _value)
{
key=_key;
value=_value;
}
Pair(const Pair<K, V>& pair)
{
key=pair.key;
value=pair.value;
}
vint CompareTo(const Pair<K, V>& pair)const
{
if(key<pair.key)
{
return -1;
}
else if(key>pair.key)
{
return 1;
}
else if(value<pair.value)
{
return -1;
}
else if(value>pair.value)
{
return 1;
}
else
{
return 0;
}
}
bool operator==(const Pair<K, V>& pair)const
{
return CompareTo(pair)==0;
}
bool operator!=(const Pair<K, V>& pair)const
{
return CompareTo(pair)!=0;
}
bool operator<(const Pair<K, V>& pair)const
{
return CompareTo(pair)<0;
}
bool operator<=(const Pair<K, V>& pair)const
{
return CompareTo(pair)<=0;
}
bool operator>(const Pair<K, V>& pair)const
{
return CompareTo(pair)>0;
}
bool operator>=(const Pair<K, V>& pair)const
{
return CompareTo(pair)>=0;
}
};
}
template<typename K, typename V>
struct POD<collections::Pair<K, V>>
{
static const bool Result=POD<K>::Result && POD<V>::Result;
};
}
#endif
/***********************************************************************
.\COLLECTIONS\INTERFACES.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Interfaces
Interfaces:
IEnumerator<T> : Enumerator interface
IEnumerable<T> : Enumerable object interface
***********************************************************************/
#ifndef VCZH_COLLECTIONS_INTERFACES
#define VCZH_COLLECTIONS_INTERFACES
namespace vl
{
namespace collections
{
/***********************************************************************
Interfaces
***********************************************************************/
/// <summary>Enumerator.</summary>
/// <typeparam name="T">Type of the elements in the enumerator.</typeparam>
template<typename T>
class IEnumerator : public virtual Interface
{
public:
typedef T ElementType;
/// <summary>Copy the enumerator with the current state.</summary>
/// <returns>The copied enumerator.</returns>
virtual IEnumerator<T>* Clone()const=0;
/// <summary>Get the reference to the current element in the enumerator.</summary>
/// <returns>The reference to the current element.</returns>
virtual const T& Current()const=0;
/// <summary>Get the position of the current element in the enumerator.</summary>
/// <returns>The position of the current element.</returns>
virtual vint Index()const=0;
/// <summary>Step forward.</summary>
/// <returns>Returns false if the enumerator reaches the end.</returns>
virtual bool Next()=0;
/// <summary>Reset the enumerator.</summary>
virtual void Reset()=0;
virtual bool Evaluated()const{return false;}
};
/// <summary>Enumerable.</summary>
/// <typeparam name="T">Type of the elements in the enumerator.</typeparam>
template<typename T>
class IEnumerable : public virtual Interface
{
public:
typedef T ElementType;
/// <summary>Create an enumerator. [M:vl.collections.IEnumerator`1.Next] should be called to get the first element.</summary>
/// <returns>The enumerator.</returns>
virtual IEnumerator<T>* CreateEnumerator()const=0;
};
/***********************************************************************
Random Access
***********************************************************************/
namespace randomaccess_internal
{
template<typename T>
struct RandomAccessable
{
static const bool CanRead = false;
static const bool CanResize = false;
};
template<typename T>
struct RandomAccess
{
static vint GetCount(const T& t)
{
return t.Count();
}
static const typename T::ElementType& GetValue(const T& t, vint index)
{
return t.Get(index);
}
static void SetCount(T& t, vint count)
{
t.Resize(count);
}
static void SetValue(T& t, vint index, const typename T::ElementType& value)
{
t.Set(index, value);
}
static void AppendValue(T& t, const typename T::ElementType& value)
{
t.Add(value);
}
};
}
}
}
#endif
/***********************************************************************
.\COLLECTIONS\LIST.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::List
Classes:
ListStore<T,PODType> : Array copy helper functions
ListBase<T,K> : Base class for array
Array<T,K> : Array
List<T,K> : List
SortedList<T,K> : List with item order maintained
***********************************************************************/
#ifndef VCZH_COLLECTIONS_LIST
#define VCZH_COLLECTIONS_LIST
#include <string.h>
#ifdef VCZH_CHECK_MEMORY_LEAKS_NEW
#undef new
#endif
#include <new>
namespace vl
{
namespace collections
{
/***********************************************************************
Memory Management
***********************************************************************/
template<typename T, bool PODType>
class ListStore abstract : public Object
{
};
template<typename T>
class ListStore<T, false> abstract : public Object
{
protected:
static void InitializeItemsByDefault(void* dst, vint count)
{
T* ds = (T*)dst;
for (vint i = 0; i < count; i++)
{
new(&ds[i])T();
}
}
static void InitializeItemsByMove(void* dst, void* src, vint count)
{
T* ds = (T*)dst;
T* ss = (T*)src;
for (vint i = 0; i < count; i++)
{
new(&ds[i])T(MoveValue(ss[i]));
}
}
static void InitializeItemsByCopy(void* dst, void* src, vint count)
{
T* ds = (T*)dst;
T* ss = (T*)src;
for (vint i = 0; i < count; i++)
{
new(&ds[i])T(ss[i]);
}
}
static void MoveItemsInTheSameBuffer(void* dst, void* src, vint count)
{
T* ds = (T*)dst;
T* ss = (T*)src;
if (ds < ss)
{
for (vint i = 0; i < count; i++)
{
ds[i] = MoveValue(ss[i]);
}
}
else if (ds > ss)
{
for (vint i = count - 1; i >= 0; i--)
{
ds[i] = MoveValue(ss[i]);
}
}
}
static void ReleaseItems(void* dst, vint count)
{
T* ds = (T*)dst;
for (vint i = 0; i < count; i++)
{
ds[i].~T();
}
}
static void* AllocateBuffer(vint size)
{
if (size <= 0) return nullptr;
return (void*)malloc(sizeof(T) * size);
}
static void DeallocateBuffer(void* buffer)
{
if (buffer == nullptr)return;
free(buffer);
}
public:
};
template<typename T>
class ListStore<T, true> abstract : public Object
{
protected:
static void InitializeItemsByDefault(void* dst, vint count)
{
}
static void InitializeItemsByMove(void* dst, void* src, vint count)
{
if (count > 0)
{
memcpy(dst, src, sizeof(T) * count);
}
}
static void InitializeItemsByCopy(void* dst, void* src, vint count)
{
if (count > 0)
{
memcpy(dst, src, sizeof(T) * count);
}
}
static void MoveItemsInTheSameBuffer(void* dst, void* src, vint count)
{
if (count > 0)
{
memmove(dst, src, sizeof(T) * count);
}
}
static void ReleaseItems(void* dst, vint count)
{
}
static void* AllocateBuffer(vint size)
{
if (size <= 0) return nullptr;
return (void*)malloc(sizeof(T) * size);
}
static void DeallocateBuffer(void* buffer)
{
if (buffer == nullptr) return;
free(buffer);
}
public:
};
/***********************************************************************
ArrayBase
***********************************************************************/
/// <summary>Base type of all linear container.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
template<typename T>
class ArrayBase abstract : public ListStore<T, POD<T>::Result>, public virtual IEnumerable<T>
{
protected:
class Enumerator : public Object, public virtual IEnumerator<T>
{
private:
const ArrayBase<T>* container;
vint index;
public:
Enumerator(const ArrayBase<T>* _container, vint _index = -1)
{
container = _container;
index = _index;
}
IEnumerator<T>* Clone()const
{
return new Enumerator(container, index);
}
const T& Current()const
{
return container->Get(index);
}
vint Index()const
{
return index;
}
bool Next()
{
index++;
return index >= 0 && index < container->Count();
}
void Reset()
{
index = -1;
}
};
void* buffer = nullptr;
vint count = 0;
static void* AddressOf(void* bufferOfTs, vint index)
{
return (void*)((char*)bufferOfTs + sizeof(T) * index);
}
const T& ItemOf(vint index)const
{
return *(const T*)AddressOf(buffer, index);
}
T& ItemOf(vint index)
{
return *(T*)AddressOf(buffer, index);
}
public:
ArrayBase()
{
}
IEnumerator<T>* CreateEnumerator()const
{
return new Enumerator(this);
}
/// <summary>Get the number of elements in the container.</summary>
/// <returns>The number of elements.</returns>
vint Count()const
{
return count;
}
/// <summary>Get the reference to the specified element.</summary>
/// <returns>The reference to the specified element.</returns>
/// <param name="index">The index of the element.</param>
const T& Get(vint index)const
{
CHECK_ERROR(index >= 0 && index < this->count, L"ArrayBase<T, K>::Get(vint)#Argument index not in range.");
return ItemOf(index);
}
/// <summary>Get the reference to the specified element.</summary>
/// <returns>The reference to the specified element.</returns>
/// <param name="index">The index of the element.</param>
const T& operator[](vint index)const
{
CHECK_ERROR(index >= 0 && index < this->count, L"ArrayBase<T, K>::operator[](vint)#Argument index not in range.");
return ItemOf(index);
}
};
/***********************************************************************
Array
***********************************************************************/
/// <summary>Array.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements.</typeparam>
template<typename T, typename K = typename KeyType<T>::Type>
class Array : public ArrayBase<T>
{
public:
/// <summary>Create an array.</summary>
/// <param name="size">The size of the array.</param>
Array(vint size = 0)
{
this->buffer = this->AllocateBuffer(size);
this->InitializeItemsByDefault(this->buffer, size);
this->count = size;
}
/// <summary>Create an array.</summary>
/// <param name="_buffer">Pointer to an array to copy.</param>
/// <param name="size">The size of the array.</param>
Array(const T* _buffer, vint size)
{
this->buffer = this->AllocateBuffer(size);
this->InitializeItemsByCopy(this->buffer, (void*)_buffer, size);
this->count = size;
}
~Array()
{
this->ReleaseItems(this->buffer, this->count);
this->DeallocateBuffer(this->buffer);
}
/// <summary>Test does the array contain an item or not.</summary>
/// <returns>Returns true if the array contains the specified item.</returns>
/// <param name="item">The item to test.</param>
bool Contains(const K& item)const
{
return IndexOf(item) != -1;
}
/// <summary>Get the position of an item in this array.</summary>
/// <returns>Returns the position. Returns -1 if not exists</returns>
/// <param name="item">The item to find.</param>
vint IndexOf(const K& item)const
{
for (vint i = 0; i < this->count; i++)
{
if (this->ItemOf(i) == item)
{
return i;
}
}
return -1;
}
/// <summary>Replace an item.</summary>
/// <param name="index">The position of the item.</param>
/// <param name="item">The new item to put into the array.</param>
void Set(vint index, const T& item)
{
CHECK_ERROR(index >= 0 && index < this->count, L"Array<T, K>::Set(vint)#Argument index not in range.");
this->ItemOf(index) = item;
}
/// <summary>Get the reference to the specified element.</summary>
/// <returns>The reference to the specified element.</returns>
/// <param name="index">The index of the element.</param>
using ArrayBase<T>::operator[];
T& operator[](vint index)
{
CHECK_ERROR(index >= 0 && index < this->count, L"Array<T, K>::operator[](vint)#Argument index not in range.");
return this->ItemOf(index);
}
/// <summary>Change the size of the array.</summary>
/// <param name="size">The new size of the array.</param>
void Resize(vint size)
{
void* newBuffer = this->AllocateBuffer(size);
if (size < this->count)
{
this->InitializeItemsByMove(this->AddressOf(newBuffer, 0), this->AddressOf(this->buffer, 0), size);
}
else
{
this->InitializeItemsByMove(this->AddressOf(newBuffer, 0), this->AddressOf(this->buffer, 0), this->count);
this->InitializeItemsByDefault(this->AddressOf(newBuffer, this->count), size - this->count);
}
this->ReleaseItems(this->buffer, this->count);
this->DeallocateBuffer(this->buffer);
this->buffer = newBuffer;
this->count = size;
}
};
/***********************************************************************
ListBase
***********************************************************************/
/// <summary>Base type for a list container.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements.</typeparam>
template<typename T, typename K = typename KeyType<T>::Type>
class ListBase abstract : public ArrayBase<T>
{
protected:
vint capacity = 0;
bool lessMemoryMode = false;
vint CalculateCapacity(vint expected)
{
vint result = capacity;
while (result < expected)
{
result = result * 5 / 4 + 1;
}
return result;
}
void MakeRoom(vint index, vint _count, bool& uninitialized)
{
vint newCount = this->count + _count;
if (newCount > capacity)
{
vint newCapacity = CalculateCapacity(newCount);
void* newBuffer = this->AllocateBuffer(newCapacity);
this->InitializeItemsByMove(this->AddressOf(newBuffer, 0), this->AddressOf(this->buffer, 0), index);
this->InitializeItemsByMove(this->AddressOf(newBuffer, index + _count), this->AddressOf(this->buffer, index), this->count - index);
this->ReleaseItems(this->buffer, this->count);
this->DeallocateBuffer(this->buffer);
this->capacity = newCapacity;
this->buffer = newBuffer;
uninitialized = true;
}
else if (index >= this->count)
{
uninitialized = true;
}
else if (this->count - index < _count)
{
this->InitializeItemsByMove(this->AddressOf(this->buffer, index + _count), this->AddressOf(this->buffer, index), this->count - index);
this->ReleaseItems(this->AddressOf(this->buffer, index), _count - (this->count - index));
uninitialized = true;
}
else
{
this->InitializeItemsByMove(this->AddressOf(this->buffer, this->count), this->AddressOf(this->buffer, this->count - _count), _count);
this->MoveItemsInTheSameBuffer(this->AddressOf(this->buffer, index + _count), this->AddressOf(this->buffer, index), this->count - index - _count);
uninitialized = false;
}
this->count = newCount;
}
void ReleaseUnnecessaryBuffer(vint previousCount)
{
if (this->buffer && this->count < previousCount)
{
this->ReleaseItems(this->AddressOf(this->buffer, this->count), previousCount - this->count);
}
if (this->lessMemoryMode && this->count <= this->capacity / 2)
{
vint newCapacity = capacity * 5 / 8;
if (this->count < newCapacity)
{
void* newBuffer = this->AllocateBuffer(newCapacity);
this->InitializeItemsByMove(this->AddressOf(newBuffer, 0), this->AddressOf(this->buffer, 0), this->count);
this->ReleaseItems(this->buffer, this->count);
this->DeallocateBuffer(this->buffer);
this->capacity = newCapacity;
this->buffer = newBuffer;
}
}
}
public:
ListBase()
{
}
~ListBase()
{
this->ReleaseItems(this->buffer, this->count);
this->DeallocateBuffer(this->buffer);
}
/// <summary>Set a preference of using memory.</summary>
/// <param name="mode">Set to true (by default) to let the container efficiently reduce memory usage when necessary.</param>
void SetLessMemoryMode(bool mode)
{
this->lessMemoryMode = mode;
}
/// <summary>Remove an element.</summary>
/// <returns>Returns true if the element is removed.</returns>
/// <param name="index">The index of the element to remove.</param>
bool RemoveAt(vint index)
{
vint previousCount = this->count;
CHECK_ERROR(index >= 0 && index < this->count, L"ListBase<T, K>::RemoveAt(vint)#Argument index not in range.");
this->MoveItemsInTheSameBuffer(this->AddressOf(this->buffer, index), this->AddressOf(this->buffer, index + 1), this->count - index - 1);
this->count--;
ReleaseUnnecessaryBuffer(previousCount);
return true;
}
/// <summary>Remove elements.</summary>
/// <returns>Returns true if the element is removed.</returns>
/// <param name="index">The index of the first element to remove.</param>
/// <param name="_count">The number of elements to remove.</param>
bool RemoveRange(vint index, vint _count)
{
vint previousCount = this->count;
CHECK_ERROR(index >= 0 && index <= this->count, L"ListBase<T, K>::RemoveRange(vint, vint)#Argument index not in range.");
CHECK_ERROR(index + _count >= 0 && index + _count <= this->count, L"ListBase<T,K>::RemoveRange(vint, vint)#Argument _count not in range.");
this->MoveItemsInTheSameBuffer(this->AddressOf(this->buffer, index), this->AddressOf(this->buffer, index + _count), this->count - index - _count);
this->count -= _count;
ReleaseUnnecessaryBuffer(previousCount);
return true;
}
/// <summary>Remove all elements.</summary>
/// <returns>Returns true if all elements are removed.</returns>
bool Clear()
{
vint previousCount = this->count;
this->count = 0;
if (lessMemoryMode)
{
this->capacity = 0;
this->ReleaseItems(this->buffer, this->count);
this->DeallocateBuffer(this->buffer);
this->buffer = nullptr;
}
else
{
ReleaseUnnecessaryBuffer(previousCount);
}
return true;
}
};
/***********************************************************************
List
***********************************************************************/
/// <summary>List.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements.</typeparam>
template<typename T, typename K = typename KeyType<T>::Type>
class List : public ListBase<T, K>
{
public:
/// <summary>Create a list.</summary>
List()
{
}
/// <summary>Test does the list contain an item or not.</summary>
/// <returns>Returns true if the list contains the specified item.</returns>
/// <param name="item">The item to test.</param>
bool Contains(const K& item)const
{
return IndexOf(item) != -1;
}
/// <summary>Get the position of an item in this list.</summary>
/// <returns>Returns the position. Returns -1 if not exists</returns>
/// <param name="item">The item to find.</param>
vint IndexOf(const K& item)const
{
for (vint i = 0; i < this->count; i++)
{
if (this->ItemOf(i) == item)
{
return i;
}
}
return -1;
}
/// <summary>Add an item at the end of the list.</summary>
/// <returns>The index of the added item.</returns>
/// <param name="item">The item to add.</param>
vint Add(const T& item)
{
return Insert(this->count, item);
}
/// <summary>Add an item at the specified position.</summary>
/// <returns>The index of the added item.</returns>
/// <param name="index">The position of the item to add.</param>
/// <param name="item">The item to add.</param>
vint Insert(vint index, const T& item)
{
CHECK_ERROR(index >= 0 && index <= this->count, L"List<T, K>::Insert(vint, const T&)#Argument index not in range.");
bool uninitialized = false;
this->MakeRoom(index, 1, uninitialized);
if (uninitialized)
{
new(&this->ItemOf(index))T(item);
}
else
{
this->ItemOf(index) = item;
}
return index;
}
/// <summary>Remove an item.</summary>
/// <returns>Returns true if the item is removed.</returns>
/// <param name="item">The item to remove.</param>
bool Remove(const K& item)
{
vint index = IndexOf(item);
if (index >= 0 && index < this->count)
{
this->RemoveAt(index);
return true;
}
else
{
return false;
}
}
/// <summary>Replace an item.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="index">The position of the item.</param>
/// <param name="item">The new item to put into the array.</param>
bool Set(vint index, const T& item)
{
CHECK_ERROR(index >= 0 && index < this->count, L"List<T, K>::Set(vint)#Argument index not in range.");
this->ItemOf(index) = item;
return true;
}
/// <summary>Get the reference to the specified element.</summary>
/// <returns>The reference to the specified element.</returns>
/// <param name="index">The index of the element.</param>
using ListBase<T, K>::operator[];
T& operator[](vint index)
{
CHECK_ERROR(index >= 0 && index < this->count, L"List<T, K>::operator[](vint)#Argument index not in range.");
return this->ItemOf(index);
}
};
/***********************************************************************
SortedList
***********************************************************************/
/// <summary>List that keeps everything in order.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements.</typeparam>
template<typename T, typename K = typename KeyType<T>::Type>
class SortedList : public ListBase<T, K>
{
protected:
/// <summary>Get the position of an item in this list.</summary>
/// <typeparam name="Key">Type of the item to find.</typeparam>
/// <returns>Returns the position. Returns -1 if not exists</returns>
/// <param name="item">The item to find.</param>
/// <param name="index">Returns the last index.</param>
template<typename Key>
vint IndexOfInternal(const Key& item, vint& index)const
{
vint start = 0;
vint end = this->count - 1;
index = -1;
while (start <= end)
{
index = start + (end - start) / 2;
if (this->ItemOf(index) == item)
{
return index;
}
else if (this->ItemOf(index) > item)
{
end = index - 1;
}
else
{
start = index + 1;
}
}
return -1;
}
vint Insert(vint index, const T& item)
{
bool uninitialized = false;
this->MakeRoom(index, 1, uninitialized);
if (uninitialized)
{
new(&this->ItemOf(index))T(item);
}
else
{
this->ItemOf(index) = item;
}
return index;
}
public:
/// <summary>Create a list.</summary>
SortedList()
{
}
/// <summary>Test does the list contain an item or not.</summary>
/// <returns>Returns true if the list contains the specified item.</returns>
/// <param name="item">The item to test.</param>
bool Contains(const K& item)const
{
return IndexOf(item) != -1;
}
/// <summary>Get the position of an item in this list.</summary>
/// <returns>Returns the position. Returns -1 if not exists</returns>
/// <param name="item">The item to find.</param>
vint IndexOf(const K& item)const
{
vint outputIndex = -1;
return IndexOfInternal<K>(item, outputIndex);
}
/// <summary>Add an item at a correct position to keep everying in order.</summary>
/// <returns>The index of the added item.</returns>
/// <param name="item">The item to add.</param>
vint Add(const T& item)
{
if (ArrayBase<T>::count == 0)
{
return Insert(0, item);
}
else
{
vint outputIndex = -1;
IndexOfInternal<T>(item, outputIndex);
CHECK_ERROR(outputIndex >= 0 && outputIndex < this->count, L"SortedList<T, K>::Add(const T&)#Internal error, index not in range.");
if (this->ItemOf(outputIndex) < item)
{
outputIndex++;
}
return Insert(outputIndex, item);
}
}
/// <summary>Remove an item.</summary>
/// <returns>Returns true if the item is removed.</returns>
/// <param name="item">The item to remove.</param>
bool Remove(const K& item)
{
vint index = IndexOf(item);
if (index >= 0 && index < ArrayBase<T>::count)
{
this->RemoveAt(index);
return true;
}
else
{
return false;
}
}
};
/***********************************************************************
Special Containers
***********************************************************************/
template<typename T>
class PushOnlyAllocator : public Object, private NotCopyable
{
protected:
vint blockSize;
vint allocatedSize;
List<T*> blocks;
public:
PushOnlyAllocator(vint _blockSize = 65536)
:blockSize(_blockSize)
, allocatedSize(0)
{
}
~PushOnlyAllocator()
{
for (vint i = 0; i < blocks.Count(); i++)
{
delete[] blocks[i];
}
}
T* Get(vint index)
{
if (index >= allocatedSize)
{
return 0;
}
vint row = index / blockSize;
vint column = index % blockSize;
return &blocks[row][column];
}
T* Create()
{
if (allocatedSize == blocks.Count()*blockSize)
{
blocks.Add(new T[blockSize]);
}
vint index = allocatedSize++;
return Get(index);
}
};
namespace bom_helper
{
struct TreeNode
{
TreeNode* nodes[4];
};
template<vint Index = 4>
struct Accessor
{
static __forceinline void* Get(TreeNode* root, vuint8_t index)
{
if (!root)
{
return 0;
}
vint fragmentIndex = (index >> (2 * (Index - 1))) % 4;
TreeNode* fragmentRoot = root->nodes[fragmentIndex];
return fragmentRoot ? Accessor<Index - 1>::Get(fragmentRoot, index) : 0;
}
static __forceinline void Set(TreeNode*& root, vuint8_t index, void* value, PushOnlyAllocator<TreeNode>& allocator)
{
if (!root)
{
root = allocator.Create();
memset(root->nodes, 0, sizeof(root->nodes));
}
vint fragmentIndex = (index >> (2 * (Index - 1))) % 4;
TreeNode*& fragmentRoot = root->nodes[fragmentIndex];
Accessor<Index - 1>::Set(fragmentRoot, index, value, allocator);
}
};
template<>
struct Accessor<0>
{
static __forceinline void* Get(TreeNode* root, vuint8_t index)
{
return (void*)root;
}
static __forceinline void Set(TreeNode*& root, vuint8_t index, void* value, PushOnlyAllocator<TreeNode>& allocator)
{
((void*&)root) = value;
}
};
}
template<typename T>
class ByteObjectMap : public Object, private NotCopyable
{
public:
typedef PushOnlyAllocator<bom_helper::TreeNode> Allocator;
protected:
bom_helper::TreeNode* root;
public:
ByteObjectMap()
:root(0)
{
}
~ByteObjectMap()
{
}
T* Get(vuint8_t index)
{
return (T*)bom_helper::Accessor<>::Get(root, index);
}
void Set(vuint8_t index, T* value, Allocator& allocator)
{
bom_helper::Accessor<>::Set(root, index, value, allocator);
}
};
/***********************************************************************
Random Access
***********************************************************************/
namespace randomaccess_internal
{
template<typename T, typename K>
struct RandomAccessable<Array<T, K>>
{
static const bool CanRead = true;
static const bool CanResize = true;
};
template<typename T, typename K>
struct RandomAccessable<List<T, K>>
{
static const bool CanRead = true;
static const bool CanResize = false;
};
template<typename T, typename K>
struct RandomAccessable<SortedList<T, K>>
{
static const bool CanRead = true;
static const bool CanResize = false;
};
}
}
}
#ifdef VCZH_CHECK_MEMORY_LEAKS_NEW
#define new VCZH_CHECK_MEMORY_LEAKS_NEW
#endif
#endif
/***********************************************************************
.\COLLECTIONS\DICTIONARY.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Dictionary
Classes:
Dictionary<KT, VT, KK, VK> : One to one mapping
Group<KT, VT, KK, VK> : One to many mapping
***********************************************************************/
#ifndef VCZH_COLLECTIONS_DICTIONARY
#define VCZH_COLLECTIONS_DICTIONARY
namespace vl
{
namespace collections
{
/// <summary>Dictionary.</summary>
/// <typeparam name="KT">Type of keys.</typeparam>
/// <typeparam name="VT">Type of values.</typeparam>
/// <typeparam name="KK">Type of the key type of keys.</typeparam>
/// <typeparam name="VK">Type of the key type of values.</typeparam>
template<
typename KT,
typename VT,
typename KK=typename KeyType<KT>::Type,
typename VK=typename KeyType<VT>::Type
>
class Dictionary : public Object, public virtual IEnumerable<Pair<KT, VT>>
{
public:
typedef SortedList<KT, KK> KeyContainer;
typedef List<VT, VK> ValueContainer;
protected:
class Enumerator : public Object, public virtual IEnumerator<Pair<KT, VT>>
{
private:
const Dictionary<KT, VT, KK, VK>* container;
vint index;
Pair<KT, VT> current;
void UpdateCurrent()
{
if(index<container->Count())
{
current.key=container->Keys().Get(index);
current.value=container->Values().Get(index);
}
}
public:
Enumerator(const Dictionary<KT, VT, KK, VK>* _container, vint _index=-1)
{
container=_container;
index=_index;
}
IEnumerator<Pair<KT, VT>>* Clone()const
{
return new Enumerator(container, index);
}
const Pair<KT, VT>& Current()const
{
return current;
}
vint Index()const
{
return index;
}
bool Next()
{
index++;
UpdateCurrent();
return index>=0 && index<container->Count();
}
void Reset()
{
index=-1;
UpdateCurrent();
}
};
KeyContainer keys;
ValueContainer values;
public:
/// <summary>Create a dictionary.</summary>
Dictionary()
{
}
IEnumerator<Pair<KT, VT>>* CreateEnumerator()const
{
return new Enumerator(this);
}
/// <summary>Set a preference of using memory.</summary>
/// <param name="mode">Set to true (by default) to let the container efficiently reduce memory usage when necessary.</param>
void SetLessMemoryMode(bool mode)
{
keys.SetLessMemoryMode(mode);
values.SetLessMemoryMode(mode);
}
/// <summary>Get all keys.</summary>
/// <returns>All keys.</returns>
const KeyContainer& Keys()const
{
return keys;
}
/// <summary>Get all values.</summary>
/// <returns>All values.</returns>
const ValueContainer& Values()const
{
return values;
}
/// <summary>Get the number of keys.</summary>
/// <returns>The number of keys.</returns>
vint Count()const
{
return keys.Count();
}
/// <summary>Get the reference to the value associated with a key.</summary>
/// <returns>The reference to the value.</returns>
/// <param name="key">The key to find.</param>
const VT& Get(const KK& key)const
{
return values.Get(keys.IndexOf(key));
}
/// <summary>Get the reference to the value associated with a key.</summary>
/// <returns>The reference to the value.</returns>
/// <param name="key">The key to find.</param>
const VT& operator[](const KK& key)const
{
return values.Get(keys.IndexOf(key));
}
/// <summary>Replace the value associated with a key.</summary>
/// <returns>Returns true if the value is replaced.</returns>
/// <param name="key">The key to find.</param>
/// <param name="value">The key to replace.</param>
bool Set(const KT& key, const VT& value)
{
vint index=keys.IndexOf(KeyType<KT>::GetKeyValue(key));
if(index==-1)
{
index=keys.Add(key);
values.Insert(index, value);
}
else
{
values[index]=value;
}
return true;
}
/// <summary>Add a key with an associated value. Exception will raise if the key already exists.</summary>
/// <returns>Returns true if the pair is added.</returns>
/// <param name="value">The pair of key and value.</param>
bool Add(const Pair<KT, VT>& value)
{
return Add(value.key, value.value);
}
/// <summary>Add a key with an associated value. Exception will raise if the key already exists.</summary>
/// <returns>Returns true if the pair is added.</returns>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
bool Add(const KT& key, const VT& value)
{
CHECK_ERROR(!keys.Contains(KeyType<KT>::GetKeyValue(key)), L"Dictionary<KT, KK, ValueContainer, VT, VK>::Add(const KT&, const VT&)#Key already exists.");
vint index=keys.Add(key);
values.Insert(index, value);
return true;
}
/// <summary>Remove a key with the associated value.</summary>
/// <returns>Returns true if the key and the value is removed.</returns>
/// <param name="key">The key.</param>
bool Remove(const KK& key)
{
vint index=keys.IndexOf(key);
if(index!=-1)
{
keys.RemoveAt(index);
values.RemoveAt(index);
return true;
}
else
{
return false;
}
}
/// <summary>Remove everything.</summary>
/// <returns>Returns true if all keys and values are removed.</returns>
bool Clear()
{
keys.Clear();
values.Clear();
return true;
}
};
/// <summary>Group, which is similar to an dictionary, but a group can associate multiple values with a key.</summary>
/// <typeparam name="KT">Type of keys.</typeparam>
/// <typeparam name="VT">Type of values.</typeparam>
/// <typeparam name="KK">Type of the key type of keys.</typeparam>
/// <typeparam name="VK">Type of the key type of values.</typeparam>
template<
typename KT,
typename VT,
typename KK=typename KeyType<KT>::Type,
typename VK=typename KeyType<VT>::Type
>
class Group : public Object, public virtual IEnumerable<Pair<KT, VT>>
{
typedef SortedList<KT, KK> KeyContainer;
typedef List<VT, VK> ValueContainer;
protected:
class Enumerator : public Object, public virtual IEnumerator<Pair<KT, VT>>
{
private:
const Group<KT, VT, KK, VK>* container;
vint keyIndex;
vint valueIndex;
Pair<KT, VT> current;
void UpdateCurrent()
{
if(keyIndex<container->Count())
{
const ValueContainer& values=container->GetByIndex(keyIndex);
if(valueIndex<values.Count())
{
current.key=container->Keys().Get(keyIndex);
current.value=values.Get(valueIndex);
}
}
}
public:
Enumerator(const Group<KT, VT, KK, VK>* _container, vint _keyIndex=-1, vint _valueIndex=-1)
{
container=_container;
keyIndex=_keyIndex;
valueIndex=_valueIndex;
}
IEnumerator<Pair<KT, VT>>* Clone()const
{
return new Enumerator(container, keyIndex, valueIndex);
}
const Pair<KT, VT>& Current()const
{
return current;
}
vint Index()const
{
if(0<=keyIndex && keyIndex<container->Count())
{
vint index=0;
for(vint i=0;i<keyIndex;i++)
{
index+=container->GetByIndex(i).Count();
}
return index+valueIndex;
}
else
{
return -1;
}
}
bool Next()
{
if(keyIndex==-1)
{
keyIndex=0;
}
while(keyIndex<container->Count())
{
valueIndex++;
const ValueContainer& values=container->GetByIndex(keyIndex);
if(valueIndex<values.Count())
{
UpdateCurrent();
return true;
}
else
{
keyIndex++;
valueIndex=-1;
}
}
return false;
}
void Reset()
{
keyIndex=-1;
valueIndex=-1;
UpdateCurrent();
}
};
KeyContainer keys;
List<ValueContainer*> values;
public:
Group()
{
}
~Group()
{
Clear();
}
IEnumerator<Pair<KT, VT>>* CreateEnumerator()const
{
return new Enumerator(this);
}
/// <summary>Get all keys.</summary>
/// <returns>All keys.</returns>
const KeyContainer& Keys()const
{
return keys;
}
/// <summary>Get the number of keys.</summary>
/// <returns>The number of keys.</returns>
vint Count()const
{
return keys.Count();
}
/// <summary>Get all values associated with a key.</summary>
/// <returns>All values.</returns>
/// <param name="key">The key to find.</param>
const ValueContainer& Get(const KK& key)const
{
return *values.Get(keys.IndexOf(key));
}
/// <summary>Get all values associated with a key.</summary>
/// <returns>All values.</returns>
/// <param name="index">The position of a the key.</param>
const ValueContainer& GetByIndex(vint index)const
{
return *values.Get(index);
}
/// <summary>Get all values associated with a key.</summary>
/// <returns>All values.</returns>
/// <param name="key">The key to find.</param>
const ValueContainer& operator[](const KK& key)const
{
return *values.Get(keys.IndexOf(key));
}
/// <summary>Test if a key exists in the group or not.</summary>
/// <returns>Returns true if the key exists.</returns>
/// <param name="key">The key to find.</param>
bool Contains(const KK& key)const
{
return keys.Contains(key);
}
/// <summary>Test if a key exists with an associated value in the group or not.</summary>
/// <returns>Returns true if the key exists with an associated value.</returns>
/// <param name="key">The key to find.</param>
/// <param name="value">The value to find.</param>
bool Contains(const KK& key, const VK& value)const
{
vint index=keys.IndexOf(key);
if(index!=-1)
{
return values.Get(index)->Contains(value);
}
else
{
return false;
}
}
/// <summary>Add a key with an associated value. If the key already exists, the value will be associated with the key with other values.</summary>
/// <returns>Returns true if the pair is added.</returns>
/// <param name="value">The pair of key and value.</param>
bool Add(const Pair<KT, VT>& value)
{
return Add(value.key, value.value);
}
/// <summary>Add a key with an associated value. If the key already exists, the value will be associated with the key with other values.</summary>
/// <returns>Returns true if the pair is added.</returns>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
bool Add(const KT& key, const VT& value)
{
ValueContainer* target=0;
vint index=keys.IndexOf(KeyType<KT>::GetKeyValue(key));
if(index==-1)
{
target=new ValueContainer;
values.Insert(keys.Add(key), target);
}
else
{
target=values[index];
}
target->Add(value);
return true;
}
/// <summary>Remove a key with all associated values.</summary>
/// <returns>Returns true if the key and all associated values are removed.</returns>
/// <param name="key">The key.</param>
bool Remove(const KK& key)
{
vint index=keys.IndexOf(key);
if(index!=-1)
{
keys.RemoveAt(index);
List<VT, VK>* target=values[index];
values.RemoveAt(index);
delete target;
return true;
}
else
{
return false;
}
}
/// <summary>Remove a key with the associated values.</summary>
/// <returns>Returns true if the key and the associated values are removed. If there are multiple values associated with the key, only the value will be removed.</returns>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
bool Remove(const KK& key, const VK& value)
{
vint index=keys.IndexOf(key);
if(index!=-1)
{
List<VT, VK>* target=values[index];
target->Remove(value);
if(target->Count()==0)
{
keys.RemoveAt(index);
values.RemoveAt(index);
delete target;
}
return true;
}
else
{
return false;
}
}
/// <summary>Remove everything.</summary>
/// <returns>Returns true if all keys and values are removed.</returns>
bool Clear()
{
for(vint i=0;i<values.Count();i++)
{
delete values[i];
}
keys.Clear();
values.Clear();
return true;
}
};
/***********************************************************************
GroupInnerJoin
***********************************************************************/
template<
typename TKey,
typename TValueFirst,
typename TValueSecond,
typename TDiscardFirst, // TKey * [TValueFirst] -> void
typename TDiscardSecond, // TKey * [TValueSecond] -> void
typename TAccept // TKey * [TValueFirst] * [TValueSecond] -> void
>
void GroupInnerJoin(
const Group<TKey, TValueFirst>& first,
const Group<TKey, TValueSecond>& second,
const TDiscardFirst& discardFirst,
const TDiscardSecond& discardSecond,
const TAccept& accept
)
{
vint firstIndex = 0;
vint secondIndex = 0;
vint firstCount = first.Keys().Count();
vint secondCount = second.Keys().Count();
while (true)
{
if (firstIndex < firstCount)
{
auto firstKey = first.Keys()[firstIndex];
const List<TValueFirst>& firstValues = first.GetByIndex(firstIndex);
if (secondIndex < secondCount)
{
auto secondKey = second.Keys()[secondIndex];
const List<TValueSecond>& secondValues = second.GetByIndex(secondIndex);
if (firstKey < secondKey)
{
discardFirst(firstKey, firstValues);
firstIndex++;
}
else if (firstKey > secondKey)
{
discardSecond(secondKey, secondValues);
secondIndex++;
}
else
{
accept(firstKey, firstValues, secondValues);
firstIndex++;
secondIndex++;
}
}
else
{
discardFirst(firstKey, firstValues);
firstIndex++;
}
}
else
{
if (secondIndex < secondCount)
{
auto secondKey = second.Keys()[secondIndex];
const List<TValueSecond>& secondValues = second.GetByIndex(secondIndex);
discardSecond(secondKey, secondValues);
secondIndex++;
}
else
{
break;
}
}
}
}
/***********************************************************************
Random Access
***********************************************************************/
namespace randomaccess_internal
{
template<typename KT, typename VT, typename KK, typename VK>
struct RandomAccessable<Dictionary<KT, VT, KK, VK>>
{
static const bool CanRead = true;
static const bool CanResize = false;
};
template<typename KT, typename VT, typename KK, typename VK>
struct RandomAccess<Dictionary<KT, VT, KK, VK>>
{
static vint GetCount(const Dictionary<KT, VT, KK, VK>& t)
{
return t.Count();
}
static Pair<KT, VT> GetValue(const Dictionary<KT, VT, KK, VK>& t, vint index)
{
return Pair<KT, VT>(t.Keys().Get(index), t.Values().Get(index));
}
static void AppendValue(Dictionary<KT, VT, KK, VK>& t, const Pair<KT, VT>& value)
{
t.Set(value.key, value.value);
}
};
}
}
}
#endif
/***********************************************************************
.\STREAM\INTERFACES.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::Interfaces
Interfaces:
IStream : Stream
***********************************************************************/
#ifndef VCZH_STREAM_INTERFACES
#define VCZH_STREAM_INTERFACES
namespace vl
{
namespace stream
{
/// <summary>
/// Interface for streams. Stream functions are grouped into 5 categories:
/// 1) Feature testing functions.
/// 2) Read functions, available only if [M:vl.stream.IStream.CanRead] returns true.
/// 3) Peek functions, available only if [M:vl.stream.IStream.CanPeek] returns true.
/// 4) Write functions, available only if [M:vl.stream.IStream.CanWrite] returns true.
/// 5) Seek functions, available only if [M:vl.stream.IStream.CanSeek] returns true.
/// 6) Size functions, available only if [M:vl.stream.IStream.IsLimited] returns true. But there are still some streams knows that the content is limited, but the size is unknown. In this case, [M:vl.stream.IStream.Size] will return -1.
/// </summary>
class IStream : public virtual Interface
{
public:
/// <summary>Test if the stream is readable.</summary>
/// <returns>Returns true if the stream is readable.</returns>
virtual bool CanRead()const=0;
/// <summary>Test if the stream is writable.</summary>
/// <returns>Returns true if the stream is writable.</returns>
virtual bool CanWrite()const=0;
/// <summary>Test if the stream is seekable.</summary>
/// <returns>Returns true if the stream is seekable.</returns>
virtual bool CanSeek()const=0;
/// <summary>Test if the stream is peekable.</summary>
/// <returns>Returns true if the stream is peekable.</returns>
virtual bool CanPeek()const=0;
/// <summary>Test if the content of the stream is limited. A writable stream can also be limited, it means that you can only write a limited content to the stream.</summary>
/// <returns>Returns true if the content of the stream is limited.</returns>
virtual bool IsLimited()const=0;
/// <summary>Test if the stream is available. For example, if you create a readable [T:vl.stream.FileStream] giving a wrong file name, it will be unavailable.</summary>
/// <returns>Returns true if the stream is available.</returns>
virtual bool IsAvailable()const=0;
/// <summary>Close the stream.</summary>
virtual void Close()=0;
/// <summary>Get the current position in the stream.</summary>
/// <returns>The position in the stream. Returns -1 if the stream is not available.</returns>
virtual pos_t Position()const=0;
/// <summary>Get the size of the content..</summary>
/// <returns>The size of the content. Returns -1 if the size is unknown or the stream is not available.</returns>
virtual pos_t Size()const=0;
/// <summary>Step forward or backward from the current position. Will throw exception if the stream is not seekable or not available.</summary>
/// <param name="_size">The length of the step.</param>
virtual void Seek(pos_t _size)=0;
/// <summary>Step fowward from the beginning. Will throw exception if the stream is not seekable or not available.</summary>
/// <param name="_size">The length of the step.</param>
virtual void SeekFromBegin(pos_t _size)=0;
/// <summary>Step backward from the end. Will throw exception if the stream is not seekable or not available.</summary>
/// <param name="_size">The length of the step.</param>
virtual void SeekFromEnd(pos_t _size)=0;
/// <summary>Read from the current position and step forward. Will throw exception if the stream is not readable or not available.</summary>
/// <returns>Returns the actual size of the content that is read. Returns 0 indicates that the stream reaches the end if the stream is limited.</returns>
/// <param name="_buffer">A buffer to store the content.</param>
/// <param name="_size">The size of the content that is expected to read.</param>
virtual vint Read(void* _buffer, vint _size)=0;
/// <summary>Write to the current position and step forward. Will throw exception if the stream is not writable or not available.</summary>
/// <returns>Returns the actual size of the content that is written. Returns 0 indicates that the stream reaches the end if the stream is limited.</returns>
/// <param name="_buffer">A buffer storing the content to write.</param>
/// <param name="_size">The size of the content that is expected to write.</param>
virtual vint Write(void* _buffer, vint _size)=0;
/// <summary>Read from the current position but not step forward. Will throw exception if the stream is not peekable or not available.</summary>
/// <returns>Returns the actual size of the content that is read. Returns 0 indicates that the stream reaches the end if the stream is limited.</returns>
/// <param name="_buffer">A buffer to store the content.</param>
/// <param name="_size">The size of the content that is expected to peek.</param>
virtual vint Peek(void* _buffer, vint _size)=0;
};
/// <summary>Encoder interface. This interface defines a writable transformation from one stream to another stream. You can create a [T:vl.stream.EncoderStream] after you have an encoder.</summary>
class IEncoder : public Interface
{
public:
/// <summary>Set a target writable stream. The <see cref="Write"/> function will transform the content and write to this tream.</summary>
/// <param name="_stream">The target writable stream.</param>
virtual void Setup(IStream* _stream)=0;
/// <summary>Stop the transformation, ensuring all written content is transformed to the target stream.</summary>
virtual void Close()=0;
/// <summary>Transform content and write to the target stream. This function may cache something to increase performance, so it cannot expect that all transformed content will be written to the target stream immediately.</summary>
/// <returns>Returns the actual size of the content before transforming that is written. The content is treated as being written even it is cached and not actually write to the target stream.</returns>
/// <param name="_buffer">A buffer storing the content to write.</param>
/// <param name="_size">The size of the content that is expected to write.</param>
virtual vint Write(void* _buffer, vint _size)=0;
};
/// <summary>Decoder interface. This interface defines a readable transformation from one stream to another stream. You can create a [T:vl.stream.DecoderStream] after you have an decoder.</summary>
class IDecoder : public Interface
{
public:
/// <summary>Set a target readable stream. The <see cref="Read"/> function will read from this tream and transform the content.</summary>
/// <param name="_stream">The target readable stream.</param>
virtual void Setup(IStream* _stream)=0;
/// <summary>Stop the transformation.</summary>
virtual void Close()=0;
/// <summary>Read from the target stream and transform the content.</summary>
/// <returns>Returns the actual size of the content after transforming that is read.</returns>
/// <param name="_buffer">A buffer to store the content.</param>
/// <param name="_size">The size of the content that is expected to read.</param>
virtual vint Read(void* _buffer, vint _size)=0;
};
}
}
#endif
/***********************************************************************
.\STREAM\MEMORYSTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::MemoryStream
Interfaces:
MemoryStream : Memory stream
***********************************************************************/
#ifndef VCZH_STREAM_MEMORYSTREAM
#define VCZH_STREAM_MEMORYSTREAM
namespace vl
{
namespace stream
{
/// <summary>A readable, writable, seekable and peekable stream that stores everything in memory.</summary>
class MemoryStream : public Object, public virtual IStream
{
protected:
vint block;
char* buffer;
vint size;
vint position;
vint capacity;
void PrepareSpace(vint totalSpace);
public:
/// <summary>Create a stream.</summary>
/// <param name="_block">Size for each allocation. The stream will only allocate new memory of size "_block" when it reaches the end and has to extend.</param>
MemoryStream(vint _block=65536);
~MemoryStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
void* GetInternalBuffer();
};
}
}
#endif
/***********************************************************************
.\STREAM\MEMORYWRAPPERSTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::MemoryWrapperStream
Interfaces:
MemoryWrapperStream : Memory stream which manipulate a given buffer
***********************************************************************/
#ifndef VCZH_STREAM_MEMORYWRAPPERSTREAM
#define VCZH_STREAM_MEMORYWRAPPERSTREAM
namespace vl
{
namespace stream
{
/// <summary>A readable, writable, seekable and peekable stream that operates a buffer.</summary>
class MemoryWrapperStream : public Object, public virtual IStream
{
protected:
char* buffer;
vint size;
vint position;
public:
/// <summary>Create a stream.</summary>
/// <param name="_buffer">The buffer to operate.</param>
/// <param name="_size">Size of the buffer.</param>
MemoryWrapperStream(void* _buffer, vint _size);
~MemoryWrapperStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
}
}
#endif
/***********************************************************************
.\STREAM\CHARFORMAT.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::CharFormat
Classes:
CharEncoder : Encoder to translate from wchar_t to some specified format
CharDecoder : Decoder to transate from some specified format to wchar_t
MbcsEncoder : Mbcs encoder (using the code page of the current locale)
MbcsDecoder : Mbcs decoder (using the code page of the current locale)
Utf16Encoder : UTF-16 encoder
Utf16Decoder : UTF-16 decoder
Utf16BEEncoder : UTF-16 encoder with big endian
Utf16BEDecoder : UTF-16 decoder with big endian
Utf8Encoder : UTF-8 encoder
Utf8Decoder : UTF-8 decoder
BomEncoder : Character encoder which writes a BOM before the text
BomDecoder : Character decoder which reads a BOM from the data to know the encoding
***********************************************************************/
#ifndef VCZH_STREAM_CHARFORMAT
#define VCZH_STREAM_CHARFORMAT
namespace vl
{
namespace stream
{
/*
How UCS-4 translate to UTF-8
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
BOM:
FFFE =Unicode (vceUtf16)
FEFF =Unicode Big Endian (vceUtf16_be)
EFBBBF =UTF-8 (vceUtf8)
other =MBCS(GBK) (vceMbcs)
*/
/***********************************************************************
Char Encoder and Decoder
***********************************************************************/
/// <summary>Base type of all character encoder.</summary>
class CharEncoder : public Object, public IEncoder
{
protected:
IStream* stream;
vuint8_t cacheBuffer[sizeof(wchar_t)];
vint cacheSize;
virtual vint WriteString(wchar_t* _buffer, vint chars)=0;
public:
CharEncoder();
void Setup(IStream* _stream);
void Close();
vint Write(void* _buffer, vint _size);
};
/// <summary>Base type of all character decoder.</summary>
class CharDecoder : public Object, public IDecoder
{
protected:
IStream* stream;
vuint8_t cacheBuffer[sizeof(wchar_t)];
vint cacheSize;
virtual vint ReadString(wchar_t* _buffer, vint chars)=0;
public:
CharDecoder();
void Setup(IStream* _stream);
void Close();
vint Read(void* _buffer, vint _size);
};
/***********************************************************************
Mbcs
***********************************************************************/
/// <summary>Encoder to transform text in a local code page from wchar_t.</summary>
class MbcsEncoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// <summary>Encoder to transform text in a local code page to wchar_t.</summary>
class MbcsDecoder : public CharDecoder
{
protected:
vint ReadString(wchar_t* _buffer, vint chars);
};
/***********************************************************************
Utf-16
***********************************************************************/
/// <summary>Encoder to transform UTF-16 text from wchar_t.</summary>
class Utf16Encoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// <summary>Decoder to transform UTF-16 text to wchar_t.</summary>
class Utf16Decoder : public CharDecoder
{
protected:
vint ReadString(wchar_t* _buffer, vint chars);
};
/***********************************************************************
Utf-16-be
***********************************************************************/
/// <summary>Encoder to transform big endian UTF-16 text from wchar_t.</summary>
class Utf16BEEncoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// <summary>Decoder to transform big endian UTF-16 text to wchar_t.</summary>
class Utf16BEDecoder : public CharDecoder
{
protected:
vint ReadString(wchar_t* _buffer, vint chars);
};
/***********************************************************************
Utf-8
***********************************************************************/
/// <summary>Encoder to transform UTF-8 text from wchar_t.</summary>
class Utf8Encoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// <summary>Decoder to transform UTF-8 text to wchar_t.</summary>
class Utf8Decoder : public CharDecoder
{
protected:
#if defined VCZH_MSVC
wchar_t cache;
bool cacheAvailable;
#endif
vint ReadString(wchar_t* _buffer, vint chars);
public:
Utf8Decoder();
};
/***********************************************************************
Bom
***********************************************************************/
/// <summary>Encoder to transform text from wchar_t. A BOM will be added at the beginning.</summary>
class BomEncoder : public Object, public IEncoder
{
public:
/// <summary>Text encoding.</summary>
enum Encoding
{
/// <summary>Multi-bytes character string.</summary>
Mbcs,
/// <summary>UTF-8.</summary>
Utf8,
/// <summary>UTF-16.</summary>
Utf16,
/// <summary>Big endian UTF-16.</summary>
Utf16BE
};
protected:
Encoding encoding;
IEncoder* encoder;
public:
/// <summary>Create an encoder.</summary>
/// <param name="_encoding">Specified encoding.</param>
BomEncoder(Encoding _encoding);
~BomEncoder();
void Setup(IStream* _stream);
void Close();
vint Write(void* _buffer, vint _size);
};
/// <summary>Decoder to transform text to wchar_t. This decoder depends on the BOM information at the beginning to decide the format of the input.</summary>
class BomDecoder : public Object, public IDecoder
{
private:
class BomStream : public Object, public IStream
{
protected:
IStream* stream;
char bom[3];
vint bomLength;
vint bomPosition;
public:
BomStream(IStream* _stream, char* _bom, vint _bomLength);
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
protected:
IDecoder* decoder;
IStream* stream;
public:
/// <summary>Create an decoder.</summary>
BomDecoder();
~BomDecoder();
void Setup(IStream* _stream);
void Close();
vint Read(void* _buffer, vint _size);
};
/***********************************************************************
Encoding Test
***********************************************************************/
/// <summary>Guess the text encoding in a buffer.</summary>
/// <param name="buffer">The buffer to guess.</param>
/// <param name="size">Size of the buffer in bytes.</param>
/// <param name="encoding">Returns the most possible encoding.</param>
/// <param name="containsBom">Returns true if the BOM information is at the beginning of the buffer.</param>
extern void TestEncoding(unsigned char* buffer, vint size, BomEncoder::Encoding& encoding, bool& containsBom);
/***********************************************************************
Serialization
***********************************************************************/
namespace internal
{
template<typename T>
struct Reader
{
stream::IStream& input;
T context;
Reader(stream::IStream& _input)
:input(_input)
, context(nullptr)
{
}
};
template<typename T>
struct Writer
{
stream::IStream& output;
T context;
Writer(stream::IStream& _output)
:output(_output)
, context(nullptr)
{
}
};
using ContextFreeReader = Reader<void*>;
using ContextFreeWriter = Writer<void*>;
template<typename T>
struct Serialization
{
template<typename TIO>
static void IO(TIO& io, T& value);
};
template<typename TValue, typename TContext>
Reader<TContext>& operator<<(Reader<TContext>& reader, TValue& value)
{
Serialization<TValue>::IO(reader, value);
return reader;
}
template<typename TValue, typename TContext>
Writer<TContext>& operator<<(Writer<TContext>& writer, TValue& value)
{
Serialization<TValue>::IO(writer, value);
return writer;
}
//---------------------------------------------
template<>
struct Serialization<vint64_t>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, vint64_t& value)
{
if (reader.input.Read(&value, sizeof(value)) != sizeof(value))
{
CHECK_FAIL(L"Deserialization failed.");
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, vint64_t& value)
{
if (writer.output.Write(&value, sizeof(value)) != sizeof(value))
{
CHECK_FAIL(L"Serialization failed.");
}
}
};
template<>
struct Serialization<vint32_t>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, vint32_t& value)
{
vint64_t v = 0;
Serialization<vint64_t>::IO(reader, v);
value = (vint32_t)v;
}
template<typename TContext>
static void IO(Writer<TContext>& writer, vint32_t& value)
{
vint64_t v = (vint64_t)value;
Serialization<vint64_t>::IO(writer, v);
}
};
template<>
struct Serialization<bool>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, bool& value)
{
vint8_t v = 0;
if (reader.input.Read(&v, sizeof(v)) != sizeof(v))
{
CHECK_FAIL(L"Deserialization failed.");
}
else
{
value = v == -1;
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, bool& value)
{
vint8_t v = value ? -1 : 0;
if (writer.output.Write(&v, sizeof(v)) != sizeof(v))
{
CHECK_FAIL(L"Serialization failed.");
}
}
};
template<typename T>
struct Serialization<Ptr<T>>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, Ptr<T>& value)
{
bool notNull = false;
reader << notNull;
if (notNull)
{
value = new T;
Serialization<T>::IO(reader, *value.Obj());
}
else
{
value = 0;
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, Ptr<T>& value)
{
bool notNull = value;
writer << notNull;
if (notNull)
{
Serialization<T>::IO(writer, *value.Obj());
}
}
};
template<typename T>
struct Serialization<Nullable<T>>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, Nullable<T>& value)
{
bool notNull = false;
reader << notNull;
if (notNull)
{
T data;
Serialization<T>::IO(reader, data);
value = Nullable<T>(data);
}
else
{
value = Nullable<T>();
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, Nullable<T>& value)
{
bool notNull = value;
writer << notNull;
if (notNull)
{
T data = value.Value();
Serialization<T>::IO(writer, data);
}
}
};
template<>
struct Serialization<WString>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, WString& value)
{
vint count = -1;
reader << count;
if (count > 0)
{
MemoryStream stream;
reader << (IStream&)stream;
Utf8Decoder decoder;
decoder.Setup(&stream);
collections::Array<wchar_t> stringBuffer(count + 1);
vint stringSize = decoder.Read(&stringBuffer[0], count * sizeof(wchar_t));
stringBuffer[stringSize / sizeof(wchar_t)] = 0;
value = &stringBuffer[0];
}
else
{
value = L"";
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, WString& value)
{
vint count = value.Length();
writer << count;
if (count > 0)
{
MemoryStream stream;
{
Utf8Encoder encoder;
encoder.Setup(&stream);
encoder.Write((void*)value.Buffer(), count * sizeof(wchar_t));
}
writer << (IStream&)stream;
}
}
};
template<typename T>
struct Serialization<collections::List<T>>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, collections::List<T>& value)
{
vint32_t count = -1;
reader << count;
value.Clear();
for (vint i = 0; i < count; i++)
{
T t;
reader << t;
value.Add(t);
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, collections::List<T>& value)
{
vint32_t count = (vint32_t)value.Count();
writer << count;
for (vint i = 0; i < count; i++)
{
writer << value[i];
}
}
};
template<typename T>
struct Serialization<collections::Array<T>>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, collections::Array<T>& value)
{
vint32_t count = -1;
reader << count;
value.Resize(count);
for (vint i = 0; i < count; i++)
{
reader << value[i];
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, collections::Array<T>& value)
{
vint32_t count = (vint32_t)value.Count();
writer << count;
for (vint i = 0; i < count; i++)
{
writer << value[i];
}
}
};
template<typename K, typename V>
struct Serialization<collections::Dictionary<K, V>>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, collections::Dictionary<K, V>& value)
{
vint32_t count = -1;
reader << count;
value.Clear();
for (vint i = 0; i < count; i++)
{
K k;
V v;
reader << k << v;
value.Add(k, v);
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, collections::Dictionary<K, V>& value)
{
vint32_t count = (vint32_t)value.Count();
writer << count;
for (vint i = 0; i < count; i++)
{
K k = value.Keys()[i];
V v = value.Values()[i];
writer << k << v;
}
}
};
template<typename K, typename V>
struct Serialization<collections::Group<K, V>>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, collections::Group<K, V>& value)
{
vint32_t count = -1;
reader << count;
value.Clear();
for (vint i = 0; i < count; i++)
{
K k;
collections::List<V> v;
reader << k << v;
for (vint j = 0; j < v.Count(); j++)
{
value.Add(k, v[j]);
}
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, collections::Group<K, V>& value)
{
vint32_t count = (vint32_t)value.Count();
writer << count;
for (vint i = 0; i < count; i++)
{
K k = value.Keys()[i];
collections::List<V>& v = const_cast<collections::List<V>&>(value.GetByIndex(i));
writer << k << v;
}
}
};
template<>
struct Serialization<stream::IStream>
{
template<typename TContext>
static void IO(Reader<TContext>& reader, stream::IStream& value)
{
vint32_t count = 0;
reader.input.Read(&count, sizeof(count));
if (count > 0)
{
vint length = 0;
collections::Array<vuint8_t> buffer(count);
value.SeekFromBegin(0);
length = reader.input.Read(&buffer[0], count);
if (length != count)
{
CHECK_FAIL(L"Deserialization failed.");
}
length = value.Write(&buffer[0], count);
if (length != count)
{
CHECK_FAIL(L"Deserialization failed.");
}
value.SeekFromBegin(0);
}
}
template<typename TContext>
static void IO(Writer<TContext>& writer, stream::IStream& value)
{
vint32_t count = (vint32_t)value.Size();
writer.output.Write(&count, sizeof(count));
if (count > 0)
{
vint length = 0;
collections::Array<vuint8_t> buffer(count);
value.SeekFromBegin(0);
length = value.Read(&buffer[0], count);
if (length != count)
{
CHECK_FAIL(L"Serialization failed.");
}
length = writer.output.Write(&buffer[0], count);
if (length != count)
{
CHECK_FAIL(L"Serialization failed.");
}
value.SeekFromBegin(0);
}
}
};
//---------------------------------------------
#define BEGIN_SERIALIZATION(TYPE)\
template<>\
struct Serialization<TYPE>\
{\
template<typename TIO>\
static void IO(TIO& op, TYPE& value)\
{\
op\
#define SERIALIZE(FIELD)\
<< value.FIELD\
#define END_SERIALIZATION\
;\
}\
};\
#define SERIALIZE_ENUM(TYPE)\
template<>\
struct Serialization<TYPE>\
{\
template<typename TContext>\
static void IO(Reader<TContext>& reader, TYPE& value)\
{\
vint32_t v = 0;\
Serialization<vint32_t>::IO(reader, v);\
value = (TYPE)v;\
}\
template<typename TContext>\
static void IO(Writer<TContext>& writer, TYPE& value)\
{\
vint32_t v = (vint32_t)value;\
Serialization<vint32_t>::IO(writer, v);\
}\
};\
}
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONCOPYFROM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONCOPYFROM
#define VCZH_COLLECTIONS_OPERATIONCOPYFROM
namespace vl
{
namespace collections
{
/***********************************************************************
Copy Functions for Containers
***********************************************************************/
namespace copyfrom_internal
{
using namespace randomaccess_internal;
template<typename Ds, typename Ss, bool DsRA, bool SsRA>
struct CopyFromAlgorithm
{
};
template<typename Ds, typename Ss>
struct CopyFromAlgorithm<Ds, Ss, true, true>
{
static void Perform(Ds& ds, const Ss& ss, bool append)
{
vint copyCount=RandomAccess<Ss>::GetCount(ss);
vint index=(append?RandomAccess<Ds>::GetCount(ds):0);
vint resizeCount=index+copyCount;
RandomAccess<Ds>::SetCount(ds, resizeCount);
for(vint i=0;i<copyCount;i++)
{
RandomAccess<Ds>::SetValue(ds, index+i, RandomAccess<Ss>::GetValue(ss, i));
}
}
};
template<typename Ds, typename Ss>
struct CopyFromAlgorithm<Ds, Ss, false, true>
{
static void Perform(Ds& ds, const Ss& ss, bool append)
{
if(!append)
{
ds.Clear();
}
vint copyCount=RandomAccess<Ss>::GetCount(ss);
for(vint i=0;i<copyCount;i++)
{
RandomAccess<Ds>::AppendValue(ds, RandomAccess<Ss>::GetValue(ss, i));
}
}
};
template<typename Ds, typename Ss>
struct CopyFromAlgorithm<Ds, Ss, true, false>
{
static void Perform(Ds& ds, const Ss& ss, bool append)
{
Ptr<IEnumerator<typename Ss::ElementType>> enumerator;
vint copyCount=0;
enumerator=ss.CreateEnumerator();
while(enumerator->Next())
{
copyCount++;
}
vint index=(append?RandomAccess<Ds>::GetCount(ds):0);
vint resizeCount=index+copyCount;
RandomAccess<Ds>::SetCount(ds, resizeCount);
enumerator=ss.CreateEnumerator();
while(enumerator->Next())
{
RandomAccess<Ds>::SetValue(ds, index++, enumerator->Current());
}
}
};
template<typename Ds, typename Ss>
struct CopyFromAlgorithm<Ds, Ss, false, false>
{
static void Perform(Ds& ds, const Ss& ss, bool append)
{
if(!append)
{
ds.Clear();
}
Ptr<IEnumerator<typename Ss::ElementType>> enumerator=ss.CreateEnumerator();
while(enumerator->Next())
{
RandomAccess<Ds>::AppendValue(ds, enumerator->Current());
}
}
};
template<typename T>
struct Slice
{
const T* items;
vint count;
};
}
namespace randomaccess_internal
{
template<typename T>
struct RandomAccessable<copyfrom_internal::Slice<T>>
{
static const bool CanRead = true;
static const bool CanResize = true;
};
template<typename T>
struct RandomAccess<copyfrom_internal::Slice<T>>
{
static vint GetCount(const copyfrom_internal::Slice<T>& t)
{
return t.count;
}
static const T& GetValue(const copyfrom_internal::Slice<T>& t, vint index)
{
return t.items[index];
}
};
}
/// <summary>Copy containers.</summary>
/// <typeparam name="Ds">Type of the destination container.</typeparam>
/// <typeparam name="Ss">Type of the source container.</typeparam>
/// <param name="ds">The destination container.</param>
/// <param name="ss">The source container.</param>
/// <param name="append">Set to false to delete everything in the destination container before copying.</param>
template<typename Ds, typename Ss>
void CopyFrom(Ds& ds, const Ss& ss, bool append=false)
{
copyfrom_internal::CopyFromAlgorithm<Ds, Ss, randomaccess_internal::RandomAccessable<Ds>::CanResize, randomaccess_internal::RandomAccessable<Ss>::CanRead>::Perform(ds, ss, append);
}
/// <summary>Copy containers.</summary>
/// <typeparam name="Ds">Type of the destination container.</typeparam>
/// <typeparam name="S">Type of the elements in the source container.</typeparam>
/// <param name="ds">The destination container.</param>
/// <param name="buffer">Pointer to the source array.</param>
/// <param name="count">The number of elements to copy.</param>
/// <param name="append">Set to false to delete everything in the destination container before copying.</param>
template<typename Ds, typename S>
void CopyFrom(Ds& ds, const S* buffer, vint count, bool append=false)
{
copyfrom_internal::Slice<S> slice={buffer, count};
CopyFrom(ds, slice, append);
}
/// <summary>Copy containers.</summary>
/// <typeparam name="Ds">Type of the destination container.</typeparam>
/// <typeparam name="S">Type of the elements in the source container.</typeparam>
/// <param name="ds">The destination container.</param>
/// <param name="begin">Pointer to the first element in the source array.</param>
/// <param name="end">Pointer to the element after the last element in the source array.</param>
/// <param name="append">Set to false to delete everything in the destination container before copying.</param>
template<typename Ds, typename S>
void CopyFrom(Ds& ds, const S* begin, const S* end, bool append=false)
{
copyfrom_internal::Slice<S> slice={begin, end-begin};
CopyFrom(ds, slice, append);
}
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONENUMERABLE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONENUMERABLE
#define VCZH_COLLECTIONS_OPERATIONENUMERABLE
namespace vl
{
namespace collections
{
/***********************************************************************
EmptyEnumerable
***********************************************************************/
template<typename T>
class EmptyEnumerable : public Object, public IEnumerable<T>
{
private:
class Enumerator : public Object, public virtual IEnumerator<T>
{
IEnumerator<T>* Clone()const override
{
return new Enumerator;
}
const T& Current()const override
{
CHECK_FAIL(L"EmptyEnumerable<T>::Enumerator::Current()#This collection is empty.");
}
vint Index()const override
{
return -1;
}
bool Next()override
{
return false;
}
void Reset()override
{
}
bool Evaluated()const override
{
return true;
}
};
public:
IEnumerator<T>* CreateEnumerator()const
{
return new Enumerator;
}
};
/***********************************************************************
RangeEnumerator
***********************************************************************/
template<typename T>
class RangeEnumerator : public Object, public virtual IEnumerator<T>
{
protected:
T start;
T count;
T current;
public:
RangeEnumerator(T _start, T _count, T _current)
:start(_start)
,count(_count)
,current(_current)
{
}
RangeEnumerator(T _start, T _count)
:start(_start)
,count(_count)
,current(_start-1)
{
}
IEnumerator<T>* Clone()const override
{
return new RangeEnumerator(start, count, current);
}
const T& Current()const override
{
return current;
}
T Index()const override
{
return current-start;
}
bool Next()override
{
if(start-1<=current && current<start+count-1)
{
current++;
return true;
}
else
{
return false;
}
}
void Reset()override
{
current=start-1;
}
bool Evaluated()const override
{
return true;
}
};
/***********************************************************************
ContainerEnumerator
***********************************************************************/
template<typename T, typename TContainer>
class ContainerEnumerator : public Object, public virtual IEnumerator<T>
{
private:
Ptr<TContainer> container;
vint index;
public:
ContainerEnumerator(Ptr<TContainer> _container, vint _index=-1)
{
container=_container;
index=_index;
}
IEnumerator<T>* Clone()const override
{
return new ContainerEnumerator(container, index);
}
const T& Current()const override
{
return container->Get(index);
}
vint Index()const override
{
return index;
}
bool Next()override
{
index++;
return index>=0 && index<container->Count();
}
void Reset()override
{
index=-1;
}
bool Evaluated()const override
{
return true;
}
};
/***********************************************************************
CompareEnumerable
***********************************************************************/
template<typename T, typename U>
vint CompareEnumerable(const IEnumerable<T>& a, const IEnumerable<U>& b)
{
Ptr<IEnumerator<T>> ator=a.CreateEnumerator();
Ptr<IEnumerator<U>> btor=b.CreateEnumerator();
while(true)
{
bool a=ator->Next();
bool b=btor->Next();
if(a&&!b) return 1;
if(!a&&b) return -1;
if(!a&&!b) break;
const T& ac=ator->Current();
const U& bc=btor->Current();
if(ac<bc)
{
return -1;
}
else if(ac>bc)
{
return 1;
}
ator->Next();
btor->Next();
}
return 0;
}
template<typename T>
struct SortedListOperations
{
static bool Contains(const SortedList<T>& items, const T& item)
{
return items.Contains(item);
}
};
template<typename T>
struct SortedListOperations<Ptr<T>>
{
static bool Contains(const SortedList<Ptr<T>>& items, const Ptr<T>& item)
{
return items.Contains(item.Obj());
}
};
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONSELECT.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONSELECT
#define VCZH_COLLECTIONS_OPERATIONSELECT
namespace vl
{
namespace collections
{
/***********************************************************************
Select
***********************************************************************/
template<typename T, typename K>
class SelectEnumerator : public virtual IEnumerator<K>
{
protected:
IEnumerator<T>* enumerator;
Func<K(T)> selector;
K current;
public:
SelectEnumerator(IEnumerator<T>* _enumerator, const Func<K(T)>& _selector, K _current=K())
:enumerator(_enumerator)
,selector(_selector)
,current(_current)
{
}
~SelectEnumerator()
{
delete enumerator;
}
IEnumerator<K>* Clone()const override
{
return new SelectEnumerator(enumerator->Clone(), selector, current);
}
const K& Current()const override
{
return current;
}
vint Index()const override
{
return enumerator->Index();
}
bool Next()override
{
if(enumerator->Next())
{
current=selector(enumerator->Current());
return true;
}
else
{
return false;
}
}
void Reset()override
{
enumerator->Reset();
}
};
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONWHERE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONWHERE
#define VCZH_COLLECTIONS_OPERATIONWHERE
namespace vl
{
namespace collections
{
/***********************************************************************
Where
***********************************************************************/
template<typename T>
class WhereEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator;
Func<bool(T)> selector;
vint index;
public:
WhereEnumerator(IEnumerator<T>* _enumerator, const Func<bool(T)>& _selector, vint _index=-1)
:enumerator(_enumerator)
,selector(_selector)
,index(_index)
{
}
~WhereEnumerator()
{
delete enumerator;
}
IEnumerator<T>* Clone()const override
{
return new WhereEnumerator(enumerator->Clone(), selector, index);
}
const T& Current()const override
{
return enumerator->Current();
}
vint Index()const override
{
return index;
}
bool Next()override
{
while(enumerator->Next())
{
if(selector(enumerator->Current()))
{
index++;
return true;
}
}
return false;
}
void Reset()override
{
enumerator->Reset();
index=-1;
}
};
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONCONCAT.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONCONCAT
#define VCZH_COLLECTIONS_OPERATIONCONCAT
namespace vl
{
namespace collections
{
/***********************************************************************
Concat
***********************************************************************/
template<typename T>
class ConcatEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator1;
IEnumerator<T>* enumerator2;
vint index;
bool turned;
public:
ConcatEnumerator(IEnumerator<T>* _enumerator1, IEnumerator<T>* _enumerator2, vint _index=-1, bool _turned=false)
:enumerator1(_enumerator1)
,enumerator2(_enumerator2)
,index(_index)
,turned(_turned)
{
}
~ConcatEnumerator()
{
delete enumerator1;
delete enumerator2;
}
IEnumerator<T>* Clone()const override
{
return new ConcatEnumerator(enumerator1->Clone(), enumerator2->Clone(), index, turned);
}
const T& Current()const override
{
if(turned)
{
return enumerator2->Current();
}
else
{
return enumerator1->Current();
}
}
vint Index()const override
{
return index;
}
bool Next()override
{
index++;
if(turned)
{
return enumerator2->Next();
}
else
{
if(enumerator1->Next())
{
return true;
}
else
{
turned=true;
return enumerator2->Next();
}
}
}
void Reset()override
{
enumerator1->Reset();
enumerator2->Reset();
index=-1;
turned=false;
}
bool Evaluated()const override
{
return enumerator1->Evaluated() && enumerator2->Evaluated();
}
};
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONSEQUENCE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONSEQUENCE
#define VCZH_COLLECTIONS_OPERATIONSEQUENCE
namespace vl
{
namespace collections
{
/***********************************************************************
Take
***********************************************************************/
template<typename T>
class TakeEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator;
vint count;
public:
TakeEnumerator(IEnumerator<T>* _enumerator, vint _count)
:enumerator(_enumerator)
,count(_count)
{
}
~TakeEnumerator()
{
delete enumerator;
}
IEnumerator<T>* Clone()const override
{
return new TakeEnumerator(enumerator->Clone(), count);
}
const T& Current()const override
{
return enumerator->Current();
}
vint Index()const override
{
return enumerator->Index();
}
bool Next()override
{
if(enumerator->Index()>=count-1) return false;
return enumerator->Next();
}
void Reset()override
{
enumerator->Reset();
}
bool Evaluated()const override
{
return enumerator->Evaluated();
}
};
/***********************************************************************
Skip
***********************************************************************/
template<typename T>
class SkipEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator;
vint count;
bool skipped;
public:
SkipEnumerator(IEnumerator<T>* _enumerator, vint _count, bool _skipped=false)
:enumerator(_enumerator)
,count(_count)
,skipped(_skipped)
{
}
~SkipEnumerator()
{
delete enumerator;
}
IEnumerator<T>* Clone()const override
{
return new SkipEnumerator(enumerator->Clone(), count, skipped);
}
const T& Current()const override
{
return enumerator->Current();
}
vint Index()const override
{
return enumerator->Index()-count;
}
bool Next()override
{
if(!skipped)
{
skipped=true;
for(vint i=0;i<count;i++)
{
if(!enumerator->Next())
{
return false;
}
}
}
return enumerator->Next();
}
void Reset()override
{
enumerator->Reset();
skipped=false;
}
bool Evaluated()const override
{
return enumerator->Evaluated();
}
};
/***********************************************************************
Repeat
***********************************************************************/
template<typename T>
class RepeatEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator;
vint count;
vint index;
vint repeatedCount;
public:
RepeatEnumerator(IEnumerator<T>* _enumerator, vint _count, vint _index=-1, vint _repeatedCount=0)
:enumerator(_enumerator)
,count(_count)
,index(_index)
,repeatedCount(_repeatedCount)
{
}
~RepeatEnumerator()
{
delete enumerator;
}
IEnumerator<T>* Clone()const override
{
return new RepeatEnumerator(enumerator->Clone(), count, index, repeatedCount);
}
const T& Current()const override
{
return enumerator->Current();
}
vint Index()const override
{
return index;
}
bool Next()override
{
while(repeatedCount<count)
{
if(enumerator->Next())
{
index++;
return true;
}
repeatedCount++;
enumerator->Reset();
}
return false;
}
void Reset()override
{
enumerator->Reset();
index=-1;
repeatedCount=0;
}
bool Evaluated()const override
{
return enumerator->Evaluated();
}
};
/***********************************************************************
Distinct
***********************************************************************/
template<typename T>
class DistinctEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator;
SortedList<T> distinct;
T lastValue;
public:
DistinctEnumerator(IEnumerator<T>* _enumerator)
:enumerator(_enumerator)
{
}
DistinctEnumerator(const DistinctEnumerator& _enumerator)
:lastValue(_enumerator.lastValue)
{
enumerator=_enumerator.enumerator->Clone();
CopyFrom(distinct, _enumerator.distinct);
}
~DistinctEnumerator()
{
delete enumerator;
}
IEnumerator<T>* Clone()const override
{
return new DistinctEnumerator(*this);
}
const T& Current()const override
{
return lastValue;
}
vint Index()const override
{
return distinct.Count()-1;
}
bool Next()override
{
while(enumerator->Next())
{
const T& current=enumerator->Current();
if(!SortedListOperations<T>::Contains(distinct, current))
{
lastValue=current;
distinct.Add(current);
return true;
}
}
return false;
}
void Reset()override
{
enumerator->Reset();
distinct.Clear();
}
};
/***********************************************************************
Reverse
***********************************************************************/
template<typename T>
class ReverseEnumerator : public virtual IEnumerator<T>
{
protected:
List<T> cache;
vint index;
public:
ReverseEnumerator(const IEnumerable<T>& enumerable)
:index(-1)
{
CopyFrom(cache, enumerable);
}
ReverseEnumerator(const ReverseEnumerator& _enumerator)
:index(_enumerator.index)
{
CopyFrom(cache, _enumerator.cache);
}
~ReverseEnumerator()
{
}
IEnumerator<T>* Clone()const override
{
return new ReverseEnumerator(*this);
}
const T& Current()const override
{
return cache.Get(cache.Count()-1-index);
}
vint Index()const override
{
return index;
}
bool Next()override
{
index++;
return index<cache.Count();
}
void Reset()override
{
index=-1;
}
bool Evaluated()const override
{
return true;
}
};
/***********************************************************************
FromIterator
***********************************************************************/
template<typename T, typename I>
class FromIteratorEnumerable : public Object, public IEnumerable<T>
{
private:
class Enumerator : public Object, public IEnumerator<T>
{
private:
I begin;
I end;
I current;
public:
Enumerator(I _begin, I _end, I _current)
:begin(_begin)
,end(_end)
,current(_current)
{
}
IEnumerator<T>* Clone()const override
{
return new Enumerator(begin, end, current);
}
const T& Current()const override
{
return *current;
}
vint Index()const override
{
return current-begin;
}
bool Next()override
{
current++;
return begin<=current && current<end;
}
void Reset()override
{
current=begin-1;
}
bool Evaluated()const override
{
return true;
}
};
private:
I begin;
I end;
public:
IEnumerator<T>* CreateEnumerator()const
{
return new Enumerator(begin, end, begin-1);
}
FromIteratorEnumerable(I _begin, I _end)
:begin(_begin)
,end(_end)
{
}
FromIteratorEnumerable(const FromIteratorEnumerable<T, I>& enumerable)
:begin(enumerable.begin)
,end(enumerable.end)
{
}
};
template<typename T>
class FromIterator
{
public:
template<typename I>
static FromIteratorEnumerable<T, I> Wrap(I begin, I end)
{
return FromIteratorEnumerable<T, I>(begin, end);
}
};
template<typename T>
FromIteratorEnumerable<T, const T*> FromPointer(const T* begin, const T* end)
{
return FromIteratorEnumerable<T, const T*>(begin, end);
}
template<typename T, int size>
FromIteratorEnumerable<T, T*> FromArray(T (&items)[size])
{
return FromIteratorEnumerable<T, T*>(&items[0], &items[size]);
}
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONSET.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONSET
#define VCZH_COLLECTIONS_OPERATIONSET
namespace vl
{
namespace collections
{
/***********************************************************************
Intersect/Except
***********************************************************************/
template<typename T, bool Intersect>
class IntersectExceptEnumerator : public virtual IEnumerator<T>
{
protected:
IEnumerator<T>* enumerator;
SortedList<T> reference;
vint index;
public:
IntersectExceptEnumerator(IEnumerator<T>* _enumerator, const IEnumerable<T>& _reference)
:enumerator(_enumerator)
,index(-1)
{
CopyFrom(reference, _reference);
}
IntersectExceptEnumerator(const IntersectExceptEnumerator& _enumerator)
{
enumerator=_enumerator.enumerator->Clone();
CopyFrom(reference, _enumerator.reference);
index=_enumerator.index;
}
~IntersectExceptEnumerator()
{
delete enumerator;
}
IEnumerator<T>* Clone()const override
{
return new IntersectExceptEnumerator(*this);
}
const T& Current()const override
{
return enumerator->Current();
}
vint Index()const override
{
return index;
}
bool Next()override
{
while(enumerator->Next())
{
if(SortedListOperations<T>::Contains(reference, enumerator->Current())==Intersect)
{
index++;
return true;
}
}
return false;
}
void Reset()override
{
enumerator->Reset();
index=-1;
}
};
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONPAIR.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONPAIR
#define VCZH_COLLECTIONS_OPERATIONPAIR
namespace vl
{
namespace collections
{
/***********************************************************************
Pairwise
***********************************************************************/
template<typename S, typename T>
class PairwiseEnumerator : public virtual IEnumerator<Pair<S, T>>
{
protected:
IEnumerator<S>* enumerator1;
IEnumerator<T>* enumerator2;
Pair<S, T> current;
public:
PairwiseEnumerator(IEnumerator<S>* _enumerator1, IEnumerator<T>* _enumerator2, Pair<S, T> _current=Pair<S, T>())
:enumerator1(_enumerator1)
,enumerator2(_enumerator2)
,current(_current)
{
}
~PairwiseEnumerator()
{
delete enumerator1;
delete enumerator2;
}
IEnumerator<Pair<S, T>>* Clone()const override
{
return new PairwiseEnumerator(enumerator1->Clone(), enumerator2->Clone(), current);
}
const Pair<S, T>& Current()const override
{
return current;
}
vint Index()const override
{
return enumerator1->Index();
}
bool Next()override
{
if(enumerator1->Next() && enumerator2->Next())
{
current=Pair<S, T>(enumerator1->Current(), enumerator2->Current());
return true;
}
else
{
return false;
}
}
void Reset()override
{
enumerator1->Reset();
enumerator2->Reset();
}
bool Evaluated()const override
{
return enumerator1->Evaluated() && enumerator2->Evaluated();
}
};
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONSTRING.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATIONSTRING
#define VCZH_COLLECTIONS_OPERATIONSTRING
namespace vl
{
namespace collections
{
template<typename Ds, typename S>
void CopyFrom(Ds& ds, const ObjectString<S>& ss, bool append=false)
{
const S* buffer=ss.Buffer();
vint count=ss.Length();
CopyFrom(ds, buffer, count, append);
}
template<typename D, typename Ss>
void CopyFrom(ObjectString<D>& ds, const Ss& ss, bool append=false)
{
Array<D> da(ds.Buffer(), ds.Length());
CopyFrom(da, ss, append);
if(da.Count()==0)
{
ds=ObjectString<D>();
}
else
{
ds=ObjectString<D>(&da[0], da.Count());
}
}
}
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATIONFOREACH.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
In order to let a container support FOREACH and FOREACH_INDEXER
Implement a global function overloading: IteratorType vl::collections::CreateForEachIterator(const CollectionType& collection);
CollectionType is the container type
IteratorType should inherit from ForEachIterator<T>
***********************************************************************/
#ifndef VCZH_COLLECTIONS_FOREACH
#define VCZH_COLLECTIONS_FOREACH
namespace vl
{
namespace collections
{
/***********************************************************************
ForEachIterator
***********************************************************************/
template<typename T>
class ForEachIterator : public Object
{
public:
virtual bool Next(T& variable)const=0;
operator bool()const
{
return true;
}
};
/***********************************************************************
ForEachIterator for IEnumerable
***********************************************************************/
template<typename T>
class EnumerableForEachIterator : public ForEachIterator<T>
{
protected:
Ptr<IEnumerator<T>> enumerator;
public:
EnumerableForEachIterator(const IEnumerable<T>& enumerable)
:enumerator(enumerable.CreateEnumerator())
{
}
EnumerableForEachIterator(const EnumerableForEachIterator<T>& enumerableIterator)
:enumerator(enumerableIterator.enumerator)
{
}
bool Next(T& variable)const
{
if(enumerator->Next())
{
variable=enumerator->Current();
return true;
}
else
{
return false;
}
}
};
template<typename T>
EnumerableForEachIterator<T> CreateForEachIterator(const IEnumerable<T>& enumerable)
{
return enumerable;
}
/***********************************************************************
FOREACH and FOREACH_INDEXER
***********************************************************************/
#define FOREACH(TYPE, VARIABLE, COLLECTION)\
SCOPE_VARIABLE(const ::vl::collections::ForEachIterator<TYPE>&, __foreach_iterator__, ::vl::collections::CreateForEachIterator(COLLECTION))\
for(TYPE VARIABLE;__foreach_iterator__.Next(VARIABLE);)
#define FOREACH_INDEXER(TYPE, VARIABLE, INDEXER, COLLECTION)\
SCOPE_VARIABLE(const ::vl::collections::ForEachIterator<TYPE>&, __foreach_iterator__, ::vl::collections::CreateForEachIterator(COLLECTION))\
SCOPE_VARIABLE(vint, INDEXER, 0)\
for(TYPE VARIABLE;__foreach_iterator__.Next(VARIABLE);INDEXER++)
}
}
#endif
/***********************************************************************
.\REGEX\REGEX.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::Regular Expression
Classes:
RegexString : String Fragment
RegexMatch : Match Result
Regex : Regular Expression
RegexToken : Token
RegexTokens : Token Stream
RegexLexer : Tokenizer
***********************************************************************/
#ifndef VCZH_REGEX_REGEX
#define VCZH_REGEX_REGEX
namespace vl
{
namespace regex_internal
{
class PureResult;
class PureInterpretor;
class RichResult;
class RichInterpretor;
}
namespace regex
{
/***********************************************************************
Data Structure
***********************************************************************/
/// <summary>A type representing a fragment of the input string.</summary>
class RegexString : public Object
{
protected:
WString value;
vint start;
vint length;
public:
RegexString(vint _start=0);
RegexString(const WString& _string, vint _start, vint _length);
/// <summary>The position of the input string.</summary>
/// <returns>The position.</returns>
vint Start()const;
/// <summary>The size of the fragment in characters.</summary>
/// <returns>The size.</returns>
vint Length()const;
/// <summary>Get the fragment.</summary>
/// <returns>The fragment.</returns>
const WString& Value()const;
bool operator==(const RegexString& string)const;
};
/// <summary>A type representing a match of the input string.</summary>
class RegexMatch : public Object, private NotCopyable
{
friend class Regex;
public:
typedef Ptr<RegexMatch> Ref;
typedef collections::List<Ref> List;
typedef collections::List<RegexString> CaptureList;
typedef collections::Group<WString, RegexString> CaptureGroup;
protected:
collections::List<RegexString> captures;
collections::Group<WString, RegexString> groups;
bool success;
RegexString result;
RegexMatch(const WString& _string, regex_internal::PureResult* _result);
RegexMatch(const WString& _string, regex_internal::RichResult* _result, regex_internal::RichInterpretor* _rich);
RegexMatch(const RegexString& _result);
public:
/// <summary>Test if this match is a success match or a failed match. A failed match will only appear when calling [M:vl.regex.Regex.Split] or [M:vl.regex.Regex.Cut]. In other cases, failed matches are either not included in the result, or become null pointers.</summary>
/// <returns>Returns true if this match is a success match.</returns>
bool Success()const;
/// <summary>Get the whole fragment that matches.</summary>
/// <returns>The whole fragment.</returns>
const RegexString& Result()const;
/// <summary>Get all fragments that are captured.</summary>
/// <returns>All fragments that are captured.</returns>
const CaptureList& Captures()const;
/// <summary>Get all fragments that are captured by named groups.</summary>
/// <returns>All fragments that are captured.</returns>
const CaptureGroup& Groups()const;
};
/***********************************************************************
Regex
***********************************************************************/
/// <summary><![CDATA[
/// Regular Expression. Here is a brief description of the regular expression grammar:
/// 1) Charset:
/// a, [a-z], [^a-z]
/// 2) Functional characters:
/// ^: the beginning of the input (DFA incompatible)
/// $: the end of the input (DFA incompatible)
/// regex1|regex2: match either regex1 or regex2
/// 3) Escaping (both \ and / mean the next character is escaped)
/// Escaped characters:
/// \r: the CR character
/// \n: the LF character
/// \t: the tab character
/// \s: spacing characters (including space, \r, \n, \t)
/// \S: non-spacing characters
/// \d: [0-9]
/// \D: [^0-9]
/// \l: [a-zA-Z]
/// \L: [^a-zA-Z]
/// \w: [a-zA-Z0-9_]
/// \W: [^a-zA-Z0-9_]
/// \.: any character (this is the main different from other regex, which treat "." as any characters and "\." as the dot character)
/// \\, \/, \(, \), \+, \*, \?, \{, \}, \[, \], \<, \>, \^, \$, \!, \=: represents itself
/// Escaped characters in charset defined in a square bracket:
/// \r: the CR character
/// \n: the LF character
/// \t: the tab character
/// \-, \[, \], \\, \/, \^, \$: represents itself
/// 4) Loops:
/// regex{3}: repeats 3 times
/// regex{3,}: repeats 3 or more times
/// regex{1,3}: repeats 1 to 3 times
/// regex?: repeats 0 or 1 times
/// regex*: repeats 0 or more times
/// regex+: repeats 1 or more times
/// if you add a "?" right after a loop, it means repeating as less as possible (DFA incompatible)
/// 5) Capturing: (DFA incompatible)
/// (regex): No capturing, just change the operators' association
/// (?regex): Capture matched fragment
/// (<name>regex): Capture matched fragment in a named group called "name"
/// (<$i>): Match the i-th captured fragment, begins from 0
/// (<$name;i>): Match the i-th captured fragment in the named group called "name", begins from 0
/// (<$name>): Match any captured fragment in the named group called "name"
/// 6) MISC
/// (=regex): The prefix of the following text should match the regex, but it is not counted in the whole match (DFA incompatible)
/// (!regex): Any prefix of the following text should not match the regex, and it is not counted in the whole match (DFA incompatible)
/// (<#name>regex): Name the regex "name", and it applies here
/// (<&name>): Copy the named regex "name" here and apply
/// ]]></summary>
class Regex : public Object, private NotCopyable
{
protected:
regex_internal::PureInterpretor* pure;
regex_internal::RichInterpretor* rich;
void Process(const WString& text, bool keepEmpty, bool keepSuccess, bool keepFail, RegexMatch::List& matches)const;
public:
/// <summary>Create a regular expression.</summary>
/// <param name="code">The regular expression in a string.</param>
/// <param name="preferPure">Set to true to tell the Regex to use DFA if possible.</param>
Regex(const WString& code, bool preferPure=true);
~Regex();
/// <summary>Test does the Regex uses DFA to match a string.</summary>
/// <returns>Returns true if DFA is used.</returns>
bool IsPureMatch()const;
/// <summary>Test does the Regex uses DFA to test a string. Test means ignoring all capturing requirements.</summary>
/// <returns>Returns true if DFA is used.</returns>
bool IsPureTest()const;
/// <summary>Match a prefix of the text.</summary>
/// <returns>Returns the match. Returns null if failed.</returns>
/// <param name="text">The text to match.</param>
RegexMatch::Ref MatchHead(const WString& text)const;
/// <summary>Match a fragment of the text.</summary>
/// <returns>Returns the match. Returns null if failed.</returns>
/// <param name="text">The text to match.</param>
RegexMatch::Ref Match(const WString& text)const;
/// <summary>Match a prefix of the text, ignoring all capturing requirements.</summary>
/// <returns>Returns true if succeeded.</returns>
/// <param name="text">The text to match.</param>
bool TestHead(const WString& text)const;
/// <summary>Match a fragment of the text, ignoring all capturing requirements.</summary>
/// <returns>Returns true if succeeded.</returns>
/// <param name="text">The text to match.</param>
bool Test(const WString& text)const;
/// <summary>Find all matched fragments of the text, returning all matched fragments.</summary>
/// <param name="text">The text to match.</param>
/// <param name="matches">All successful matches.</param>
void Search(const WString& text, RegexMatch::List& matches)const;
/// <summary>Split the text by matched fragments, returning all unmatched fragments.</summary>
/// <param name="text">The text to match.</param>
/// <param name="keepEmptyMatch">Set to true to keep all empty matches.</param>
/// <param name="matches">All failed matches.</param>
void Split(const WString& text, bool keepEmptyMatch, RegexMatch::List& matches)const;
/// <summary>Cut the text by matched fragments, returning all matched or unmatched fragments.</summary>
/// <param name="text">The text to match.</param>
/// <param name="keepEmptyMatch">Set to true to keep all empty matches.</param>
/// <param name="matches">All successful and failed matches.</param>
void Cut(const WString& text, bool keepEmptyMatch, RegexMatch::List& matches)const;
};
/***********************************************************************
Tokenizer
***********************************************************************/
/// <summary>A token.</summary>
class RegexToken
{
public:
/// <summary>Position in the input string.</summary>
vint start;
/// <summary>Size of this token in characters.</summary>
vint length;
/// <summary>The token id, begins at 0, represents the regular expression in the list that matches this token. -1 means this token is produced by an error.</summary>
vint token;
/// <summary>The pointer to where this token starts in the input string .</summary>
const wchar_t* reading;
/// <summary>The argument value from [M:vl.regex.RegexLexer.Parse].</summary>
vint codeIndex;
/// <summary>True if this token is complete. False if this token does not end here.</summary>
bool completeToken;
/// <summary>Row number of the first character, begins at 0.</summary>
vint rowStart;
/// <summary>Column number of the first character, begins at 0.</summary>
vint columnStart;
/// <summary>Row number of the last character, begins at 0.</summary>
vint rowEnd;
/// <summary>Column number of the last character, begins at 0.</summary>
vint columnEnd;
bool operator==(const RegexToken& _token)const;
bool operator==(const wchar_t* _token)const;
};
/// <summary>Token collection representing the result from the lexical analyzer.</summary>
class RegexTokens : public Object, public collections::IEnumerable<RegexToken>
{
friend class RegexLexer;
protected:
regex_internal::PureInterpretor* pure;
const collections::Array<vint>& stateTokens;
WString code;
vint codeIndex;
RegexTokens(regex_internal::PureInterpretor* _pure, const collections::Array<vint>& _stateTokens, const WString& _code, vint _codeIndex);
public:
RegexTokens(const RegexTokens& tokens);
collections::IEnumerator<RegexToken>* CreateEnumerator()const;
/// <summary>Copy all tokens.</summary>
/// <param name="tokens">Returns all tokens.</param>
/// <param name="discard">A callback to decide which kind of tokens to discard. The input is [F:vl.regex.RegexToken.token]. Returns true to discard this kind of tokens.</param>
void ReadToEnd(collections::List<RegexToken>& tokens, bool(*discard)(vint)=0)const;
};
/// <summary>Lexical walker.</summary>
class RegexLexerWalker : public Object
{
friend class RegexLexer;
protected:
regex_internal::PureInterpretor* pure;
const collections::Array<vint>& stateTokens;
RegexLexerWalker(regex_internal::PureInterpretor* _pure, const collections::Array<vint>& _stateTokens);
public:
RegexLexerWalker(const RegexLexerWalker& walker);
~RegexLexerWalker();
/// <summary>Get the start DFA state number, which represents the correct state before parsing any input.</summary>
/// <returns>The DFA state number.</returns>
vint GetStartState()const;
/// <summary>Test if this state can only lead to the end of one kind of token.</summary>
/// <returns>Returns the token index if this state can only lead to the end of one kind of token. Returns -1 if not.</returns>
/// <param name="state">The DFA state number.</param>
vint GetRelatedToken(vint state)const;
/// <summary>Step forward by one character.</summary>
/// <param name="input">The input character.</param>
/// <param name="state">The current state. Returns the new current state when this function returns.</param>
/// <param name="token">Returns the token index at the end of the token.</param>
/// <param name="finalState">Returns true if it reach the end of the token.</param>
/// <param name="previousTokenStop">Returns true if the last character is the end of the token.</param>
void Walk(wchar_t input, vint& state, vint& token, bool& finalState, bool& previousTokenStop)const;
/// <summary>Step forward by one character.</summary>
/// <returns>Returns the new current state.</returns>
/// <param name="input">The input character.</param>
/// <param name="state">The current state.</param>
vint Walk(wchar_t input, vint state)const;
/// <summary>Test if the input text is a complete token.</summary>
/// <returns>Returns true if the input text is a complete token.</returns>
/// <param name="input">The input text.</param>
/// <param name="length">Size of the input text in characters.</param>
bool IsClosedToken(const wchar_t* input, vint length)const;
/// <summary>Test if the input is a complete token.</summary>
/// <returns>Returns true if the input text is a complete token.</returns>
/// <param name="input">The input text.</param>
bool IsClosedToken(const WString& input)const;
};
/// <summary>Lexical colorizer.</summary>
class RegexLexerColorizer : public Object
{
friend class RegexLexer;
public:
typedef void(*TokenProc)(void* argument, vint start, vint length, vint token);
protected:
RegexLexerWalker walker;
vint currentState;
RegexLexerColorizer(const RegexLexerWalker& _walker);
public:
RegexLexerColorizer(const RegexLexerColorizer& colorizer);
~RegexLexerColorizer();
/// <summary>Reset the colorizer using the DFA state number.</summary>
/// <param name="state">The DFA state number.</param>
void Reset(vint state);
/// <summary>Step forward by one character.</summary>
/// <param name="input">The input character.</param>
void Pass(wchar_t input);
/// <summary>Get the start DFA state number, which represents the correct state before colorizing any characters.</summary>
/// <returns>The DFA state number.</returns>
vint GetStartState()const;
/// <summary>Get the current DFA state number.</summary>
/// <returns>The DFA state number.</returns>
vint GetCurrentState()const;
/// <summary>Colorize a text.</summary>
/// <param name="input">The text to colorize.</param>
/// <param name="length">Size of the text in characters.</param>
/// <param name="tokenProc">Colorizer callback. This callback will be called if any token is found..</param>
/// <param name="tokenProcArgument">The argument to call the callback.</param>
void Colorize(const wchar_t* input, vint length, TokenProc tokenProc, void* tokenProcArgument);
};
/// <summary>Lexical analyzer.</summary>
class RegexLexer : public Object, private NotCopyable
{
protected:
regex_internal::PureInterpretor* pure;
collections::Array<vint> ids;
collections::Array<vint> stateTokens;
public:
/// <summary>Create a lexical analyzer by a set of regular expressions. [F:vl.regex.RegexToken.token] will be the index of the matched regular expression.</summary>
/// <param name="tokens">The regular expressions.</param>
RegexLexer(const collections::IEnumerable<WString>& tokens);
~RegexLexer();
/// <summary>Tokenize a input text.</summary>
/// <returns>The result.</returns>
/// <param name="code">The text to tokenize.</param>
/// <param name="codeIndex">Extra information that will store in [F:vl.regex.RegexToken.codeIndex].</param>
RegexTokens Parse(const WString& code, vint codeIndex=-1)const;
/// <summary>Create a equivalence walker from this lexical analyzer.</summary>
/// <returns>The walker.</returns>
RegexLexerWalker Walk()const;
/// <summary>Create a equivalence colorizer from this lexical analyzer.</summary>
/// <returns>The colorizer.</returns>
RegexLexerColorizer Colorize()const;
};
}
}
#endif
/***********************************************************************
.\STREAM\ACCESSOR.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::Accessor
Classes:
TextReader : Text reader base class
TextWriter : Text writer base class
StringReader : Text reader from a string
StreamReader : Text reader from a stream
StreamWriter : Text writer to a stream
EncoderStream : Stream that takes an encoder to translate another stream
DecoderStream : Stream that takes a decoder to translate another stream
***********************************************************************/
#ifndef VCZH_STREAM_ACCESSOR
#define VCZH_STREAM_ACCESSOR
namespace vl
{
namespace stream
{
/***********************************************************************
Text Related
***********************************************************************/
/// <summary>Text reader. All line breaks are normalized to CRLF regardless the format in the source.</summary>
class TextReader : public Object, private NotCopyable
{
public:
/// <summary>Test does the reader reach the end or not.</summary>
/// <returns>Returns true if the reader reaches the end.</returns>
virtual bool IsEnd()=0;
/// <summary>Read a single character.</summary>
/// <returns>The character.</returns>
virtual wchar_t ReadChar()=0;
/// <summary>Read a string of a specified size.</summary>
/// <returns>The string.</returns>
/// <param name="length">Expected length of the string to read.</param>
virtual WString ReadString(vint length);
/// <summary>Read a string until a line breaks is reached.</summary>
/// <returns>The string. It does not contain the line break.</returns>
virtual WString ReadLine();
/// <summary>Read everying remain.</summary>
/// <returns>The string.</returns>
virtual WString ReadToEnd();
};
/// <summary>Text writer.</summary>
class TextWriter : public Object, private NotCopyable
{
public:
/// <summary>Write a single character.</summary>
/// <param name="c">The character to write.</param>
virtual void WriteChar(wchar_t c)=0;
/// <summary>Write a string.</summary>
/// <param name="string">Buffer to the string to write.</param>
/// <param name="charCount">Size of the string in characters not including the zero terminator.</param>
virtual void WriteString(const wchar_t* string, vint charCount);
/// <summary>Write a string.</summary>
/// <param name="string">Buffer to the zero terminated string to write.</param>
virtual void WriteString(const wchar_t* string);
/// <summary>Write a string.</summary>
/// <param name="string">The string to write.</param>
virtual void WriteString(const WString& string);
/// <summary>Write a string with a CRLF.</summary>
/// <param name="string">Buffer to the string to write.</param>
/// <param name="charCount">Size of the string in characters not including the zero terminator.</param>
virtual void WriteLine(const wchar_t* string, vint charCount);
/// <summary>Write a string with a CRLF.</summary>
/// <param name="string">Buffer to the zero terminated string to write.</param>
virtual void WriteLine(const wchar_t* string);
/// <summary>Write a string with a CRLF.</summary>
/// <param name="string">The string to write.</param>
virtual void WriteLine(const WString& string);
virtual void WriteMonospacedEnglishTable(collections::Array<WString>& tableByRow, vint rows, vint columns);
};
/// <summary>Text reader from a string.</summary>
class StringReader : public TextReader
{
protected:
WString string;
vint current;
bool lastCallIsReadLine;
void PrepareIfLastCallIsReadLine();
public:
/// <summary>Create a text reader.</summary>
/// <param name="_string">The string to read.</param>
StringReader(const WString& _string);
bool IsEnd();
wchar_t ReadChar();
WString ReadString(vint length);
WString ReadLine();
WString ReadToEnd();
};
/// <summary>Text reader from a stream.</summary>
class StreamReader : public TextReader
{
protected:
IStream* stream;
public:
/// <summary>Create a text reader.</summary>
/// <param name="_stream">The stream to read.</param>
StreamReader(IStream& _stream);
bool IsEnd();
wchar_t ReadChar();
};
/// <summary>Text writer to a stream.</summary>
class StreamWriter : public TextWriter
{
protected:
IStream* stream;
public:
/// <summary>Create a text writer.</summary>
/// <param name="_stream">The stream to write.</param>
StreamWriter(IStream& _stream);
using TextWriter::WriteString;
void WriteChar(wchar_t c);
void WriteString(const wchar_t* string, vint charCount);
};
/***********************************************************************
Encoding Related
***********************************************************************/
/// <summary>Encoder stream, a writable stream using an [T:vl.stream.IEncoder] to transform content.</summary>
class EncoderStream : public virtual IStream
{
protected:
IStream* stream;
IEncoder* encoder;
pos_t position;
public:
/// <summary>Create a stream.</summary>
/// <param name="_stream">The target stream to write.</param>
/// <param name="_encoder">The encoder to transform content.</param>
EncoderStream(IStream& _stream, IEncoder& _encoder);
~EncoderStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
/// <summary>Decoder stream, a readable stream using an [T:vl.stream.IDecoder] to transform content.</summary>
class DecoderStream : public virtual IStream
{
protected:
IStream* stream;
IDecoder* decoder;
pos_t position;
public:
/// <summary>Create a stream.</summary>
/// <param name="_stream">The target stream to read.</param>
/// <param name="_decoder">The decoder to transform content.</param>
DecoderStream(IStream& _stream, IDecoder& _decoder);
~DecoderStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
/***********************************************************************
Helper Functions
***********************************************************************/
template<typename TCallback>
WString GenerateToStream(const TCallback& callback, vint block = 65536)
{
MemoryStream stream(block);
{
StreamWriter writer(stream);
callback(writer);
}
stream.SeekFromBegin(0);
{
StreamReader reader(stream);
return reader.ReadToEnd();
}
}
}
}
#endif
/***********************************************************************
.\STREAM\COMPRESSIONSTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::CharFormat
Classes:
***********************************************************************/
#ifndef VCZH_STREAM_COMPRESSIONSTREAM
#define VCZH_STREAM_COMPRESSIONSTREAM
namespace vl
{
namespace stream
{
/***********************************************************************
Compression
***********************************************************************/
namespace lzw
{
static const vint BufferSize = 1024;
static const vint MaxDictionarySize = 1 << 24;
struct Code
{
typedef collections::PushOnlyAllocator<Code> CodeAllocator;
typedef collections::ByteObjectMap<Code>::Allocator MapAllocator;
vuint8_t byte = 0;
vint code = -1;
Code* parent = 0;
vint size = 0;
collections::ByteObjectMap<Code> children;
};
}
class LzwBase : public Object
{
protected:
lzw::Code::CodeAllocator codeAllocator;
lzw::Code::MapAllocator mapAllocator;
lzw::Code* root;
vint eofIndex = -1;
vint nextIndex = 0;
vint indexBits = 1;
void UpdateIndexBits();
lzw::Code* CreateCode(lzw::Code* parent, vuint8_t byte);
LzwBase();
LzwBase(bool (&existingBytes)[256]);
~LzwBase();
};
/// <summary>An encoder to compress using Lzw algorithm.</summary>
class LzwEncoder : public LzwBase, public IEncoder
{
protected:
IStream* stream = 0;
vuint8_t buffer[lzw::BufferSize];
vint bufferUsedBits = 0;
lzw::Code* prefix;
void Flush();
void WriteNumber(vint number, vint bitSize);
public:
/// <summary>Create an encoder.</summary>
LzwEncoder();
/// <summary>Create an encoder and tell it which byte will never appear in the data before compression.</summary>
/// <param name="existingBytes">An array to tell the encoder which byte will never appear in the data before compression.</param>
LzwEncoder(bool (&existingBytes)[256]);
~LzwEncoder();
void Setup(IStream* _stream)override;
void Close()override;
vint Write(void* _buffer, vint _size)override;
};
/// <summary>An decoder to decompress using Lzw algorithm.</summary>
class LzwDecoder :public LzwBase, public IDecoder
{
protected:
IStream* stream = 0;
collections::List<lzw::Code*> dictionary;
lzw::Code* lastCode = 0;
vuint8_t inputBuffer[lzw::BufferSize];
vint inputBufferSize = 0;
vint inputBufferUsedBits = 0;
collections::Array<vuint8_t> outputBuffer;
vint outputBufferSize = 0;
vint outputBufferUsedBytes = 0;
bool ReadNumber(vint& number, vint bitSize);
void PrepareOutputBuffer(vint size);
void ExpandCodeToOutputBuffer(lzw::Code* code);
public:
/// <summary>Create an decoder.</summary>
LzwDecoder();
/// <summary>Create an decoder and tell it which byte will never appear in the data before compression.</summary>
/// <param name="existingBytes">An array to tell the encoder which byte will never appear in the data before compression.</param>
LzwDecoder(bool (&existingBytes)[256]);
~LzwDecoder();
void Setup(IStream* _stream)override;
void Close()override;
vint Read(void* _buffer, vint _size)override;
};
/***********************************************************************
Helper Functions
***********************************************************************/
extern vint CopyStream(stream::IStream& inputStream, stream::IStream& outputStream);
extern void CompressStream(stream::IStream& inputStream, stream::IStream& outputStream);
extern void DecompressStream(stream::IStream& inputStream, stream::IStream& outputStream);
}
}
#endif
/***********************************************************************
.\LOCALE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Locale
Interfaces:
***********************************************************************/
#ifndef VCZH_LOCALE
#define VCZH_LOCALE
namespace vl
{
/// <summary>Locale awared operations. Macro "INVLOC" is a shortcut to get a invariant locale.</summary>
class Locale : public Object
{
protected:
WString localeName;
public:
Locale(const WString& _localeName=WString::Empty);
~Locale();
bool operator==(const Locale& value)const { return localeName==value.localeName; }
bool operator!=(const Locale& value)const { return localeName!=value.localeName; }
bool operator<(const Locale& value)const { return localeName<value.localeName; }
bool operator<=(const Locale& value)const { return localeName<=value.localeName; }
bool operator>(const Locale& value)const { return localeName>value.localeName; }
bool operator>=(const Locale& value)const { return localeName>=value.localeName; }
/// <summary>Get the invariant locale.</summary>
/// <returns>The invariant locale.</returns>
static Locale Invariant();
/// <summary>Get the system default locale. This locale controls the code page that used by the the system to interpret ANSI string buffers.</summary>
/// <returns>The system default locale.</returns>
static Locale SystemDefault();
/// <summary>Get the user default locale. This locale reflect the user's setting.</summary>
/// <returns>The user default locale.</returns>
static Locale UserDefault();
/// <summary>Get all supported locales.</summary>
/// <param name="locales">All supported locales.</param>
static void Enumerate(collections::List<Locale>& locales);
/// <summary>Get the name of the locale.</summary>
/// <returns>The name of the locale.</returns>
const WString& GetName()const;
/// <summary>Get all short date formats for the locale.</summary>
/// <param name="formats">The formats.</param>
void GetShortDateFormats(collections::List<WString>& formats)const;
/// <summary>Get all long date formats for the locale.</summary>
/// <param name="formats">The formats.</param>
void GetLongDateFormats(collections::List<WString>& formats)const;
/// <summary>Get all Year-Month date formats for the locale.</summary>
/// <param name="formats">The formats.</param>
void GetYearMonthDateFormats(collections::List<WString>& formats)const;
/// <summary>Get all long time formats for the locale.</summary>
/// <param name="formats">The formats.</param>
void GetLongTimeFormats(collections::List<WString>& formats)const;
/// <summary>Get all short time formats for the locale.</summary>
/// <param name="formats">The formats.</param>
void GetShortTimeFormats(collections::List<WString>& formats)const;
/// <summary>Convert a date to a formatted string.</summary>
/// <returns>The formatted string.</returns>
/// <param name="format">The format to use.</param>
/// <param name="date">The date to convert.</param>
WString FormatDate(const WString& format, DateTime date)const;
/// <summary>Convert a time to a formatted string.</summary>
/// <returns>The formatted string.</returns>
/// <param name="format">The format to use.</param>
/// <param name="time">The time to convert.</param>
WString FormatTime(const WString& format, DateTime time)const;
/// <summary>Convert a number to a formatted string.</summary>
/// <returns>The formatted string.</returns>
/// <param name="number">The number to convert.</param>
WString FormatNumber(const WString& number)const;
/// <summary>Convert a currency (money) to a formatted string.</summary>
/// <returns>The formatted string.</returns>
/// <param name="currency">The currency to convert.</param>
WString FormatCurrency(const WString& currency)const;
/// <summary>Get the short display string of a day of week.</summary>
/// <returns>The display string.</returns>
/// <param name="dayOfWeek">Day of week, begins from 0 as Sunday.</param>
WString GetShortDayOfWeekName(vint dayOfWeek)const;
/// <summary>Get the long display string of a day of week.</summary>
/// <returns>The display string.</returns>
/// <param name="dayOfWeek">Day of week, begins from 0 as Sunday.</param>
WString GetLongDayOfWeekName(vint dayOfWeek)const;
/// <summary>Get the short display string of a month.</summary>
/// <returns>The display string.</returns>
/// <param name="month">Month, begins from 1 as January.</param>
WString GetShortMonthName(vint month)const;
/// <summary>Get the long display string of a month.</summary>
/// <returns>The display string.</returns>
/// <param name="month">Month, begins from 1 as January.</param>
WString GetLongMonthName(vint month)const;
#ifdef VCZH_MSVC
/// <summary>Convert characters to the full width.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToFullWidth(const WString& str)const;
/// <summary>Convert characters to the half width.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToHalfWidth(const WString& str)const;
/// <summary>Convert characters to the Hiragana.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToHiragana(const WString& str)const;
/// <summary>Convert characters to the Katagana.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToKatagana(const WString& str)const;
#endif
/// <summary>Convert characters to the lower case using the file system rule.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToLower(const WString& str)const;
/// <summary>Convert characters to the upper case using the file system rule.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToUpper(const WString& str)const;
/// <summary>Convert characters to the lower case using the linguistic rule.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToLinguisticLower(const WString& str)const;
/// <summary>Convert characters to the upper case using the linguistic rule.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToLinguisticUpper(const WString& str)const;
#ifdef VCZH_MSVC
/// <summary>Convert characters to Simplified Chinese.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToSimplifiedChinese(const WString& str)const;
/// <summary>Convert characters to the Traditional Chinese.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToTraditionalChinese(const WString& str)const;
/// <summary>Convert characters to the tile case, in which the first letter of each major word is capitalized.</summary>
/// <returns>The converted string.</returns>
/// <param name="str">The string to convert.</param>
WString ToTileCase(const WString& str)const;
#endif
/// <summary>Mergable flags controlling how to normalize a string.</summary>
enum Normalization
{
/// <summary>Do nothing.</summary>
None=0,
/// <summary>Ignore case using the file system rule.</summary>
IgnoreCase=1,
#ifdef VCZH_MSVC
/// <summary>Ignore case using the linguistic rule.</summary>
IgnoreCaseLinguistic=2,
/// <summary>Ignore the difference between between hiragana and katakana characters.</summary>
IgnoreKanaType=4,
/// <summary>Ignore nonspacing characters.</summary>
IgnoreNonSpace=8,
/// <summary>Ignore symbols and punctuation.</summary>
IgnoreSymbol=16,
/// <summary>Ignore the difference between half-width and full-width characters.</summary>
IgnoreWidth=32,
/// <summary>Treat digits as numbers during sorting.</summary>
DigitsAsNumbers=64,
/// <summary>Treat punctuation the same as symbols.</summary>
StringSoft=128,
#endif
};
/// <summary>Compare two strings.</summary>
/// <returns>Returns 0 if two strings are equal. Returns a positive number if the first string is larger. Returns a negative number if the second string is larger. When sorting strings, larger strings are put after then smaller strings.</returns>
/// <param name="s1">The first string to compare.</param>
/// <param name="s2">The second string to compare.</param>
/// <param name="normalization">Flags controlling how to normalize a string.</param>
vint Compare(const WString& s1, const WString& s2, Normalization normalization)const;
/// <summary>Compare two strings to test binary equivalence.</summary>
/// <returns>Returns 0 if two strings are equal. Returns a positive number if the first string is larger. Returns a negative number if the second string is larger. When sorting strings, larger strings are put after then smaller strings.</returns>
/// <param name="s1">The first string to compare.</param>
/// <param name="s2">The second string to compare.</param>
vint CompareOrdinal(const WString& s1, const WString& s2)const;
/// <summary>Compare two strings to test binary equivalence, ignoring case.</summary>
/// <returns>Returns 0 if two strings are equal. Returns a positive number if the first string is larger. Returns a negative number if the second string is larger. When sorting strings, larger strings are put after then smaller strings.</returns>
/// <param name="s1">The first string to compare.</param>
/// <param name="s2">The second string to compare.</param>
vint CompareOrdinalIgnoreCase(const WString& s1, const WString& s2)const;
/// <summary>Find the first position that the sub string appears in a text.</summary>
/// <returns>Returns a pair of numbers, the first number indicating the position in the text, the second number indicating the size of the equivalence sub string in the text. For some normalization, the found sub string may be binary different to the string you want to find.</returns>
/// <param name="text">The text to find the sub string.</param>
/// <param name="find">The sub string to match.</param>
/// <param name="normalization">Flags controlling how to normalize a string.</param>
collections::Pair<vint, vint> FindFirst(const WString& text, const WString& find, Normalization normalization)const;
/// <summary>Find the last position that the sub string appears in a text.</summary>
/// <returns>Returns a pair of numbers, the first number indicating the position in the text, the second number indicating the size of the equivalence sub string in the text. For some normalization, the found sub string may be binary different to the string you want to find.</returns>
/// <param name="text">The text to find the sub string.</param>
/// <param name="find">The sub string to match.</param>
/// <param name="normalization">Flags controlling how to normalize a string.</param>
collections::Pair<vint, vint> FindLast(const WString& text, const WString& find, Normalization normalization)const;
/// <summary>Test is the prefix of the text equivalence to the provided sub string.</summary>
/// <returns>Returns true if the prefix of the text equivalence to the provided sub string.</returns>
/// <param name="text">The text to test the prefix.</param>
/// <param name="find">The sub string to match.</param>
/// <param name="normalization">Flags controlling how to normalize a string.</param>
bool StartsWith(const WString& text, const WString& find, Normalization normalization)const;
/// <summary>Test is the postfix of the text equivalence to the provided sub string.</summary>
/// <returns>Returns true if the postfix of the text equivalence to the provided sub string.</returns>
/// <param name="text">The text to test the postfix.</param>
/// <param name="find">The sub string to match.</param>
/// <param name="normalization">Flags controlling how to normalize a string.</param>
bool EndsWith(const WString& text, const WString& find, Normalization normalization)const;
};
#define INVLOC vl::Locale::Invariant()
}
#endif
/***********************************************************************
.\EXCEPTION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Exception
Classes:
Exception : Exception
***********************************************************************/
#ifndef VCZH_EXCEPTION
#define VCZH_EXCEPTION
namespace vl
{
/// <summary>Base type of all exceptions.</summary>
class Exception : public Object
{
protected:
WString message;
public:
Exception(const WString& _message=WString::Empty);
const WString& Message()const;
};
class ArgumentException : public Exception
{
protected:
WString function;
WString name;
public:
ArgumentException(const WString& _message=WString::Empty, const WString& _function=WString::Empty, const WString& _name=WString::Empty);
const WString& GetFunction()const;
const WString& GetName()const;
};
class ParsingException : public Exception
{
protected:
vint position;
WString expression;
public:
ParsingException(const WString& _message, const WString& _expression, vint _position);
const WString& GetExpression()const;
vint GetPosition()const;
};
}
#endif
/***********************************************************************
.\EVENT.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Event
Classes:
Event<function-type> : Event object, which is a functor with no return value, executing multiple functors stored inside
***********************************************************************/
#ifndef VCZH_EVENT
#define VCZH_EVENT
namespace vl
{
template<typename T>
class Event
{
};
class EventHandler : public Object
{
public:
virtual bool IsAttached() = 0;
};
/// <summary>Event.</summary>
/// <typeparam name="TArgs">Types of callback parameters.</typeparam>
template<typename ...TArgs>
class Event<void(TArgs...)> : public Object, private NotCopyable
{
protected:
class EventHandlerImpl : public EventHandler
{
public:
bool attached;
Func<void(TArgs...)> function;
EventHandlerImpl(const Func<void(TArgs...)>& _function)
:attached(true)
, function(_function)
{
}
bool IsAttached()override
{
return attached;
}
};
collections::SortedList<Ptr<EventHandlerImpl>> handlers;
public:
/// <summary>Add a callback to the event.</summary>
/// <returns>The event handler representing the callback.</returns>
/// <param name="function">The callback.</param>
Ptr<EventHandler> Add(const Func<void(TArgs...)>& function)
{
Ptr<EventHandlerImpl> handler = new EventHandlerImpl(function);
handlers.Add(handler);
return handler;
}
/// <summary>Add a callback to the event.</summary>
/// <returns>The event handler representing the callback.</returns>
/// <param name="function">The callback.</param>
Ptr<EventHandler> Add(void(*function)(TArgs...))
{
return Add(Func<void(TArgs...)>(function));
}
/// <summary>Add a method callback to the event.</summary>
/// <typeparam name="C">Type of the class that has the method callback.</typeparam>
/// <returns>The event handler representing the callback.</returns>
/// <param name="sender">The object that has the method callback.</param>
/// <param name="function">The method callback.</param>
template<typename C>
Ptr<EventHandler> Add(C* sender, void(C::*function)(TArgs...))
{
return Add(Func<void(TArgs...)>(sender, function));
}
/// <summary>Remove a callback.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="handler">The event handler representing the callback.</param>
bool Remove(Ptr<EventHandler> handler)
{
Ptr<EventHandlerImpl> impl = handler.Cast<EventHandlerImpl>();
if (!impl) return false;
vint index = handlers.IndexOf(impl.Obj());
if (index == -1) return false;
impl->attached = false;
handlers.RemoveAt(index);
return true;
}
/// <summary>Invoke all callbacks in the event.</summary>
/// <param name="args">Arguments to invoke all callbacks.</param>
void operator()(TArgs ...args)const
{
for(vint i = 0; i < handlers.Count(); i++)
{
handlers[i]->function(args...);
}
}
};
}
#endif
/***********************************************************************
.\COLLECTIONS\OPERATION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Operations
Functions:
CopyFrom(TargetContainer, SourceContainer)
[T] .Select(T->K) => [K]
[T] .SelectMany(T->[K]) => [K]
[T] .Where(T->bool) => [T]
[Ptr<T>].Cast<K>() => [Ptr<K>]
[Ptr<T>].FindType<K>() => [Ptr<K>]
[T] .OrderBy(T->T->int) => [T]
[T] .Aggregate(T->T->T) => T
[T] .Aggregate(T->T->T, T) => T
[T] .All(T->bool) => bool
[T] .Any(T->bool) => bool
[T] .Max() => T
[T] .Min() => T
[T] .First() => T
[T] .FirstOrDefault(T) => T
[T] .Last() => T
[T] .LastOrDefault(T) => T
[T] .Count() => vint
[T] .IsEmpty() => bool
[T] .Concat([T]) => [T]
[T] .Repeat(vint) => [T]
[T] .Take(vint) => [T]
[T] .Skip(vint) => [T]
[T] .Distinct() => [T]
[T] .Reverse() => [T]
[T] .Pairwise([K]) => [(T,K)]
[T] .Intersect([T]) => [T]
[T] .Union([T]) => [T]
[T] .Except([T]) => [T]
[T] .Evaluate() => [T]
[T] .GroupBy(T->K) => [(K, [T])]
From(begin, end) => [T]
From(array) => [T]
Range(start, count) => [vint]
FOREACH(X, a, XList)
FOREACH_INDEXER(X, a, index, XList)
***********************************************************************/
#ifndef VCZH_COLLECTIONS_OPERATION
#define VCZH_COLLECTIONS_OPERATION
namespace vl
{
namespace collections
{
/***********************************************************************
OrderBy Quick Sort
***********************************************************************/
template<typename T, typename F>
void SortLambda(T* items, vint length, F orderer)
{
if(length==0) return;
vint pivot=0;
vint left=0;
vint right=0;
bool flag=false;
while(left+right+1!=length)
{
vint& mine=(flag?left:right);
vint& theirs=(flag?right:left);
vint candidate=(flag?left:length-right-1);
vint factor=(flag?-1:1);
if(orderer(items[pivot], items[candidate])*factor<=0)
{
mine++;
}
else
{
theirs++;
T temp=items[pivot];
items[pivot]=items[candidate];
items[candidate]=temp;
pivot=candidate;
flag=!flag;
}
}
SortLambda(items, left, orderer);
SortLambda(items+left+1, right, orderer);
}
template<typename T>
void Sort(T* items, vint length, const Func<vint(T, T)>& orderer)
{
SortLambda<T, Func<vint(T, T)>>(items, length, orderer);
}
/***********************************************************************
LazyList
***********************************************************************/
/// <summary>A lazy evaluated readonly container.</summary>
/// <typeparam name="T">The type of elements.</typeparam>
template<typename T>
class LazyList : public Object, public IEnumerable<T>
{
protected:
Ptr<IEnumerator<T>> enumeratorPrototype;
template<typename U>
static U Element(const IEnumerable<U>&);
IEnumerator<T>* xs()const
{
return enumeratorPrototype->Clone();
}
public:
/// <summary>Create a lazy list with an enumerator.</summary>
/// <param name="enumerator">The enumerator.</param>
LazyList(IEnumerator<T>* enumerator)
:enumeratorPrototype(enumerator)
{
}
/// <summary>Create a lazy list with an enumerator.</summary>
/// <param name="enumerator">The enumerator.</param>
LazyList(Ptr<IEnumerator<T>> enumerator)
:enumeratorPrototype(enumerator)
{
}
/// <summary>Create a lazy list with an enumerable.</summary>
/// <param name="enumerable">The enumerator.</param>
LazyList(const IEnumerable<T>& enumerable)
:enumeratorPrototype(enumerable.CreateEnumerator())
{
}
/// <summary>Create a lazy list with an lazy list.</summary>
/// <param name="lazyList">The lazy list.</param>
LazyList(const LazyList<T>& lazyList)
:enumeratorPrototype(lazyList.enumeratorPrototype)
{
}
/// <summary>Create a lazy list with a container.</summary>
/// <typeparam name="TContainer">Type of the container.</typeparam>
/// <param name="container">The container.</param>
template<typename TContainer>
LazyList(Ptr<TContainer> container)
:enumeratorPrototype(new ContainerEnumerator<T, TContainer>(container))
{
}
/// <summary>Create an empty lazy list.</summary>
LazyList()
:enumeratorPrototype(EmptyEnumerable<T>().CreateEnumerator())
{
}
LazyList<T>& operator=(const LazyList<T>& lazyList)
{
enumeratorPrototype=lazyList.enumeratorPrototype;
return *this;
}
IEnumerator<T>* CreateEnumerator()const
{
return enumeratorPrototype->Clone();
}
//-------------------------------------------------------
/// <summary>Create a new lazy list with all elements transformed.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The created lazy list.</returns>
/// <param name="f">The lambda expression as a transformation function.</param>
template<typename F>
LazyList<FUNCTION_RESULT_TYPE(F)> Select(F f)const
{
return new SelectEnumerator<T, FUNCTION_RESULT_TYPE(F)>(xs(), f);
}
/// <summary>Create a new lazy list with all elements that satisfy with a condition.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The created lazy list.</returns>
/// <param name="f">The lambda expression as a filter.</param>
template<typename F>
LazyList<T> Where(F f)const
{
return new WhereEnumerator<T>(xs(), f);
}
/// <summary>Create a new lazy list with all elements casted to a new type.</summary>
/// <typeparam name="U">The new type.</typeparam>
/// <returns>The created lazy list.</returns>
template<typename U>
LazyList<Ptr<U>> Cast()const
{
Func<Ptr<U>(T)> f=[](T t)->Ptr<U>{return t.template Cast<U>();};
return new SelectEnumerator<T, Ptr<U>>(xs(), f);
}
/// <summary>Create a new lazy list with only elements that successfully casted to a new type.</summary>
/// <typeparam name="U">The new type.</typeparam>
/// <returns>The created lazy list.</returns>
template<typename U>
LazyList<Ptr<U>> FindType()const
{
return Cast<U>().Where([](T t){return t;});
}
/// <summary>Create a new lazy list with all elements sorted.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The created lazy list.</returns>
/// <param name="f">The lambda expression as a comparing function.</param>
template<typename F>
LazyList<T> OrderBy(F f)const
{
Ptr<List<T>> sorted=new List<T>;
CopyFrom(*sorted.Obj(), *this);
if(sorted->Count()>0)
{
SortLambda<T, F>(&sorted->operator[](0), sorted->Count(), f);
}
return new ContainerEnumerator<T, List<T>>(sorted);
}
//-------------------------------------------------------
/// <summary>Aggregate a lazy list. An exception will raise if the lazy list is empty.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The aggregated value.</returns>
/// <param name="f">The lambda expression as an aggregator.</param>
template<typename F>
T Aggregate(F f)const
{
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
if(!enumerator->Next())
{
throw Error(L"LazyList<T>::Aggregate(F)#Aggregate failed to calculate from an empty container.");
}
T result=enumerator->Current();
while(enumerator->Next())
{
result=f(result, enumerator->Current());
}
return result;
}
/// <summary>Aggregate a lazy list.</summary>
/// <typeparam name="I">Type of the initial value.</typeparam>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The aggregated value.</returns>
/// <param name="init">The initial value that is virtually added before the lazy list.</param>
/// <param name="f">The lambda expression as an aggregator.</param>
template<typename I, typename F>
I Aggregate(I init, F f)const
{
FOREACH(T, t, *this)
{
init=f(init, t);
}
return init;
}
/// <summary>Test does all elements in the lazy list satisfy with a condition.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>Returns true if all elements satisfy with a condition.</returns>
/// <param name="f">The lambda expression as a filter.</param>
template<typename F>
bool All(F f)const
{
return Select(f).Aggregate(true, [](bool a, bool b){return a&&b;});
}
/// <summary>Test does any elements in the lazy list satisfy with a condition.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>Returns true if at least one element satisfies with a condition.</returns>
/// <param name="f">The lambda expression as a filter.</param>
template<typename F>
bool Any(F f)const
{
return Select(f).Aggregate(false, [](bool a, bool b){return a||b;});
}
/// <summary>Get the maximum value in the lazy list. An exception will raise if the lazy list is empty.</summary>
/// <returns>The maximum value.</returns>
T Max()const
{
return Aggregate([](T a, T b){return a>b?a:b;});
}
/// <summary>Get the minimum value in the lazy list. An exception will raise if the lazy list is empty.</summary>
/// <returns>The minimum value.</returns>
T Min()const
{
return Aggregate([](T a, T b){return a<b?a:b;});
}
/// <summary>Get the first value in the lazy list. An exception will raise if the lazy list is empty.</summary>
/// <returns>The first value.</returns>
T First()const
{
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
if(!enumerator->Next())
{
throw Error(L"LazyList<T>::First(F)#First failed to calculate from an empty container.");
}
return enumerator->Current();
}
/// <summary>Get the first value in the lazy list.</summary>
/// <returns>The first value.</returns>
/// <param name="defaultValue">Returns this argument if the lazy list is empty.</param>
T First(T defaultValue)const
{
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
if(!enumerator->Next())
{
return defaultValue;
}
return enumerator->Current();
}
/// <summary>Get the last value in the lazy list. An exception will raise if the lazy list is empty.</summary>
/// <returns>The last value.</returns>
T Last()const
{
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
if(!enumerator->Next())
{
throw Error(L"LazyList<T>::Last(F)#Last failed to calculate from an empty container.");
}
else
{
T value=enumerator->Current();
while(enumerator->Next())
{
value=enumerator->Current();
}
return value;
}
}
/// <summary>Get the last value in the lazy list.</summary>
/// <returns>The last value.</returns>
/// <param name="defaultValue">Returns this argument if the lazy list is empty.</param>
T Last(T defaultValue)const
{
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
while(enumerator->Next())
{
defaultValue=enumerator->Current();
}
return defaultValue;
}
/// <summary>Get the number of elements in the lazy list.</summary>
/// <returns>The number of elements.</returns>
vint Count()const
{
vint result=0;
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
while(enumerator->Next())
{
result++;
}
return result;
}
/// <summary>Test is the lazy list empty.</summary>
/// <returns>Returns true if the lazy list is empty.</returns>
bool IsEmpty()const
{
Ptr<IEnumerator<T>> enumerator=CreateEnumerator();
return !enumerator->Next();
}
//-------------------------------------------------------
/// <summary>Create a new lazy list containing elements of the two container one after another.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="remains">Elements that put after this lazy list.</param>
LazyList<T> Concat(const IEnumerable<T>& remains)const
{
return new ConcatEnumerator<T>(xs(), remains.CreateEnumerator());
}
/// <summary>Create a new lazy list with some prefix elements.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="count">The size of the prefix.</param>
LazyList<T> Take(vint count)const
{
return new TakeEnumerator<T>(xs(), count);
}
/// <summary>Create a new lazy list without some prefix elements.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="count">The size of the prefix.</param>
LazyList<T> Skip(vint count)const
{
return new SkipEnumerator<T>(xs(), count);
}
/// <summary>Create a new lazy list with several copies of this lazy list one after another.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="count">The numbers of copies.</param>
LazyList<T> Repeat(vint count)const
{
return new RepeatEnumerator<T>(xs(), count);
}
/// <summary>Create a new lazy list with all elements in this lazy list. If some elements appear several times, only one will be kept.</summary>
/// <returns>The created lazy list.</returns>
LazyList<T> Distinct()const
{
return new DistinctEnumerator<T>(xs());
}
/// <summary>Create a new lazy list with all elements in this lazy list in a reverse order.</summary>
/// <returns>The created lazy list.</returns>
LazyList<T> Reverse()const
{
return new ReverseEnumerator<T>(*this);
}
//-------------------------------------------------------
/// <summary>Create a new lazy list of pairs from elements from two containers.</summary>
/// <typeparam name="U">Type of all elements in the second container.</typeparam>
/// <returns>The created lazy list.</returns>
/// <param name="remains">The second container.</param>
template<typename U>
LazyList<Pair<T, U>> Pairwise(const IEnumerable<U>& remains)const
{
return new PairwiseEnumerator<T, U>(xs(), remains.CreateEnumerator());
}
/// <summary>Create a new lazy list with only elements that appear in both containers.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="remains">The second container.</param>
LazyList<T> Intersect(const IEnumerable<T>& remains)const
{
return LazyList<T>(new IntersectExceptEnumerator<T, true>(xs(), remains)).Distinct();
}
/// <summary>Create a new lazy list with only elements that appear in this lazy list but not in another container.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="remains">The second container.</param>
LazyList<T> Except(const IEnumerable<T>& remains)const
{
return LazyList<T>(new IntersectExceptEnumerator<T, false>(xs(), remains)).Distinct();
}
/// <summary>Create a new lazy list with elements in two containers. If some elements appear several times, only one will be kept.</summary>
/// <returns>The created lazy list.</returns>
/// <param name="remains">The second container.</param>
LazyList<T> Union(const IEnumerable<T>& remains)const
{
return Concat(remains).Distinct();
}
//-------------------------------------------------------
LazyList<T> Evaluate()const
{
if(enumeratorPrototype->Evaluated())
{
return *this;
}
else
{
Ptr<List<T>> xs=new List<T>;
CopyFrom(*xs.Obj(), *this);
return xs;
}
}
/// <summary>Create a new lazy list, whose elements are from transformed elements in this lazy list.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The created lazy list.</returns>
/// <param name="f">The lambda expression as a transformation function to transform one element to multiple elements.</param>
template<typename F>
FUNCTION_RESULT_TYPE(F) SelectMany(F f)const
{
typedef FUNCTION_RESULT_TYPE(F) LazyListU;
typedef typename LazyListU::ElementType U;
return Select(f).Aggregate(LazyList<U>(), [](const LazyList<U>& a, const IEnumerable<U>& b)->LazyList<U>{return a.Concat(b);});
}
/// <summary>Create a new lazy list, whose elements are groupd by from elements in this lazy list.</summary>
/// <typeparam name="F">Type of the lambda expression.</typeparam>
/// <returns>The created lazy list.</returns>
/// <param name="f">The lambda expression as a key retriver to calcuate a key from an element.</param>
template<typename F>
LazyList<Pair<FUNCTION_RESULT_TYPE(F), LazyList<T>>> GroupBy(F f)const
{
typedef FUNCTION_RESULT_TYPE(F) K;
return Select(f)
.Distinct()
.Select([=](K k)
{
return Pair<K, LazyList<T>>(
k,
Where([=](T t){return k==f(t);})
);
});
}
};
template<typename T>
LazyList<T> Range(T start, T count)
{
return new RangeEnumerator<T>(start, count);
}
template<typename T>
LazyList<T> From(const IEnumerable<T>& enumerable)
{
return enumerable;
}
template<typename T>
LazyList<T> From(const LazyList<T>& enumerable)
{
return enumerable;
}
template<typename T>
LazyList<T> From(const T* begin, const T* end)
{
return FromPointer(begin, end);
}
template<typename T, int size>
LazyList<T> From(T (&items)[size])
{
return FromArray(items);
}
template<typename T, int size>
LazyList<T> From(const T (&items)[size])
{
return FromArray(items);
}
}
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTOR.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTOR
#define VCZH_REFLECTION_GUITYPEDESCRIPTOR
namespace vl
{
namespace reflection
{
/***********************************************************************
Attribute
***********************************************************************/
namespace description
{
class ITypeDescriptor;
class ITypeInfo;
class IEventHandler;
class IEventInfo;
class IPropertyInfo;
class IParameterInfo;
class IMethodInfo;
class IMethodGroupInfo;
class IValueFunctionProxy;
class IValueInterfaceProxy;
class IValueSubscription;
class IValueEnumerable;
class IValueEnumerator;
class IValueReadonlyList;
class IValueList;
class IValueObservableList;
class IValueReadonlyDictionary;
class IValueDictionary;
class IValueCallStack;
class IValueException;
template<typename T>
struct TypedValueSerializerProvider
{
};
}
/// <summary>Base class of all reflectable object. You can use pointer or smart pointer to DescriptableObject to define variables, but if you want to create a reflectable class, you should inherit from [T:vl.reflection.Description`1].</summary>
class DescriptableObject
{
template<typename T, typename Enabled>
friend struct vl::ReferenceCounterOperator;
template<typename T>
friend class Description;
typedef collections::Dictionary<WString, Ptr<Object>> InternalPropertyMap;
typedef bool(*DestructorProc)(DescriptableObject* obj, bool forceDisposing);
private:
volatile vint referenceCounter;
#ifndef VCZH_DEBUG_NO_REFLECTION
size_t objectSize;
description::ITypeDescriptor** typeDescriptor;
#endif
Ptr<InternalPropertyMap> internalProperties;
#ifndef VCZH_DEBUG_NO_REFLECTION
bool destructing;
DescriptableObject** aggregationInfo;
vint aggregationSize;
#endif
protected:
DestructorProc sharedPtrDestructorProc;
protected:
#ifndef VCZH_DEBUG_NO_REFLECTION
bool IsAggregated();
vint GetAggregationSize();
DescriptableObject* GetAggregationRoot();
void SetAggregationRoot(DescriptableObject* value);
DescriptableObject* GetAggregationParent(vint index);
void SetAggregationParent(vint index, DescriptableObject* value);
void SetAggregationParent(vint index, Ptr<DescriptableObject>& value);
void InitializeAggregation(vint size);
#endif
void FinalizeAggregation();
#ifndef VCZH_DEBUG_NO_REFLECTION
template<typename T>
void SafeAggregationCast(T*& result)
{
auto expected = dynamic_cast<T*>(this);
if (expected)
{
CHECK_ERROR(result == nullptr, L"vl::reflection::DescriptableObject::SafeAggregationCast<T>()#Found multiple ways to do aggregation cast.");
result = expected;
}
if (IsAggregated())
{
for (vint i = 0; i < aggregationSize; i++)
{
if (auto parent = GetAggregationParent(i))
{
parent->SafeAggregationCast<T>(result);
}
}
}
}
#endif
public:
DescriptableObject();
virtual ~DescriptableObject();
#ifndef VCZH_DEBUG_NO_REFLECTION
/// <summary>Get the type descriptor that describe the real type of this object.</summary>
/// <returns>The real type.</returns>
description::ITypeDescriptor* GetTypeDescriptor();
#endif
/// <summary>Get an internal property of this object. This map is totally for customization.</summary>
/// <returns>Value of the internal property of this object.</returns>
/// <param name="name">Name of the property.</param>
Ptr<Object> GetInternalProperty(const WString& name);
/// <summary>Set an internal property of this object. This map is totally for customization.</summary>
/// <param name="name">Name of the property.</param>
/// <param name="value">Value of the internal property of this object.</param>
void SetInternalProperty(const WString& name, Ptr<Object> value);
/// <summary>Try to delete this object.</summary>
/// <returns>Returns true if this operation succeeded. Returns false if the object refuces to be dispose.</returns>
/// <param name="forceDisposing">Set to true to force disposing this object. If the reference counter is not 0 if you force disposing it, it will raise a [T:vl.reflection.description.ValueNotDisposableException].</param>
bool Dispose(bool forceDisposing);
#ifndef VCZH_DEBUG_NO_REFLECTION
/// <summary>Get the aggregation root object.</summary>
/// <returns>The aggregation root object. If this object is not aggregated, or it is the root object of others, than this function return itself.</returns>
DescriptableObject* SafeGetAggregationRoot();
#endif
/// <summary>Cast the object to another type, considered aggregation.</summary>
/// <returns>The object with the expected type in all aggregated objects.</returns>
/// <typeparam name="T">The expected type to cast.</typeparam>
template<typename T>
T* SafeAggregationCast()
{
#ifndef VCZH_DEBUG_NO_REFLECTION
T* result = nullptr;
SafeGetAggregationRoot()->SafeAggregationCast<T>(result);
return result;
#else
return dynamic_cast<T*>(this);
#endif
}
};
/// <summary><![CDATA[
/// Inherit from this class when you want to create a reflectable class. It should be used like this:
/// class YourClass : public Description<YourClass>
/// {
/// ...
/// };
///
/// If you want YourClass to be inheritable in scripts, instead of using Description, you should use AggregatableDescription, like this:
/// class YourClass : public AggregatableDescription<YourClass>
/// {
/// ~YourClass()
/// {
/// FinalizeAggregation();
/// }
/// };
///
/// After you have complete your type, use the following macros and functions to register your class into the global type table. Everything should be defined in vl::reflection::description namespaces.
/// Some of the predefined type has already been registered, if your types depend on these types, you should load those types by calling some or all of them:
/// [F:vl.reflection.description.LoadPredefinedTypes]
/// [F:vl.reflection.description.LoadParsingTypes]
/// [F:vl.reflection.description.JsonLoadTypes]
/// [F:vl.reflection.description.XmlLoadTypes]
///
/// 1) (in header files) Create a macro that contains all types that you want to register. Content in the list will become the registered type names, so it is strongly recommended to use the full name.
/// #define MY_TYPELIST(F)\
/// F(mynamespaces::MyClass1)\
/// F(mynamespaces::MyClass2)\
///
/// 2) (in header files) Connect type names and types:
/// MY_TYPELIST(DECL_TYPE_INFO)
///
/// 3) (in cpp files) Connect type names and types:
/// MY_TYPELIST(IMPL_VL_TYPE_INFO)
///
/// 4) (in cpp files) Register all members:
///
/// #define _ ,
///
/// a) enum:
/// use BEGIN_ENUM_ITEM_MERGABLE instead of BEGIN_ENUM_ITEM if enum items are consider mergable using "|".
///
/// BEGIN_ENUM_ITEM(Season)
/// ENUM_ITEM(Spring)
/// ENUM_ITEM(Summer)
/// ENUM_ITEM(Autumn)
/// ENUM_ITEM(Winter)
/// END_ENUM_ITEM(Season)
///
/// b) enum class:
/// use BEGIN_ENUM_ITEM_MERGABLE instead of BEGIN_ENUM_ITEM if enum items are consider mergable using "|".
///
/// BEGIN_ENUM_ITEM(Season)
/// ENUM_CLASS_ITEM(Spring)
/// ENUM_CLASS_ITEM(Summer)
/// ENUM_CLASS_ITEM(Autumn)
/// ENUM_CLASS_ITEM(Winter)
/// END_ENUM_ITEM(Season)
///
/// c) struct (pure data structure):
/// BEGIN_STRUCT_MEMBER(Point)
/// STRUCT_MEMBER(x)
/// STRUCT_MEMBER(y)
/// END_STRUCT_MEMBER(Point)
///
/// d) class:
/// BEGIN_CLASS_MEMBER(MyClass)
///
/// I) declare a base class (can have multiple base classes):
/// CLASS_MEMBER_BASE(MyBaseClass)
///
/// II) declare a field:
/// CLASS_MEMBER_FIELD(myField)
///
/// III) Empty constructor that results in a raw pointer:
/// CLASS_MEMBER_CONSTRUCTIOR(MyClass*(), NO_PARAMETER)
///
/// IV) Empty constructor that results in a smart pointer:
/// CLASS_MEMBER_CONSTRUCTIOR(Ptr<MyClass>(), NO_PARAMETER)
///
/// V) Constructor with arguments:
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"})
///
/// VI) Inject a global function as a constructor
/// CLASS_MEMBER_EXTERNALCTOR(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"}, mynamespace::CreateMyClass)
/// CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"}, CreateMyClass, L"mynamespace::GetMyClass($Arguments)", L"::vl::Func<$Func>(&mynamespace::GetMyClass)")
/// CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr<MyClass>(), NO_PARAMETER, []()->Ptr<MyClass>{return nullptr;}, L"*", L"*")
///
/// VII) Add unoverloaded functions
/// CLASS_MEMBER_METHOD(MyFunction1, NO_PARAMETER)
/// CLASS_MEMBER_METHOD(MyFunction2, {L"parameter1" _ L"parameter2"})
///
/// VIII) Add unoverloaded function but give a different names
/// CLASS_MEMBER_METHOD_RENAME(MyNewName1, MyFunction1, NO_PARAMETER)
/// CLASS_MEMBER_METHOD_RENAME(MyNewName2, MyFunction2, {L"parameter1" _ L"parameter2"})
///
/// IX) Add overloaded functions
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, NO_PARAMETER, int(MyClass::*)())
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, {L"parameter"}, int(MyClass::*)(int))
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&))
///
/// IX) Add overloaded functions but give different names
/// CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName3, MyFunction3, NO_PARAMETER, int(MyClass::*)())
/// CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName4, MyFunction3, {L"parameter"}, int(MyClass::*)(int))
/// CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName4, MyFunction3, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&))
///
/// X) Inject global functions as methods:
/// CLASS_MEMBER_EXTERNALMETHOD(MyNewName5, {L"parameter"}, int(MyClass::*)(int), mynamespace::AGlobalFunction)
/// CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(MyNewName5, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&), [](MyClass* a, int b, const WString& c){return 0;}, L"*", L"*")
///
/// XI) Add unoverloaded static functions
/// CLASS_MEMBER_STATIC_METHOD(MyFunction4, NO_PARAMETER)
/// CLASS_MEMBER_STATIC_METHOD(MyFunction5, {L"parameter1" _ L"parameter2"})
///
/// XII) Add overloaded static functions
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction6, NO_PARAMETER, int(*)())
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction6, {L"parameter"}, int(*)(int))
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction6, {L"parameter1" _ L"parameter2"}, int(*)(int, const WString&))
///
/// XIII) Inject global functions as static methods:
/// CLASS_MEMBER_STATIC_EXTERNALMETHOD(MyNewName6, {L"parameter"}, int(*)(int), mynamespace::AGlobalFunction2)
/// CLASS_MEMBER_STATIC_EXTERNALMETHOD_INVOKETEMPLATE(MyNewName6, {L"parameter1" _ L"parameter2"}, int(*)(int, const WString&), [](int b, const WString& c){return 0;}, L"*")
///
/// XIV) Add a getter function as a property
/// CLASS_MEMBER_PROPERTY_READONLY_FAST(X)
/// which is short for
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
/// CLASS_MEMBER_PROPERTY_READONLY(X, GetX)
///
/// XV) Add a pair of getter and setter functions as a property
/// CLASS_MEMBER_PROPERTY_FAST(X)
/// which is short for
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
/// CLASS_MEMBER_METHOD(SetX, {L"value"})
/// CLASS_MEMBER_PROPERTY(X, GetX, SetX)
///
/// XVI) Add a getter function as a property with a property changed event
/// CLASS_MEMBER_EVENT(XChanged)
/// CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(X)
/// which is short for
/// CLASS_MEMBER_EVENT(XChanged)
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
/// CLASS_MEMBER_PROPERTY_EVENT_READONLY(X, GetX, XChanged)
///
/// XVII) Add a pair of getter and setter functions as a property with a property changed event
/// CLASS_MEMBER_EVENT(XChanged)
/// CLASS_MEMBER_PROPERTY_EVENT_FAST(X)
/// which is short for
/// CLASS_MEMBER_EVENT(XChanged)
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
/// CLASS_MEMBER_METHOD(SetX, {L"value"})
/// CLASS_MEMBER_PROPERTY_EVENT(X, GetX, SetX, XChanged)
///
/// END_CLASS_MEMBER(MyClass)
///
/// If the code compiles, the class should look like this:
/// class MyClass : public Description<MyClass>
/// {
/// public:
/// MyClass();
/// MyClass(int numberParameter, const WString& stringParameter);
///
/// int MyFunction1();
/// int MyFunction2(int parameter1, const WString& parameter2);
/// int MyFunction3();
/// int MyFunction3(int parameter);
/// int MyFunction3(int parameter1, const WString& parameter2);
///
/// static int MyFunction4();
/// static int MyFunction5(int parameter1, const WString& parameter2);
/// static int MyFunction6();
/// static int MyFunction6(int parameter);
/// static int MyFunction6(int parameter1, const WString& parameter2);
///
/// Event<void()> XChanged;
/// int GetX();
/// void SetX(int value);
/// };
///
/// Ptr<MyClass> CreateMyClass(int numberParameter, const WString7 stringParameter);
/// int GlobalFunction(MyClass* self, int parameter);
///
/// e) interface:
/// An interface is defined by
/// I) Directly or indirectly inherits [T:vl.reflection.IDescriptable]
/// II) The only registered constructor (if exists) should use Ptr<[T:vl.reflection.description.IValueInterfaceProxy]> as a parameter
///
/// Suppose you have an interface like this:
/// class IMyInterface : public virtual IDescriptable, public Description<IMyInterface>
/// {
/// public:
/// int GetX();
/// void SetX(int value);
/// };
///
/// If you want this interface implementable by Workflow script, you should first add a proxy like this:
/// #pragma warning(push)
/// #pragma warning(disable:4250)
/// BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(IMyInterface)
/// or BEGIN_INTERFACE_PROXY_RAWPTR(IMyInterface, baseInterfaces...)
/// or BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IMyInterface)
/// or BEGIN_INTERFACE_PROXY_SHAREDPTR(IMyInterface, baseInterfaces...)
/// int GetX()override
/// {
/// INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetX)
/// }
///
/// void SetX(int value)override
/// {
/// INVOKE_INTERFACE_PROXY(SetX, value)
/// }
/// END_INTERFACE_PROXY(IMyInterface)
/// #pragma warning(pop)
///
/// And then use this code to register the interface:
/// BEGIN_INTERFACE_MEMBER(IMyInterface)
/// ...
/// END_INTERFACE_MEMBER(IMyInterface)
///
/// Everything else is the same as registering classes. Use BEGIN_INTERFACE_MEMBER_NOPROXY to register an interface without a proxy, which means you cannot implement it in runtime dynamically.
///
/// #undef _
///
/// 5) (in cpp files) Create a type loader:
/// class MyTypeLoader : public Object, public ITypeLoader
/// {
/// public:
/// void Load(ITypeManager* manager)
/// {
/// MY_TYPELIST(ADD_TYPE_INFO)
/// }
///
/// void Unload(ITypeManager* manager)
/// {
/// }
/// };
///
/// 6) Load types when you think is a good timing using this code:
/// vl::reflection::description::GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
///
/// ]]></summary>
/// <typeparam name="T">Type of your created reflection class.</typeparam>
template<typename T>
class Description : public virtual DescriptableObject
{
protected:
#ifndef VCZH_DEBUG_NO_REFLECTION
static description::ITypeDescriptor* associatedTypeDescriptor;
#endif
public:
Description()
{
#ifndef VCZH_DEBUG_NO_REFLECTION
if(objectSize<sizeof(T))
{
objectSize=sizeof(T);
if(!typeDescriptor || !*typeDescriptor || associatedTypeDescriptor)
{
typeDescriptor=&associatedTypeDescriptor;
}
}
#endif
}
#ifndef VCZH_DEBUG_NO_REFLECTION
static description::ITypeDescriptor* GetAssociatedTypeDescriptor()
{
return associatedTypeDescriptor;
}
static void SetAssociatedTypeDescroptor(description::ITypeDescriptor* typeDescroptor)
{
associatedTypeDescriptor=typeDescroptor;
}
#endif
};
template<typename T>
class AggregatableDescription : public Description<T>
{
};
#ifndef VCZH_DEBUG_NO_REFLECTION
template<typename T>
description::ITypeDescriptor* Description<T>::associatedTypeDescriptor=0;
#endif
/// <summary>Base types of all reflectable interfaces. All reflectable interface types should be virtual inherited.</summary>
class IDescriptable : public virtual Interface, public Description<IDescriptable>
{
public:
~IDescriptable(){}
};
/***********************************************************************
ReferenceCounterOperator
***********************************************************************/
}
template<typename T>
struct ReferenceCounterOperator<T, typename RequiresConvertable<T, reflection::DescriptableObject>::YesNoType>
{
static __forceinline volatile vint* CreateCounter(T* reference)
{
reflection::DescriptableObject* obj=reference;
#ifndef VCZH_DEBUG_NO_REFLECTION
if (obj->IsAggregated())
{
if (auto root = obj->GetAggregationRoot())
{
return &root->referenceCounter;
}
}
#endif
return &obj->referenceCounter;
}
static __forceinline void DeleteReference(volatile vint* counter, void* reference)
{
reflection::DescriptableObject* obj=(T*)reference;
obj->Dispose(false);
}
};
namespace reflection
{
namespace description
{
/***********************************************************************
Value
***********************************************************************/
class IBoxedValue : public virtual IDescriptable, public Description<IBoxedValue>
{
public:
enum CompareResult
{
Smaller,
Greater,
Equal,
NotComparable,
};
virtual Ptr<IBoxedValue> Copy() = 0;
virtual CompareResult ComparePrimitive(Ptr<IBoxedValue> boxedValue) = 0;
};
/// <summary>A type to store all values of reflectable types.</summary>
class Value : public Object
{
public:
/// <summary>Representing how the value is stored.</summary>
enum ValueType
{
/// <summary>The value is null.</summary>
Null,
/// <summary>The value stored using a raw pointer.</summary>
RawPtr,
/// <summary>The value stored using a smart pointer.</summary>
SharedPtr,
/// <summary>The value stored using a boxed value.</summary>
BoxedValue,
};
protected:
ValueType valueType;
DescriptableObject* rawPtr;
Ptr<DescriptableObject> sharedPtr;
Ptr<IBoxedValue> boxedValue;
#ifndef VCZH_DEBUG_NO_REFLECTION
ITypeDescriptor* typeDescriptor;
#endif
Value(DescriptableObject* value);
Value(Ptr<DescriptableObject> value);
Value(Ptr<IBoxedValue> value, ITypeDescriptor* associatedTypeDescriptor);
vint Compare(const Value& a, const Value& b)const;
public:
Value();
Value(const Value& value);
Value& operator=(const Value& value);
bool operator==(const Value& value)const { return Compare(*this, value) == 0; }
bool operator!=(const Value& value)const { return Compare(*this, value) != 0; }
bool operator<(const Value& value)const { return Compare(*this, value)<0; }
bool operator<=(const Value& value)const { return Compare(*this, value) <= 0; }
bool operator>(const Value& value)const { return Compare(*this, value)>0; }
bool operator>=(const Value& value)const { return Compare(*this, value) >= 0; }
/// <summary>Get how the value is stored.</summary>
/// <returns>How the value is stored.</returns>
ValueType GetValueType()const;
/// <summary>Get the stored raw pointer if possible.</summary>
/// <returns>The stored raw pointer. Returns null if failed.</returns>
DescriptableObject* GetRawPtr()const;
/// <summary>Get the stored shared pointer if possible.</summary>
/// <returns>The stored shared pointer. Returns null if failed.</returns>
Ptr<DescriptableObject> GetSharedPtr()const;
/// <summary>Get the stored text if possible.</summary>
/// <returns>The stored text. Returns empty if failed.</returns>
Ptr<IBoxedValue> GetBoxedValue()const;
/// <summary>Get the real type of the stored object.</summary>
/// <returns>The real type. Returns null if the value is null.</returns>
bool IsNull()const;
#ifndef VCZH_DEBUG_NO_REFLECTION
ITypeDescriptor* GetTypeDescriptor()const;
WString GetTypeFriendlyName()const;
bool CanConvertTo(ITypeDescriptor* targetType, ValueType targetValueType)const;
bool CanConvertTo(ITypeInfo* targetType)const;
#endif
/// <summary>Store a raw pointer.</summary>
/// <returns>The boxed value.</returns>
/// <param name="value">The raw pointer to store.</param>
static Value From(DescriptableObject* value);
/// <summary>Store a shared pointer.</summary>
/// <returns>The boxed value.</returns>
/// <param name="value">The shared pointer to store.</param>
static Value From(Ptr<DescriptableObject> value);
/// <summary>Store a text.</summary>
/// <returns>The boxed value.</returns>
/// <param name="value">The text to store.</param>
/// <param name="type">The type that you expect to interpret the text.</param>
static Value From(Ptr<IBoxedValue> value, ITypeDescriptor* type);
#ifndef VCZH_DEBUG_NO_REFLECTION
static IMethodInfo* SelectMethod(IMethodGroupInfo* methodGroup, collections::Array<Value>& arguments);
static Value Create(ITypeDescriptor* type);
static Value Create(ITypeDescriptor* type, collections::Array<Value>& arguments);
static Value Create(const WString& typeName);
static Value Create(const WString& typeName, collections::Array<Value>& arguments);
static Value InvokeStatic(const WString& typeName, const WString& name);
static Value InvokeStatic(const WString& typeName, const WString& name, collections::Array<Value>& arguments);
Value GetProperty(const WString& name)const;
void SetProperty(const WString& name, const Value& newValue);
Value Invoke(const WString& name)const;
Value Invoke(const WString& name, collections::Array<Value>& arguments)const;
Ptr<IEventHandler> AttachEvent(const WString& name, const Value& function)const;
bool DetachEvent(const WString& name, Ptr<IEventHandler> handler)const;
#endif
/// <summary>Dispose the object is it is stored as a raw pointer.</summary>
/// <returns>Returns true if the object is disposed. Returns false if the object cannot be disposed. An exception will be thrown if the reference counter is not 0.</returns>
bool DeleteRawPtr();
};
/***********************************************************************
ValueType
***********************************************************************/
class IValueType : public virtual IDescriptable, public Description<IValueType>
{
public:
template<typename T>
class TypedBox : public IBoxedValue
{
private:
template<typename U = T>
static CompareResult ComparePrimitiveInternal(const U& a, const U& b, typename AcceptAlways<vint, decltype(&TypedValueSerializerProvider<U>::Compare)>::Type)
{
return TypedValueSerializerProvider<U>::Compare(a, b);
}
template<typename U = T>
static CompareResult ComparePrimitiveInternal(const U& a, const U& b, double)
{
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdynamic-class-memaccess"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdynamic-class-memaccess"
#endif
auto result = memcmp(&a, &b, sizeof(U));
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#endif
if (result < 0) return IBoxedValue::Smaller;
if (result > 0) return IBoxedValue::Greater;
return IBoxedValue::Equal;
}
public:
T value;
TypedBox()
:value{}
{
}
TypedBox(const T& _value)
:value(_value)
{
}
Ptr<IBoxedValue> Copy()override
{
return new TypedBox<T>(value);
}
CompareResult ComparePrimitive(Ptr<IBoxedValue> boxedValue)override
{
if (auto typedBox = boxedValue.Cast<TypedBox<T>>())
{
return ComparePrimitiveInternal(value, typedBox->value, (vint)0);
}
else
{
return IBoxedValue::NotComparable;
}
}
};
virtual Value CreateDefault() = 0;
virtual IBoxedValue::CompareResult Compare(const Value& a, const Value& b) = 0;
};
class IEnumType : public virtual IDescriptable, public Description<IEnumType>
{
public:
virtual bool IsFlagEnum() = 0;
virtual vint GetItemCount() = 0;
virtual WString GetItemName(vint index) = 0;
virtual vuint64_t GetItemValue(vint index) = 0;
virtual vint IndexOfItem(WString name) = 0;
virtual Value ToEnum(vuint64_t value) = 0;
virtual vuint64_t FromEnum(const Value& value) = 0;
};
class ISerializableType : public virtual IDescriptable, public Description<ISerializableType>
{
public:
virtual bool Serialize(const Value& input, WString& output) = 0;
virtual bool Deserialize(const WString& input, Value& output) = 0;
};
/***********************************************************************
ITypeDescriptor (type)
***********************************************************************/
enum class TypeInfoHint
{
Normal,
LazyList,
Array,
List,
SortedList,
ObservableList,
Dictionary,
NativeCollectionReference,
};
class ITypeInfo : public virtual IDescriptable, public Description<ITypeInfo>
{
public:
enum Decorator
{
RawPtr,
SharedPtr,
Nullable,
TypeDescriptor,
Generic,
};
virtual Decorator GetDecorator() = 0;
virtual TypeInfoHint GetHint() = 0;
virtual ITypeInfo* GetElementType() = 0;
virtual ITypeDescriptor* GetTypeDescriptor() = 0;
virtual vint GetGenericArgumentCount() = 0;
virtual ITypeInfo* GetGenericArgument(vint index) = 0;
virtual WString GetTypeFriendlyName() = 0;
};
/***********************************************************************
ITypeDescriptor (basic)
***********************************************************************/
class IMemberInfo : public virtual IDescriptable, public Description<IMemberInfo>
{
public:
virtual ITypeDescriptor* GetOwnerTypeDescriptor()=0;
virtual const WString& GetName()=0;
};
/***********************************************************************
ITypeDescriptor (event)
***********************************************************************/
class IEventHandler : public virtual IDescriptable, public Description<IEventHandler>
{
public:
virtual bool IsAttached()=0;
};
class IEventInfo : public virtual IMemberInfo, public Description<IEventInfo>
{
public:
class ICpp : public virtual IDescriptable, public Description<ICpp>
{
public:
/*
Arguments:
$Name: Event name
$This: Expression for the "this" argument
$Handler: Event handler function / Event handler object
$Arguments: Expressions for arguments separated by ", "
Default (for Vlpp Event):
Attach: ::vl::__vwsn::EventAttach($This->$Name, $Handler)
Detach: ::vl::__vwsn::EventDetach($This->$Name, $Handler)
Invoke: ::vl::__vwsn::EventInvoke($This->$Name)($Arguments)
GetInvokeTemplate() == L"*":
This event does not exist in C++
*/
virtual const WString& GetAttachTemplate() = 0;
virtual const WString& GetDetachTemplate() = 0;
virtual const WString& GetInvokeTemplate() = 0;
};
/*
Priority:
1. Use ICpp
2. Use Default
*/
virtual ICpp* GetCpp() = 0;
virtual ITypeInfo* GetHandlerType()=0;
virtual vint GetObservingPropertyCount()=0;
virtual IPropertyInfo* GetObservingProperty(vint index)=0;
virtual Ptr<IEventHandler> Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler)=0;
virtual bool Detach(const Value& thisObject, Ptr<IEventHandler> handler)=0;
virtual void Invoke(const Value& thisObject, Ptr<IValueList> arguments)=0;
};
/***********************************************************************
ITypeDescriptor (property)
***********************************************************************/
class IPropertyInfo : public virtual IMemberInfo, public Description<IPropertyInfo>
{
public:
class ICpp : public virtual IDescriptable, public Description<ICpp>
{
public:
/*
Arguments:
$Type: C++ full type name
$Name: Property name
$This: Expression for the "this" argument
Default:
Struct: $This.$Name
Class: $This->$Name
Example:
Token in syntax tree: $This->$Name.value
GetReferenceTemplate() == L"*":
This property does not exist in C++
*/
virtual const WString& GetReferenceTemplate() = 0;
};
/*
Priority:
1. Use ICpp
2. Use ICpp from getter and setter
3. Use default
*/
virtual ICpp* GetCpp() = 0;
virtual bool IsReadable()=0;
virtual bool IsWritable()=0;
virtual ITypeInfo* GetReturn()=0;
virtual IMethodInfo* GetGetter()=0;
virtual IMethodInfo* GetSetter()=0;
virtual IEventInfo* GetValueChangedEvent()=0;
virtual Value GetValue(const Value& thisObject)=0;
virtual void SetValue(Value& thisObject, const Value& newValue)=0;
};
/***********************************************************************
ITypeDescriptor (method)
***********************************************************************/
class IParameterInfo : public virtual IMemberInfo, public Description<IParameterInfo>
{
public:
virtual ITypeInfo* GetType()=0;
virtual IMethodInfo* GetOwnerMethod()=0;
};
class IMethodInfo : public virtual IMemberInfo, public Description<IMethodInfo>
{
public:
class ICpp : public virtual IDescriptable, public Description<ICpp>
{
public:
/*
Arguments:
$Type: C++ full type name
$Func: C++ function type (e.g. void(int)), object type not included for method
$Name: Method name
$This: Expression for the "this" argument;
$Arguments: Expressions for arguments separated by ", "
Default:
Constructor: new $Type($Arguments)
Static: $Type::$Name($Arguments)
Normal: $This->$Name($Arguments)
Example:
External constructor: <full-function-name>($Arguments)
External method: <full-function-name>($This, $Arguments)
Renamed method: $This-><function-name>($Arguments)
GetInvokeTemplate() == L"*":
This method does not exist in C++
*/
virtual const WString& GetInvokeTemplate() = 0;
virtual const WString& GetClosureTemplate() = 0;
};
/*
Priority:
1. Use ICpp
2. Use default
*/
virtual ICpp* GetCpp() = 0;
virtual IMethodGroupInfo* GetOwnerMethodGroup()=0;
virtual IPropertyInfo* GetOwnerProperty()=0;
virtual vint GetParameterCount()=0;
virtual IParameterInfo* GetParameter(vint index)=0;
virtual ITypeInfo* GetReturn()=0;
virtual bool IsStatic()=0;
virtual void CheckArguments(collections::Array<Value>& arguments)=0;
virtual Value Invoke(const Value& thisObject, collections::Array<Value>& arguments)=0;
virtual Value CreateFunctionProxy(const Value& thisObject) = 0;
};
class IMethodGroupInfo : public virtual IMemberInfo, public Description<IMethodGroupInfo>
{
public:
virtual vint GetMethodCount()=0;
virtual IMethodInfo* GetMethod(vint index)=0;
};
/***********************************************************************
ITypeDescriptor
***********************************************************************/
enum class TypeDescriptorFlags : vint
{
Undefined = 0,
Object = 1<<0,
IDescriptable = 1<<1,
Class = 1<<2,
Interface = 1<<3,
Primitive = 1<<4,
Struct = 1<<5,
FlagEnum = 1<<6,
NormalEnum = 1<<7,
ClassType = Object | Class,
InterfaceType = IDescriptable | Interface,
ReferenceType = ClassType | InterfaceType,
EnumType = FlagEnum | NormalEnum,
StructType = Primitive | Struct,
};
inline TypeDescriptorFlags operator&(TypeDescriptorFlags a, TypeDescriptorFlags b)
{
return (TypeDescriptorFlags)((vint)a & (vint)b);
}
inline TypeDescriptorFlags operator|(TypeDescriptorFlags a, TypeDescriptorFlags b)
{
return (TypeDescriptorFlags)((vint)a | (vint)b);
}
class ITypeDescriptor : public virtual IDescriptable, public Description<ITypeDescriptor>
{
public:
class ICpp : public virtual IDescriptable, public Description<ICpp>
{
public:
/*
Default: refer to TypeInfoContent::VlppType
GetFullName() == L"*":
This type does not exist in C++
*/
virtual const WString& GetFullName() = 0;
};
/*
Priority:
1. Use ICpp
2. Use default
*/
virtual ICpp* GetCpp() = 0;
virtual TypeDescriptorFlags GetTypeDescriptorFlags() = 0;
virtual bool IsAggregatable() = 0;
virtual const WString& GetTypeName() = 0;
virtual IValueType* GetValueType() = 0;
virtual IEnumType* GetEnumType() = 0;
virtual ISerializableType* GetSerializableType() = 0;
virtual vint GetBaseTypeDescriptorCount() = 0;
virtual ITypeDescriptor* GetBaseTypeDescriptor(vint index) = 0;
virtual bool CanConvertTo(ITypeDescriptor* targetType) = 0;
virtual vint GetPropertyCount() = 0;
virtual IPropertyInfo* GetProperty(vint index) = 0;
virtual bool IsPropertyExists(const WString& name, bool inheritable) = 0;
virtual IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable) = 0;
virtual vint GetEventCount() = 0;
virtual IEventInfo* GetEvent(vint index) = 0;
virtual bool IsEventExists(const WString& name, bool inheritable) = 0;
virtual IEventInfo* GetEventByName(const WString& name, bool inheritable) = 0;
virtual vint GetMethodGroupCount() = 0;
virtual IMethodGroupInfo* GetMethodGroup(vint index) = 0;
virtual bool IsMethodGroupExists(const WString& name, bool inheritable) = 0;
virtual IMethodGroupInfo* GetMethodGroupByName(const WString& name, bool inheritable) = 0;
virtual IMethodGroupInfo* GetConstructorGroup() = 0;
};
#ifndef VCZH_DEBUG_NO_REFLECTION
/***********************************************************************
ITypeManager
***********************************************************************/
class ITypeManager;
class ITypeLoader : public virtual Interface
{
public:
virtual void Load(ITypeManager* manager)=0;
virtual void Unload(ITypeManager* manager)=0;
};
class ITypeManager : public virtual Interface
{
public:
virtual vint GetTypeDescriptorCount()=0;
virtual ITypeDescriptor* GetTypeDescriptor(vint index)=0;
virtual ITypeDescriptor* GetTypeDescriptor(const WString& name)=0;
virtual bool SetTypeDescriptor(const WString& name, Ptr<ITypeDescriptor> typeDescriptor)=0;
virtual bool AddTypeLoader(Ptr<ITypeLoader> typeLoader)=0;
virtual bool RemoveTypeLoader(Ptr<ITypeLoader> typeLoader)=0;
virtual bool Load()=0;
virtual bool Unload()=0;
virtual bool Reload()=0;
virtual bool IsLoaded()=0;
virtual ITypeDescriptor* GetRootType()=0;
};
extern ITypeManager* GetGlobalTypeManager();
extern bool DestroyGlobalTypeManager();
extern bool ResetGlobalTypeManager();
extern ITypeDescriptor* GetTypeDescriptor(const WString& name);
extern bool IsInterfaceType(ITypeDescriptor* typeDescriptor, bool& acceptProxy);
extern void LogTypeManager(stream::TextWriter& writer);
/***********************************************************************
Cpp Helper Functions
***********************************************************************/
extern WString CppGetFullName(ITypeDescriptor* type);
extern WString CppGetReferenceTemplate(IPropertyInfo* prop);
extern WString CppGetClosureTemplate(IMethodInfo* method);
extern WString CppGetInvokeTemplate(IMethodInfo* method);
extern WString CppGetAttachTemplate(IEventInfo* ev);
extern WString CppGetDetachTemplate(IEventInfo* ev);
extern WString CppGetInvokeTemplate(IEventInfo* ev);
extern bool CppExists(ITypeDescriptor* type);
extern bool CppExists(IPropertyInfo* prop);
extern bool CppExists(IMethodInfo* method);
extern bool CppExists(IEventInfo* ev);
#endif
/***********************************************************************
Exceptions
***********************************************************************/
class TypeDescriptorException abstract : public Exception
{
public:
TypeDescriptorException(const WString& message)
:Exception(message)
{
}
};
class ValueNotDisposableException : public TypeDescriptorException
{
public:
ValueNotDisposableException()
:TypeDescriptorException(L"Cannot dispose an object whose reference counter is not 0.")
{
}
};
#ifndef VCZH_DEBUG_NO_REFLECTION
class TypeNotExistsException : public TypeDescriptorException
{
public:
TypeNotExistsException(const WString& name)
:TypeDescriptorException(L"Cannot find the type \""+name+L"\".")
{
}
};
class ConstructorNotExistsException : public TypeDescriptorException
{
public:
ConstructorNotExistsException(ITypeDescriptor* type)
:TypeDescriptorException(L"Cannot find any constructor in type \"" + type->GetTypeName() + L"\".")
{
}
};
class MemberNotExistsException : public TypeDescriptorException
{
public:
MemberNotExistsException(const WString& name, ITypeDescriptor* type)
:TypeDescriptorException(L"Cannot find the member \"" + name + L"\" in type \"" + type->GetTypeName() + L"\".")
{
}
};
class PropertyIsNotReadableException : public TypeDescriptorException
{
public:
PropertyIsNotReadableException(IPropertyInfo* propertyInfo)
:TypeDescriptorException(L"Cannot read value from a property \"" + propertyInfo->GetName() + L"\" that is not readable in type \"" + propertyInfo->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
{
}
};
class PropertyIsNotWritableException : public TypeDescriptorException
{
public:
PropertyIsNotWritableException(IPropertyInfo* propertyInfo)
:TypeDescriptorException(L"Cannot write value to a property \"" + propertyInfo->GetName() + L"\" that is not writable in type \"" + propertyInfo->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
{
}
};
class ArgumentNullException : public TypeDescriptorException
{
public:
ArgumentNullException(const WString& name, const WString& member)
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when accessing its member \"" + member + L"\".")
{
}
ArgumentNullException(const WString& name, IMethodInfo* target)
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when invoking method \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
{
}
ArgumentNullException(const WString& name, IEventInfo* target)
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when accessing event \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
{
}
ArgumentNullException(const WString& name, IPropertyInfo* target)
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when invoking property \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
{
}
};
class ArgumentTypeMismtatchException : public TypeDescriptorException
{
public:
ArgumentTypeMismtatchException(const WString& name, ITypeInfo* expected, const Value& actual)
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual.GetTypeFriendlyName() + L"\" to \"" + expected->GetTypeFriendlyName() + L"\".")
{
}
ArgumentTypeMismtatchException(const WString& name, ITypeDescriptor* type, Value::ValueType valueType, const Value& actual)
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual.GetTypeFriendlyName() + L"\" to \"" +
(valueType == Value::SharedPtr ? L"Ptr<" : L"") + type->GetTypeName() + (valueType == Value::SharedPtr ? L">" : valueType == Value::RawPtr ? L"*" : L"")
+ L"\".")
{
}
};
class ArgumentCountMismtatchException : public TypeDescriptorException
{
public:
ArgumentCountMismtatchException()
:TypeDescriptorException(L"Argument count does not match the definition.")
{
}
ArgumentCountMismtatchException(IMethodGroupInfo* target)
:TypeDescriptorException(L"Argument count does not match the definition when invoking method \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
{
}
};
#endif
}
}
}
#endif
/***********************************************************************
.\PARSING\PARSINGTREE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::Parsing Tree
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSINGTREE
#define VCZH_PARSING_PARSINGTREE
namespace vl
{
namespace parsing
{
/***********************************************************************
Location
***********************************************************************/
/// <summary>A type representing text position.</summary>
struct ParsingTextPos
{
static const vint UnknownValue=-2;
/// <summary>Character index, begins at 0.</summary>
vint index;
/// <summary>Row number, begins at 0.</summary>
vint row;
/// <summary>Column number, begins at 0.</summary>
vint column;
ParsingTextPos()
:index(UnknownValue)
,row(UnknownValue)
,column(UnknownValue)
{
}
ParsingTextPos(vint _index)
:index(_index)
,row(UnknownValue)
,column(UnknownValue)
{
}
ParsingTextPos(vint _row, vint _column)
:index(UnknownValue)
,row(_row)
,column(_column)
{
}
ParsingTextPos(vint _index, vint _row, vint _column)
:index(_index)
,row(_row)
,column(_column)
{
}
/// <summary>Test if this position a valid position.</summary>
/// <returns>Returns true if this position is a valid position.</returns>
bool IsInvalid()const
{
return index < 0 && row < 0 && column < 0;
}
static vint Compare(const ParsingTextPos& a, const ParsingTextPos& b)
{
if (a.IsInvalid() && b.IsInvalid())
{
return 0;
}
else if (a.IsInvalid())
{
return -1;
}
else if (b.IsInvalid())
{
return 1;
}
else if (a.index >= 0 && b.index >= 0)
{
return a.index - b.index;
}
else if (a.row >= 0 && a.column >= 0 && b.row >= 0 && b.column >= 0)
{
if (a.row == b.row)
{
return a.column - b.column;
}
else
{
return a.row - b.row;
}
}
else
{
return 0;
}
}
bool operator==(const ParsingTextPos& pos)const{return Compare(*this, pos)==0;}
bool operator!=(const ParsingTextPos& pos)const{return Compare(*this, pos)!=0;}
bool operator<(const ParsingTextPos& pos)const{return Compare(*this, pos)<0;}
bool operator<=(const ParsingTextPos& pos)const{return Compare(*this, pos)<=0;}
bool operator>(const ParsingTextPos& pos)const{return Compare(*this, pos)>0;}
bool operator>=(const ParsingTextPos& pos)const{return Compare(*this, pos)>=0;}
};
/// <summary>A type representing text range.</summary>
struct ParsingTextRange
{
/// <summary>Text position for the first character.</summary>
ParsingTextPos start;
/// <summary>Text position for the last character.</summary>
ParsingTextPos end;
/// <summary>Code index, refer to [F:vl.regex.RegexToken.codeIndex]</summary>
vint codeIndex;
ParsingTextRange()
:codeIndex(-1)
{
end.index=-1;
end.column=-1;
}
ParsingTextRange(const ParsingTextPos& _start, const ParsingTextPos& _end, vint _codeIndex = -1)
:start(_start)
, end(_end)
, codeIndex(_codeIndex)
{
}
ParsingTextRange(const regex::RegexToken* startToken, const regex::RegexToken* endToken)
:codeIndex(startToken->codeIndex)
{
start.index=startToken->start;
start.row=startToken->rowStart;
start.column=startToken->columnStart;
end.index=endToken->start+endToken->length-1;
end.row=endToken->rowEnd;
end.column=endToken->columnEnd;
}
bool operator==(const ParsingTextRange& range)const{return start==range.start && end==range.end;}
bool operator!=(const ParsingTextRange& range)const{return start!=range.start || end!=range.end;}
bool Contains(const ParsingTextPos& pos)const{return start<=pos && pos<=end;}
bool Contains(const ParsingTextRange& range)const{return start<=range.start && range.end<=end;}
};
}
namespace stream
{
namespace internal
{
BEGIN_SERIALIZATION(parsing::ParsingTextPos)
SERIALIZE(index)
SERIALIZE(row)
SERIALIZE(column)
END_SERIALIZATION
BEGIN_SERIALIZATION(parsing::ParsingTextRange)
SERIALIZE(start)
SERIALIZE(end)
SERIALIZE(codeIndex)
END_SERIALIZATION
}
}
namespace parsing
{
/***********************************************************************
General Syntax Tree
***********************************************************************/
class ParsingTreeNode;
class ParsingTreeToken;
class ParsingTreeObject;
class ParsingTreeArray;
/// <summary>Abstract syntax tree.</summary>
class ParsingTreeNode : public Object, public reflection::Description<ParsingTreeNode>
{
public:
class IVisitor : public Interface
{
public:
virtual void Visit(ParsingTreeToken* node)=0;
virtual void Visit(ParsingTreeObject* node)=0;
virtual void Visit(ParsingTreeArray* node)=0;
};
class TraversalVisitor : public Object, public IVisitor
{
public:
enum TraverseDirection
{
ByTextPosition,
ByStorePosition
};
protected:
TraverseDirection direction;
public:
TraversalVisitor(TraverseDirection _direction);
virtual void BeforeVisit(ParsingTreeToken* node);
virtual void AfterVisit(ParsingTreeToken* node);
virtual void BeforeVisit(ParsingTreeObject* node);
virtual void AfterVisit(ParsingTreeObject* node);
virtual void BeforeVisit(ParsingTreeArray* node);
virtual void AfterVisit(ParsingTreeArray* node);
virtual void Visit(ParsingTreeToken* node)override;
virtual void Visit(ParsingTreeObject* node)override;
virtual void Visit(ParsingTreeArray* node)override;
};
protected:
typedef collections::List<Ptr<ParsingTreeNode>> NodeList;
ParsingTextRange codeRange;
ParsingTreeNode* parent;
NodeList cachedOrderedSubNodes;
virtual const NodeList& GetSubNodesInternal()=0;
bool BeforeAddChild(Ptr<ParsingTreeNode> node);
void AfterAddChild(Ptr<ParsingTreeNode> node);
bool BeforeRemoveChild(Ptr<ParsingTreeNode> node);
void AfterRemoveChild(Ptr<ParsingTreeNode> node);
public:
ParsingTreeNode(const ParsingTextRange& _codeRange);
~ParsingTreeNode();
virtual void Accept(IVisitor* visitor)=0;
virtual Ptr<ParsingTreeNode> Clone()=0;
ParsingTextRange GetCodeRange();
void SetCodeRange(const ParsingTextRange& range);
/// <summary>Precalculate for enhance searching performance for this node and all child nodes.</summary>
void InitializeQueryCache();
/// <summary>Clear all cache made by <see cref="InitializeQueryCache"/>.</summary>
void ClearQueryCache();
/// <summary>Get the parent node. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
/// <returns>The parent node.</returns>
ParsingTreeNode* GetParent();
/// <summary>Get the child nodes. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
/// <returns>The child nodes.</returns>
const NodeList& GetSubNodes();
/// <summary>Find a direct child node at the position. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
/// <returns>The found node.</returns>
/// <param name="position">The position.</param>
ParsingTreeNode* FindSubNode(const ParsingTextPos& position);
/// <summary>Find a direct child node at the range. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
/// <returns>The found node.</returns>
/// <param name="range">The range.</param>
ParsingTreeNode* FindSubNode(const ParsingTextRange& range);
/// <summary>Find a most deepest indirect child node at the position. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
/// <returns>The found node.</returns>
/// <param name="position">The position.</param>
ParsingTreeNode* FindDeepestNode(const ParsingTextPos& position);
/// <summary>Find a most deepest indirect child node at the range. Using this function requires running <see cref="InitializeQueryCache"/> before.</summary>
/// <returns>The found node.</returns>
/// <param name="range">The range.</param>
ParsingTreeNode* FindDeepestNode(const ParsingTextRange& range);
};
/// <summary>Representing a token node in a abstract syntax tree.</summary>
class ParsingTreeToken : public ParsingTreeNode, public reflection::Description<ParsingTreeToken>
{
protected:
WString value;
vint tokenIndex;
const NodeList& GetSubNodesInternal()override;
public:
ParsingTreeToken(const WString& _value, vint _tokenIndex=-1, const ParsingTextRange& _codeRange=ParsingTextRange());
~ParsingTreeToken();
void Accept(IVisitor* visitor)override;
Ptr<ParsingTreeNode> Clone()override;
vint GetTokenIndex();
void SetTokenIndex(vint _tokenIndex);
/// <summary>Get the content of the token.</summary>
/// <returns>The content of the token.</returns>
const WString& GetValue();
void SetValue(const WString& _value);
};
/// <summary>Representing an object node in a abstract syntax tree.</summary>
class ParsingTreeObject : public ParsingTreeNode, public reflection::Description<ParsingTreeObject>
{
protected:
typedef collections::Dictionary<WString, Ptr<ParsingTreeNode>> NodeMap;
typedef collections::SortedList<WString> NameList;
typedef collections::List<WString> RuleList;
WString type;
NodeMap members;
RuleList rules;
const NodeList& GetSubNodesInternal()override;
public:
ParsingTreeObject(const WString& _type=L"", const ParsingTextRange& _codeRange=ParsingTextRange());
~ParsingTreeObject();
void Accept(IVisitor* visitor)override;
Ptr<ParsingTreeNode> Clone()override;
/// <summary>Get the type name of the object.</summary>
/// <returns>The type name of the object.</returns>
const WString& GetType();
void SetType(const WString& _type);
/// <summary>Get all fields of the object.</summary>
/// <returns>All fields of the object.</returns>
NodeMap& GetMembers();
/// <summary>Get a field of the object by the field name.</summary>
/// <returns>The field of the object.</returns>
/// <param name="name">The field name.</param>
Ptr<ParsingTreeNode> GetMember(const WString& name);
bool SetMember(const WString& name, Ptr<ParsingTreeNode> node);
bool RemoveMember(const WString& name);
/// <summary>Get all field names.</summary>
/// <returns>All field names of the object.</returns>
const NameList& GetMemberNames();
/// <summary>Get names of all rules that return this object.</summary>
/// <returns>Names of all rules.</returns>
RuleList& GetCreatorRules();
};
/// <summary>Representing an array node in a abstract syntax tree.</summary>
class ParsingTreeArray : public ParsingTreeNode, public reflection::Description<ParsingTreeArray>
{
protected:
typedef collections::List<Ptr<ParsingTreeNode>> NodeArray;
WString elementType;
NodeArray items;
const NodeList& GetSubNodesInternal()override;
public:
ParsingTreeArray(const WString& _elementType=L"", const ParsingTextRange& _codeRange=ParsingTextRange());
~ParsingTreeArray();
void Accept(IVisitor* visitor)override;
Ptr<ParsingTreeNode> Clone()override;
/// <summary>Get the type of all elements. It could be different from any actual element's type, but it should at least be the base types of them.</summary>
/// <returns>The type of all elements.</returns>
const WString& GetElementType();
void SetElementType(const WString& _elementType);
/// <summary>Get all elements in this array.</summary>
/// <returns>All elements in this array.</returns>
NodeArray& GetItems();
/// <summary>Get a specified element in this array by the index.</summary>
/// <returns>The element.</returns>
/// <param name="index">The index of the element.</param>
Ptr<ParsingTreeNode> GetItem(vint index);
bool SetItem(vint index, Ptr<ParsingTreeNode> node);
bool AddItem(Ptr<ParsingTreeNode> node);
bool InsertItem(vint index, Ptr<ParsingTreeNode> node);
bool RemoveItem(vint index);
bool RemoveItem(ParsingTreeNode* node);
vint IndexOfItem(ParsingTreeNode* node);
bool ContainsItem(ParsingTreeNode* node);
vint Count();
bool Clear();
};
/***********************************************************************
AST Building Block
***********************************************************************/
/// <summary>Base type of all strong typed syntax tree. Normally all strong typed syntax tree are generated from a grammar file using ParserGen.exe in Tools project. See [T:vl.parsing.tabling.ParsingTable] for details.</summary>
class ParsingTreeCustomBase : public Object, public reflection::Description<ParsingTreeCustomBase>
{
public:
/// <summary>Range of all tokens that form this object.</summary>
ParsingTextRange codeRange;
/// <summary>Names of all rules that return this object.</summary>
collections::List<WString> creatorRules;
};
/// <summary>Strong typed token syntax node, for all class fields of type "token" in the grammar file. See [T:vl.parsing.tabling.ParsingTable] for details.</summary>
class ParsingToken : public ParsingTreeCustomBase, public reflection::Description<ParsingToken>
{
public:
/// <summary>Type of the token, representing the index of a regular expression that creates this token in the regular expression list in the grammar file.</summary>
vint tokenIndex;
/// <summary>Content of the token.</summary>
WString value;
ParsingToken():tokenIndex(-1){}
};
/// <summary>Error.</summary>
class ParsingError : public Object, public reflection::Description<ParsingError>
{
public:
/// <summary>Range where the error happens.</summary>
ParsingTextRange codeRange;
/// <summary>Token at which the error happens.</summary>
const regex::RegexToken* token;
/// <summary>A syntax tree that contains this error.</summary>
ParsingTreeCustomBase* parsingTree;
/// <summary>The error message.</summary>
WString errorMessage;
ParsingError();
ParsingError(const WString& _errorMessage);
ParsingError(const regex::RegexToken* _token, const WString& _errorMessage);
ParsingError(ParsingTreeCustomBase* _parsingTree, const WString& _errorMessage);
~ParsingError();
};
/***********************************************************************
Syntax Tree Serialization Helper
***********************************************************************/
class ParsingTreeConverter : public Object
{
public:
typedef collections::List<regex::RegexToken> TokenList;
virtual Ptr<ParsingTreeCustomBase> ConvertClass(Ptr<ParsingTreeObject> obj, const TokenList& tokens)=0;
bool SetMember(ParsingToken& member, Ptr<ParsingTreeNode> node, const TokenList& tokens)
{
Ptr<ParsingTreeToken> token=node.Cast<ParsingTreeToken>();
if(token)
{
member.tokenIndex=token->GetTokenIndex();
member.value=token->GetValue();
member.codeRange=token->GetCodeRange();
return true;
}
return false;
}
template<typename T>
bool SetMember(collections::List<T>& member, Ptr<ParsingTreeNode> node, const TokenList& tokens)
{
Ptr<ParsingTreeArray> arr=node.Cast<ParsingTreeArray>();
if(arr)
{
member.Clear();
vint count=arr->Count();
for(vint i=0;i<count;i++)
{
T t;
SetMember(t, arr->GetItem(i), tokens);
member.Add(t);
}
return true;
}
return false;
}
template<typename T>
bool SetMember(Ptr<T>& member, Ptr<ParsingTreeNode> node, const TokenList& tokens)
{
Ptr<ParsingTreeObject> obj=node.Cast<ParsingTreeObject>();
if(obj)
{
Ptr<ParsingTreeCustomBase> tree=ConvertClass(obj, tokens);
if(tree)
{
tree->codeRange=node->GetCodeRange();
member=tree.Cast<T>();
return member;
}
}
return false;
}
};
/***********************************************************************
Logging
***********************************************************************/
class IParsingPrintNodeRecorder : public virtual Interface
{
public:
virtual void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range) = 0;
};
class ParsingEmptyPrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder
{
public:
ParsingEmptyPrintNodeRecorder();
~ParsingEmptyPrintNodeRecorder();
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
};
class ParsingMultiplePrintNodeRecorder : public Object, public virtual IParsingPrintNodeRecorder
{
typedef collections::List<Ptr<IParsingPrintNodeRecorder>> RecorderList;
protected:
RecorderList recorders;
public:
ParsingMultiplePrintNodeRecorder();
~ParsingMultiplePrintNodeRecorder();
void AddRecorder(Ptr<IParsingPrintNodeRecorder> recorder);
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
};
class ParsingOriginalLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
{
protected:
Ptr<IParsingPrintNodeRecorder> recorder;
public:
ParsingOriginalLocationRecorder(Ptr<IParsingPrintNodeRecorder> _recorder);
~ParsingOriginalLocationRecorder();
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
};
class ParsingGeneratedLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
{
typedef collections::Dictionary<ParsingTreeCustomBase*, ParsingTextRange> RangeMap;
protected:
RangeMap& rangeMap;
public:
ParsingGeneratedLocationRecorder(RangeMap& _rangeMap);
~ParsingGeneratedLocationRecorder();
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
};
class ParsingUpdateLocationRecorder : public Object, public virtual IParsingPrintNodeRecorder
{
public:
ParsingUpdateLocationRecorder();
~ParsingUpdateLocationRecorder();
void Record(ParsingTreeCustomBase* node, const ParsingTextRange& range)override;
};
class ParsingWriter : public stream::TextWriter
{
typedef collections::Pair<ParsingTreeCustomBase*, ParsingTextPos> NodePosPair;
typedef collections::List<NodePosPair> NodePosList;
protected:
stream::TextWriter& writer;
Ptr<IParsingPrintNodeRecorder> recorder;
vint codeIndex;
ParsingTextPos lastPos;
ParsingTextPos currentPos;
NodePosList nodePositions;
void HandleChar(wchar_t c);
public:
ParsingWriter(stream::TextWriter& _writer, Ptr<IParsingPrintNodeRecorder> _recorder = nullptr, vint _codeIndex = -1);
~ParsingWriter();
using stream::TextWriter::WriteString;
void WriteChar(wchar_t c)override;
void WriteString(const wchar_t* string, vint charCount)override;
void BeforePrint(ParsingTreeCustomBase* node);
void AfterPrint(ParsingTreeCustomBase* node);
};
extern void Log(ParsingTreeNode* node, const WString& originalInput, stream::TextWriter& writer, const WString& prefix=L"");
}
}
#endif
/***********************************************************************
.\PARSING\PARSINGTABLE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::Table
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSINGTABLE
#define VCZH_PARSING_PARSINGTABLE
namespace vl
{
namespace parsing
{
namespace tabling
{
/***********************************************************************
Parsing Table
***********************************************************************/
/// <summary><![CDATA[
/// The parsing table. When you complete a grammar file, ParserGen.exe which is in the Tools project will generate the C++ code for you to create a parsing table.
///
/// Here is a brief description of the grammar file format:
///
/// include:"<releative path to the Vlpp.h>" // (multiple) e.g. "../Import/Vlpp.h"
/// classPrefix:<class prefix> // (single) A prefix that will be add before all generated types and function. e.g. Xml
/// guard:<C++ header guard> // (single) The C++ header guard pattern macro name. e.g. VCZH_PARSING_XML_PARSINGXML_PARSER
/// namespace:<C++ namespaces> // (single) Namespaces separated by "." to contain the generated code. e.g. vl.parsing.xml
/// reflection:<namespace> // (single) Namespaces separated by "." to contain the name of reflectable types. In most of the cases this should be the same as namespace. e.g. vl.parsing.xml
/// parser:<name>(<rule>) // (multiple) Pair a function name to a rule name. ParserGen.exe will generate a function called "<prefix><name>" to parse the input using rule named "<rule>". e.g. ParseDocument(XDocument)
/// ambiguity:(enabled|disabled) // (single) Set to "enabled" indicating that the grammar is by design to have ambiguity.
/// serialization:(enabled|disabled) // (single) Set to "enabled" to serialize the parsing table as binary in the generated C++ code, so that when the "<prefix>LoadTable" function is called to load the table, it can deserialize from the binary data directly, instead of parsing the grammar again. But the grammar text will always be contained in the generated C++ code regardless of the value of "serialization", it can always be retrived using the "<prefix>GetParserTextBuffer" function.
/// grammar: // (single) Configuration ends here. All content after "grammar:" will be treated as the grammar to define the input.
///
/// Here is the brief description of the grammar.
/// The grammar is formed by 3 parts: types, token definitions and rule definitions. There is only one character escaping in strings: "", which means the " character.
///
/// 1) Types:
/// You can write attributes like @AttributeName("argument1", "argument2", ...) in the middle of types. But attributes don't affect the parsing. All attribute definitions will be stored in the generated parsing table, and who uses the table defines how attributes work. Multiple attributes are separated by ",".
///
/// a) Enum:
/// enum EnumName <attributes>
/// {
/// Item1 <attributes>,
/// Item2 <attributes>,
/// ... // cannot skip the last ","
/// }
///
/// b) Class:
/// class Name [ambiguous(AmbiguousType)] [: ParentType] <attributes>
/// {
/// Type name [(UnescapingFunction)] <attributes> ;
/// }
///
/// UnescapingFunction is a callback, which will be called when the contained type is fully constructed. The generated C++ code will define forward declarations of all unescaping functions in the cpp file. You should implement them in other places, or you will get linking errors.
///
/// If the grammar enables ambiguity, then the parsing result may contain ambiguous results for the same part of the input. For example, in C++:
/// A*B;
/// has two meaning (if we only consider context-free parsing): multiplication expression and pointer variable definition.
/// So if the grammar doesn't enable ambiguity, ParserGen.exe will refuce to generate C++ codes because the grammar is wrong.
/// If the grammar enables ambiguity, than the syntax tree should be defined like this:
///
/// class Statement ambiguous(AmbiguousStatement)
/// {
/// }
///
/// class AmbiguousStatement : Statement // due to the definition of "Statement" class, "AmbiguousStatement" should inherit from "Statement"
/// {
/// Statement[] items; // required by naming convention
/// }
///
/// class ExpressionStatement : Statement
/// {
/// Expression expression;
/// }
///
/// class VariableDefinitionStatement : Statement
/// {
/// Type type;
/// token name;
/// }
///
/// So for the "A*B;" part in the whole input, it will becomes an AmbiguousStatement, in which the "items" field contains 2 instance of "ExpressionStatement" and "VariableDefinitionStatement".
/// And you can write C++ code to resolve the ambiguity in later passes.
///
/// c) Type references:
/// Types can be defined globally or inside classes. Generic type is not supported. When you want to refer to a specific type, it could be:
/// token: Store a token, which will becomes [T:vl.parsing.ParsingToken].
/// Type[]: Array, which will becomes [T:vl.collections.List`2] to the element type. Token cannot be the element of arrays.
/// ClassName: Instance of a specified type, which will becomes [T:vl.Ptr`1] to that type.
/// OuterClass.InnerClass: Refer to the "InnerClass" defined inside the "OuterClass".
///
/// 2) Token definitions:
/// token TokenName = "regular expression" <attributes>;
/// discardtoken TokenName = "regular expression";
///
/// "discardtoken" means if such a token is identified, it will not appear in the lexical analyzing result. And you cannot refer to names of "discardtoken" in the grammar.
///
/// 3) Rule definitions:
/// rule RuleType RuleName <attributes>
/// = Grammar1
/// = Grammar2
/// ...
/// ;
///
/// It means rule "RuleName" is defined by those grammars, and matching this rule will create an instance of "RuleType" or its whatever types that inheriting "RuleType".
///
/// 4) Grammars:
/// RuleName: Defines an input that matches a rule.
/// TokenName: Defines an input that formed by the specified token.
/// "StringConstant": Defins an input that formed by exactly the string constant. This constant should define a token in the token list.
/// Grammar : FieldName: Defines an input that matches Grammar (should be either a rule name or a token name), and the result will be stored in field "FieldName" of a class, whose type will appear later.
/// !Grammar: Defines an input that matches Grammar, and the rule will return the result from this grammar. The input should still match other part of the rule, but result of other parts are ignored.
/// [Grammar]: Defines an input that, if match Grammar, will returns the result from that grammar; if not, the result is null.
/// {Grammar}: Defines an input that matches 0, 1 or more Grammar.
/// (Grammar): Defins an input that matches the the grammar. Brackets is only for changing operator associations.
/// Grammar1 Grammar2: Defines an input that should match Grammar1 right before Grammar2.
/// Grammar1 | Grammar2: Defines an input that match either Grammar1 or Grammar2.
/// Grammar as Type: Defines an input that matches the Grammar, and the whole branch of the rule creates an instance of type "Type"
/// Grammar with { FieldName = Value }: Defins an input that matches the Grammar, and will assign "Value", which should be an enum item, to the field "FieldName" of the created instance.
///
/// 5) Example
/// Here is an example to parse expression containing +, -, *, /, () and numbers:\
///
/// include:"Vlpp.h"
/// classPrefix:Calc
/// guard:VCZH_CALCULATOR_PARSER
/// namespace:vl.calculator
/// reflection:vl.calculator
/// parser:ParseExpression(Expr)
/// ambiguity:disabled
/// serialization:enabled
/// grammar:
///
/// class Expression
/// {
/// }
///
/// enum BinaryOperator
/// {
/// Add, Sub, Mul, Div,
/// }
///
/// class NumberExpression : Expression
/// {
/// token number;
/// }
///
/// class BinaryExpression : Expression
/// {
/// BinaryOperator op;
/// Expression left;
/// Expression right;
/// }
///
/// token ADD "\+"
/// token SUB "-"
/// token MUL "\*"
/// token DIV "\/"
/// token NUMBER "\d+(.\d+)?"
/// token OPEN "("
/// token CLOSE ")"
///
/// rule Expression Factor
/// = NUMBER : number as NumberExpression
/// = "(" !Expr ")"
/// ;
/// rule Expression Term
/// = !Factor
/// = Term : left "*" Factor : right as BinaryExpression with {op = "Mul"}
/// = Term : left "/" Factor : right as BinaryExpression with {op = "Div"}
/// ;
/// rule Expression Expr
/// = !Term
/// = Expr : left "+" Term : right as BinaryExpression with {op = "Add"}
/// = Expr : left "-" Term : right as BinaryExpression with {op = "Sub"}
/// ;
///
/// After using ParserGen.exe to generate C++ codes, you can do this:
/// auto table = CalcLoadTable(); // this table can be used several times, don't load each type for each parsing, it will have a big performance overhead.
/// List<Ptr<ParsingError>> errors;
/// auto expression = CalcParseExpression(L"(1+2) * (3+4)", table, errors); // it should be a Ptr<CalcExpression>, will returns nullptr if the input is wrong, with all errors filled into the "errors" variable.
/// You don't need to define the "errors" if you don't actually care how the input is wrong. There will be a overloaded version of CalcParseExpression that doesn't need the error list.
///
/// If you want to parse a wrong input and do automatic error recovering, which means if the input is not too wrong, you can still get a syntax tree, but some fields are null, with errors filled into the "error" variable. It will be a little complex:
/// auto table = CalcLoadTable(); // Load the table.
/// ParsingState state(L"(1+2) * (3+4)", table); // Initialize a state with the input and the table.
/// state.Reset(L"Expr"); // Set the rule to parse.
/// auto parser = CreateAutoRecoverParser(table); // Create an appropriate automatic error recoverable parser.
/// List<Ptr<ParsingError>> errors; // Define an error list.
/// auto node = parser->Parse(state, errors); // Parse to get an abstract syntax tree, which is a Ptr<ParsingTreeNode>.
/// if (node)
/// {
/// auto expression = CalcConvertParsingTreeNode(node, state.GetTokens()).Cast<CalcExpression>();
/// }
///
/// After you get a strong typed syntax tree, you can use the generated visitor interface to do something, like evaluate the results of the expression:
/// class Evaluator : public Object, public virtual CalcExpression::IVisitor
/// {
/// private:
/// double result;
///
/// double Call(CalcExpression* node)
/// {
/// node->Accept(this);
/// return result;
/// }
///
/// public:
///
/// static double Evaluate(CalcExpression* node)
/// {
/// return Evaluator().Call(node);
/// }
///
/// void Visit(CalcNumberExpression* node)override
/// {
/// return wtof(node->number.value);
/// }
///
/// void Visit(CalcBinaryExpression* node)override
/// {
/// auto left = Calc(node->left.Obj());
/// auto right = Calc(node->right.Obj());
/// switch (node->op)
/// {
/// case CalcBinaryOperator::Add:
/// result = left + right;
/// break;
/// case CalcBinaryOperator::Sub:
/// result = left 0 right;
/// break;
/// case CalcBinaryOperator::Mul:
/// result = left * right;
/// break;
/// case CalcBinaryOperator::Div:
/// result = left / right;
/// break;
/// }
/// }
/// };
///
/// Nullable<double> EvaluateExpression(const WString& input)
/// {
/// static auto table = CalcLoadTable();
/// auto expression = CalcParseExpression(input, table);
/// Nulllable<double> result;
/// if (expression)
/// {
/// result = Evaluator::Evaulate(expression.Obj());
/// }
/// return result;
/// }
///
/// ]]></summary>
class ParsingTable : public Object
{
public:
static const vint TokenBegin=0;
static const vint TokenFinish=1;
static const vint NormalReduce=2;
static const vint LeftRecursiveReduce=3;
static const vint UserTokenStart=4;
class AttributeInfo : public Object
{
public:
WString name;
collections::List<WString> arguments;
AttributeInfo(const WString& _name = L"")
:name(_name)
{
}
AttributeInfo* Argument(const WString& argument)
{
arguments.Add(argument);
return this;
}
};
class AttributeInfoList : public Object
{
public:
collections::List<Ptr<AttributeInfo>> attributes;
Ptr<AttributeInfo> FindFirst(const WString& name);
};
class TreeTypeInfo
{
public:
WString type;
vint attributeIndex;
TreeTypeInfo()
:attributeIndex(-1)
{
}
TreeTypeInfo(const WString& _type, vint _attributeIndex)
:type(_type)
,attributeIndex(_attributeIndex)
{
}
};
class TreeFieldInfo
{
public:
WString type;
WString field;
vint attributeIndex;
TreeFieldInfo()
:attributeIndex(-1)
{
}
TreeFieldInfo(const WString& _type, const WString& _field, vint _attributeIndex)
:type(_type)
,field(_field)
,attributeIndex(_attributeIndex)
{
}
};
class TokenInfo
{
public:
WString name;
WString regex;
vint regexTokenIndex;
vint attributeIndex;
TokenInfo()
:regexTokenIndex(-1)
,attributeIndex(-1)
{
}
TokenInfo(const WString& _name, const WString& _regex, vint _attributeIndex)
:name(_name)
,regex(_regex)
,regexTokenIndex(-1)
,attributeIndex(_attributeIndex)
{
}
};
class StateInfo
{
public:
WString ruleName;
WString stateName;
WString stateExpression;
WString ruleAmbiguousType; // filled in Initialize()
StateInfo()
{
}
StateInfo(const WString& _ruleName, const WString& _stateName, const WString& _stateExpression)
:ruleName(_ruleName)
,stateName(_stateName)
,stateExpression(_stateExpression)
{
}
};
class RuleInfo
{
public:
WString name;
WString type;
WString ambiguousType;
vint rootStartState;
vint attributeIndex;
RuleInfo()
:rootStartState(-1)
,attributeIndex(-1)
{
}
RuleInfo(const WString& _name, const WString& _type, const WString& _ambiguousType, vint _rootStartState, vint _attributeIndex)
:name(_name)
,type(_type)
,ambiguousType(_ambiguousType)
,rootStartState(_rootStartState)
,attributeIndex(_attributeIndex)
{
}
};
class Instruction
{
public:
enum InstructionType
{
Create,
Assign,
Item,
Using,
Setter,
Shift,
Reduce,
LeftRecursiveReduce,
};
InstructionType instructionType;
vint stateParameter;
WString nameParameter;
WString value;
WString creatorRule;
Instruction()
:instructionType(Create)
,stateParameter(0)
{
}
Instruction(InstructionType _instructionType, vint _stateParameter, const WString& _nameParameter, const WString& _value, const WString& _creatorRule)
:instructionType(_instructionType)
,stateParameter(_stateParameter)
,nameParameter(_nameParameter)
,value(_value)
,creatorRule(_creatorRule)
{
}
};
class LookAheadInfo
{
public:
collections::List<vint> tokens;
vint state;
LookAheadInfo()
:state(-1)
{
}
enum PrefixResult
{
Prefix,
Equal,
NotPrefix,
};
static PrefixResult TestPrefix(Ptr<LookAheadInfo> a, Ptr<LookAheadInfo> b);
static void WalkInternal(Ptr<ParsingTable> table, Ptr<LookAheadInfo> previous, vint state, collections::SortedList<vint>& walkedStates, collections::List<Ptr<LookAheadInfo>>& newInfos);
static void Walk(Ptr<ParsingTable> table, Ptr<LookAheadInfo> previous, vint state, collections::List<Ptr<LookAheadInfo>>& newInfos);
};
class TransitionItem
{
public:
vint token;
vint targetState;
collections::List<Ptr<LookAheadInfo>> lookAheads;
collections::List<vint> stackPattern;
collections::List<Instruction> instructions;
enum OrderResult
{
CorrectOrder,
WrongOrder,
SameOrder,
UnknownOrder,
};
TransitionItem(){}
TransitionItem(vint _token, vint _targetState)
:token(_token)
,targetState(_targetState)
{
}
static OrderResult CheckOrder(Ptr<TransitionItem> t1, Ptr<TransitionItem> t2, OrderResult defaultResult = UnknownOrder);
static vint Compare(Ptr<TransitionItem> t1, Ptr<TransitionItem> t2, OrderResult defaultResult);
};
class TransitionBag
{
public:
collections::List<Ptr<TransitionItem>> transitionItems;
};
protected:
// metadata
bool ambiguity;
collections::Array<Ptr<AttributeInfoList>> attributeInfos;
collections::Array<TreeTypeInfo> treeTypeInfos;
collections::Array<TreeFieldInfo> treeFieldInfos;
// LALR table
vint tokenCount; // tokenInfos.Count() + discardTokenInfos.Count()
vint stateCount; // stateInfos.Count()
collections::Array<TokenInfo> tokenInfos;
collections::Array<TokenInfo> discardTokenInfos;
collections::Array<StateInfo> stateInfos;
collections::Array<RuleInfo> ruleInfos;
collections::Array<Ptr<TransitionBag>> transitionBags;
// generated data
Ptr<regex::RegexLexer> lexer;
collections::Dictionary<WString, vint> ruleMap;
collections::Dictionary<WString, vint> treeTypeInfoMap;
collections::Dictionary<collections::Pair<WString, WString>, vint> treeFieldInfoMap;
template<typename TIO>
void IO(TIO& io);
public:
ParsingTable(vint _attributeInfoCount, vint _treeTypeInfoCount, vint _treeFieldInfoCount, vint _tokenCount, vint _discardTokenCount, vint _stateCount, vint _ruleCount);
/// <summary>Deserialize the parsing table from a stream. <see cref="Initialize"/> should be before using this table.</summary>
/// <param name="input">The stream.</param>
ParsingTable(stream::IStream& input);
~ParsingTable();
/// <summary>Serialize the parsing table to a stream.</summary>
/// <param name="output">The stream.</param>
void Serialize(stream::IStream& output);
bool GetAmbiguity();
void SetAmbiguity(bool value);
vint GetAttributeInfoCount();
Ptr<AttributeInfoList> GetAttributeInfo(vint index);
void SetAttributeInfo(vint index, Ptr<AttributeInfoList> info);
vint GetTreeTypeInfoCount();
const TreeTypeInfo& GetTreeTypeInfo(vint index);
const TreeTypeInfo& GetTreeTypeInfo(const WString& type);
void SetTreeTypeInfo(vint index, const TreeTypeInfo& info);
vint GetTreeFieldInfoCount();
const TreeFieldInfo& GetTreeFieldInfo(vint index);
const TreeFieldInfo& GetTreeFieldInfo(const WString& type, const WString& field);
void SetTreeFieldInfo(vint index, const TreeFieldInfo& info);
vint GetTokenCount();
const TokenInfo& GetTokenInfo(vint token);
void SetTokenInfo(vint token, const TokenInfo& info);
vint GetDiscardTokenCount();
const TokenInfo& GetDiscardTokenInfo(vint token);
void SetDiscardTokenInfo(vint token, const TokenInfo& info);
vint GetStateCount();
const StateInfo& GetStateInfo(vint state);
void SetStateInfo(vint state, const StateInfo& info);
vint GetRuleCount();
const RuleInfo& GetRuleInfo(const WString& ruleName);
const RuleInfo& GetRuleInfo(vint rule);
void SetRuleInfo(vint rule, const RuleInfo& info);
const regex::RegexLexer& GetLexer();
Ptr<TransitionBag> GetTransitionBag(vint state, vint token);
void SetTransitionBag(vint state, vint token, Ptr<TransitionBag> bag);
/// <summary>Initialize the parsing table. This function should be called after deserializing the table from a string.</summary>
void Initialize();
bool IsInputToken(vint regexTokenIndex);
vint GetTableTokenIndex(vint regexTokenIndex);
vint GetTableDiscardTokenIndex(vint regexTokenIndex);
};
/***********************************************************************
Helper Functions
***********************************************************************/
extern void Log(Ptr<ParsingTable> table, stream::TextWriter& writer);
}
}
}
#endif
/***********************************************************************
.\PARSING\PARSINGSTATE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::State
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSINGSTATE
#define VCZH_PARSING_PARSINGSTATE
namespace vl
{
namespace parsing
{
namespace tabling
{
/***********************************************************************
Syntax Analyzer
***********************************************************************/
class ParsingTokenWalker : public Object
{
protected:
class LookAheadEnumerator : public Object, public collections::IEnumerator<vint>
{
protected:
const ParsingTokenWalker* walker;
vint firstToken;
vint currentToken;
vint currentValue;
vint index;
public:
LookAheadEnumerator(const ParsingTokenWalker* _walker, vint _currentToken);
LookAheadEnumerator(const LookAheadEnumerator& _enumerator);
collections::IEnumerator<vint>* Clone()const override;
const vint& Current()const override;
vint Index()const override;
bool Next()override;
void Reset()override;
};
class TokenLookAhead : public Object, public collections::IEnumerable<vint>
{
protected:
const ParsingTokenWalker* walker;
public:
TokenLookAhead(const ParsingTokenWalker* _talker);
collections::IEnumerator<vint>* CreateEnumerator()const override;
};
class ReduceLookAhead : public Object, public collections::IEnumerable<vint>
{
protected:
const ParsingTokenWalker* walker;
public:
ReduceLookAhead(const ParsingTokenWalker* _walker);
collections::IEnumerator<vint>* CreateEnumerator()const override;
};
protected:
collections::List<regex::RegexToken>& tokens;
Ptr<ParsingTable> table;
vint currentToken;
TokenLookAhead tokenLookAhead;
ReduceLookAhead reduceLookAhead;
vint GetNextIndex(vint index)const;
vint GetTableTokenIndex(vint index)const;
public:
ParsingTokenWalker(collections::List<regex::RegexToken>& _tokens, Ptr<ParsingTable> _table);
~ParsingTokenWalker();
const collections::IEnumerable<vint>& GetTokenLookahead()const;
const collections::IEnumerable<vint>& GetReduceLookahead()const;
void Reset();
bool Move();
vint GetTableTokenIndex()const;
regex::RegexToken* GetRegexToken()const;
vint GetTokenIndexInStream()const;
};
class ParsingState : public Object
{
public:
struct ShiftReduceRange
{
regex::RegexToken* shiftToken;
regex::RegexToken* reduceToken;
ShiftReduceRange()
:shiftToken(0)
,reduceToken(0)
{
}
};
struct TransitionResult
{
enum TransitionType
{
ExecuteInstructions,
AmbiguityBegin,
AmbiguityBranch,
AmbiguityEnd,
SkipToken,
};
TransitionType transitionType;
vint ambiguityAffectedStackNodeCount;
WString ambiguityNodeType;
vint tableTokenIndex;
vint tableStateSource;
vint tableStateTarget;
vint tokenIndexInStream;
regex::RegexToken* token;
ParsingTable::TransitionItem* transition;
vint instructionBegin;
vint instructionCount;
Ptr<collections::List<ShiftReduceRange>> shiftReduceRanges;
TransitionResult(TransitionType _transitionType=ExecuteInstructions)
:transitionType(_transitionType)
,ambiguityAffectedStackNodeCount(0)
,tableTokenIndex(-1)
,tableStateSource(-1)
,tableStateTarget(-1)
,tokenIndexInStream(-1)
,token(0)
,transition(0)
,instructionBegin(-1)
,instructionCount(-1)
{
}
operator bool()const
{
return transitionType!=ExecuteInstructions || transition!=0;
}
void AddShiftReduceRange(regex::RegexToken* shiftToken, regex::RegexToken* reduceToken)
{
ShiftReduceRange range;
range.shiftToken=shiftToken;
range.reduceToken=reduceToken;
if(!shiftReduceRanges)
{
shiftReduceRanges=new collections::List<ShiftReduceRange>();
}
shiftReduceRanges->Add(range);
}
};
struct Future
{
vint currentState;
vint reduceStateCount;
collections::List<vint> shiftStates;
regex::RegexToken* selectedRegexToken;
vint selectedToken;
ParsingTable::TransitionItem* selectedItem;
Future* previous;
Future* next;
Future()
:currentState(-1)
,reduceStateCount(0)
,selectedRegexToken(0)
,selectedToken(-1)
,selectedItem(0)
,previous(0)
,next(0)
{
}
Future* Clone()
{
Future* future = new Future;
future->currentState = currentState;
future->reduceStateCount = reduceStateCount;
CopyFrom(future->shiftStates, shiftStates);
future->selectedRegexToken = selectedRegexToken;
future->selectedToken = selectedToken;
future->selectedItem = selectedItem;
future->previous = previous;
return future;
}
};
struct StateGroup
{
collections::List<vint> stateStack;
vint currentState;
vint tokenSequenceIndex;
collections::List<regex::RegexToken*> shiftTokenStack;
regex::RegexToken* shiftToken;
regex::RegexToken* reduceToken;
StateGroup();
StateGroup(const ParsingTable::RuleInfo& info);
StateGroup(const StateGroup& group);
};
private:
WString input;
Ptr<ParsingTable> table;
collections::List<regex::RegexToken> tokens;
Ptr<ParsingTokenWalker> walker;
WString parsingRule;
vint parsingRuleStartState;
Ptr<StateGroup> stateGroup;
public:
ParsingState(const WString& _input, Ptr<ParsingTable> _table, vint codeIndex=-1);
~ParsingState();
const WString& GetInput();
Ptr<ParsingTable> GetTable();
const collections::List<regex::RegexToken>& GetTokens();
regex::RegexToken* GetToken(vint index);
vint Reset(const WString& rule);
WString GetParsingRule();
vint GetParsingRuleStartState();
vint GetCurrentToken();
vint GetCurrentTableTokenIndex();
const collections::List<vint>& GetStateStack();
vint GetCurrentState();
void SkipCurrentToken();
bool TestTransitionItemInFuture(vint tableTokenIndex, Future* future, ParsingTable::TransitionItem* item, const collections::IEnumerable<vint>* lookAheadTokens);
ParsingTable::TransitionItem* MatchTokenInFuture(vint tableTokenIndex, Future* future, const collections::IEnumerable<vint>* lookAheadTokens);
ParsingTable::TransitionItem* MatchToken(vint tableTokenIndex, const collections::IEnumerable<vint>* lookAheadTokens);
void RunTransitionInFuture(ParsingTable::TransitionItem* transition, Future* previous, Future* now);
ParsingState::TransitionResult RunTransition(ParsingTable::TransitionItem* transition, regex::RegexToken* regexToken, vint instructionBegin, vint instructionCount, bool lastPart);
ParsingState::TransitionResult RunTransition(ParsingTable::TransitionItem* transition, regex::RegexToken* regexToken);
bool ReadTokenInFuture(vint tableTokenIndex, Future* previous, Future* now, const collections::IEnumerable<vint>* lookAheadTokens);
TransitionResult ReadToken(vint tableTokenIndex, regex::RegexToken* regexToken, const collections::IEnumerable<vint>* lookAheadTokens);
TransitionResult ReadToken();
bool TestExplore(vint tableTokenIndex, Future* previous);
bool Explore(vint tableTokenIndex, Future* previous, collections::List<Future*>& possibilities);
bool ExploreStep(collections::List<Future*>& previousFutures, vint start, vint count, collections::List<Future*>& possibilities);
bool ExploreNormalReduce(collections::List<Future*>& previousFutures, vint start, vint count, collections::List<Future*>& possibilities);
bool ExploreLeftRecursiveReduce(collections::List<Future*>& previousFutures, vint start, vint count, collections::List<Future*>& possibilities);
Future* ExploreCreateRootFuture();
Ptr<StateGroup> TakeSnapshot();
void RestoreSnapshot(Ptr<StateGroup> group);
};
/***********************************************************************
AST Generating
***********************************************************************/
class ParsingTransitionProcessor : public Object
{
public:
virtual void Reset()=0;
virtual bool Run(const ParsingState::TransitionResult& result)=0;
virtual bool GetProcessingAmbiguityBranch()=0;
};
class ParsingTreeBuilder : public ParsingTransitionProcessor
{
protected:
Ptr<ParsingTreeNode> createdObject;
Ptr<ParsingTreeObject> operationTarget;
collections::List<Ptr<ParsingTreeObject>> nodeStack;
bool processingAmbiguityBranch;
Ptr<ParsingTreeNode> ambiguityBranchCreatedObject;
Ptr<ParsingTreeNode> ambiguityBranchOperationTarget;
vint ambiguityBranchSharedNodeCount;
collections::List<Ptr<ParsingTreeObject>> ambiguityBranchNodeStack;
collections::List<Ptr<ParsingTreeObject>> ambiguityNodes;
public:
ParsingTreeBuilder();
~ParsingTreeBuilder();
void Reset()override;
bool Run(const ParsingState::TransitionResult& result)override;
bool GetProcessingAmbiguityBranch()override;
Ptr<ParsingTreeObject> GetNode()const;
};
class ParsingTransitionCollector : public ParsingTransitionProcessor
{
typedef collections::List<ParsingState::TransitionResult> TransitionResultList;
protected:
vint ambiguityBegin;
TransitionResultList transitions;
collections::Dictionary<vint, vint> ambiguityBeginToEnds;
collections::Group<vint, vint> ambiguityBeginToBranches;
collections::Dictionary<vint, vint> ambiguityBranchToBegins;
public:
ParsingTransitionCollector();
~ParsingTransitionCollector();
void Reset()override;
bool Run(const ParsingState::TransitionResult& result)override;
bool GetProcessingAmbiguityBranch()override;
const TransitionResultList& GetTransitions()const;
vint GetAmbiguityEndFromBegin(vint transitionIndex)const;
const collections::List<vint>& GetAmbiguityBranchesFromBegin(vint transitionIndex)const;
vint GetAmbiguityBeginFromBranch(vint transitionIndex)const;
};
}
}
}
#endif
/***********************************************************************
.\THREADING.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Threading
Classes:
Thread : Thread
CriticalSection
Mutex
Semaphore
EventObject
***********************************************************************/
#ifndef VCZH_THREADING
#define VCZH_THREADING
namespace vl
{
/***********************************************************************
Kernel Mode Objects
***********************************************************************/
namespace threading_internal
{
struct WaitableData;
struct ThreadData;
struct MutexData;
struct SemaphoreData;
struct EventData;
struct CriticalSectionData;
struct ReaderWriterLockData;
struct ConditionVariableData;
}
/// <summary>Base type of all synchronization objects.</summary>
class WaitableObject : public Object, public NotCopyable
{
#if defined VCZH_MSVC
private:
threading_internal::WaitableData* waitableData;
protected:
WaitableObject();
void SetData(threading_internal::WaitableData* data);
public:
/// <summary>Test if the object has already been created. Some of the synchronization objects should initialize itself after the constructor. This function is only available in Windows.</summary>
/// <returns>Returns true if the object has already been created.</returns>
bool IsCreated();
/// <summary>Wait for this object to signal.</summary>
/// <returns>Returns true if the object is signaled. Returns false if this operation failed.</returns>
bool Wait();
/// <summary>Wait for this object to signal for a period of time. This function is only available in Windows.</summary>
/// <returns>Returns true if the object is signaled. Returns false if this operation failed, including time out.</returns>
/// <param name="ms">Time in milliseconds.</param>
bool WaitForTime(vint ms);
/// <summary>Wait for multiple objects. This function is only available in Windows.</summary>
/// <returns>Returns true if all objects are signaled. Returns false if this operation failed.</returns>
/// <param name="objects">A pointer to an array to <see cref="WaitableObject"/> pointers.</param>
/// <param name="count">The number of <see cref="WaitableObject"/> objects in the array.</param>
static bool WaitAll(WaitableObject** objects, vint count);
/// <summary>Wait for multiple objects for a period of time. This function is only available in Windows.</summary>
/// <returns>Returns true if all objects are signaled. Returns false if this operation failed, including time out.</returns>
/// <param name="objects">A pointer to an array to <see cref="WaitableObject"/> pointers.</param>
/// <param name="count">The number of <see cref="WaitableObject"/> objects in the array.</param>
/// <param name="ms">Time in milliseconds.</param>
static bool WaitAllForTime(WaitableObject** objects, vint count, vint ms);
/// <summary>Wait for one of the objects. This function is only available in Windows.</summary>
/// <returns>Returns the index of the first signaled or abandoned object, according to the "abandoned" parameter. Returns -1 if this operation failed.</returns>
/// <param name="objects">A pointer to an array to <see cref="WaitableObject"/> pointers.</param>
/// <param name="count">The number of <see cref="WaitableObject"/> objects in the array.</param>
/// <param name="abandoned">Returns true if the waiting is canceled by an abandoned object. An abandoned object is caused by it's owner thread existing without releasing it.</param>
static vint WaitAny(WaitableObject** objects, vint count, bool* abandoned);
/// <summary>Wait for one of the objects for a period of time. This function is only available in Windows.</summary>
/// <returns>Returns the index of the first signaled or abandoned object, according to the "abandoned" parameter. Returns -1 if this operation failed, including time out.</returns>
/// <param name="objects">A pointer to an array to <see cref="WaitableObject"/> pointers.</param>
/// <param name="count">The number of <see cref="WaitableObject"/> objects in the array.</param>
/// <param name="ms">Time in milliseconds.</param>
/// <param name="abandoned">Returns true if the waiting is canceled by an abandoned object. An abandoned object is caused by it's owner thread existing without releasing it.</param>
static vint WaitAnyForTime(WaitableObject** objects, vint count, vint ms, bool* abandoned);
#elif defined VCZH_GCC
virtual bool Wait() = 0;
#endif
};
/// <summary>Representing a thread. [M:vl.Thread.CreateAndStart] is the suggested way to create threads.</summary>
class Thread : public WaitableObject
{
friend void InternalThreadProc(Thread* thread);
public:
/// <summary>Thread state.</summary>
enum ThreadState
{
/// <summary>The thread has not started.</summary>
NotStarted,
/// <summary>The thread is running.</summary>
Running,
/// <summary>The thread has been stopped.</summary>
Stopped
};
typedef void(*ThreadProcedure)(Thread*, void*);
protected:
threading_internal::ThreadData* internalData;
volatile ThreadState threadState;
virtual void Run()=0;
Thread();
public:
~Thread();
/// <summary>Create a thread using a function pointer.</summary>
/// <returns>Returns the created thread.</returns>
/// <param name="procedure">The function pointer.</param>
/// <param name="argument">The argument to call the function pointer.</param>
/// <param name="deleteAfterStopped">Set to true (by default) to make the thread delete itself after the job is done. If you set this argument to true, you are not suggested to touch the returned thread pointer in any way.</param>
static Thread* CreateAndStart(ThreadProcedure procedure, void* argument=0, bool deleteAfterStopped=true);
/// <summary>Create a thread using a function object or a lambda expression.</summary>
/// <returns>Returns the created thread.</returns>
/// <param name="procedure">The function object or the lambda expression.</param>
/// <param name="deleteAfterStopped">Set to true (by default) to make the thread delete itself after the job is done. If you set this argument to true, you are not suggested to touch the returned thread pointer in any way.</param>
static Thread* CreateAndStart(const Func<void()>& procedure, bool deleteAfterStopped=true);
/// <summary>Pause the caller thread for a period of time.</summary>
/// <param name="ms">Time in milliseconds.</param>
static void Sleep(vint ms);
/// <summary>Get the number of logical processors.</summary>
/// <returns>The number of logical processor.</returns>
static vint GetCPUCount();
/// <summary>Get the current thread id.</summary>
/// <returns>The current thread id.</returns>
static vint GetCurrentThreadId();
/// <summary>Start the thread.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Start();
#if defined VCZH_GCC
bool Wait();
#endif
/// <summary>Stop the thread.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Stop();
/// <summary>Get the state of the thread.</summary>
/// <returns>The state of the thread.</returns>
ThreadState GetState();
#ifdef VCZH_MSVC
void SetCPU(vint index);
#endif
};
/// <summary>Mutex.</summary>
class Mutex : public WaitableObject
{
private:
threading_internal::MutexData* internalData;
public:
Mutex();
~Mutex();
/// <summary>Create a mutex.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="owned">Set to true to own the created mutex.</param>
/// <param name="name">Name of the mutex. If it is not empty, than it is a global named mutex. This argument is ignored in Linux.</param>
bool Create(bool owned=false, const WString& name=L"");
/// <summary>Open an existing global named mutex.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="inheritable">Set to true make the mutex visible to all all child processes. This argument is only used in Windows.</param>
/// <param name="name">Name of the mutex. This argument is ignored in Linux.</param>
bool Open(bool inheritable, const WString& name);
/// <summary>
/// Release the mutex.
/// In the implementation for Linux, calling Release() more than once between two Wait(), or calling Wait() more than once between two Release(), will results in an undefined behavior.
/// </summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Release();
#ifdef VCZH_GCC
bool Wait();
#endif
};
/// <summary>Semaphore.</summary>
class Semaphore : public WaitableObject
{
private:
threading_internal::SemaphoreData* internalData;
public:
Semaphore();
~Semaphore();
/// <summary>Create a semaphore.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="initialCount">Define the counter of the semaphore.</param>
/// <param name="maxCount">Define the maximum value of the counter of the semaphore. This argument is only used in Windows.</param>
/// <param name="name">Name of the semaphore. If it is not empty, than it is a global named semaphore. This argument is ignored in Linux.</param>
bool Create(vint initialCount, vint maxCount, const WString& name=L"");
/// <summary>Open an existing global named semaphore.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="inheritable">Set to true make the semaphore visible to all all child processes. This argument is only used in Windows.</param>
/// <param name="name">Name of the semaphore. This argument is ignored in Linux.</param>
bool Open(bool inheritable, const WString& name);
/// <summary> Release the semaphore once. </summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Release();
/// <summary> Release the semaphore multiple times. </summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="count">The amout to release.</param>
vint Release(vint count);
#ifdef VCZH_GCC
bool Wait();
#endif
};
/// <summary>Event.</summary>
class EventObject : public WaitableObject
{
private:
threading_internal::EventData* internalData;
public:
EventObject();
~EventObject();
/// <summary>Create an auto unsignal event. Auto unsignal means, when one thread waits for the event and succeeded, the event will become unsignaled immediately.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="signaled">Set to true make the event signaled at the beginning.</param>
/// <param name="name">Name of the event. If it is not empty, than it is a global named mutex. This argument is only used in Windows.</param>
bool CreateAutoUnsignal(bool signaled, const WString& name=L"");
/// <summary>Create a manual unsignal event.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="signaled">Set to true make the event signaled at the beginning.</param>
/// <param name="name">Name of the event. If it is not empty, than it is a global named mutex. This argument is only used in Windows.</param>
bool CreateManualUnsignal(bool signaled, const WString& name=L"");
/// <summary>Open an existing global named event.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="inheritable">Set to true make the event visible to all all child processes. This argument is only used in Windows.</param>
/// <param name="name">Name of the event. This argument is only used in Windows.</param>
bool Open(bool inheritable, const WString& name);
/// <summary>Signal the event.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Signal();
/// <summary>Unsignal the event.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Unsignal();
#ifdef VCZH_GCC
bool Wait();
#endif
};
/***********************************************************************
Thread Pool
***********************************************************************/
/// <summary>A light-weight thread pool.</summary>
class ThreadPoolLite : public Object
{
private:
ThreadPoolLite();
~ThreadPoolLite();
public:
/// <summary>Queue a function pointer.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="proc">The function pointer.</param>
/// <param name="argument">The argument to call the function pointer.</param>
static bool Queue(void(*proc)(void*), void* argument);
/// <summary>Queue a function object.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="proc">The function object.</param>
static bool Queue(const Func<void()>& proc);
/// <summary>Queue a lambda expression.</summary>
/// <typeparam name="T">The type of the lambda expression.</typeparam>
/// <param name="proc">The lambda expression.</param>
template<typename T>
static void QueueLambda(const T& proc)
{
Queue(Func<void()>(proc));
}
#ifdef VCZH_GCC
static bool Stop(bool discardPendingTasks);
#endif
};
/***********************************************************************
Kernel Mode Objects in Process
***********************************************************************/
/// <summary><![CDATA[
/// Critical section. It is similar to mutex, but in Windows, enter a owned critical section will not cause dead lock.
/// The macro "CS_LOCK" is encouraged to use instead of calling [M:vl.CriticalSection.Enter] and [M:vl.CriticalSection.Leave] like this:
/// CS_LOCK(yourCriticalSection)
/// {
/// <code>
/// }
/// ]]></summary>
class CriticalSection : public Object, public NotCopyable
{
private:
friend class ConditionVariable;
threading_internal::CriticalSectionData* internalData;
public:
/// <summary>Create a critical section.</summary>
CriticalSection();
~CriticalSection();
/// <summary>Try enter a critical section. This function will return immediately.</summary>
/// <returns>Returns true if the current thread owned the critical section.</returns>
bool TryEnter();
/// <summary>Enter a critical section.</summary>
void Enter();
/// <summary>Leave a critical section.</summary>
void Leave();
public:
class Scope : public Object, public NotCopyable
{
private:
CriticalSection* criticalSection;
public:
Scope(CriticalSection& _criticalSection);
~Scope();
};
};
/// <summary><![CDATA[
/// Reader writer lock.
/// The macro "READER_LOCK" and "WRITER_LOCK" are encouraged to use instead of calling [M:vl.ReaderWriterLock.EnterReader], [M:vl.ReaderWriterLock.LeaveReader], [M:vl.ReaderWriterLock.EnterWriter] and [M:vl.ReaderWriterLock.LeaveWriter] like this:
/// READER_LOCK(yourLock)
/// {
/// <code>
/// }
/// or
/// WRITER_LOCK(yourLock)
/// {
/// <code>
/// }
/// ]]></summary>
class ReaderWriterLock : public Object, public NotCopyable
{
private:
friend class ConditionVariable;
threading_internal::ReaderWriterLockData* internalData;
public:
/// <summary>Create a reader writer lock.</summary>
ReaderWriterLock();
~ReaderWriterLock();
/// <summary>Try acquire a reader lock. This function will return immediately.</summary>
/// <returns>Returns true if the current thread acquired the reader lock.</returns>
bool TryEnterReader();
/// <summary>Acquire a reader lock.</summary>
void EnterReader();
/// <summary>Release a reader lock.</summary>
void LeaveReader();
/// <summary>Try acquire a writer lock. This function will return immediately.</summary>
/// <returns>Returns true if the current thread acquired the writer lock.</returns>
bool TryEnterWriter();
/// <summary>Acquire a writer lock.</summary>
void EnterWriter();
/// <summary>Release a writer lock.</summary>
void LeaveWriter();
public:
class ReaderScope : public Object, public NotCopyable
{
private:
ReaderWriterLock* lock;
public:
ReaderScope(ReaderWriterLock& _lock);
~ReaderScope();
};
class WriterScope : public Object, public NotCopyable
{
private:
ReaderWriterLock* lock;
public:
WriterScope(ReaderWriterLock& _lock);
~WriterScope();
};
};
/// <summary>Conditional variable.</summary>
class ConditionVariable : public Object, public NotCopyable
{
private:
threading_internal::ConditionVariableData* internalData;
public:
/// <summary>Create a conditional variable.</summary>
ConditionVariable();
~ConditionVariable();
/// <summary>Bind a conditional variable with a owned critical section and release it. When the function returns, the condition variable is activated, and the current thread owned the critical section again.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="cs">The critical section.</param>
bool SleepWith(CriticalSection& cs);
#ifdef VCZH_MSVC
/// <summary>Bind a conditional variable with a owned critical section and release it for a period of time. When the function returns, the condition variable is activated or it is time out, and the current thread owned the critical section again. This function is only available in Windows.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="cs">The critical section.</param>
/// <param name="ms">Time in milliseconds.</param>
bool SleepWithForTime(CriticalSection& cs, vint ms);
/// <summary>Bind a conditional variable with a owned reader lock and release it. When the function returns, the condition variable is activated, and the current thread owned the reader lock again. This function is only available in Windows.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="lock">The reader lock.</param>
bool SleepWithReader(ReaderWriterLock& lock);
/// <summary>Bind a conditional variable with a owned reader lock and release it for a period of time. When the function returns, the condition variable is activated or it is time out, and the current thread owned the reader lock again. This function is only available in Windows.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="lock">The reader lock.</param>
/// <param name="ms">Time in milliseconds.</param>
bool SleepWithReaderForTime(ReaderWriterLock& lock, vint ms);
/// <summary>Bind a conditional variable with a owned writer lock and release it. When the function returns, the condition variable is activated, and the current thread owned the writer lock again. This function is only available in Windows.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="lock">The writer lock.</param>
bool SleepWithWriter(ReaderWriterLock& lock);
/// <summary>Bind a conditional variable with a owned writer lock and release it for a period of time. When the function returns, the condition variable is activated or it is time out, and the current thread owned the writer lock again. This function is only available in Windows.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="lock">The writer lock.</param>
/// <param name="ms">Time in milliseconds.</param>
bool SleepWithWriterForTime(ReaderWriterLock& lock, vint ms);
#endif
/// <summary>Wake one thread that pending on this condition variable.</summary>
void WakeOnePending();
/// <summary>Wake all thread that pending on this condition variable.</summary>
void WakeAllPendings();
};
/***********************************************************************
User Mode Objects
***********************************************************************/
typedef long LockedInt;
/// <summary><![CDATA[
/// Spin lock. It is similar to mutex.
/// The macro "SPIN_LOCK" is encouraged to use instead of calling [M:vl.SpinLock.Enter] and [M:vl.SpinLock.Leave] like this:
/// SPIN_LOCK(yourLock)
/// {
/// <code>
/// }
/// ]]></summary>
class SpinLock : public Object, public NotCopyable
{
protected:
volatile LockedInt token;
public:
/// <summary>Create a spin lock.</summary>
SpinLock();
~SpinLock();
/// <summary>Try enter a spin lock. This function will return immediately.</summary>
/// <returns>Returns true if the current thread owned the spin lock.</returns>
bool TryEnter();
/// <summary>Enter a spin lock.</summary>
void Enter();
/// <summary>Leave a spin lock.</summary>
void Leave();
public:
class Scope : public Object, public NotCopyable
{
private:
SpinLock* spinLock;
public:
Scope(SpinLock& _spinLock);
~Scope();
};
};
#define SPIN_LOCK(LOCK) SCOPE_VARIABLE(const SpinLock::Scope&, scope, LOCK)
#define CS_LOCK(LOCK) SCOPE_VARIABLE(const CriticalSection::Scope&, scope, LOCK)
#define READER_LOCK(LOCK) SCOPE_VARIABLE(const ReaderWriterLock::ReaderScope&, scope, LOCK)
#define WRITER_LOCK(LOCK) SCOPE_VARIABLE(const ReaderWriterLock::WriterScope&, scope, LOCK)
/***********************************************************************
Thread Local Storage
ThreadLocalStorage and ThreadVariable<T> are designed to be used as global value types only.
Dynamically create instances of them are undefined behavior.
***********************************************************************/
/// <summary>Thread local storage operations.</summary>
class ThreadLocalStorage : public Object, private NotCopyable
{
typedef void(*Destructor)(void*);
protected:
vuint64_t key;
Destructor destructor;
volatile bool disposed = false;
static void PushStorage(ThreadLocalStorage* storage);
public:
ThreadLocalStorage(Destructor _destructor);
~ThreadLocalStorage();
void* Get();
void Set(void* data);
void Clear();
void Dispose();
/// <summary>Fix all storage creation.</summary>
static void FixStorages();
/// <summary>Clear all storages for the current thread. For threads that are created using [T:vl.Thread], this function will be automatically called when before the thread exit.</summary>
static void ClearStorages();
/// <summary>Clear all storages for the current thread (should be the main thread) and clear all records. This function can only be called by the main thread when all other threads are exited. It will reduce noices when you want to detect memory leaks.</summary>
static void DisposeStorages();
};
/// <summary>Thread local variable. This type can only be used to define global variables. Different threads can store different values to and obtain differnt values from a thread local variable.</summary>
/// <typeparam name="T">Type of the storage.</typeparam>
template<typename T>
class ThreadVariable : public Object, private NotCopyable
{
protected:
ThreadLocalStorage storage;
static void Destructor(void* data)
{
if (data)
{
delete (T*)data;
}
}
public:
/// <summary>Create a thread local variable.</summary>
ThreadVariable()
:storage(&Destructor)
{
}
~ThreadVariable()
{
}
/// <summary>Test if the storage has data.</summary>
/// <returns>Returns true if the storage has data.</returns>
bool HasData()
{
return storage.Get() != nullptr;
}
/// <summary>Remove the data from this storage.</summary>
void Clear()
{
storage.Clear();
}
/// <summary>Get the stored data.</summary>
/// <returns>The stored ata.</returns>
T& Get()
{
return *(T*)storage.Get();
}
/// <summary>Set data to this storage.</summary>
/// <param name="value">The data to set.</param>
void Set(const T& value)
{
storage.Clear();
storage.Set(new T(value));
}
};
template<typename T>
class ThreadVariable<T*> : public Object, private NotCopyable
{
protected:
ThreadLocalStorage storage;
public:
ThreadVariable()
:storage(nullptr)
{
}
~ThreadVariable()
{
}
bool HasData()
{
return storage.Get() != nullptr;
}
void Clear()
{
storage.Set(nullptr);
}
T* Get()
{
return (T*)storage.Get();
}
void Set(T* value)
{
storage.Set((void*)value);
}
};
/***********************************************************************
RepeatingTaskExecutor
***********************************************************************/
/// <summary>Queued task executor. It is different from a thread pool by: 1) Task execution is single threaded, 2) If you queue a task, it will override the the unexecuted queued task.</summary>
/// <typeparam name="T">The type of the argument to run a task.</typeparam>
template<typename T>
class RepeatingTaskExecutor : public Object
{
private:
SpinLock inputLock;
T inputData;
volatile bool inputDataAvailable;
SpinLock executingEvent;
volatile bool executing;
void ExecutingProcInternal()
{
while(true)
{
bool currentInputDataAvailable;
T currentInputData;
SPIN_LOCK(inputLock)
{
currentInputData=inputData;
inputData=T();
currentInputDataAvailable=inputDataAvailable;
inputDataAvailable=false;
if(!currentInputDataAvailable)
{
executing=false;
goto FINISH_EXECUTING;
}
}
Execute(currentInputData);
}
FINISH_EXECUTING:
executingEvent.Leave();
}
static void ExecutingProc(void* argument)
{
((RepeatingTaskExecutor<T>*)argument)->ExecutingProcInternal();
}
protected:
/// <summary>This function is called when it is ready to execute a task. Task execution is single threaded. All task code should be put inside the function.</summary>
/// <param name="input">The argument to run a task.</param>
virtual void Execute(const T& input)=0;
public:
/// <summary>Create a task executor.</summary>
RepeatingTaskExecutor()
:inputDataAvailable(false)
,executing(false)
{
}
~RepeatingTaskExecutor()
{
EnsureTaskFinished();
}
/// <summary>Wait for all tasks to finish.</summary>
void EnsureTaskFinished()
{
executingEvent.Enter();
executingEvent.Leave();
}
/// <summary>Queue a task. If there is a queued task that has not been executied yet, those tasks will be canceled. Only one task can be queued at the same moment.</summary>
/// <param name="input">The argument to run a task.</param>
void SubmitTask(const T& input)
{
SPIN_LOCK(inputLock)
{
inputData=input;
inputDataAvailable=true;
}
if(!executing)
{
executing=true;
executingEvent.Enter();
ThreadPoolLite::Queue(&ExecutingProc, this);
}
}
};
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORPREDEFINED.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORPREDEFINED
#define VCZH_REFLECTION_GUITYPEDESCRIPTORPREDEFINED
#include <math.h>
namespace vl
{
namespace reflection
{
namespace description
{
struct VoidValue {};
/***********************************************************************
Collections
***********************************************************************/
class IValueEnumerator : public virtual IDescriptable, public Description<IValueEnumerator>
{
public:
virtual Value GetCurrent() = 0;
virtual vint GetIndex() = 0;
virtual bool Next() = 0;
};
class IValueEnumerable : public virtual IDescriptable, public Description<IValueEnumerable>
{
public:
virtual Ptr<IValueEnumerator> CreateEnumerator() = 0;
static Ptr<IValueEnumerable> Create(collections::LazyList<Value> values);
};
class IValueReadonlyList : public virtual IValueEnumerable, public Description<IValueReadonlyList>
{
public:
virtual vint GetCount() = 0;
virtual Value Get(vint index) = 0;
virtual bool Contains(const Value& value) = 0;
virtual vint IndexOf(const Value& value) = 0;
};
class IValueList : public virtual IValueReadonlyList, public Description<IValueList>
{
public:
virtual void Set(vint index, const Value& value) = 0;
virtual vint Add(const Value& value) = 0;
virtual vint Insert(vint index, const Value& value) = 0;
virtual bool Remove(const Value& value) = 0;
virtual bool RemoveAt(vint index) = 0;
virtual void Clear() = 0;
static Ptr<IValueList> Create();
static Ptr<IValueList> Create(Ptr<IValueReadonlyList> values);
static Ptr<IValueList> Create(collections::LazyList<Value> values);
};
class IValueObservableList : public virtual IValueList, public Description<IValueObservableList>
{
typedef void ItemChangedProc(vint index, vint oldCount, vint newCount);
public:
Event<ItemChangedProc> ItemChanged;
static Ptr<IValueObservableList> Create();
static Ptr<IValueObservableList> Create(Ptr<IValueReadonlyList> values);
static Ptr<IValueObservableList> Create(collections::LazyList<Value> values);
};
class IValueReadonlyDictionary : public virtual IDescriptable, public Description<IValueReadonlyDictionary>
{
public:
virtual Ptr<IValueReadonlyList> GetKeys() = 0;
virtual Ptr<IValueReadonlyList> GetValues() = 0;
virtual vint GetCount() = 0;
virtual Value Get(const Value& key) = 0;
};
class IValueDictionary : public virtual IValueReadonlyDictionary, public Description<IValueDictionary>
{
public:
virtual void Set(const Value& key, const Value& value) = 0;
virtual bool Remove(const Value& key) = 0;
virtual void Clear() = 0;
static Ptr<IValueDictionary> Create();
static Ptr<IValueDictionary> Create(Ptr<IValueReadonlyDictionary> values);
static Ptr<IValueDictionary> Create(collections::LazyList<collections::Pair<Value, Value>> values);
};
/***********************************************************************
Interface Implementation Proxy
***********************************************************************/
class IValueInterfaceProxy : public virtual IDescriptable, public Description<IValueInterfaceProxy>
{
public:
virtual Value Invoke(IMethodInfo* methodInfo, Ptr<IValueList> arguments) = 0;
};
class IValueFunctionProxy : public virtual IDescriptable, public Description<IValueFunctionProxy>
{
public:
virtual Value Invoke(Ptr<IValueList> arguments) = 0;
};
class IValueSubscription : public virtual IDescriptable, public Description<IValueSubscription>
{
typedef void ValueChangedProc(const Value& newValue);
public:
Event<ValueChangedProc> ValueChanged;
virtual bool Open() = 0;
virtual bool Update() = 0;
virtual bool Close() = 0;
};
/***********************************************************************
Interface Implementation Proxy (Implement)
***********************************************************************/
class ValueInterfaceRoot : public virtual IDescriptable
{
protected:
Ptr<IValueInterfaceProxy> proxy;
void SetProxy(Ptr<IValueInterfaceProxy> value)
{
proxy = value;
}
public:
Ptr<IValueInterfaceProxy> GetProxy()
{
return proxy;
}
};
template<typename T>
class ValueInterfaceProxy
{
};
#pragma warning(push)
#pragma warning(disable:4250)
template<typename TInterface, typename ...TBaseInterfaces>
class ValueInterfaceImpl : public virtual ValueInterfaceRoot, public virtual TInterface, public ValueInterfaceProxy<TBaseInterfaces>...
{
public:
~ValueInterfaceImpl()
{
FinalizeAggregation();
}
};
#pragma warning(pop)
/***********************************************************************
Runtime Exception
***********************************************************************/
class IValueCallStack : public virtual IDescriptable, public Description<IValueCallStack>
{
public:
virtual Ptr<IValueReadonlyDictionary> GetLocalVariables() = 0;
virtual Ptr<IValueReadonlyDictionary> GetLocalArguments() = 0;
virtual Ptr<IValueReadonlyDictionary> GetCapturedVariables() = 0;
virtual Ptr<IValueReadonlyDictionary> GetGlobalVariables() = 0;
virtual WString GetFunctionName() = 0;
virtual WString GetSourceCodeBeforeCodegen() = 0;
virtual WString GetSourceCodeAfterCodegen() = 0;
virtual vint GetRowBeforeCodegen() = 0;
virtual vint GetRowAfterCodegen() = 0;
};
class IValueException : public virtual IDescriptable, public Description<IValueException>
{
public:
#pragma push_macro("GetMessage")
#if defined GetMessage
#undef GetMessage
#endif
virtual WString GetMessage() = 0;
#pragma pop_macro("GetMessage")
virtual bool GetFatal() = 0;
virtual Ptr<IValueReadonlyList> GetCallStack() = 0;
static Ptr<IValueException> Create(const WString& message);
};
}
}
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORBUILDER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER
namespace vl
{
namespace collections
{
template<typename T>
class ObservableList;
}
namespace reflection
{
namespace description
{
#ifndef VCZH_DEBUG_NO_REFLECTION
/***********************************************************************
TypeInfo
***********************************************************************/
#define DECL_TYPE_INFO(TYPENAME) template<>struct TypeInfo<TYPENAME>{ static const TypeInfoContent content; };
#define IMPL_VL_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #TYPENAME, nullptr, TypeInfoContent::VlppType };
#define IMPL_CPP_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #TYPENAME, nullptr, TypeInfoContent::CppType };
#define IMPL_TYPE_INFO_RENAME(TYPENAME, EXPECTEDNAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #EXPECTEDNAME, L ## #TYPENAME, TypeInfoContent::Renamed };
struct TypeInfoContent
{
enum TypeInfoCppName
{
VlppType, // vl::<type-name>
CppType, // <type-name>
Renamed, // CppFullTypeName
};
const wchar_t* typeName;
const wchar_t* cppFullTypeName;
TypeInfoCppName cppName;
};
template<typename T>
struct TypeInfo
{
};
template<typename T>
ITypeDescriptor* GetTypeDescriptor()
{
return GetTypeDescriptor(TypeInfo<T>::content.typeName);
}
/***********************************************************************
SerializableTypeDescriptor
***********************************************************************/
class TypeDescriptorImplBase : public Object, public ITypeDescriptor, private ITypeDescriptor::ICpp
{
private:
TypeDescriptorFlags typeDescriptorFlags;
const TypeInfoContent* typeInfoContent;
WString typeName;
WString cppFullTypeName;
const WString& GetFullName()override;
protected:
const TypeInfoContent* GetTypeInfoContentInternal();
public:
TypeDescriptorImplBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
~TypeDescriptorImplBase();
ITypeDescriptor::ICpp* GetCpp()override;
TypeDescriptorFlags GetTypeDescriptorFlags()override;
const WString& GetTypeName()override;
};
class ValueTypeDescriptorBase : public TypeDescriptorImplBase
{
protected:
bool loaded;
Ptr<IValueType> valueType;
Ptr<IEnumType> enumType;
Ptr<ISerializableType> serializableType;
virtual void LoadInternal();;
void Load();
public:
ValueTypeDescriptorBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
~ValueTypeDescriptorBase();
bool IsAggregatable()override;
IValueType* GetValueType()override;
IEnumType* GetEnumType()override;
ISerializableType* GetSerializableType()override;
vint GetBaseTypeDescriptorCount()override;
ITypeDescriptor* GetBaseTypeDescriptor(vint index)override;
bool CanConvertTo(ITypeDescriptor* targetType)override;
vint GetPropertyCount()override;
IPropertyInfo* GetProperty(vint index)override;
bool IsPropertyExists(const WString& name, bool inheritable)override;
IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable)override;
vint GetEventCount()override;
IEventInfo* GetEvent(vint index)override;
bool IsEventExists(const WString& name, bool inheritable)override;
IEventInfo* GetEventByName(const WString& name, bool inheritable)override;
vint GetMethodGroupCount()override;
IMethodGroupInfo* GetMethodGroup(vint index)override;
bool IsMethodGroupExists(const WString& name, bool inheritable)override;
IMethodGroupInfo* GetMethodGroupByName(const WString& name, bool inheritable)override;
IMethodGroupInfo* GetConstructorGroup()override;
};
template<typename T, TypeDescriptorFlags TDFlags>
class TypedValueTypeDescriptorBase : public ValueTypeDescriptorBase
{
public:
TypedValueTypeDescriptorBase()
:ValueTypeDescriptorBase(TDFlags, &TypeInfo<T>::content)
{
}
};
/***********************************************************************
TypeInfoImp
***********************************************************************/
class TypeDescriptorTypeInfo : public Object, public ITypeInfo
{
protected:
ITypeDescriptor* typeDescriptor;
TypeInfoHint hint;
public:
TypeDescriptorTypeInfo(ITypeDescriptor* _typeDescriptor, TypeInfoHint _hint);
~TypeDescriptorTypeInfo();
Decorator GetDecorator()override;
TypeInfoHint GetHint()override;
ITypeInfo* GetElementType()override;
ITypeDescriptor* GetTypeDescriptor()override;
vint GetGenericArgumentCount()override;
ITypeInfo* GetGenericArgument(vint index)override;
WString GetTypeFriendlyName()override;
};
class DecoratedTypeInfo : public Object, public ITypeInfo
{
protected:
Ptr<ITypeInfo> elementType;
public:
DecoratedTypeInfo(Ptr<ITypeInfo> _elementType);
~DecoratedTypeInfo();
TypeInfoHint GetHint()override;
ITypeInfo* GetElementType()override;
ITypeDescriptor* GetTypeDescriptor()override;
vint GetGenericArgumentCount()override;
ITypeInfo* GetGenericArgument(vint index)override;
};
class RawPtrTypeInfo : public DecoratedTypeInfo
{
public:
RawPtrTypeInfo(Ptr<ITypeInfo> _elementType);
~RawPtrTypeInfo();
Decorator GetDecorator()override;
WString GetTypeFriendlyName()override;
};
class SharedPtrTypeInfo : public DecoratedTypeInfo
{
public:
SharedPtrTypeInfo(Ptr<ITypeInfo> _elementType);
~SharedPtrTypeInfo();
Decorator GetDecorator()override;
WString GetTypeFriendlyName()override;
};
class NullableTypeInfo : public DecoratedTypeInfo
{
public:
NullableTypeInfo(Ptr<ITypeInfo> _elementType);
~NullableTypeInfo();
Decorator GetDecorator()override;
WString GetTypeFriendlyName()override;
};
class GenericTypeInfo : public DecoratedTypeInfo
{
protected:
collections::List<Ptr<ITypeInfo>> genericArguments;
public:
GenericTypeInfo(Ptr<ITypeInfo> _elementType);
~GenericTypeInfo();
Decorator GetDecorator()override;
vint GetGenericArgumentCount()override;
ITypeInfo* GetGenericArgument(vint index)override;
WString GetTypeFriendlyName()override;
void AddGenericArgument(Ptr<ITypeInfo> value);
};
/***********************************************************************
ParameterInfoImpl
***********************************************************************/
class ParameterInfoImpl : public Object, public IParameterInfo
{
protected:
IMethodInfo* ownerMethod;
WString name;
Ptr<ITypeInfo> type;
public:
ParameterInfoImpl(IMethodInfo* _ownerMethod, const WString& _name, Ptr<ITypeInfo> _type);
~ParameterInfoImpl();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
const WString& GetName()override;
ITypeInfo* GetType()override;
IMethodInfo* GetOwnerMethod()override;
};
/***********************************************************************
MethodInfoImpl
***********************************************************************/
class MethodInfoImpl : public Object, public IMethodInfo
{
friend class PropertyInfoImpl;
protected:
IMethodGroupInfo* ownerMethodGroup;
IPropertyInfo* ownerProperty;
collections::List<Ptr<IParameterInfo>> parameters;
Ptr<ITypeInfo> returnInfo;
bool isStatic;
virtual Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)=0;
virtual Value CreateFunctionProxyInternal(const Value& thisObject) = 0;
public:
MethodInfoImpl(IMethodGroupInfo* _ownerMethodGroup, Ptr<ITypeInfo> _return, bool _isStatic);
~MethodInfoImpl();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
IPropertyInfo* GetOwnerProperty()override;
const WString& GetName()override;
IMethodGroupInfo* GetOwnerMethodGroup()override;
vint GetParameterCount()override;
IParameterInfo* GetParameter(vint index)override;
ITypeInfo* GetReturn()override;
bool IsStatic()override;
void CheckArguments(collections::Array<Value>& arguments)override;
Value Invoke(const Value& thisObject, collections::Array<Value>& arguments)override;
Value CreateFunctionProxy(const Value& thisObject)override;
bool AddParameter(Ptr<IParameterInfo> parameter);
bool SetOwnerMethodgroup(IMethodGroupInfo* _ownerMethodGroup);
};
/***********************************************************************
MethodGroupInfoImpl
***********************************************************************/
class MethodGroupInfoImpl : public Object, public IMethodGroupInfo
{
protected:
ITypeDescriptor* ownerTypeDescriptor;
WString name;
collections::List<Ptr<IMethodInfo>> methods;
public:
MethodGroupInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name);
~MethodGroupInfoImpl();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
const WString& GetName()override;
vint GetMethodCount()override;
IMethodInfo* GetMethod(vint index)override;
bool AddMethod(Ptr<IMethodInfo> _method);
};
/***********************************************************************
EventInfoImpl
***********************************************************************/
class EventInfoImpl : public Object, public IEventInfo
{
friend class PropertyInfoImpl;
protected:
ITypeDescriptor* ownerTypeDescriptor;
collections::List<IPropertyInfo*> observingProperties;
WString name;
Ptr<ITypeInfo> handlerType;
virtual Ptr<IEventHandler> AttachInternal(DescriptableObject* thisObject, Ptr<IValueFunctionProxy> handler)=0;
virtual bool DetachInternal(DescriptableObject* thisObject, Ptr<IEventHandler> handler)=0;
virtual void InvokeInternal(DescriptableObject* thisObject, Ptr<IValueList> arguments)=0;
virtual Ptr<ITypeInfo> GetHandlerTypeInternal()=0;
public:
EventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name);
~EventInfoImpl();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
const WString& GetName()override;
ITypeInfo* GetHandlerType()override;
vint GetObservingPropertyCount()override;
IPropertyInfo* GetObservingProperty(vint index)override;
Ptr<IEventHandler> Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler)override;
bool Detach(const Value& thisObject, Ptr<IEventHandler> handler)override;
void Invoke(const Value& thisObject, Ptr<IValueList> arguments)override;
};
/***********************************************************************
TypeDescriptorImpl
***********************************************************************/
class PropertyInfoImpl : public Object, public IPropertyInfo
{
protected:
ITypeDescriptor* ownerTypeDescriptor;
WString name;
Ptr<ICpp> cpp;
MethodInfoImpl* getter;
MethodInfoImpl* setter;
EventInfoImpl* valueChangedEvent;
public:
PropertyInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent);
~PropertyInfoImpl();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
const WString& GetName()override;
IPropertyInfo::ICpp* GetCpp()override;
bool IsReadable()override;
bool IsWritable()override;
ITypeInfo* GetReturn()override;
IMethodInfo* GetGetter()override;
IMethodInfo* GetSetter()override;
IEventInfo* GetValueChangedEvent()override;
Value GetValue(const Value& thisObject)override;
void SetValue(Value& thisObject, const Value& newValue)override;
};
class PropertyInfoImpl_StaticCpp : public PropertyInfoImpl, private IPropertyInfo::ICpp
{
private:
WString referenceTemplate;
const WString& GetReferenceTemplate()override;
public:
PropertyInfoImpl_StaticCpp(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent, const WString& _referenceTemplate);
~PropertyInfoImpl_StaticCpp();
IPropertyInfo::ICpp* GetCpp()override;
};
/***********************************************************************
FieldInfoImpl
***********************************************************************/
class FieldInfoImpl : public Object, public IPropertyInfo
{
protected:
ITypeDescriptor* ownerTypeDescriptor;
Ptr<ITypeInfo> returnInfo;
WString name;
virtual Value GetValueInternal(const Value& thisObject)=0;
virtual void SetValueInternal(Value& thisObject, const Value& newValue)=0;
public:
FieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Ptr<ITypeInfo> _returnInfo);
~FieldInfoImpl();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
const WString& GetName()override;
bool IsReadable()override;
bool IsWritable()override;
ITypeInfo* GetReturn()override;
IMethodInfo* GetGetter()override;
IMethodInfo* GetSetter()override;
IEventInfo* GetValueChangedEvent()override;
Value GetValue(const Value& thisObject)override;
void SetValue(Value& thisObject, const Value& newValue)override;
};
/***********************************************************************
TypeDescriptorImpl
***********************************************************************/
class TypeDescriptorImpl : public TypeDescriptorImplBase
{
private:
bool loaded;
collections::List<ITypeDescriptor*> baseTypeDescriptors;
collections::Dictionary<WString, Ptr<IPropertyInfo>> properties;
collections::Dictionary<WString, Ptr<IEventInfo>> events;
collections::Dictionary<WString, Ptr<MethodGroupInfoImpl>> methodGroups;
Ptr<MethodGroupInfoImpl> constructorGroup;
protected:
MethodGroupInfoImpl* PrepareMethodGroup(const WString& name);
MethodGroupInfoImpl* PrepareConstructorGroup();
IPropertyInfo* AddProperty(Ptr<IPropertyInfo> value);
IEventInfo* AddEvent(Ptr<IEventInfo> value);
IMethodInfo* AddMethod(const WString& name, Ptr<MethodInfoImpl> value);
IMethodInfo* AddConstructor(Ptr<MethodInfoImpl> value);
void AddBaseType(ITypeDescriptor* value);
virtual void LoadInternal()=0;
void Load();
public:
TypeDescriptorImpl(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
~TypeDescriptorImpl();
bool IsAggregatable()override;
IValueType* GetValueType()override;
IEnumType* GetEnumType()override;
ISerializableType* GetSerializableType()override;
vint GetBaseTypeDescriptorCount()override;
ITypeDescriptor* GetBaseTypeDescriptor(vint index)override;
bool CanConvertTo(ITypeDescriptor* targetType)override;
vint GetPropertyCount()override;
IPropertyInfo* GetProperty(vint index)override;
bool IsPropertyExists(const WString& name, bool inheritable)override;
IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable)override;
vint GetEventCount()override;
IEventInfo* GetEvent(vint index)override;
bool IsEventExists(const WString& name, bool inheritable)override;
IEventInfo* GetEventByName(const WString& name, bool inheritable)override;
vint GetMethodGroupCount()override;
IMethodGroupInfo* GetMethodGroup(vint index)override;
bool IsMethodGroupExists(const WString& name, bool inheritable)override;
IMethodGroupInfo* GetMethodGroupByName(const WString& name, bool inheritable)override;
IMethodGroupInfo* GetConstructorGroup()override;
};
#endif
/***********************************************************************
TypeFlagTester
***********************************************************************/
enum class TypeFlags
{
NonGenericType =0,
FunctionType =1<<0,
EnumerableType =1<<1,
ReadonlyListType =1<<2,
ListType =1<<3,
ObservableListType =1<<4,
ReadonlyDictionaryType =1<<5,
DictionaryType =1<<6,
};
template<typename T>
struct ValueRetriver
{
T* pointer;
};
template<typename T>
struct ValueRetriver<T&>
{
T* pointer;
};
template<typename TDerived, TypeFlags Flag>
struct TypeFlagTester
{
static const TypeFlags Result=TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::FunctionType>
{
template<typename T>
static void* Inherit(const Func<T>* source){}
static char Inherit(void* source){}
static char Inherit(const void* source){}
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::FunctionType:TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::EnumerableType>
{
template<typename T>
static void* Inherit(const collections::LazyList<T>* source){}
static char Inherit(void* source){}
static char Inherit(const void* source){}
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::EnumerableType:TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::ReadonlyListType>
{
template<typename T>
static void* Inherit(const collections::IEnumerable<T>* source){}
static char Inherit(void* source){}
static char Inherit(const void* source){}
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyListType:TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::ListType>
{
template<typename T>
static void* Inherit(collections::IEnumerable<T>* source){}
static char Inherit(void* source){}
static char Inherit(const void* source){}
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ListType:TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::ObservableListType>
{
template<typename T>
static void* Inherit(collections::ObservableList<T>* source) {}
static char Inherit(void* source) {}
static char Inherit(const void* source) {}
static const TypeFlags Result = sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer)) == sizeof(void*) ? TypeFlags::ObservableListType : TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::ReadonlyDictionaryType>
{
template<typename K, typename V>
static void* Inherit(const collections::Dictionary<K, V>* source){}
static char Inherit(void* source){}
static char Inherit(const void* source){}
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyDictionaryType:TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::DictionaryType>
{
template<typename K, typename V>
static void* Inherit(collections::Dictionary<K, V>* source){}
static char Inherit(void* source){}
static char Inherit(const void* source){}
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::DictionaryType:TypeFlags::NonGenericType;
};
/***********************************************************************
TypeFlagSelector
***********************************************************************/
template<typename T, TypeFlags Flag>
struct TypeFlagSelectorCase
{
static const TypeFlags Result=TypeFlags::NonGenericType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::FunctionType)>
{
static const TypeFlags Result=TypeFlags::FunctionType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::EnumerableType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::EnumerableType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::ListType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ObservableListType|(vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result = TypeFlags::ObservableListType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::ReadonlyListType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::DictionaryType|(vint)TypeFlags::ReadonlyDictionaryType)>
{
static const TypeFlags Result=TypeFlags::DictionaryType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ReadonlyDictionaryType)>
{
static const TypeFlags Result=TypeFlags::ReadonlyDictionaryType;
};
template<typename T>
struct TypeFlagSelector
{
static const TypeFlags Result =
TypeFlagSelectorCase<
T,
(TypeFlags)
( (vint)TypeFlagTester<T, TypeFlags::FunctionType>::Result
| (vint)TypeFlagTester<T, TypeFlags::EnumerableType>::Result
| (vint)TypeFlagTester<T, TypeFlags::ReadonlyListType>::Result
| (vint)TypeFlagTester<T, TypeFlags::ListType>::Result
| (vint)TypeFlagTester<T, TypeFlags::ObservableListType>::Result
| (vint)TypeFlagTester<T, TypeFlags::ReadonlyDictionaryType>::Result
| (vint)TypeFlagTester<T, TypeFlags::DictionaryType>::Result
)
>::Result;
};
/***********************************************************************
TypeHintTester
***********************************************************************/
template<typename T>
struct TypeHintTester
{
static const TypeInfoHint Result = TypeInfoHint::Normal;
};
template<TypeFlags Flags>
struct TypeHintTesterForReference
{
static const TypeInfoHint Result = TypeInfoHint::NativeCollectionReference;
};
template<>
struct TypeHintTesterForReference<TypeFlags::NonGenericType>
{
static const TypeInfoHint Result = TypeInfoHint::Normal;
};
template<>
struct TypeHintTesterForReference<TypeFlags::FunctionType>
{
static const TypeInfoHint Result = TypeInfoHint::Normal;
};
template<typename T>
struct TypeHintTester<T*>
{
static const TypeInfoHint Result = TypeHintTester<T>::Result;
};
template<typename T>
struct TypeHintTester<T&>
{
static const TypeInfoHint Result = TypeHintTester<T>::Result == TypeInfoHint::Normal
? TypeHintTesterForReference<TypeFlagSelector<T&>::Result>::Result
: TypeHintTester<T>::Result
;
};
template<typename T>
struct TypeHintTester<const T>
{
static const TypeInfoHint Result = TypeHintTester<T>::Result;
};
template<typename T>
struct TypeHintTester<collections::LazyList<T>>
{
static const TypeInfoHint Result = TypeInfoHint::LazyList;
};
template<typename T>
struct TypeHintTester<collections::Array<T>>
{
static const TypeInfoHint Result = TypeInfoHint::Array;
};
template<typename T>
struct TypeHintTester<collections::List<T>>
{
static const TypeInfoHint Result = TypeInfoHint::List;
};
template<typename T>
struct TypeHintTester<collections::SortedList<T>>
{
static const TypeInfoHint Result = TypeInfoHint::SortedList;
};
template<typename T>
struct TypeHintTester<collections::ObservableList<T>>
{
static const TypeInfoHint Result = TypeInfoHint::ObservableList;
};
template<typename K, typename V>
struct TypeHintTester<collections::Dictionary<K, V>>
{
static const TypeInfoHint Result = TypeInfoHint::Dictionary;
};
/***********************************************************************
TypeInfoRetriver
***********************************************************************/
template<typename T, TypeFlags Flag>
struct DetailTypeInfoRetriver
{
static const ITypeInfo::Decorator Decorator=ITypeInfo::TypeDescriptor;
typedef void Type;
typedef void TempValueType;
typedef void ResultReferenceType;
typedef void ResultNonReferenceType;
};
template<typename T>
struct TypeInfoRetriver
{
static const TypeFlags TypeFlag = TypeFlagSelector<T>::Result;
static const TypeInfoHint Hint = TypeHintTester<T>::Result;
static const ITypeInfo::Decorator Decorator = DetailTypeInfoRetriver<T, TypeFlag>::Decorator;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::Type Type;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::TempValueType TempValueType;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::ResultReferenceType ResultReferenceType;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo()
{
return DetailTypeInfoRetriver<typename RemoveCVR<T>::Type, TypeFlag>::CreateTypeInfo(Hint);
}
#endif
};
/***********************************************************************
TypeInfoRetriver Helper Functions (BoxValue, UnboxValue)
***********************************************************************/
template<typename T, ITypeInfo::Decorator Decorator>
struct ValueAccessor
{
};
/// <summary>Box an reflectable object. Its type cannot be generic.</summary>
/// <returns>The boxed value.</returns>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="object">The object to box.</param>
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
template<typename T>
Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor=0)
{
using Type = typename RemoveCVR<T>::Type;
return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::BoxValue(object, typeDescriptor);
}
/// <summary>Unbox an reflectable object. Its type cannot be generic.</summary>
/// <returns>The unboxed object.</returns>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="value">The value to unbox.</param>
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
/// <param name="valueName">The name of the object to provide a friendly exception message if the conversion is failed (optional).</param>
template<typename T>
T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor=0, const WString& valueName=L"value")
{
using Type = typename RemoveCVR<T>::Type;
return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::UnboxValue(value, typeDescriptor, valueName);
}
/***********************************************************************
TypeInfoRetriver Helper Functions (UnboxParameter)
***********************************************************************/
template<typename T, TypeFlags Flag>
struct ParameterAccessor
{
};
/// <summary>Box an reflectable object. It supports generic types such as containers, functions, etc.</summary>
/// <returns>The boxed value.</returns>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="object">The object to box.</param>
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
template<typename T>
Value BoxParameter(typename TypeInfoRetriver<T>::ResultReferenceType object, ITypeDescriptor* typeDescriptor=0)
{
return ParameterAccessor<typename TypeInfoRetriver<T>::ResultNonReferenceType, TypeInfoRetriver<T>::TypeFlag>::BoxParameter(object, typeDescriptor);
}
/// <summary>Box an reflectable object. It supports generic types such as containers, functions, etc.</summary>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="value">The value to unbox.</param>
/// <param name="result">The unboxed object.</param>
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
/// <param name="valueName">The name of the object to provide a friendly exception message if the conversion is failed (optional).</param>
template<typename T>
void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor=0, const WString& valueName=L"value")
{
ParameterAccessor<T, TypeInfoRetriver<T>::TypeFlag>::UnboxParameter(value, result, typeDescriptor, valueName);
}
#ifndef VCZH_DEBUG_NO_REFLECTION
/***********************************************************************
Value_xs
***********************************************************************/
class Value_xs
{
protected:
collections::Array<Value> arguments;
public:
Value_xs()
{
}
template<typename T>
Value_xs& operator,(T& value)
{
arguments.Resize(arguments.Count() + 1);
arguments[arguments.Count() - 1] = BoxParameter<T>(value);
return *this;
}
template<typename T>
Value_xs& operator,(const T& value)
{
arguments.Resize(arguments.Count() + 1);
arguments[arguments.Count() - 1] = BoxParameter<const T>(value);
return *this;
}
Value_xs& operator,(const Value& value)
{
arguments.Resize(arguments.Count()+1);
arguments[arguments.Count()-1]=value;
return *this;
}
operator collections::Array<Value>&()
{
return arguments;
}
};
/***********************************************************************
CustomFieldInfoImpl
***********************************************************************/
template<typename TClass, typename TField>
class CustomFieldInfoImpl : public FieldInfoImpl
{
protected:
TField TClass::* fieldRef;
Value GetValueInternal(const Value& thisObject)override
{
TClass* object=UnboxValue<TClass*>(thisObject);
if(object)
{
return BoxParameter<TField>(object->*fieldRef, GetReturn()->GetTypeDescriptor());
}
return Value();
}
void SetValueInternal(Value& thisObject, const Value& newValue)override
{
TClass* object=UnboxValue<TClass*>(thisObject);
if(object)
{
UnboxParameter<TField>(newValue, object->*fieldRef, GetReturn()->GetTypeDescriptor(), L"newValue");
}
}
public:
CustomFieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, TField TClass::* _fieldRef)
:FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
, fieldRef(_fieldRef)
{
}
IPropertyInfo::ICpp* GetCpp()override
{
return nullptr;
}
};
/***********************************************************************
PrimitiveTypeDescriptor
***********************************************************************/
template<typename T>
class SerializableValueType : public Object, public virtual IValueType
{
public:
Value CreateDefault()override
{
return BoxValue<T>(TypedValueSerializerProvider<T>::GetDefaultValue());
}
IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override
{
auto va = UnboxValue<T>(a);
auto vb = UnboxValue<T>(b);
return TypedValueSerializerProvider<T>::Compare(va, vb);
}
};
template<typename T>
class SerializableType : public Object, public virtual ISerializableType
{
public:
bool Serialize(const Value& input, WString& output)override
{
return TypedValueSerializerProvider<T>::Serialize(UnboxValue<T>(input), output);
}
bool Deserialize(const WString& input, Value& output)override
{
T value;
if (!TypedValueSerializerProvider<T>::Deserialize(input, value))
{
return false;
}
output = BoxValue<T>(value);
return true;
}
};
template<typename T>
class PrimitiveTypeDescriptor : public TypedValueTypeDescriptorBase<T, TypeDescriptorFlags::Primitive>
{
protected:
void LoadInternal()override
{
this->valueType = new SerializableValueType<T>();
this->serializableType = new SerializableType<T>();
}
};
/***********************************************************************
EnumTypeDescriptor
***********************************************************************/
template<typename T>
class EnumValueType : public Object, public virtual IValueType
{
public:
Value CreateDefault()override
{
return BoxValue<T>(static_cast<T>(0));
}
IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override
{
auto ea = static_cast<vuint64_t>(UnboxValue<T>(a));
auto eb = static_cast<vuint64_t>(UnboxValue<T>(b));
if (ea < eb) return IBoxedValue::Smaller;
if (ea > eb)return IBoxedValue::Greater;
return IBoxedValue::Equal;
}
};
template<typename T, bool Flag>
class EnumType : public Object, public virtual IEnumType
{
protected:
collections::Dictionary<WString, T> candidates;
public:
void AddItem(WString name, T value)
{
candidates.Add(name, value);
}
bool IsFlagEnum()override
{
return Flag;
}
vint GetItemCount()override
{
return candidates.Count();
}
WString GetItemName(vint index)override
{
if (index < 0 || index >= candidates.Count())
{
return L"";
}
return candidates.Keys()[index];
}
vuint64_t GetItemValue(vint index)override
{
if (index < 0 || index >= candidates.Count())
{
return 0;
}
return static_cast<vuint64_t>(candidates.Values()[index]);
}
vint IndexOfItem(WString name)override
{
return candidates.Keys().IndexOf(name);
}
Value ToEnum(vuint64_t value)override
{
return BoxValue<T>(static_cast<T>(value));
}
vuint64_t FromEnum(const Value& value)override
{
return static_cast<vuint64_t>(UnboxValue<T>(value));
}
};
template<typename T, TypeDescriptorFlags TDFlags>
class EnumTypeDescriptor : public TypedValueTypeDescriptorBase<T, TDFlags>
{
using TEnumType = EnumType<T, TDFlags == TypeDescriptorFlags::FlagEnum>;
protected:
Ptr<TEnumType> enumType;
void LoadInternal()override
{
this->enumType = new TEnumType;
this->valueType = new EnumValueType<T>();
TypedValueTypeDescriptorBase<T, TDFlags>::enumType = enumType;
}
};
/***********************************************************************
StructTypeDescriptor
***********************************************************************/
template<typename T>
class StructValueType : public Object, public virtual IValueType
{
public:
Value CreateDefault()override
{
return BoxValue<T>(T{});
}
IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override
{
return IBoxedValue::NotComparable;
}
};
template<typename T, TypeDescriptorFlags TDFlags>
class StructTypeDescriptor : public TypedValueTypeDescriptorBase<T, TDFlags>
{
protected:
template<typename TField>
class StructFieldInfo : public FieldInfoImpl
{
protected:
TField T::* field;
Value GetValueInternal(const Value& thisObject)override
{
auto structValue = thisObject.GetBoxedValue().Cast<IValueType::TypedBox<T>>();
if (!structValue)
{
throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject);
}
return BoxValue<TField>(structValue->value.*field);
}
void SetValueInternal(Value& thisObject, const Value& newValue)override
{
auto structValue = thisObject.GetBoxedValue().Cast<IValueType::TypedBox<T>>();
if (!structValue)
{
throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject);
}
(structValue->value.*field) = UnboxValue<TField>(newValue);
}
public:
StructFieldInfo(ITypeDescriptor* _ownerTypeDescriptor, TField T::* _field, const WString& _name)
:field(_field)
, FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
{
}
IPropertyInfo::ICpp* GetCpp()override
{
return nullptr;
}
};
protected:
collections::Dictionary<WString, Ptr<IPropertyInfo>> fields;
public:
StructTypeDescriptor()
{
this->valueType = new StructValueType<T>();
}
vint GetPropertyCount()override
{
this->Load();
return fields.Count();
}
IPropertyInfo* GetProperty(vint index)override
{
this->Load();
if (index < 0 || index >= fields.Count())
{
return nullptr;
}
return fields.Values()[index].Obj();
}
bool IsPropertyExists(const WString& name, bool inheritable)override
{
this->Load();
return fields.Keys().Contains(name);
}
IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable)override
{
this->Load();
vint index = fields.Keys().IndexOf(name);
if (index == -1) return nullptr;
return fields.Values()[index].Obj();
}
};
#endif
}
}
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORBUILDER_CONTAINER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_CONTAINER
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_CONTAINER
namespace vl
{
namespace reflection
{
namespace description
{
/***********************************************************************
Enumerable Wrappers
***********************************************************************/
template<typename T>
class TypedEnumerator : public Object, public collections::IEnumerator<T>
{
private:
Ptr<IValueEnumerable> enumerable;
Ptr<IValueEnumerator> enumerator;
vint index;
T value;
public:
TypedEnumerator(Ptr<IValueEnumerable> _enumerable, vint _index, const T& _value)
:enumerable(_enumerable)
,index(_index)
,value(_value)
{
enumerator=enumerable->CreateEnumerator();
vint current=-1;
while(current++<index)
{
enumerator->Next();
}
}
TypedEnumerator(Ptr<IValueEnumerable> _enumerable)
:enumerable(_enumerable)
,index(-1)
{
Reset();
}
collections::IEnumerator<T>* Clone()const override
{
return new TypedEnumerator<T>(enumerable, index, value);
}
const T& Current()const override
{
return value;
}
vint Index()const override
{
return index;
}
bool Next() override
{
if(enumerator->Next())
{
index++;
value=UnboxValue<T>(enumerator->GetCurrent());
return true;
}
else
{
return false;
}
}
void Reset() override
{
index=-1;
enumerator=enumerable->CreateEnumerator();
}
};
template<typename T>
collections::LazyList<T> GetLazyList(Ptr<IValueEnumerable> value)
{
return collections::LazyList<T>(new TypedEnumerator<T>(value));
}
template<typename T>
collections::LazyList<T> GetLazyList(Ptr<IValueReadonlyList> value)
{
return collections::Range<vint>(0, value->GetCount())
.Select([value](vint i)
{
return UnboxValue<T>(value->Get(i));
});
}
template<typename T>
collections::LazyList<T> GetLazyList(Ptr<IValueList> value)
{
return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
}
template<typename T>
collections::LazyList<T> GetLazyList(Ptr<IValueObservableList> value)
{
return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
}
template<typename K, typename V>
collections::LazyList<collections::Pair<K, V>> GetLazyList(Ptr<IValueReadonlyDictionary> value)
{
return collections::Range<vint>(0, value->GetCount())
.Select([value](vint i)
{
return collections::Pair<K, V>(UnboxValue<K>(value->GetKeys()->Get(i)), UnboxValue<V>(value->GetValues()->Get(i)));
});
}
template<typename K, typename V>
collections::LazyList<collections::Pair<K, V>> GetLazyList(Ptr<IValueDictionary> value)
{
return GetLazyList<K, V>(Ptr<IValueReadonlyDictionary>(value));
}
/***********************************************************************
Collection Wrappers
***********************************************************************/
namespace trait_helper
{
template<typename T>
struct RemovePtr
{
typedef T Type;
};
template<typename T>
struct RemovePtr<T*>
{
typedef T Type;
};
template<typename T>
struct RemovePtr<Ptr<T>>
{
typedef T Type;
};
}
#pragma warning(push)
#pragma warning(disable:4250)
template<typename T>
class ValueEnumeratorWrapper : public Object, public virtual IValueEnumerator
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
T wrapperPointer;
public:
ValueEnumeratorWrapper(const T& _wrapperPointer)
:wrapperPointer(_wrapperPointer)
{
}
Value GetCurrent()override
{
return BoxValue<ElementType>(wrapperPointer->Current());
}
vint GetIndex()override
{
return wrapperPointer->Index();
}
bool Next()override
{
return wrapperPointer->Next();
}
};
template<typename T>
class ValueEnumerableWrapper : public Object, public virtual IValueEnumerable
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
T wrapperPointer;
public:
ValueEnumerableWrapper(const T& _wrapperPointer)
:wrapperPointer(_wrapperPointer)
{
}
Ptr<IValueEnumerator> CreateEnumerator()override
{
return new ValueEnumeratorWrapper<Ptr<collections::IEnumerator<ElementType>>>(wrapperPointer->CreateEnumerator());
}
};
#define WRAPPER_POINTER this->wrapperPointer
template<typename T>
class ValueReadonlyListWrapper : public ValueEnumerableWrapper<T>, public virtual IValueReadonlyList
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
typedef typename KeyType<ElementType>::Type ElementKeyType;
public:
ValueReadonlyListWrapper(const T& _wrapperPointer)
:ValueEnumerableWrapper<T>(_wrapperPointer)
{
}
vint GetCount()override
{
return WRAPPER_POINTER->Count();
}
Value Get(vint index)override
{
return BoxValue<ElementType>(WRAPPER_POINTER->Get(index));
}
bool Contains(const Value& value)override
{
ElementKeyType item=UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->Contains(item);
}
vint IndexOf(const Value& value)override
{
ElementKeyType item=UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->IndexOf(item);
}
};
template<typename T>
class ValueListWrapper : public ValueReadonlyListWrapper<T>, public virtual IValueList
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
typedef typename KeyType<ElementType>::Type ElementKeyType;
public:
ValueListWrapper(const T& _wrapperPointer)
:ValueReadonlyListWrapper<T>(_wrapperPointer)
{
}
void Set(vint index, const Value& value)override
{
ElementType item=UnboxValue<ElementType>(value);
WRAPPER_POINTER->Set(index, item);
}
vint Add(const Value& value)override
{
ElementType item=UnboxValue<ElementType>(value);
return WRAPPER_POINTER->Add(item);
}
vint Insert(vint index, const Value& value)override
{
ElementType item=UnboxValue<ElementType>(value);
return WRAPPER_POINTER->Insert(index, item);
}
bool Remove(const Value& value)override
{
ElementKeyType item=UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->Remove(item);
}
bool RemoveAt(vint index)override
{
return WRAPPER_POINTER->RemoveAt(index);
}
void Clear()override
{
WRAPPER_POINTER->Clear();
}
};
template<typename T, typename K>
class ValueListWrapper<collections::Array<T, K>*> : public ValueReadonlyListWrapper<collections::Array<T, K>*>, public virtual IValueList
{
protected:
typedef collections::Array<T, K> ContainerType;
typedef T ElementType;
typedef K ElementKeyType;
public:
ValueListWrapper(collections::Array<T, K>* _wrapperPointer)
:ValueReadonlyListWrapper<collections::Array<T, K>*>(_wrapperPointer)
{
}
void Set(vint index, const Value& value)override
{
ElementType item = UnboxValue<ElementType>(value);
WRAPPER_POINTER->Set(index, item);
}
vint Add(const Value& value)override
{
throw Exception(L"Array doesn't have Add method.");
}
vint Insert(vint index, const Value& value)override
{
throw Exception(L"Array doesn't have Insert method.");
}
bool Remove(const Value& value)override
{
throw Exception(L"Array doesn't have Remove method.");
}
bool RemoveAt(vint index)override
{
throw Exception(L"Array doesn't have RemoveAt method.");
}
void Clear()override
{
throw Exception(L"Array doesn't have Clear method.");
}
};
template<typename T, typename K>
class ValueListWrapper<collections::SortedList<T, K>*> : public ValueReadonlyListWrapper<collections::SortedList<T, K>*>, public virtual IValueList
{
protected:
typedef collections::SortedList<T, K> ContainerType;
typedef T ElementType;
typedef K ElementKeyType;
public:
ValueListWrapper(collections::SortedList<T, K>* _wrapperPointer)
:ValueReadonlyListWrapper<collections::SortedList<T, K>*>(_wrapperPointer)
{
}
void Set(vint index, const Value& value)override
{
throw Exception(L"SortedList doesn't have Set method.");
}
vint Add(const Value& value)override
{
ElementType item = UnboxValue<ElementType>(value);
return WRAPPER_POINTER->Add(item);
}
vint Insert(vint index, const Value& value)override
{
throw Exception(L"SortedList doesn't have Insert method.");
}
bool Remove(const Value& value)override
{
ElementKeyType item = UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->Remove(item);
}
bool RemoveAt(vint index)override
{
return WRAPPER_POINTER->RemoveAt(index);
}
void Clear()override
{
WRAPPER_POINTER->Clear();
}
};
template<typename T>
class ValueObservableListWrapper : public ValueListWrapper<T>, public virtual IValueObservableList
{
public:
ValueObservableListWrapper(const T& _wrapperPointer)
:ValueListWrapper<T>(_wrapperPointer)
{
}
};
#undef WRAPPER_POINTER
template<typename T>
class ValueReadonlyDictionaryWrapper : public virtual Object, public virtual IValueReadonlyDictionary
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::KeyContainer KeyContainer;
typedef typename ContainerType::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyValueType;
typedef typename KeyType<KeyValueType>::Type KeyKeyType;
typedef typename ValueContainer::ElementType ValueType;
T wrapperPointer;
Ptr<IValueReadonlyList> keys;
Ptr<IValueReadonlyList> values;
public:
ValueReadonlyDictionaryWrapper(const T& _wrapperPointer)
:wrapperPointer(_wrapperPointer)
{
}
Ptr<IValueReadonlyList> GetKeys()override
{
if(!keys)
{
keys=new ValueReadonlyListWrapper<const KeyContainer*>(&wrapperPointer->Keys());
}
return keys;
}
Ptr<IValueReadonlyList> GetValues()override
{
if(!values)
{
values=new ValueReadonlyListWrapper<const ValueContainer*>(&wrapperPointer->Values());
}
return values;
}
vint GetCount()override
{
return wrapperPointer->Count();
}
Value Get(const Value& key)override
{
KeyKeyType item=UnboxValue<KeyKeyType>(key);
ValueType result=wrapperPointer->Get(item);
return BoxValue<ValueType>(result);
}
};
#define WRAPPER_POINTER ValueReadonlyDictionaryWrapper<T>::wrapperPointer
#define KEY_VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyValueType
#define VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::ValueType
#define KEY_KEY_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyKeyType
template<typename T>
class ValueDictionaryWrapper : public virtual ValueReadonlyDictionaryWrapper<T>, public virtual IValueDictionary
{
public:
ValueDictionaryWrapper(const T& _wrapperPointer)
:ValueReadonlyDictionaryWrapper<T>(_wrapperPointer)
{
}
void Set(const Value& key, const Value& value)override
{
KEY_VALUE_TYPE item=UnboxValue<KEY_VALUE_TYPE>(key);
VALUE_TYPE result=UnboxValue<VALUE_TYPE>(value);
WRAPPER_POINTER->Set(item, result);
}
bool Remove(const Value& key)override
{
KEY_KEY_TYPE item=UnboxValue<KEY_KEY_TYPE>(key);
return WRAPPER_POINTER->Remove(item);
}
void Clear()override
{
WRAPPER_POINTER->Clear();
}
};
#undef WRAPPER_POINTER
#undef KEY_VALUE_TYPE
#undef VALUE_TYPE
#undef KEY_KEY_TYPE
#pragma warning(pop)
/***********************************************************************
DetailTypeInfoRetriver<TContainer>
***********************************************************************/
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::EnumerableType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueEnumerable Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueEnumerable>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyListType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueReadonlyList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueReadonlyList>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ListType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueList>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ObservableListType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator = UpLevelRetriver::Decorator;
typedef IValueObservableList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueObservableList>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyDictionaryType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueReadonlyList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::KeyContainer KeyContainer;
typedef typename ContainerType::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueReadonlyDictionary>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<KeyType>::CreateTypeInfo());
genericType->AddGenericArgument(TypeInfoRetriver<ValueType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::DictionaryType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueReadonlyList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::KeyContainer KeyContainer;
typedef typename ContainerType::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueDictionary>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<KeyType>::CreateTypeInfo());
genericType->AddGenericArgument(TypeInfoRetriver<ValueType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
/***********************************************************************
ParameterAccessor<TContainer>
***********************************************************************/
template<typename T>
struct ParameterAccessor<collections::LazyList<T>, TypeFlags::EnumerableType>
{
static Value BoxParameter(collections::LazyList<T>& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueEnumerable> result=IValueEnumerable::Create(
collections::From(object)
.Select([](const T& item)
{
return BoxValue<T>(item);
})
);
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueEnumerable>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueEnumerable>>(result, td);
}
static void UnboxParameter(const Value& value, collections::LazyList<T>& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename collections::LazyList<T>::ElementType ElementType;
Ptr<IValueEnumerable> listProxy=UnboxValue<Ptr<IValueEnumerable>>(value, typeDescriptor, valueName);
result=GetLazyList<T>(listProxy);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::ReadonlyListType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueReadonlyList> result=new ValueReadonlyListWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueReadonlyList>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueReadonlyList>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::ElementType ElementType;
Ptr<IValueReadonlyList> listProxy=UnboxValue<Ptr<IValueReadonlyList>>(value, typeDescriptor, valueName);
collections::LazyList<ElementType> lazyList=GetLazyList<ElementType>(listProxy);
collections::CopyFrom(result, lazyList);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::ListType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueList> result=new ValueListWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueList>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueList>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::ElementType ElementType;
Ptr<IValueList> listProxy=UnboxValue<Ptr<IValueList>>(value, typeDescriptor, valueName);
collections::LazyList<ElementType> lazyList=GetLazyList<ElementType>(listProxy);
collections::CopyFrom(result, lazyList);
}
};
template<typename T>
struct ParameterAccessor<collections::ObservableList<T>, TypeFlags::ObservableListType>
{
static Value BoxParameter(collections::ObservableList<T>& object, ITypeDescriptor* typeDescriptor)
{
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueObservableList>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueObservableList>>(object.GetWrapper(), td);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::ReadonlyDictionaryType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueReadonlyDictionary> result=new ValueReadonlyDictionaryWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueReadonlyDictionary>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueReadonlyDictionary>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::KeyContainer KeyContainer;
typedef typename T::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
Ptr<IValueReadonlyDictionary> dictionaryProxy=UnboxValue<Ptr<IValueReadonlyDictionary>>(value, typeDescriptor, valueName);
collections::LazyList<collections::Pair<KeyType, ValueType>> lazyList=GetLazyList<KeyType, ValueType>(dictionaryProxy);
collections::CopyFrom(result, lazyList);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::DictionaryType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueDictionary> result=new ValueDictionaryWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueDictionary>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueDictionary>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::KeyContainer KeyContainer;
typedef typename T::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
Ptr<IValueDictionary> dictionaryProxy=UnboxValue<Ptr<IValueDictionary>>(value, typeDescriptor, valueName);
collections::LazyList<collections::Pair<KeyType, ValueType>> lazyList=GetLazyList<KeyType, ValueType>(dictionaryProxy);
collections::CopyFrom(result, lazyList);
}
};
}
}
namespace collections
{
template<typename T, typename K = typename KeyType<T>::Type>
class ObservableListBase : public Object, public virtual collections::IEnumerable<T>
{
protected:
collections::List<T, K> items;
virtual void NotifyUpdateInternal(vint start, vint count, vint newCount)
{
}
virtual bool QueryInsert(vint index, const T& value)
{
return true;
}
virtual void BeforeInsert(vint index, const T& value)
{
}
virtual void AfterInsert(vint index, const T& value)
{
}
virtual bool QueryRemove(vint index, const T& value)
{
return true;
}
virtual void BeforeRemove(vint index, const T& value)
{
}
virtual void AfterRemove(vint index, vint count)
{
}
public:
ObservableListBase()
{
}
~ObservableListBase()
{
}
collections::IEnumerator<T>* CreateEnumerator()const
{
return items.CreateEnumerator();
}
bool NotifyUpdate(vint start, vint count = 1)
{
if (start<0 || start >= items.Count() || count <= 0 || start + count>items.Count())
{
return false;
}
else
{
NotifyUpdateInternal(start, count, count);
return true;
}
}
bool Contains(const K& item)const
{
return items.Contains(item);
}
vint Count()const
{
return items.Count();
}
vint Count()
{
return items.Count();
}
const T& Get(vint index)const
{
return items.Get(index);
}
const T& operator[](vint index)const
{
return items.Get(index);
}
vint IndexOf(const K& item)const
{
return items.IndexOf(item);
}
vint Add(const T& item)
{
return Insert(items.Count(), item);
}
bool Remove(const K& item)
{
vint index = items.IndexOf(item);
if (index == -1) return false;
return RemoveAt(index);
}
bool RemoveAt(vint index)
{
if (0 <= index && index < items.Count() && QueryRemove(index, items[index]))
{
BeforeRemove(index, items[index]);
T item = items[index];
items.RemoveAt(index);
AfterRemove(index, 1);
NotifyUpdateInternal(index, 1, 0);
return true;
}
return false;
}
bool RemoveRange(vint index, vint count)
{
if (count <= 0) return false;
if (0 <= index && index<items.Count() && index + count <= items.Count())
{
for (vint i = 0; i < count; i++)
{
if (!QueryRemove(index + 1, items[index + i])) return false;
}
for (vint i = 0; i < count; i++)
{
BeforeRemove(index + i, items[index + i]);
}
items.RemoveRange(index, count);
AfterRemove(index, count);
NotifyUpdateInternal(index, count, 0);
return true;
}
return false;
}
bool Clear()
{
vint count = items.Count();
for (vint i = 0; i < count; i++)
{
if (!QueryRemove(i, items[i])) return false;
}
for (vint i = 0; i < count; i++)
{
BeforeRemove(i, items[i]);
}
items.Clear();
AfterRemove(0, count);
NotifyUpdateInternal(0, count, 0);
return true;
}
vint Insert(vint index, const T& item)
{
if (0 <= index && index <= items.Count() && QueryInsert(index, item))
{
BeforeInsert(index, item);
items.Insert(index, item);
AfterInsert(index, item);
NotifyUpdateInternal(index, 0, 1);
return index;
}
else
{
return -1;
}
}
bool Set(vint index, const T& item)
{
if (0 <= index && index < items.Count())
{
if (QueryRemove(index, items[index]) && QueryInsert(index, item))
{
BeforeRemove(index, items[index]);
items.RemoveAt(index);
AfterRemove(index, 1);
BeforeInsert(index, item);
items.Insert(index, item);
AfterInsert(index, item);
NotifyUpdateInternal(index, 1, 1);
return true;
}
}
return false;
}
};
template<typename T>
class ObservableList : public ObservableListBase<T>
{
protected:
Ptr<reflection::description::IValueObservableList> observableList;
void NotifyUpdateInternal(vint start, vint count, vint newCount)override
{
if (observableList)
{
observableList->ItemChanged(start, count, newCount);
}
}
public:
Ptr<reflection::description::IValueObservableList> GetWrapper()
{
if (!observableList)
{
observableList = new reflection::description::ValueObservableListWrapper<ObservableList<T>*>(this);
}
return observableList;
}
};
namespace randomaccess_internal
{
template<typename T>
struct RandomAccessable<ObservableListBase<T>>
{
static const bool CanRead = true;
static const bool CanResize = false;
};
template<typename T>
struct RandomAccessable<ObservableList<T>>
{
static const bool CanRead = true;
static const bool CanResize = false;
};
}
}
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORBUILDER_FUNCTION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_FUNCTION
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_FUNCTION
namespace vl
{
namespace reflection
{
namespace description
{
template<typename ...TArgs>
struct EventHelper
{
using Handler = const Func<void(TArgs...)>&;
class EventHandlerImpl : public Object, public reflection::description::IEventHandler
{
public:
Ptr<EventHandler> handler;
EventHandlerImpl(Ptr<EventHandler> _handler)
:handler(_handler)
{
}
bool IsAttached()override
{
return handler->IsAttached();
}
};
static Ptr<reflection::description::IEventHandler> Attach(Event<void(TArgs...)>& e, Handler handler)
{
return MakePtr<EventHandlerImpl>(e.Add(handler));
}
static bool Detach(Event<void(TArgs...)>& e, Ptr<reflection::description::IEventHandler> handler)
{
auto impl = handler.Cast<EventHandlerImpl>();
if (!impl) return false;
return e.Remove(impl->handler);
}
static Event<void(TArgs...)>& Invoke(Event<void(TArgs...)>& e)
{
return e;
}
};
/***********************************************************************
DetailTypeInfoRetriver<Func<R(TArgs...)>>
***********************************************************************/
#ifndef VCZH_DEBUG_NO_REFLECTION
namespace internal_helper
{
template<typename T>
struct GenericArgumentAdder
{
static void Add(Ptr<GenericTypeInfo> genericType)
{
}
};
template<typename T0, typename ...TNextArgs>
struct GenericArgumentAdder<TypeTuple<T0, TNextArgs...>>
{
static void Add(Ptr<GenericTypeInfo> genericType)
{
genericType->AddGenericArgument(TypeInfoRetriver<T0>::CreateTypeInfo());
GenericArgumentAdder<TypeTuple<TNextArgs...>>::Add(genericType);
}
};
}
#endif
template<typename R, typename ...TArgs>
struct DetailTypeInfoRetriver<Func<R(TArgs...)>, TypeFlags::FunctionType>
{
typedef DetailTypeInfoRetriver<const Func<R(TArgs...)>, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
auto functionType = MakePtr<TypeDescriptorTypeInfo>(Description<IValueFunctionProxy>::GetAssociatedTypeDescriptor(), hint);
auto genericType = MakePtr<GenericTypeInfo>(functionType);
genericType->AddGenericArgument(TypeInfoRetriver<R>::CreateTypeInfo());
internal_helper::GenericArgumentAdder<TypeTuple<TArgs...>>::Add(genericType);
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename R, typename ...TArgs>
struct DetailTypeInfoRetriver<const Func<R(TArgs...)>, TypeFlags::FunctionType>
: DetailTypeInfoRetriver<Func<R(TArgs...)>, TypeFlags::FunctionType>
{
};
/***********************************************************************
ValueFunctionProxyWrapper<Func<R(TArgs...)>>
***********************************************************************/
template<typename T>
class ValueFunctionProxyWrapper
{
};
namespace internal_helper
{
extern void UnboxSpecifiedParameter(Ptr<IValueList> arguments, vint index);
template<typename T0, typename ...TArgs>
void UnboxSpecifiedParameter(Ptr<IValueList> arguments, vint index, T0& p0, TArgs& ...args)
{
UnboxParameter<typename TypeInfoRetriver<T0>::TempValueType>(arguments->Get(index), p0, 0, itow(index + 1) + L"-th argument");
UnboxSpecifiedParameter(arguments, index + 1, args...);
}
template<typename R, typename ...TArgs>
struct BoxedFunctionInvoker
{
static Value Invoke(const Func<R(TArgs...)>& function, Ptr<IValueList> arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(arguments, 0, args...);
R result = function(args...);
return BoxParameter<R>(result);
}
};
template<typename ...TArgs>
struct BoxedFunctionInvoker<void, TArgs...>
{
static Value Invoke(const Func<void(TArgs...)>& function, Ptr<IValueList> arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(arguments, 0, args...);
function(args...);
return Value();
}
};
}
template<typename R, typename ...TArgs>
class ValueFunctionProxyWrapper<R(TArgs...)> : public Object, public virtual IValueFunctionProxy
{
typedef Func<R(TArgs...)> FunctionType;
protected:
FunctionType function;
public:
ValueFunctionProxyWrapper(const FunctionType& _function)
:function(_function)
{
}
FunctionType GetFunction()
{
return function;
}
Value Invoke(Ptr<IValueList> arguments)override
{
if (!arguments || arguments->GetCount() != sizeof...(TArgs))
{
#ifndef VCZH_DEBUG_NO_REFLECTION
throw ArgumentCountMismtatchException();
#else
CHECK_FAIL(L"Argument count mismatch.");
#endif
}
return internal_helper::BoxedFunctionInvoker<R, TArgs...>::Invoke(function, arguments, typename RemoveCVR<TArgs>::Type()...);
}
};
/***********************************************************************
ParameterAccessor<Func<R(TArgs...)>>
***********************************************************************/
namespace internal_helper
{
extern void AddValueToList(Ptr<IValueList> arguments);
template<typename T0, typename ...TArgs>
void AddValueToList(Ptr<IValueList> arguments, T0&& p0, TArgs&& ...args)
{
arguments->Add(description::BoxParameter<T0>(p0));
AddValueToList(arguments, args...);
}
}
template<typename R, typename ...TArgs>
struct ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
{
static Value BoxParameter(const Func<R(TArgs...)>& object, ITypeDescriptor* typeDescriptor)
{
typedef R(RawFunctionType)(TArgs...);
Ptr<IValueFunctionProxy> result=new ValueFunctionProxyWrapper<RawFunctionType>(object);
ITypeDescriptor* td = nullptr;
#ifndef VCZH_DEBUG_NO_REFLECTION
td = Description<IValueFunctionProxy>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueFunctionProxy>>(result, td);
}
static void UnboxParameter(const Value& value, Func<R(TArgs...)>& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef R(RawFunctionType)(TArgs...);
typedef ValueFunctionProxyWrapper<RawFunctionType> ProxyType;
Ptr<IValueFunctionProxy> functionProxy=UnboxValue<Ptr<IValueFunctionProxy>>(value, typeDescriptor, valueName);
if(functionProxy)
{
if(Ptr<ProxyType> proxy=functionProxy.Cast<ProxyType>())
{
result=proxy->GetFunction();
}
else
{
result=[functionProxy](TArgs ...args)
{
Ptr<IValueList> arguments = IValueList::Create();
internal_helper::AddValueToList(arguments, ForwardValue<TArgs>(args)...);
#if defined VCZH_MSVC
typedef TypeInfoRetriver<R>::TempValueType ResultType;
#elif defined VCZH_GCC
typedef typename TypeInfoRetriver<R>::TempValueType ResultType;
#endif
ResultType proxyResult;
description::UnboxParameter<ResultType>(functionProxy->Invoke(arguments), proxyResult);
return proxyResult;
};
}
}
}
};
template<typename R, typename ...TArgs>
struct ParameterAccessor<const Func<R(TArgs...)>, TypeFlags::FunctionType> : ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
{
};
#ifndef VCZH_DEBUG_NO_REFLECTION
/***********************************************************************
MethodInfoImpl
***********************************************************************/
template<typename T>
class CustomConstructorInfoImpl{};
template<typename TClass, typename T>
class CustomMethodInfoImpl{};
template<typename TClass, typename T>
class CustomExternalMethodInfoImpl{};
template<typename T>
class CustomStaticMethodInfoImpl{};
template<typename TClass, typename T>
class CustomEventInfoImpl{};
/***********************************************************************
CustomConstructorInfoImpl<R(TArgs...)>
***********************************************************************/
namespace internal_helper
{
extern void UnboxSpecifiedParameter(MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, vint index);
template<typename T0, typename ...TArgs>
void UnboxSpecifiedParameter(MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, vint index, T0& p0, TArgs& ...args)
{
UnboxParameter<typename TypeInfoRetriver<T0>::TempValueType>(arguments[index], p0, methodInfo->GetParameter(index)->GetType()->GetTypeDescriptor(), itow(index) + L"-th argument");
UnboxSpecifiedParameter(methodInfo, arguments, index + 1, args...);
}
template<typename R, typename ...TArgs>
struct BoxedConstructorInvoker
{
static Value Invoke(MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = new typename TypeInfoRetriver<R>::Type(args...);
return BoxParameter<R>(result);
}
};
template<typename T>
struct ConstructorArgumentAdder
{
static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index)
{
}
};
template<typename T0, typename ...TNextArgs>
struct ConstructorArgumentAdder<TypeTuple<T0, TNextArgs...>>
{
static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index)
{
methodInfo->AddParameter(new ParameterInfoImpl(methodInfo, parameterNames[index], TypeInfoRetriver<T0>::CreateTypeInfo()));
ConstructorArgumentAdder<TypeTuple<TNextArgs...>>::Add(methodInfo, parameterNames, index + 1);
}
};
}
template<typename R, typename ...TArgs>
class CustomConstructorInfoImpl<R(TArgs...)> : public MethodInfoImpl
{
protected:
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
{
return internal_helper::BoxedConstructorInvoker<R, TArgs...>::Invoke(this, arguments, typename RemoveCVR<TArgs>::Type()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
Func<R(TArgs...)> proxy(
LAMBDA([](TArgs ...args)->R
{
R result = new typename TypeInfoRetriver<R>::Type(args...);
return result;
})
);
return BoxParameter<Func<R(TArgs...)>>(proxy);
}
public:
CustomConstructorInfoImpl(const wchar_t* parameterNames[])
:MethodInfoImpl(0, TypeInfoRetriver<R>::CreateTypeInfo(), true)
{
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
}
IMethodInfo::ICpp* GetCpp()override
{
return nullptr;
}
};
/***********************************************************************
CustomMethodInfoImpl<TClass, R(TArgs...)>
CustomStaticMethodInfoImpl<TClass, R(TArgs...)>
***********************************************************************/
namespace internal_helper
{
template<typename TClass, typename R, typename ...TArgs>
struct BoxedMethodInvoker
{
static Value Invoke(TClass* object, R(__thiscall TClass::* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = (object->*method)(args...);
return BoxParameter<R>(result, methodInfo->GetReturn()->GetTypeDescriptor());
}
};
template<typename TClass, typename ...TArgs>
struct BoxedMethodInvoker<TClass, void, TArgs...>
{
static Value Invoke(TClass* object, void(__thiscall TClass::* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
(object->*method)(args...);
return Value();
}
};
template<typename TClass, typename R, typename ...TArgs>
struct BoxedExternalMethodInvoker
{
static Value Invoke(TClass* object, R(*method)(TClass*, TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = method(object, args...);
return BoxParameter<R>(result, methodInfo->GetReturn()->GetTypeDescriptor());
}
};
template<typename TClass, typename ...TArgs>
struct BoxedExternalMethodInvoker<TClass, void, TArgs...>
{
static Value Invoke(TClass* object, void(*method)(TClass*, TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
method(object, args...);
return Value();
}
};
}
class MethodInfoImpl_StaticCpp : public MethodInfoImpl, private IMethodInfo::ICpp
{
private:
WString invokeTemplate;
WString closureTemplate;
const WString& GetInvokeTemplate()override
{
return invokeTemplate;
}
const WString& GetClosureTemplate()override
{
return closureTemplate;
}
public:
MethodInfoImpl_StaticCpp(IMethodGroupInfo* _ownerMethodGroup, Ptr<ITypeInfo> _return, bool _isStatic, const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
:MethodInfoImpl(_ownerMethodGroup, _return, _isStatic)
{
CHECK_ERROR((_invokeTemplate == nullptr) == (_closureTemplate == nullptr), L"MethodInfoImpl_StaticCpp::MethodInfoImpl_StaticCpp()#Templates should all be set or default at the same time.");
if (_invokeTemplate)
{
invokeTemplate = WString(_invokeTemplate, false);
}
if (_closureTemplate)
{
closureTemplate = WString(_closureTemplate, false);
}
}
IMethodInfo::ICpp* GetCpp()override
{
return invokeTemplate.Length() == 0 || closureTemplate.Length() == 0 ? nullptr : this;
}
};
template<typename TClass, typename R, typename ...TArgs>
class CustomMethodInfoImpl<TClass, R(TArgs...)> : public MethodInfoImpl_StaticCpp
{
protected:
R(__thiscall TClass::* method)(TArgs...);
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
{
TClass* object=UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
return internal_helper::BoxedMethodInvoker<TClass, R, TArgs...>::Invoke(object, method, this, arguments, typename RemoveCVR<TArgs>::Type()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
TClass* object=UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
Func<R(TArgs...)> proxy(object, method);
return BoxParameter<Func<R(TArgs...)>>(proxy);
}
public:
CustomMethodInfoImpl(const wchar_t* parameterNames[], R(__thiscall TClass::* _method)(TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate)
,method(_method)
{
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
}
};
template<typename TClass, typename R, typename ...TArgs>
class CustomExternalMethodInfoImpl<TClass, R(TArgs...)> : public MethodInfoImpl_StaticCpp
{
protected:
R(*method)(TClass*, TArgs...);
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
{
TClass* object=UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
return internal_helper::BoxedExternalMethodInvoker<TClass, R, TArgs...>::Invoke(object, method, this, arguments, typename RemoveCVR<TArgs>::Type()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
TClass* object=UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
Func<R(TArgs...)> proxy = Curry(Func<R(TClass*, TArgs...)>(method))(object);
return BoxParameter<Func<R(TArgs...)>>(proxy);
}
public:
CustomExternalMethodInfoImpl(const wchar_t* parameterNames[], R(*_method)(TClass*, TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate)
,method(_method)
{
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
}
};
/***********************************************************************
CustomStaticMethodInfoImpl<R(TArgs...)>
***********************************************************************/
namespace internal_helper
{
template<typename R, typename ...TArgs>
struct BoxedStaticMethodInvoker
{
static Value Invoke(R(* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = method(args...);
return BoxParameter<R>(result, methodInfo->GetReturn()->GetTypeDescriptor());
}
};
template<typename ...TArgs>
struct BoxedStaticMethodInvoker<void, TArgs...>
{
static Value Invoke(void(* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
method(args...);
return Value();
}
};
}
template<typename R, typename ...TArgs>
class CustomStaticMethodInfoImpl<R(TArgs...)> : public MethodInfoImpl_StaticCpp
{
protected:
R(* method)(TArgs...);
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
{
return internal_helper::BoxedStaticMethodInvoker<R, TArgs...>::Invoke(method, this, arguments, typename RemoveCVR<TArgs>::Type()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
Func<R(TArgs...)> proxy(method);
return BoxParameter<Func<R(TArgs...)>>(proxy);
}
public:
CustomStaticMethodInfoImpl(const wchar_t* parameterNames[], R(* _method)(TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), true, _invokeTemplate, _closureTemplate)
,method(_method)
{
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
}
};
/***********************************************************************
CustomEventInfoImpl<void(TArgs...)>
***********************************************************************/
namespace internal_helper
{
template<typename ...TArgs>
struct BoxedEventInvoker
{
static void Invoke(Event<void(TArgs...)>& eventObject, Ptr<IValueList> arguments, typename RemoveCVR<TArgs>::Type&& ...args)
{
UnboxSpecifiedParameter(arguments, 0, args...);
eventObject(args...);
}
};
}
template<typename TClass, typename ...TArgs>
class CustomEventInfoImpl<TClass, void(TArgs...)> : public EventInfoImpl
{
protected:
Event<void(TArgs...)> TClass::* eventRef;
Ptr<IEventHandler> AttachInternal(DescriptableObject* thisObject, Ptr<IValueFunctionProxy> handler)override
{
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
Event<void(TArgs...)>& eventObject = object->*eventRef;
auto func = Func<void(TArgs...)>([=](TArgs ...args)
{
auto arguments = IValueList::Create();
internal_helper::AddValueToList(arguments, ForwardValue<TArgs>(args)...);
handler->Invoke(arguments);
});
return EventHelper<TArgs...>::Attach(eventObject, func);
}
bool DetachInternal(DescriptableObject* thisObject, Ptr<IEventHandler> handler)override
{
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
Event<void(TArgs...)>& eventObject = object->*eventRef;
return EventHelper<TArgs...>::Detach(eventObject, handler);
}
void InvokeInternal(DescriptableObject* thisObject, Ptr<IValueList> arguments)override
{
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
Event<void(TArgs...)>& eventObject = object->*eventRef;
internal_helper::BoxedEventInvoker<TArgs...>::Invoke(eventObject, arguments, typename RemoveCVR<TArgs>::Type()...);
}
Ptr<ITypeInfo> GetHandlerTypeInternal()override
{
return TypeInfoRetriver<Func<void(TArgs...)>>::CreateTypeInfo();
}
public:
CustomEventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Event<void(TArgs...)> TClass::* _eventRef)
:EventInfoImpl(_ownerTypeDescriptor, _name)
, eventRef(_eventRef)
{
}
~CustomEventInfoImpl()
{
}
IEventInfo::ICpp* GetCpp()override
{
return nullptr;
}
};
template<typename T>
struct CustomEventFunctionTypeRetriver
{
typedef vint Type;
};
template<typename TClass, typename TEvent>
struct CustomEventFunctionTypeRetriver<Event<TEvent> TClass::*>
{
typedef TEvent Type;
};
#endif
}
}
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORBUILDER_STRUCT.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_STRUCT
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_STRUCT
namespace vl
{
namespace reflection
{
namespace description
{
/***********************************************************************
DetailTypeInfoRetriver<TStruct>
***********************************************************************/
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>
{
static const ITypeInfo::Decorator Decorator=ITypeInfo::TypeDescriptor;
typedef T Type;
typedef T TempValueType;
typedef T& ResultReferenceType;
typedef T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<Type>(), hint);
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<const T, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef typename UpLevelRetriver::Type Type;
typedef T TempValueType;
typedef const T& ResultReferenceType;
typedef const T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return TypeInfoRetriver<T>::CreateTypeInfo();
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<volatile T, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef typename UpLevelRetriver::Type Type;
typedef T TempValueType;
typedef T& ResultReferenceType;
typedef T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return TypeInfoRetriver<T>::CreateTypeInfo();
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T*, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=ITypeInfo::RawPtr;
typedef typename UpLevelRetriver::Type Type;
typedef T* TempValueType;
typedef T*& ResultReferenceType;
typedef T* ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<RawPtrTypeInfo>(TypeInfoRetriver<T>::CreateTypeInfo());
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<Ptr<T>, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=ITypeInfo::SharedPtr;
typedef typename UpLevelRetriver::Type Type;
typedef Ptr<T> TempValueType;
typedef Ptr<T>& ResultReferenceType;
typedef Ptr<T> ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<SharedPtrTypeInfo>(TypeInfoRetriver<T>::CreateTypeInfo());
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<Nullable<T>, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=ITypeInfo::Nullable;
typedef typename UpLevelRetriver::Type Type;
typedef Nullable<T> TempValueType;
typedef Nullable<T>& ResultReferenceType;
typedef Nullable<T> ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<NullableTypeInfo>(TypeInfoRetriver<T>::CreateTypeInfo());
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T&, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef typename UpLevelRetriver::Type Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef T& ResultReferenceType;
typedef T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return TypeInfoRetriver<T>::CreateTypeInfo();
}
#endif
};
template<>
struct TypeInfoRetriver<void> : public TypeInfoRetriver<VoidValue>
{
};
/***********************************************************************
ParameterAccessor<TStruct>
***********************************************************************/
template<typename T>
struct ParameterAccessor<T, TypeFlags::NonGenericType>
{
static Value BoxParameter(const T& object, ITypeDescriptor* typeDescriptor)
{
return BoxValue<T>(object, typeDescriptor);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
result=UnboxValue<T>(value, typeDescriptor, valueName);
}
};
template<typename T>
struct ValueAccessor<T*, ITypeInfo::RawPtr>
{
static Value BoxValue(T* object, ITypeDescriptor* typeDescriptor)
{
return Value::From(object);
}
static T* UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
if(value.IsNull()) return nullptr;
T* result = nullptr;
if (value.GetRawPtr())
{
result = value.GetRawPtr()->SafeAggregationCast<T>();
}
if(!result)
{
#ifndef VCZH_DEBUG_NO_REFLECTION
if(!typeDescriptor)
{
typeDescriptor=GetTypeDescriptor<T>();
}
throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::RawPtr, value);
#else
CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
#endif
}
return result;
}
};
template<typename T>
struct ValueAccessor<Ptr<T>, ITypeInfo::SharedPtr>
{
static Value BoxValue(Ptr<T> object, ITypeDescriptor* typeDescriptor)
{
return Value::From(object);
}
static Ptr<T> UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
if (value.IsNull()) return nullptr;
Ptr<T> result;
if(value.GetValueType()==Value::RawPtr || value.GetValueType()==Value::SharedPtr)
{
result = value.GetRawPtr()->SafeAggregationCast<T>();
}
if(!result)
{
#ifndef VCZH_DEBUG_NO_REFLECTION
if(!typeDescriptor)
{
typeDescriptor=GetTypeDescriptor<T>();
}
throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::SharedPtr, value);
#else
CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
#endif
}
return result;
}
};
template<typename T>
struct ValueAccessor<Nullable<T>, ITypeInfo::Nullable>
{
static Value BoxValue(Nullable<T> object, ITypeDescriptor* typeDescriptor)
{
return object?ValueAccessor<T, ITypeInfo::TypeDescriptor>::BoxValue(object.Value(), typeDescriptor):Value();
}
static Nullable<T> UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
if(value.IsNull())
{
return Nullable<T>();
}
else
{
return ValueAccessor<T, ITypeInfo::TypeDescriptor>::UnboxValue(value, typeDescriptor, valueName);
}
}
};
template<typename T>
struct ValueAccessor<T, ITypeInfo::TypeDescriptor>
{
static Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor)
{
#ifndef VCZH_DEBUG_NO_REFLECTION
if(!typeDescriptor)
{
typeDescriptor = GetTypeDescriptor<typename TypeInfoRetriver<T>::Type>();
}
#endif
using Type = typename vl::RemoveCVR<T>::Type;
return Value::From(new IValueType::TypedBox<Type>(object), typeDescriptor);
}
static T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
using Type = typename vl::RemoveCVR<T>::Type;
if (auto unboxedValue = value.GetBoxedValue().Cast<IValueType::TypedBox<Type>>())
{
return unboxedValue->value;
}
else
{
#ifndef VCZH_DEBUG_NO_REFLECTION
if (!typeDescriptor)
{
typeDescriptor = GetTypeDescriptor<typename TypeInfoRetriver<T>::Type>();
}
throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::BoxedValue, value);
#else
CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
#endif
}
}
};
template<>
struct ValueAccessor<Value, ITypeInfo::TypeDescriptor>
{
static Value BoxValue(const Value& object, ITypeDescriptor* typeDescriptor)
{
return object;
}
static Value UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
return value;
}
};
template<>
struct ValueAccessor<VoidValue, ITypeInfo::TypeDescriptor>
{
static Value BoxValue(const VoidValue& object, ITypeDescriptor* typeDescriptor)
{
return Value();
}
static VoidValue UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
return VoidValue();
}
};
}
}
}
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORMACROS.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORMACROS
#define VCZH_REFLECTION_GUITYPEDESCRIPTORMACROS
#ifndef VCZH_DEBUG_NO_REFLECTION
/***********************************************************************
Macros
***********************************************************************/
namespace vl
{
namespace reflection
{
namespace description
{
template<typename T>
struct CustomTypeDescriptorSelector{};
struct MethodPointerBinaryData
{
typedef collections::Dictionary<MethodPointerBinaryData, IMethodInfo*> MethodMap;
class IIndexer : public virtual IDescriptable
{
public:
virtual void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo) = 0;
virtual IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data) = 0;
};
vint data[4];
static inline vint Compare(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b)
{
{
auto result = a.data[0] - b.data[0];
if (result != 0) return result;
}
{
auto result = a.data[1] - b.data[1];
if (result != 0) return result;
}
{
auto result = a.data[2] - b.data[2];
if (result != 0) return result;
}
{
auto result = a.data[3] - b.data[3];
if (result != 0) return result;
}
return 0;
}
#define COMPARE(OPERATOR)\
inline bool operator OPERATOR(const MethodPointerBinaryData& d)const\
{\
return Compare(*this, d) OPERATOR 0;\
}
COMPARE(<)
COMPARE(<=)
COMPARE(>)
COMPARE(>=)
COMPARE(==)
COMPARE(!=)
#undef COMPARE
};
template<typename T>
union MethodPointerBinaryDataRetriver
{
T methodPointer;
MethodPointerBinaryData binaryData;
MethodPointerBinaryDataRetriver(T _methodPointer)
{
memset(&binaryData, 0, sizeof(binaryData));
methodPointer = _methodPointer;
}
const MethodPointerBinaryData& GetBinaryData()
{
static_assert(sizeof(T) <= sizeof(MethodPointerBinaryData), "Your C++ compiler is bad!");
return binaryData;
}
};
template<typename T, TypeDescriptorFlags TDFlags>
struct MethodPointerBinaryDataRecorder
{
static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo)
{
}
};
template<typename T>
struct MethodPointerBinaryDataRecorder<T, TypeDescriptorFlags::Interface>
{
static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo)
{
auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(td);
CHECK_ERROR(impl != nullptr, L"Internal error: RecordMethod can only be called when registering methods.");
impl->IndexMethodInfo(data, methodInfo);
}
};
template<typename T>
using FUNCTIONNAME_AddPointer = T*;
/***********************************************************************
Type
***********************************************************************/
#define BEGIN_TYPE_INFO_NAMESPACE namespace vl{namespace reflection{namespace description{
#define END_TYPE_INFO_NAMESPACE }}}
#define ADD_TYPE_INFO(TYPENAME)\
{\
Ptr<ITypeDescriptor> type=new CustomTypeDescriptorSelector<TYPENAME>::CustomTypeDescriptorImpl();\
manager->SetTypeDescriptor(TypeInfo<TYPENAME>::content.typeName, type);\
}
/***********************************************************************
InterfaceProxy
***********************************************************************/
#define INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
static INTERFACE* Create(Ptr<IValueInterfaceProxy> proxy)\
{\
auto obj = new ValueInterfaceProxy<INTERFACE>();\
obj->SetProxy(proxy);\
return obj;\
}\
#define INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
static Ptr<INTERFACE> Create(Ptr<IValueInterfaceProxy> proxy)\
{\
auto obj = new ValueInterfaceProxy<INTERFACE>();\
obj->SetProxy(proxy);\
return obj;\
}\
#define BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
template<>\
class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE>\
{\
typedef INTERFACE _interface_proxy_InterfaceType;\
public:\
#define BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(INTERFACE)\
BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
#define BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(INTERFACE)\
BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
#define BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, ...)\
template<>\
class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE, __VA_ARGS__>\
{\
typedef INTERFACE _interface_proxy_InterfaceType;\
public:\
#define BEGIN_INTERFACE_PROXY_RAWPTR(INTERFACE, ...)\
BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
#define BEGIN_INTERFACE_PROXY_SHAREDPTR(INTERFACE, ...)\
BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
#define END_INTERFACE_PROXY(INTERFACE)\
};
/***********************************************************************
InterfaceProxy::Invoke
***********************************************************************/
template<typename TClass, typename TReturn, typename ...TArgument>
auto MethodTypeTrait(TArgument...)->TReturn(TClass::*)(TArgument...)
{
return nullptr;
}
#define PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
static ITypeDescriptor* _interface_proxy_typeDescriptor = nullptr;\
static IMethodInfo* _interface_proxy_methodInfo = nullptr;\
if (_interface_proxy_typeDescriptor != static_cast<DescriptableObject*>(this)->GetTypeDescriptor())\
{\
_interface_proxy_typeDescriptor = static_cast<DescriptableObject*>(this)->GetTypeDescriptor();\
CHECK_ERROR(_interface_proxy_typeDescriptor != nullptr, L"Internal error: The type of this interface has not been registered.");\
auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(_interface_proxy_typeDescriptor);\
CHECK_ERROR(impl != nullptr, L"Internal error: BEGIN_INTERFACE_PROXY is the only correct way to register an interface with a proxy.");\
auto _interface_proxy_method\
= (decltype(MethodTypeTrait<_interface_proxy_InterfaceType, decltype(METHODNAME(__VA_ARGS__))>(__VA_ARGS__)))\
&_interface_proxy_InterfaceType::METHODNAME;\
MethodPointerBinaryDataRetriver<decltype(_interface_proxy_method)> binaryData(_interface_proxy_method);\
_interface_proxy_methodInfo = impl->GetIndexedMethodInfo(binaryData.GetBinaryData());\
}\
#define INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__))))
#define INVOKE_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())
#define INVOKEGET_INTERFACE_PROXY(METHODNAME, ...)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
return UnboxValue<decltype(METHODNAME(__VA_ARGS__))>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__)))))
#define INVOKEGET_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
return UnboxValue<decltype(METHODNAME())>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create()))
/***********************************************************************
Enum
***********************************************************************/
#define BEGIN_ENUM_ITEM_FLAG(TYPENAME, TDFLAGS)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public EnumTypeDescriptor<TYPENAME, TDFLAGS>\
{\
typedef TYPENAME EnumType;\
public:\
void LoadInternal()override\
{\
EnumTypeDescriptor<TYPENAME, TDFLAGS>::LoadInternal();\
#define BEGIN_ENUM_ITEM(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::NormalEnum)
#define BEGIN_ENUM_ITEM_MERGABLE(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::FlagEnum)
#define END_ENUM_ITEM(TYPENAME)\
}\
};\
};
#define ENUM_ITEM_NAMESPACE(TYPENAME) typedef TYPENAME EnumItemNamespace;
#define ENUM_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, ITEMNAME);
#define ENUM_NAMESPACE_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumItemNamespace::ITEMNAME);
#define ENUM_CLASS_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumType::ITEMNAME);
/***********************************************************************
Struct
***********************************************************************/
#define BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TDFLAGS)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public StructTypeDescriptor<TYPENAME, TDFLAGS>\
{\
typedef TYPENAME StructType;\
protected:\
void LoadInternal()override\
{
#define BEGIN_STRUCT_MEMBER(TYPENAME)\
BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TypeDescriptorFlags::Struct)
#define END_STRUCT_MEMBER(TYPENAME)\
}\
};\
};
#define STRUCT_MEMBER(FIELDNAME)\
fields.Add(L ## #FIELDNAME, new StructFieldInfo<decltype(((StructType*)0)->FIELDNAME)>(this, &StructType::FIELDNAME, L ## #FIELDNAME));
/***********************************************************************
Class
***********************************************************************/
#define BEGIN_CLASS_MEMBER(TYPENAME)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public TypeDescriptorImpl\
{\
typedef TYPENAME ClassType;\
static const TypeDescriptorFlags TDFlags = TypeDescriptorFlags::Class;\
public:\
CustomTypeDescriptorImpl()\
:TypeDescriptorImpl(TDFlags, &TypeInfo<TYPENAME>::content)\
{\
Description<TYPENAME>::SetAssociatedTypeDescroptor(this);\
}\
~CustomTypeDescriptorImpl()\
{\
Description<TYPENAME>::SetAssociatedTypeDescroptor(0);\
}\
protected:\
bool IsAggregatable()override\
{\
return AcceptValue<typename RequiresConvertable<TYPENAME, AggregatableDescription<TYPENAME>>::YesNoType>::Result;\
}\
void LoadInternal()override\
{
#define CLASS_MEMBER_BASE(TYPENAME)\
AddBaseType(description::GetTypeDescriptor<TYPENAME>());
#define END_CLASS_MEMBER(TYPENAME)\
if (GetBaseTypeDescriptorCount() == 0) CLASS_MEMBER_BASE(DescriptableObject)\
}\
};\
};
/***********************************************************************
Interface
***********************************************************************/
#define BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TDFLAGS)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public TypeDescriptorImpl, public MethodPointerBinaryData::IIndexer\
{\
typedef TYPENAME ClassType;\
static const TypeDescriptorFlags TDFlags = TDFLAGS;\
MethodPointerBinaryData::MethodMap methodsForProxy;\
public:\
CustomTypeDescriptorImpl()\
:TypeDescriptorImpl(TDFLAGS, &TypeInfo<TYPENAME>::content)\
{\
Description<TYPENAME>::SetAssociatedTypeDescroptor(this);\
}\
~CustomTypeDescriptorImpl()\
{\
Description<TYPENAME>::SetAssociatedTypeDescroptor(0);\
}\
void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo)override\
{\
methodsForProxy.Add(data, methodInfo);\
}\
IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data)override\
{\
Load();\
return methodsForProxy[data];\
}\
protected:\
void LoadInternal()override\
{
#define BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TypeDescriptorFlags::Interface)
#define BEGIN_INTERFACE_MEMBER(TYPENAME)\
BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
CLASS_MEMBER_EXTERNALCTOR(decltype(ValueInterfaceProxy<TYPENAME>::Create(nullptr))(Ptr<IValueInterfaceProxy>), { L"proxy" }, vl::reflection::description::ValueInterfaceProxy<TYPENAME>::Create)
#define END_INTERFACE_MEMBER(TYPENAME)\
if (GetBaseTypeDescriptorCount() == 0 && TDFlags == TypeDescriptorFlags::Interface) CLASS_MEMBER_BASE(IDescriptable)\
}\
};\
};
/***********************************************************************
Field
***********************************************************************/
#define CLASS_MEMBER_FIELD(FIELDNAME)\
AddProperty(\
new CustomFieldInfoImpl<\
ClassType,\
decltype(((ClassType*)0)->FIELDNAME)\
>(this, L ## #FIELDNAME, &ClassType::FIELDNAME)\
);
/***********************************************************************
Constructor
***********************************************************************/
#define NO_PARAMETER {L""}
#define PROTECT_PARAMETERS(...) __VA_ARGS__
#define CLASS_MEMBER_CONSTRUCTOR(FUNCTIONTYPE, PARAMETERNAMES)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddConstructor(new CustomConstructorInfoImpl<FUNCTIONTYPE>(parameterNames));\
}
#define CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PARAMETERNAMES, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddConstructor(\
new CustomStaticMethodInfoImpl<FUNCTIONTYPE>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
);\
}
#define CLASS_MEMBER_EXTERNALCTOR(FUNCTIONTYPE, PARAMETERNAMES, SOURCE)\
CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PROTECT_PARAMETERS(PARAMETERNAMES), (FUNCTIONNAME_AddPointer<FUNCTIONTYPE>)&::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")
/***********************************************************************
Method
***********************************************************************/
#define CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddMethod(\
L ## #FUNCTIONNAME,\
new CustomExternalMethodInfoImpl<\
ClassType,\
vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
);\
}
#define CLASS_MEMBER_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($This, $Arguments)", L"::vl::Func<$Func>($This, &::" L ## #SOURCE L")")
#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
auto methodInfo = new CustomMethodInfoImpl<\
ClassType,\
vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
>\
(parameterNames, (FUNCTIONTYPE)&ClassType::FUNCTIONNAME, INVOKETEMPLATE, CLOSURETEMPLATE);\
AddMethod(\
L ## #EXPECTEDNAME,\
methodInfo\
);\
MethodPointerBinaryDataRetriver<FUNCTIONTYPE> binaryDataRetriver(&ClassType::FUNCTIONNAME);\
MethodPointerBinaryDataRecorder<ClassType, TDFlags>::RecordMethod(binaryDataRetriver.GetBinaryData(), this, methodInfo);\
}
#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, L"$This->" L ## #FUNCTIONNAME L"($Arguments)", L"::vl::Func<$Func>($This, &$Type::" L ## #FUNCTIONNAME L")")
#define CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(FUNCTIONNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, nullptr, nullptr)
#define CLASS_MEMBER_METHOD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES)\
CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
#define CLASS_MEMBER_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
/***********************************************************************
Static Method
***********************************************************************/
#define CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddMethod(\
L ## #FUNCTIONNAME,\
new CustomStaticMethodInfoImpl<\
vl::function_lambda::FunctionObjectRetriveType<FUNCTIONTYPE>::FunctionType\
>(parameterNames, (FUNCTIONTYPE)SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
);\
}
#define CLASS_MEMBER_STATIC_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")
#define CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &ClassType::FUNCTIONNAME, nullptr, nullptr)
#define CLASS_MEMBER_STATIC_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
/***********************************************************************
Event
***********************************************************************/
#define CLASS_MEMBER_EVENT(EVENTNAME)\
AddEvent(\
new CustomEventInfoImpl<\
ClassType,\
CustomEventFunctionTypeRetriver<decltype(&ClassType::EVENTNAME)>::Type\
>(this, L ## #EVENTNAME, &ClassType::EVENTNAME)\
);
/***********************************************************************
Property
***********************************************************************/
#define CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, GETTER)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
nullptr,\
nullptr\
)\
);
#define CLASS_MEMBER_PROPERTY(PROPERTYNAME, GETTER, SETTER)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
nullptr\
)\
);
#define CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, GETTER, SETTER, EVENT)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
)\
);
#define CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, GETTER, EVENT)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
nullptr,\
dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
)\
);
#define CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE(PROPERTYNAME, GETTER, SETTER, REFERENCETEMPLATE)\
AddProperty(\
new PropertyInfoImpl_StaticCpp(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
nullptr,\
WString(REFERENCETEMPLATE, false)\
)\
);
#define CLASS_MEMBER_PROPERTY_READONLY_FAST(PROPERTYNAME)\
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, Get##PROPERTYNAME)\
#define CLASS_MEMBER_PROPERTY_FAST(PROPERTYNAME)\
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
CLASS_MEMBER_METHOD(Set##PROPERTYNAME, {L"value"})\
CLASS_MEMBER_PROPERTY(PROPERTYNAME, Get##PROPERTYNAME, Set##PROPERTYNAME)\
#define CLASS_MEMBER_PROPERTY_EVENT_FAST(PROPERTYNAME, EVENTNAME)\
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
CLASS_MEMBER_METHOD(Set##PROPERTYNAME, {L"value"})\
CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, Get##PROPERTYNAME, Set##PROPERTYNAME, EVENTNAME)\
#define CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(PROPERTYNAME, EVENTNAME)\
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, Get##PROPERTYNAME, EVENTNAME)\
}
}
}
#endif
#endif
/***********************************************************************
.\REFLECTION\GUITYPEDESCRIPTORREFLECTION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Reflection
Interfaces:
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORREFLECTION
#define VCZH_REFLECTION_GUITYPEDESCRIPTORREFLECTION
namespace vl
{
namespace reflection
{
namespace description
{
/***********************************************************************
Predefined Types
***********************************************************************/
#define REFLECTION_PREDEFINED_PRIMITIVE_TYPES(F)\
F(vuint8_t) \
F(vuint16_t) \
F(vuint32_t) \
F(vuint64_t) \
F(vint8_t) \
F(vint16_t) \
F(vint32_t) \
F(vint64_t) \
F(float) \
F(double) \
F(bool) \
F(wchar_t) \
F(WString) \
F(Locale) \
#ifndef VCZH_DEBUG_NO_REFLECTION
#define REFLECTION_PREDEFINED_COMPLEX_TYPES(F, VOID_TYPE)\
F(VOID_TYPE) \
F(VoidValue) \
F(IDescriptable) \
F(DescriptableObject) \
F(DateTime) \
F(IValueEnumerator) \
F(IValueEnumerable) \
F(IValueReadonlyList) \
F(IValueList) \
F(IValueObservableList) \
F(IValueReadonlyDictionary) \
F(IValueDictionary) \
F(IValueInterfaceProxy) \
F(IValueFunctionProxy) \
F(IValueSubscription) \
F(IValueCallStack) \
F(IValueException) \
F(IBoxedValue) \
F(IBoxedValue::CompareResult) \
F(IValueType) \
F(IEnumType) \
F(ISerializableType) \
F(ITypeInfo) \
F(ITypeInfo::Decorator) \
F(IMemberInfo) \
F(IEventHandler) \
F(IEventInfo) \
F(IPropertyInfo) \
F(IParameterInfo) \
F(IMethodInfo) \
F(IMethodGroupInfo) \
F(TypeDescriptorFlags) \
F(ITypeDescriptor) \
DECL_TYPE_INFO(Value)
REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DECL_TYPE_INFO)
REFLECTION_PREDEFINED_COMPLEX_TYPES(DECL_TYPE_INFO, void)
#endif
#define DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(TYPENAME)\
template<>\
struct TypedValueSerializerProvider<TYPENAME>\
{\
static TYPENAME GetDefaultValue();\
static bool Serialize(const TYPENAME& input, WString& output);\
static bool Deserialize(const WString& input, TYPENAME& output);\
static IBoxedValue::CompareResult Compare(const TYPENAME& a, const TYPENAME& b);\
};\
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vuint8_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vuint16_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vuint32_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vuint64_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vint8_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vint16_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vint32_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(vint64_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(float)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(double)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(bool)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(wchar_t)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(WString)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(Locale)
DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(DateTime)
#undef DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER
/***********************************************************************
Interface Implementation Proxy (Implement)
***********************************************************************/
#ifndef VCZH_DEBUG_NO_REFLECTION
#pragma warning(push)
#pragma warning(disable:4250)
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerator)
Value GetCurrent()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCurrent);
}
vint GetIndex()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetIndex);
}
bool Next()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Next);
}
END_INTERFACE_PROXY(IValueEnumerator)
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerable)
Ptr<IValueEnumerator> CreateEnumerator()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(CreateEnumerator);
}
END_INTERFACE_PROXY(IValueEnumerable)
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueReadonlyList, IValueEnumerable)
vint GetCount()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCount);
}
Value Get(vint index)override
{
INVOKEGET_INTERFACE_PROXY(Get, index);
}
bool Contains(const Value& value)override
{
INVOKEGET_INTERFACE_PROXY(Contains, value);
}
vint IndexOf(const Value& value)override
{
INVOKEGET_INTERFACE_PROXY(IndexOf, value);
}
END_INTERFACE_PROXY(IValueReadonlyList)
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueList, IValueReadonlyList)
void Set(vint index, const Value& value)override
{
INVOKE_INTERFACE_PROXY(Set, index, value);
}
vint Add(const Value& value)override
{
INVOKEGET_INTERFACE_PROXY(Add, value);
}
vint Insert(vint index, const Value& value)override
{
INVOKEGET_INTERFACE_PROXY(Insert, index, value);
}
bool Remove(const Value& value)override
{
INVOKEGET_INTERFACE_PROXY(Remove, value);
}
bool RemoveAt(vint index)override
{
INVOKEGET_INTERFACE_PROXY(RemoveAt, index);
}
void Clear()override
{
INVOKE_INTERFACE_PROXY_NOPARAMS(Clear);
}
END_INTERFACE_PROXY(IValueList)
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueObservableList, IValueList)
END_INTERFACE_PROXY(IValueObservableList)
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueReadonlyDictionary)
Ptr<IValueReadonlyList> GetKeys()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetKeys);
}
Ptr<IValueReadonlyList> GetValues()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetValues);
}
vint GetCount()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCount);
}
Value Get(const Value& key)override
{
INVOKEGET_INTERFACE_PROXY(Get, key);
}
END_INTERFACE_PROXY(IValueReadonlyDictionary)
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueDictionary, IValueReadonlyDictionary)
void Set(const Value& key, const Value& value)override
{
INVOKE_INTERFACE_PROXY(Set, key, value);
}
bool Remove(const Value& key)override
{
INVOKEGET_INTERFACE_PROXY(Remove, key);
}
void Clear()override
{
INVOKE_INTERFACE_PROXY_NOPARAMS(Clear);
}
END_INTERFACE_PROXY(IValueDictionary)
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueSubscription)
bool Open()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Open);
}
bool Update()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Update);
}
bool Close()override
{
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Close);
}
END_INTERFACE_PROXY(IValueSubscription)
#pragma warning(pop)
#endif
/***********************************************************************
Helper Functions
***********************************************************************/
extern vint ITypeDescriptor_GetTypeDescriptorCount();
extern ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(vint index);
extern ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const WString& name);
extern ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const Value& value);
/***********************************************************************
LoadPredefinedTypes
***********************************************************************/
extern bool LoadPredefinedTypes();
}
}
}
#endif
/***********************************************************************
.\PARSING\PARSINGDEFINITIONS.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::Definitions
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSINGDEFINITIONS
#define VCZH_PARSING_PARSINGDEFINITIONS
namespace vl
{
namespace parsing
{
namespace definitions
{
/***********************************************************************
Attributes
***********************************************************************/
class ParsingDefinitionAttribute : public ParsingTreeCustomBase
{
public:
WString name;
collections::List<WString> arguments;
};
class ParsingDefinitionBase : public ParsingTreeCustomBase
{
typedef collections::List<Ptr<ParsingDefinitionAttribute>> AttributeList;
public:
AttributeList attributes;
};
/***********************************************************************
Type
***********************************************************************/
class ParsingDefinitionPrimitiveType;
class ParsingDefinitionTokenType;
class ParsingDefinitionSubType;
class ParsingDefinitionArrayType;
class ParsingDefinitionType : public ParsingTreeCustomBase
{
public:
class IVisitor : public Interface
{
public:
virtual void Visit(ParsingDefinitionPrimitiveType* node)=0;
virtual void Visit(ParsingDefinitionTokenType* node)=0;
virtual void Visit(ParsingDefinitionSubType* node)=0;
virtual void Visit(ParsingDefinitionArrayType* node)=0;
};
virtual void Accept(IVisitor* visitor)=0;
};
class ParsingDefinitionPrimitiveType : public ParsingDefinitionType
{
public:
WString name;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionTokenType : public ParsingDefinitionType
{
public:
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionSubType : public ParsingDefinitionType
{
public:
Ptr<ParsingDefinitionType> parentType;
WString subTypeName;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionArrayType : public ParsingDefinitionType
{
public:
Ptr<ParsingDefinitionType> elementType;
void Accept(IVisitor* visitor)override;
};
/***********************************************************************
Type Definition
***********************************************************************/
class ParsingDefinitionClassMemberDefinition;
class ParsingDefinitionClassDefinition;
class ParsingDefinitionEnumMemberDefinition;
class ParsingDefinitionEnumDefinition;
class ParsingDefinitionTypeDefinition : public ParsingDefinitionBase
{
public:
class IVisitor : public Interface
{
public:
virtual void Visit(ParsingDefinitionClassMemberDefinition* node)=0;
virtual void Visit(ParsingDefinitionClassDefinition* node)=0;
virtual void Visit(ParsingDefinitionEnumMemberDefinition* node)=0;
virtual void Visit(ParsingDefinitionEnumDefinition* node)=0;
};
virtual void Accept(IVisitor* visitor)=0;
public:
WString name;
};
class ParsingDefinitionClassMemberDefinition : public ParsingDefinitionTypeDefinition
{
public:
Ptr<ParsingDefinitionType> type;
WString unescapingFunction;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionClassDefinition : public ParsingDefinitionTypeDefinition
{
public:
typedef collections::List<Ptr<ParsingDefinitionClassMemberDefinition>> MemberList;
typedef collections::List<Ptr<ParsingDefinitionTypeDefinition>> TypeList;
Ptr<ParsingDefinitionType> ambiguousType;
Ptr<ParsingDefinitionType> parentType;
MemberList members;
TypeList subTypes;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionEnumMemberDefinition : public ParsingDefinitionTypeDefinition
{
public:
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionEnumDefinition : public ParsingDefinitionTypeDefinition
{
public:
typedef collections::List<Ptr<ParsingDefinitionEnumMemberDefinition>> MemberList;
MemberList members;
void Accept(IVisitor* visitor)override;
};
/***********************************************************************
Grammar
***********************************************************************/
class ParsingDefinitionPrimitiveGrammar;
class ParsingDefinitionTextGrammar;
class ParsingDefinitionSequenceGrammar;
class ParsingDefinitionAlternativeGrammar;
class ParsingDefinitionLoopGrammar;
class ParsingDefinitionOptionalGrammar;
class ParsingDefinitionCreateGrammar;
class ParsingDefinitionAssignGrammar;
class ParsingDefinitionUseGrammar;
class ParsingDefinitionSetterGrammar;
class ParsingDefinitionGrammar : public ParsingTreeCustomBase
{
public:
class IVisitor : public Interface
{
public:
virtual void Visit(ParsingDefinitionPrimitiveGrammar* node)=0;
virtual void Visit(ParsingDefinitionTextGrammar* node)=0;
virtual void Visit(ParsingDefinitionSequenceGrammar* node)=0;
virtual void Visit(ParsingDefinitionAlternativeGrammar* node)=0;
virtual void Visit(ParsingDefinitionLoopGrammar* node)=0;
virtual void Visit(ParsingDefinitionOptionalGrammar* node)=0;
virtual void Visit(ParsingDefinitionCreateGrammar* node)=0;
virtual void Visit(ParsingDefinitionAssignGrammar* node)=0;
virtual void Visit(ParsingDefinitionUseGrammar* node)=0;
virtual void Visit(ParsingDefinitionSetterGrammar* node)=0;
};
virtual void Accept(IVisitor* visitor)=0;
};
class ParsingDefinitionPrimitiveGrammar : public ParsingDefinitionGrammar
{
public:
WString name;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionTextGrammar : public ParsingDefinitionGrammar
{
public:
WString text;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionSequenceGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> first;
Ptr<ParsingDefinitionGrammar> second;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionAlternativeGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> first;
Ptr<ParsingDefinitionGrammar> second;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionLoopGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> grammar;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionOptionalGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> grammar;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionCreateGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> grammar;
Ptr<ParsingDefinitionType> type;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionAssignGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> grammar;
WString memberName;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionUseGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> grammar;
void Accept(IVisitor* visitor)override;
};
class ParsingDefinitionSetterGrammar : public ParsingDefinitionGrammar
{
public:
Ptr<ParsingDefinitionGrammar> grammar;
WString memberName;
WString value;
void Accept(IVisitor* visitor)override;
};
/***********************************************************************
Token and Rule
***********************************************************************/
class ParsingDefinitionTokenDefinition : public ParsingDefinitionBase
{
public:
WString name;
WString regex;
bool discard;
};
class ParsingDefinitionRuleDefinition : public ParsingDefinitionBase
{
public:
WString name;
Ptr<ParsingDefinitionType> type;
collections::List<Ptr<ParsingDefinitionGrammar>> grammars;
};
class ParsingDefinition : public ParsingTreeCustomBase
{
public:
collections::List<Ptr<ParsingDefinitionTypeDefinition>> types;
collections::List<Ptr<ParsingDefinitionTokenDefinition>> tokens;
collections::List<Ptr<ParsingDefinitionRuleDefinition>> rules;
};
/***********************************************************************
Attribute Writer
***********************************************************************/
class ParsingDefinitionAttributeWriter : public Object
{
friend ParsingDefinitionAttributeWriter Attribute(const WString& name);
protected:
Ptr<ParsingDefinitionAttribute> attribute;
ParsingDefinitionAttributeWriter(const WString& name);
public:
ParsingDefinitionAttributeWriter(const ParsingDefinitionAttributeWriter& attributeWriter);
ParsingDefinitionAttributeWriter& Argument(const WString& argument);
Ptr<ParsingDefinitionAttribute> Attribute()const;
};
extern ParsingDefinitionAttributeWriter Attribute(const WString& name);
/***********************************************************************
Type Writer
***********************************************************************/
class ParsingDefinitionTypeWriter : public Object
{
friend ParsingDefinitionTypeWriter Type(const WString& name);
friend ParsingDefinitionTypeWriter TokenType();
protected:
Ptr<ParsingDefinitionType> type;
ParsingDefinitionTypeWriter(Ptr<ParsingDefinitionType> internalType);
ParsingDefinitionTypeWriter(const WString& name);
public:
ParsingDefinitionTypeWriter(const ParsingDefinitionTypeWriter& typeWriter);
ParsingDefinitionTypeWriter Sub(const WString& subTypeName)const;
ParsingDefinitionTypeWriter Array()const;
Ptr<ParsingDefinitionType> Type()const;
};
extern ParsingDefinitionTypeWriter Type(const WString& name);
extern ParsingDefinitionTypeWriter TokenType();
/***********************************************************************
Type Definition Writer
***********************************************************************/
class ParsingDefinitionTypeDefinitionWriter : public Object
{
public:
virtual Ptr<ParsingDefinitionTypeDefinition> Definition()const=0;
};
class ParsingDefinitionClassDefinitionWriter : public ParsingDefinitionTypeDefinitionWriter
{
protected:
Ptr<ParsingDefinitionBase> currentDefinition;
Ptr<ParsingDefinitionClassDefinition> definition;
public:
ParsingDefinitionClassDefinitionWriter(const WString& name);
ParsingDefinitionClassDefinitionWriter(const WString& name, const ParsingDefinitionTypeWriter& parentType);
ParsingDefinitionClassDefinitionWriter& AmbiguousType(const ParsingDefinitionTypeWriter& ambiguousType);
ParsingDefinitionClassDefinitionWriter& Member(const WString& name, const ParsingDefinitionTypeWriter& type, const WString& unescapingFunction=L"");
ParsingDefinitionClassDefinitionWriter& SubType(const ParsingDefinitionTypeDefinitionWriter& type);
ParsingDefinitionClassDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
Ptr<ParsingDefinitionTypeDefinition> Definition()const override;
};
extern ParsingDefinitionClassDefinitionWriter Class(const WString& name);
extern ParsingDefinitionClassDefinitionWriter Class(const WString& name, const ParsingDefinitionTypeWriter& parentType);
class ParsingDefinitionEnumDefinitionWriter : public ParsingDefinitionTypeDefinitionWriter
{
protected:
Ptr<ParsingDefinitionBase> currentDefinition;
Ptr<ParsingDefinitionEnumDefinition> definition;
public:
ParsingDefinitionEnumDefinitionWriter(const WString& name);
ParsingDefinitionEnumDefinitionWriter& Member(const WString& name);
ParsingDefinitionEnumDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
Ptr<ParsingDefinitionTypeDefinition> Definition()const override;
};
extern ParsingDefinitionEnumDefinitionWriter Enum(const WString& name);
/***********************************************************************
Grammar Writer
***********************************************************************/
class ParsingDefinitionGrammarWriter : public Object
{
friend ParsingDefinitionGrammarWriter Rule(const WString& name);
friend ParsingDefinitionGrammarWriter Text(const WString& name);
friend ParsingDefinitionGrammarWriter Opt(const ParsingDefinitionGrammarWriter& writer);
protected:
Ptr<ParsingDefinitionGrammar> grammar;
ParsingDefinitionGrammarWriter(Ptr<ParsingDefinitionGrammar> internalGrammar);
public:
ParsingDefinitionGrammarWriter(const ParsingDefinitionGrammarWriter& grammarWriter);
ParsingDefinitionGrammarWriter operator+(const ParsingDefinitionGrammarWriter& next)const;
ParsingDefinitionGrammarWriter operator|(const ParsingDefinitionGrammarWriter& next)const;
ParsingDefinitionGrammarWriter operator*()const;
ParsingDefinitionGrammarWriter As(const ParsingDefinitionTypeWriter& type)const;
ParsingDefinitionGrammarWriter operator[](const WString& memberName)const;
ParsingDefinitionGrammarWriter operator!()const;
ParsingDefinitionGrammarWriter Set(const WString& memberName, const WString& value)const;
Ptr<ParsingDefinitionGrammar> Grammar()const;
};
extern ParsingDefinitionGrammarWriter Rule(const WString& name);
extern ParsingDefinitionGrammarWriter Text(const WString& text);
extern ParsingDefinitionGrammarWriter Opt(const ParsingDefinitionGrammarWriter& writer);
/***********************************************************************
Token and Rule Writer
***********************************************************************/
class ParsingDefinitionWriter;
class ParsingDefinitionTokenDefinitionWriter : public Object
{
protected:
Ptr<ParsingDefinitionTokenDefinition> token;
ParsingDefinitionWriter& owner;
public:
ParsingDefinitionTokenDefinitionWriter(ParsingDefinitionWriter& _owner, Ptr<ParsingDefinitionTokenDefinition> _token);
ParsingDefinitionTokenDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
ParsingDefinitionWriter& EndToken();
};
class ParsingDefinitionRuleDefinitionWriter : public Object
{
protected:
Ptr<ParsingDefinitionRuleDefinition> rule;
ParsingDefinitionWriter& owner;
public:
ParsingDefinitionRuleDefinitionWriter(ParsingDefinitionWriter& _owner, Ptr<ParsingDefinitionRuleDefinition> _rule);
ParsingDefinitionRuleDefinitionWriter& Imply(const ParsingDefinitionGrammarWriter& grammar);
ParsingDefinitionRuleDefinitionWriter& Attribute(const ParsingDefinitionAttributeWriter& attribute);
ParsingDefinitionWriter& EndRule();
};
class ParsingDefinitionWriter : public Object
{
protected:
Ptr<ParsingDefinition> definition;
public:
ParsingDefinitionWriter();
ParsingDefinitionWriter& Type(const ParsingDefinitionTypeDefinitionWriter& type);
ParsingDefinitionWriter& Token(const WString& name, const WString& regex);
ParsingDefinitionTokenDefinitionWriter TokenAtt(const WString& name, const WString& regex);
ParsingDefinitionWriter& Discard(const WString& name, const WString& regex);
ParsingDefinitionRuleDefinitionWriter Rule(const WString& name, const ParsingDefinitionTypeWriter& type);
Ptr<ParsingDefinition> Definition()const;
};
/***********************************************************************
Helper Functions
***********************************************************************/
extern WString TypeToString(ParsingDefinitionType* type);
extern WString GrammarToString(ParsingDefinitionGrammar* grammar);
extern WString GrammarStateToString(ParsingDefinitionGrammar* grammar, ParsingDefinitionGrammar* stateNode, bool beforeNode);
extern ParsingDefinitionGrammar* FindAppropriateGrammarState(ParsingDefinitionGrammar* grammar, ParsingDefinitionGrammar* stateNode, bool beforeNode);
extern void Log(Ptr<ParsingDefinition> definition, stream::TextWriter& writer);
extern WString DeserializeString(const WString& value);
extern WString SerializeString(const WString& value);
/***********************************************************************
Bootstrap
***********************************************************************/
extern Ptr<ParsingDefinition> CreateParserDefinition();
extern Ptr<ParsingDefinition> DeserializeDefinition(Ptr<ParsingTreeNode> node);
}
}
}
#endif
/***********************************************************************
.\PARSING\PARSINGANALYZER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::Analyzing
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSINGANALYZER
#define VCZH_PARSING_PARSINGANALYZER
namespace vl
{
namespace parsing
{
namespace analyzing
{
/***********************************************************************
DefinitionTypeScopePair
***********************************************************************/
class ParsingSymbol;
class ParsingSymbolManager;
struct DefinitionTypeScopePair
{
definitions::ParsingDefinitionType* type;
ParsingSymbol* scope;
DefinitionTypeScopePair()
{
}
DefinitionTypeScopePair(definitions::ParsingDefinitionType* _type, ParsingSymbol* _scope)
:type(_type)
,scope(_scope)
{
}
vint Compare(const DefinitionTypeScopePair& pair)const
{
if(type<pair.type) return -1;
if(type>pair.type) return 1;
if(scope<pair.scope) return -1;
if(scope>pair.scope) return 1;
return 0;
}
bool operator== (const DefinitionTypeScopePair& pair)const {return Compare(pair)==0;}
bool operator!= (const DefinitionTypeScopePair& pair)const {return Compare(pair)!=0;}
bool operator> (const DefinitionTypeScopePair& pair)const {return Compare(pair)>0;}
bool operator>= (const DefinitionTypeScopePair& pair)const {return Compare(pair)>=0;}
bool operator< (const DefinitionTypeScopePair& pair)const {return Compare(pair)<0;}
bool operator<= (const DefinitionTypeScopePair& pair)const {return Compare(pair)<=0;}
};
/***********************************************************************
ParsingSymbol Management
***********************************************************************/
class ParsingSymbol : public Object
{
friend class ParsingSymbolManager;
typedef collections::Dictionary<WString, ParsingSymbol*> ParsingSymbolMap;
typedef collections::List<ParsingSymbol*> ParsingSymbolList;
public:
enum SymbolType
{
Global,
EnumType,
ClassType, // descriptor == base type
ArrayType, // descriptor == element type
TokenType,
EnumItem, // descriptor == parent
ClassField, // descriptor == field type
TokenDef, // descriptor == token type
RuleDef, // descriptor == rule type
};
protected:
ParsingSymbolManager* manager;
SymbolType type;
WString name;
ParsingSymbol* descriptorSymbol;
WString descriptorString;
ParsingSymbol* parentSymbol;
ParsingSymbol* arrayTypeSymbol;
ParsingSymbolList subSymbolList;
ParsingSymbolMap subSymbolMap;
bool AddSubSymbol(ParsingSymbol* subSymbol);
ParsingSymbol(ParsingSymbolManager* _manager, SymbolType _type, const WString& _name, ParsingSymbol* _descriptorSymbol, const WString& _descriptorString);
public:
~ParsingSymbol();
ParsingSymbolManager* GetManager();
SymbolType GetType();
const WString& GetName();
vint GetSubSymbolCount();
ParsingSymbol* GetSubSymbol(vint index);
ParsingSymbol* GetSubSymbolByName(const WString& name);
ParsingSymbol* GetDescriptorSymbol();
WString GetDescriptorString();
ParsingSymbol* GetParentSymbol();
bool IsType();
ParsingSymbol* SearchClassSubSymbol(const WString& name);
ParsingSymbol* SearchCommonBaseClass(ParsingSymbol* classType);
};
class ParsingSymbolManager : public Object
{
typedef definitions::ParsingDefinitionClassDefinition ClassDefinition;
typedef collections::List<Ptr<ParsingSymbol>> ParsingSymbolList;
typedef collections::Dictionary<DefinitionTypeScopePair, ParsingSymbol*> DefinitionTypeSymbolMap;
typedef collections::Dictionary<definitions::ParsingDefinitionGrammar*, ParsingSymbol*> DefinitionGrammarSymbolMap;
typedef collections::Dictionary<ParsingSymbol*, ClassDefinition*> SymbolClassDefinitionMap;
typedef collections::Dictionary<ClassDefinition*, ParsingSymbol*> ClassDefinitionSymbolMap;
protected:
ParsingSymbol* globalSymbol;
ParsingSymbol* tokenTypeSymbol;
ParsingSymbolList createdSymbols;
DefinitionTypeSymbolMap definitionTypeSymbolCache;
DefinitionGrammarSymbolMap definitionGrammarSymbolCache;
DefinitionGrammarSymbolMap definitionGrammarTypeCache;
SymbolClassDefinitionMap symbolClassDefinitionCache;
ClassDefinitionSymbolMap classDefinitionSymbolCache;
bool TryAddSubSymbol(Ptr<ParsingSymbol> subSymbol, ParsingSymbol* parentSymbol);
public:
ParsingSymbolManager();
~ParsingSymbolManager();
ParsingSymbol* GetGlobal();
ParsingSymbol* GetTokenType();
ParsingSymbol* GetArrayType(ParsingSymbol* elementType);
ParsingSymbol* AddClass(definitions::ParsingDefinitionClassDefinition* classDef, ParsingSymbol* baseType, ParsingSymbol* parentType=0);
ParsingSymbol* AddField(const WString& name, ParsingSymbol* classType, ParsingSymbol* fieldType);
ParsingSymbol* AddEnum(const WString& name, ParsingSymbol* parentType=0);
ParsingSymbol* AddEnumItem(const WString& name, ParsingSymbol* enumType);
ParsingSymbol* AddTokenDefinition(const WString& name, const WString& regex);
ParsingSymbol* AddRuleDefinition(const WString& name, ParsingSymbol* ruleType);
ClassDefinition* CacheGetClassDefinition(ParsingSymbol* type);
ParsingSymbol* CacheGetClassType(ClassDefinition* type);
ParsingSymbol* CacheGetType(definitions::ParsingDefinitionType* type, ParsingSymbol* scope);
bool CacheSetType(definitions::ParsingDefinitionType* type, ParsingSymbol* scope, ParsingSymbol* symbol);
ParsingSymbol* CacheGetSymbol(definitions::ParsingDefinitionGrammar* grammar);
bool CacheSetSymbol(definitions::ParsingDefinitionGrammar* grammar, ParsingSymbol* symbol);
ParsingSymbol* CacheGetType(definitions::ParsingDefinitionGrammar* grammar);
bool CacheSetType(definitions::ParsingDefinitionGrammar* grammar, ParsingSymbol* type);
};
/***********************************************************************
Semantic Analyzer
***********************************************************************/
extern WString GetTypeFullName(ParsingSymbol* type);
extern ParsingSymbol* FindType(definitions::ParsingDefinitionType* type, ParsingSymbolManager* manager, ParsingSymbol* scope, collections::List<Ptr<ParsingError>>& errors);
extern void PrepareSymbols(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
extern void ValidateRuleStructure(Ptr<definitions::ParsingDefinition> definition, Ptr<definitions::ParsingDefinitionRuleDefinition> rule, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
extern void ResolveRuleSymbols(Ptr<definitions::ParsingDefinitionRuleDefinition> rule, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
extern void ResolveSymbols(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
extern void ValidateDefinition(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, collections::List<Ptr<ParsingError>>& errors);
}
}
}
#endif
/***********************************************************************
.\PARSING\PARSING.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::Parser
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSING
#define VCZH_PARSING_PARSING
namespace vl
{
namespace parsing
{
namespace tabling
{
/***********************************************************************
Parser
***********************************************************************/
/// <summary>Base type of all parser strategy.</summary>
class ParsingGeneralParser : public Object
{
protected:
Ptr<ParsingTable> table;
public:
ParsingGeneralParser(Ptr<ParsingTable> _table);
~ParsingGeneralParser();
/// <summary>Get the parser table that used to do the parsing.</summary>
/// <returns>The parser table that used to do the parsing.</returns>
Ptr<ParsingTable> GetTable();
/// <summary>Initialization. It should be called before each time of parsing.</summary>
virtual void BeginParse();
virtual ParsingState::TransitionResult ParseStep(ParsingState& state, collections::List<Ptr<ParsingError>>& errors)=0;
bool Parse(ParsingState& state, ParsingTransitionProcessor& processor, collections::List<Ptr<ParsingError>>& errors);
Ptr<ParsingTreeNode> Parse(ParsingState& state, collections::List<Ptr<ParsingError>>& errors);
/// <summary>Parse an input and get an abstract syntax tree if no error happens or all errors are recovered.</summary>
/// <returns>The abstract syntax tree.</returns>
/// <param name="input">The input to parse.</param>
/// <param name="rule">The name of the rule that used to parse the input.</param>
/// <param name="errors">Returns all errors.</param>
/// <param name="codeIndex">The code index to differentiate each input. This value will be stored in every tokens and abstract syntax nodes.</param>
Ptr<ParsingTreeNode> Parse(const WString& input, const WString& rule, collections::List<Ptr<ParsingError>>& errors, vint codeIndex = -1);
};
/***********************************************************************
Parser with different strategies
***********************************************************************/
/// <summary>A strict parse. It doesn't allow ambiguity and error recovery.</summary>
class ParsingStrictParser : public ParsingGeneralParser
{
protected:
virtual bool OnTestErrorRecoverExists();
virtual void OnClearErrorRecover();
virtual ParsingState::TransitionResult OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<Ptr<ParsingError>>& errors);
public:
/// <summary>Create the parse using a parsing table.</summary>
/// <param name="_table">The parsing table.</param>
ParsingStrictParser(Ptr<ParsingTable> _table=0);
~ParsingStrictParser();
ParsingState::TransitionResult ParseStep(ParsingState& state, collections::List<Ptr<ParsingError>>& errors)override;
};
/// <summary>A strict parse. It doesn't allow ambiguity but allows error recovery.</summary>
class ParsingAutoRecoverParser : public ParsingStrictParser
{
public:
struct RecoverFuture
{
ParsingState::Future* future;
vint insertedTokenCount;
vint index;
vint previousIndex;
vint nextIndex;
RecoverFuture()
:future(0)
, insertedTokenCount(0)
, index(-1)
, previousIndex(-1)
, nextIndex(-1)
{
}
};
protected:
vint maxInsertedTokenCount;
collections::List<RecoverFuture> recoverFutures;
vint recoveringFutureIndex;
RecoverFuture& GetRecoverFuture(vint index);
RecoverFuture& CreateRecoverFuture(vint index, vint previousIndex);
bool OnTestErrorRecoverExists()override;
void OnClearErrorRecover()override;
ParsingState::TransitionResult OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<Ptr<ParsingError>>& errors)override;
public:
/// <summary>Create the parse using a parsing table.</summary>
/// <param name="_table">The parsing table.</param>
/// <param name="_maxInsertedTokenCount">The maximum number of tokens that allow to insert to recover an error.</param>
ParsingAutoRecoverParser(Ptr<ParsingTable> _table = 0, vint _maxInsertedTokenCount = -1);
~ParsingAutoRecoverParser();
void BeginParse()override;
};
/// <summary>A strict parse. It allows ambiguity but doesn't allow error recovery.</summary>
class ParsingAmbiguousParser : public ParsingGeneralParser
{
typedef collections::List<ParsingState::TransitionResult> DecisionList;
protected:
DecisionList decisions;
vint consumedDecisionCount;
virtual void OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<ParsingState::Future*>& futures, vint& begin, vint& end, collections::List<Ptr<ParsingError>>& errors);
vint GetResolvableFutureLevels(collections::List<ParsingState::Future*>& futures, vint begin, vint end);
vint SearchPathForOneStep(ParsingState& state, collections::List<ParsingState::Future*>& futures, vint& begin, vint& end, collections::List<Ptr<ParsingError>>& errors);
vint GetConflictReduceCount(collections::List<ParsingState::Future*>& futures);
void GetConflictReduceIndices(collections::List<ParsingState::Future*>& futures, vint conflictReduceCount, collections::Array<vint>& conflictReduceIndices);
vint GetAffectedStackNodeCount(collections::List<ParsingState::Future*>& futures, collections::Array<vint>& conflictReduceIndices);
void BuildSingleDecisionPath(ParsingState& state, ParsingState::Future* future, vint lastAvailableInstructionCount);
void BuildAmbiguousDecisions(ParsingState& state, collections::List<ParsingState::Future*>& futures, vint begin, vint end, vint resolvableFutureLevels, collections::List<Ptr<ParsingError>>& errors);
void BuildDecisions(ParsingState& state, collections::List<ParsingState::Future*>& futures, vint begin, vint end, vint resolvableFutureLevels, collections::List<Ptr<ParsingError>>& errors);
public:
/// <summary>Create the parse using a parsing table.</summary>
/// <param name="_table">The parsing table.</param>
ParsingAmbiguousParser(Ptr<ParsingTable> _table=0);
~ParsingAmbiguousParser();
ParsingState::TransitionResult ParseStep(ParsingState& state, collections::List<Ptr<ParsingError>>& errors)override;
void BeginParse()override;
};
/// <summary>A strict parse. It allow both ambiguity and error recovery.</summary>
class ParsingAutoRecoverAmbiguousParser : public ParsingAmbiguousParser
{
protected:
vint maxInsertedTokenCount;
void OnErrorRecover(ParsingState& state, vint currentTokenIndex, collections::List<ParsingState::Future*>& futures, vint& begin, vint& end, collections::List<Ptr<ParsingError>>& errors)override;
public:
/// <summary>Create the parse using a parsing table.</summary>
/// <param name="_table">The parsing table.</param>
/// <param name="_maxInsertedTokenCount">The maximum number of tokens that allow to insert to recover an error.</param>
ParsingAutoRecoverAmbiguousParser(Ptr<ParsingTable> _table = 0, vint _maxInsertedTokenCount = -1);
~ParsingAutoRecoverAmbiguousParser();
};
/***********************************************************************
Helper Functions
***********************************************************************/
/// <summary>Create the correct strict parser from a parsing table.</summary>
/// <returns>The created parse.</returns>
/// <param name="table">The table to create a parser.</param>
extern Ptr<ParsingGeneralParser> CreateStrictParser(Ptr<ParsingTable> table);
/// <summary>Create the correct error recoverable parser from a parsing table.</summary>
/// <returns>The created parse.</returns>
/// <param name="table">The table to create a parser.</param>
extern Ptr<ParsingGeneralParser> CreateAutoRecoverParser(Ptr<ParsingTable> table);
/// <summary>Create the correct strict parser to parse the grammar itself.</summary>
/// <returns>The created parse.</returns>
extern Ptr<ParsingGeneralParser> CreateBootstrapStrictParser();
/// <summary>Create the correct error recoverable to parse the grammar itself.</summary>
/// <returns>The created parse.</returns>
extern Ptr<ParsingGeneralParser> CreateBootstrapAutoRecoverParser();
}
}
}
/***********************************************************************
Reflection for AST
***********************************************************************/
#ifndef VCZH_DEBUG_NO_REFLECTION
namespace vl
{
namespace reflection
{
namespace description
{
#define PARSINGREFLECTION_TYPELIST(F)\
F(parsing::ParsingTextPos)\
F(parsing::ParsingTextRange)\
F(parsing::ParsingTreeNode)\
F(parsing::ParsingTreeToken)\
F(parsing::ParsingTreeObject)\
F(parsing::ParsingTreeArray)\
F(parsing::ParsingTreeCustomBase)\
F(parsing::ParsingToken)\
F(parsing::ParsingError)\
PARSINGREFLECTION_TYPELIST(DECL_TYPE_INFO)
}
}
}
#endif
namespace vl
{
namespace reflection
{
namespace description
{
extern bool LoadParsingTypes();
}
}
}
#endif
/***********************************************************************
.\PARSING\PARSINGAUTOMATON.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parsing::Automaton
Classes:
***********************************************************************/
#ifndef VCZH_PARSING_PARSINGAUTOMATON
#define VCZH_PARSING_PARSINGAUTOMATON
namespace vl
{
namespace parsing
{
namespace analyzing
{
/***********************************************************************
Automaton
***********************************************************************/
class Action;
class Transition;
class State;
class Action : public Object
{
public:
enum ActionType
{
Create, // new source
Assign, // source ::= <created symbol>
Using, // use <created symbol>
Setter, // source ::= target
Shift,
Reduce,
LeftRecursiveReduce,
};
ActionType actionType;
ParsingSymbol* actionTarget;
ParsingSymbol* actionSource;
definitions::ParsingDefinitionRuleDefinition* creatorRule;
// the following two fields record which rule symbol transition generate this shift/reduce action
State* shiftReduceSource;
State* shiftReduceTarget;
Action();
~Action();
};
class Transition : public Object
{
public:
enum TransitionType
{
TokenBegin, // token stream start
TokenFinish, // token stream end
NormalReduce, // rule end
LeftRecursiveReduce, // rule end with left recursive
Epsilon, // an epsilon transition
Symbol, // a syntax symbol
};
enum StackOperationType
{
None,
ShiftReduceCompacted,
LeftRecursive,
};
State* source;
State* target;
collections::List<Ptr<Action>> actions;
TransitionType transitionType;
StackOperationType stackOperationType;
ParsingSymbol* transitionSymbol;
Transition();
~Transition();
static bool IsEquivalent(Transition* t1, Transition* t2, bool careSourceAndTarget);
};
class State : public Object
{
public:
enum StatePosition
{
BeforeNode,
AfterNode,
};
collections::List<Transition*> transitions;
collections::List<Transition*> inputs;
bool endState;
ParsingSymbol* ownerRuleSymbol;
definitions::ParsingDefinitionRuleDefinition* ownerRule;
definitions::ParsingDefinitionGrammar* grammarNode;
definitions::ParsingDefinitionGrammar* stateNode;
StatePosition statePosition;
WString stateName;
WString stateExpression;
State();
~State();
};
class RuleInfo : public Object
{
public:
State* rootRuleStartState;
State* rootRuleEndState;
State* startState;
collections::List<State*> endStates;
int stateNameCount;
RuleInfo();
~RuleInfo();
};
class Automaton : public Object
{
typedef collections::List<definitions::ParsingDefinitionRuleDefinition*> RuleDefList;
typedef collections::Dictionary<definitions::ParsingDefinitionRuleDefinition*, Ptr<RuleInfo>> RuleInfoMap;
public:
ParsingSymbolManager* symbolManager;
collections::List<Ptr<Transition>> transitions;
collections::List<Ptr<State>> states;
collections::List<Ptr<RuleInfo>> ruleInfos;
RuleDefList orderedRulesDefs;
RuleInfoMap ruleDefToInfoMap;
Automaton(ParsingSymbolManager* _symbolManager);
~Automaton();
void AddRuleInfo(definitions::ParsingDefinitionRuleDefinition* rule, Ptr<RuleInfo> ruleInfo);
State* RuleStartState(definitions::ParsingDefinitionRuleDefinition* ownerRule);
State* RootRuleStartState(definitions::ParsingDefinitionRuleDefinition* ownerRule);
State* RootRuleEndState(definitions::ParsingDefinitionRuleDefinition* ownerRule);
State* StartState(definitions::ParsingDefinitionRuleDefinition* ownerRule, definitions::ParsingDefinitionGrammar* grammarNode, definitions::ParsingDefinitionGrammar* stateNode);
State* EndState(definitions::ParsingDefinitionRuleDefinition* ownerRule, definitions::ParsingDefinitionGrammar* grammarNode, definitions::ParsingDefinitionGrammar* stateNode);
State* CopyState(State* oldState);
Transition* CreateTransition(State* start, State* end);
Transition* TokenBegin(State* start, State* end);
Transition* TokenFinish(State* start, State* end);
Transition* NormalReduce(State* start, State* end);
Transition* LeftRecursiveReduce(State* start, State* end);
Transition* Epsilon(State* start, State* end);
Transition* Symbol(State* start, State* end, ParsingSymbol* transitionSymbol);
Transition* CopyTransition(State* start, State* end, Transition* oldTransition);
void DeleteTransition(Transition* transition);
void DeleteState(State* state);
};
/***********************************************************************
Helper: Closuer Searching
***********************************************************************/
struct ClosureItem
{
enum SearchResult
{
Continue,
Hit,
Blocked,
};
State* state; // target state of one path of a closure
Ptr<collections::List<Transition*>> transitions; // path
bool cycle; // true: invalid closure because there are cycles, and in the middle of the path there will be a transition that targets to the state field.
ClosureItem()
:state(0)
,cycle(false)
{
}
ClosureItem(State* _state, Ptr<collections::List<Transition*>> _transitions, bool _cycle)
:state(_state)
,transitions(_transitions)
,cycle(_cycle)
{
}
};
extern void SearchClosure(ClosureItem::SearchResult(*closurePredicate)(Transition*), State* startState, collections::List<ClosureItem>& closure);
extern void RemoveEpsilonTransitions(collections::Dictionary<State*, State*>& oldNewStateMap, collections::List<State*>& scanningStates, Ptr<Automaton> automaton);
/***********************************************************************
Helper: State Merging
***********************************************************************/
extern void DeleteUnnecessaryStates(Ptr<Automaton> automaton, Ptr<RuleInfo> ruleInfo, collections::List<State*>& newStates);
extern void MergeStates(Ptr<Automaton> automaton, Ptr<RuleInfo> ruleInfo, collections::List<State*>& newStates);
/***********************************************************************
Helper: Automaton Building
***********************************************************************/
extern Ptr<Automaton> CreateEpsilonPDA(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager);
extern Ptr<Automaton> CreateNondeterministicPDAFromEpsilonPDA(Ptr<Automaton> epsilonPDA);
extern Ptr<Automaton> CreateJointPDAFromNondeterministicPDA(Ptr<Automaton> nondeterministicPDA);
extern void CompactJointPDA(Ptr<Automaton> jointPDA);
extern void MarkLeftRecursiveInJointPDA(Ptr<Automaton> jointPDA, collections::List<Ptr<ParsingError>>& errors);
/***********************************************************************
Helper: Parsing Table Generating
***********************************************************************/
extern WString GetTypeNameForCreateInstruction(ParsingSymbol* type);
extern Ptr<tabling::ParsingTable> GenerateTableFromPDA(Ptr<definitions::ParsingDefinition> definition, ParsingSymbolManager* manager, Ptr<Automaton> jointPDA, bool enableAmbiguity, collections::List<Ptr<ParsingError>>& errors);
extern Ptr<tabling::ParsingTable> GenerateTable(Ptr<definitions::ParsingDefinition> definition, bool enableAmbiguity, collections::List<Ptr<ParsingError>>& errors);
extern void Log(Ptr<Automaton> automaton, stream::TextWriter& writer);
}
}
}
#endif
/***********************************************************************
.\PARSING\JSON\PARSINGJSON_AST.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingJson.parser.txt
This file is generated by: Vczh Parser Generator
***********************************************************************/
#ifndef VCZH_PARSING_JSON_PARSINGJSON_PARSER_AST
#define VCZH_PARSING_JSON_PARSINGJSON_PARSER_AST
namespace vl
{
namespace parsing
{
namespace json
{
enum class JsonParserTokenIndex
{
TRUEVALUE = 0,
FALSEVALUE = 1,
NULLVALUE = 2,
OBJOPEN = 3,
OBJCLOSE = 4,
ARROPEN = 5,
ARRCLOSE = 6,
COMMA = 7,
COLON = 8,
NUMBER = 9,
STRING = 10,
SPACE = 11,
};
class JsonNode;
class JsonLiteral;
class JsonString;
class JsonNumber;
class JsonArray;
class JsonObjectField;
class JsonObject;
class JsonNode abstract : public vl::parsing::ParsingTreeCustomBase, vl::reflection::Description<JsonNode>
{
public:
class IVisitor : public vl::reflection::IDescriptable, vl::reflection::Description<IVisitor>
{
public:
virtual void Visit(JsonLiteral* node)=0;
virtual void Visit(JsonString* node)=0;
virtual void Visit(JsonNumber* node)=0;
virtual void Visit(JsonArray* node)=0;
virtual void Visit(JsonObjectField* node)=0;
virtual void Visit(JsonObject* node)=0;
};
virtual void Accept(JsonNode::IVisitor* visitor)=0;
};
class JsonLiteral : public JsonNode, vl::reflection::Description<JsonLiteral>
{
public:
enum class JsonValue
{
True,
False,
Null,
};
JsonValue value;
void Accept(JsonNode::IVisitor* visitor)override;
static vl::Ptr<JsonLiteral> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class JsonString : public JsonNode, vl::reflection::Description<JsonString>
{
public:
vl::parsing::ParsingToken content;
void Accept(JsonNode::IVisitor* visitor)override;
static vl::Ptr<JsonString> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class JsonNumber : public JsonNode, vl::reflection::Description<JsonNumber>
{
public:
vl::parsing::ParsingToken content;
void Accept(JsonNode::IVisitor* visitor)override;
static vl::Ptr<JsonNumber> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class JsonArray : public JsonNode, vl::reflection::Description<JsonArray>
{
public:
vl::collections::List<vl::Ptr<JsonNode>> items;
void Accept(JsonNode::IVisitor* visitor)override;
static vl::Ptr<JsonArray> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class JsonObjectField : public JsonNode, vl::reflection::Description<JsonObjectField>
{
public:
vl::parsing::ParsingToken name;
vl::Ptr<JsonNode> value;
void Accept(JsonNode::IVisitor* visitor)override;
static vl::Ptr<JsonObjectField> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class JsonObject : public JsonNode, vl::reflection::Description<JsonObject>
{
public:
vl::collections::List<vl::Ptr<JsonObjectField>> fields;
void Accept(JsonNode::IVisitor* visitor)override;
static vl::Ptr<JsonObject> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
}
}
}
namespace vl
{
namespace reflection
{
namespace description
{
#ifndef VCZH_DEBUG_NO_REFLECTION
DECL_TYPE_INFO(vl::parsing::json::JsonNode)
DECL_TYPE_INFO(vl::parsing::json::JsonLiteral)
DECL_TYPE_INFO(vl::parsing::json::JsonLiteral::JsonValue)
DECL_TYPE_INFO(vl::parsing::json::JsonString)
DECL_TYPE_INFO(vl::parsing::json::JsonNumber)
DECL_TYPE_INFO(vl::parsing::json::JsonArray)
DECL_TYPE_INFO(vl::parsing::json::JsonObjectField)
DECL_TYPE_INFO(vl::parsing::json::JsonObject)
DECL_TYPE_INFO(vl::parsing::json::JsonNode::IVisitor)
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::parsing::json::JsonNode::IVisitor)
void Visit(vl::parsing::json::JsonLiteral* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::json::JsonString* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::json::JsonNumber* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::json::JsonArray* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::json::JsonObjectField* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::json::JsonObject* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
END_INTERFACE_PROXY(vl::parsing::json::JsonNode::IVisitor)
#endif
extern bool JsonLoadTypes();
}
}
}
#endif
/***********************************************************************
.\PARSING\JSON\PARSINGJSON_PARSER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingJson.parser.txt
This file is generated by: Vczh Parser Generator
***********************************************************************/
#ifndef VCZH_PARSING_JSON_PARSINGJSON_PARSER_PARSER
#define VCZH_PARSING_JSON_PARSINGJSON_PARSER_PARSER
namespace vl
{
namespace parsing
{
namespace json
{
extern vl::WString JsonGetParserTextBuffer();
extern vl::Ptr<vl::parsing::ParsingTreeCustomBase> JsonConvertParsingTreeNode(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
extern vl::Ptr<vl::parsing::tabling::ParsingTable> JsonLoadTable();
extern vl::Ptr<vl::parsing::ParsingTreeNode> JsonParseAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
extern vl::Ptr<vl::parsing::ParsingTreeNode> JsonParseAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
extern vl::Ptr<JsonNode> JsonParse(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
extern vl::Ptr<JsonNode> JsonParse(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
}
}
}
#endif
/***********************************************************************
.\PARSING\XML\PARSINGXML_AST.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingXml.parser.txt
This file is generated by: Vczh Parser Generator
***********************************************************************/
#ifndef VCZH_PARSING_XML_PARSINGXML_PARSER_AST
#define VCZH_PARSING_XML_PARSINGXML_PARSER_AST
namespace vl
{
namespace parsing
{
namespace xml
{
enum class XmlParserTokenIndex
{
INSTRUCTION_OPEN = 0,
INSTRUCTION_CLOSE = 1,
COMPLEX_ELEMENT_OPEN = 2,
SINGLE_ELEMENT_CLOSE = 3,
ELEMENT_OPEN = 4,
ELEMENT_CLOSE = 5,
EQUAL = 6,
NAME = 7,
ATTVALUE = 8,
COMMENT = 9,
CDATA = 10,
TEXT = 11,
SPACE = 12,
};
class XmlNode;
class XmlText;
class XmlCData;
class XmlAttribute;
class XmlComment;
class XmlElement;
class XmlInstruction;
class XmlDocument;
class XmlNode abstract : public vl::parsing::ParsingTreeCustomBase, vl::reflection::Description<XmlNode>
{
public:
class IVisitor : public vl::reflection::IDescriptable, vl::reflection::Description<IVisitor>
{
public:
virtual void Visit(XmlText* node)=0;
virtual void Visit(XmlCData* node)=0;
virtual void Visit(XmlAttribute* node)=0;
virtual void Visit(XmlComment* node)=0;
virtual void Visit(XmlElement* node)=0;
virtual void Visit(XmlInstruction* node)=0;
virtual void Visit(XmlDocument* node)=0;
};
virtual void Accept(XmlNode::IVisitor* visitor)=0;
};
class XmlText : public XmlNode, vl::reflection::Description<XmlText>
{
public:
vl::parsing::ParsingToken content;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlText> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class XmlCData : public XmlNode, vl::reflection::Description<XmlCData>
{
public:
vl::parsing::ParsingToken content;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlCData> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class XmlAttribute : public XmlNode, vl::reflection::Description<XmlAttribute>
{
public:
vl::parsing::ParsingToken name;
vl::parsing::ParsingToken value;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlAttribute> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class XmlComment : public XmlNode, vl::reflection::Description<XmlComment>
{
public:
vl::parsing::ParsingToken content;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlComment> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class XmlElement : public XmlNode, vl::reflection::Description<XmlElement>
{
public:
vl::parsing::ParsingToken name;
vl::parsing::ParsingToken closingName;
vl::collections::List<vl::Ptr<XmlAttribute>> attributes;
vl::collections::List<vl::Ptr<XmlNode>> subNodes;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlElement> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class XmlInstruction : public XmlNode, vl::reflection::Description<XmlInstruction>
{
public:
vl::parsing::ParsingToken name;
vl::collections::List<vl::Ptr<XmlAttribute>> attributes;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlInstruction> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
class XmlDocument : public XmlNode, vl::reflection::Description<XmlDocument>
{
public:
vl::collections::List<vl::Ptr<XmlNode>> prologs;
vl::Ptr<XmlElement> rootElement;
void Accept(XmlNode::IVisitor* visitor)override;
static vl::Ptr<XmlDocument> Convert(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
};
}
}
}
namespace vl
{
namespace reflection
{
namespace description
{
#ifndef VCZH_DEBUG_NO_REFLECTION
DECL_TYPE_INFO(vl::parsing::xml::XmlNode)
DECL_TYPE_INFO(vl::parsing::xml::XmlText)
DECL_TYPE_INFO(vl::parsing::xml::XmlCData)
DECL_TYPE_INFO(vl::parsing::xml::XmlAttribute)
DECL_TYPE_INFO(vl::parsing::xml::XmlComment)
DECL_TYPE_INFO(vl::parsing::xml::XmlElement)
DECL_TYPE_INFO(vl::parsing::xml::XmlInstruction)
DECL_TYPE_INFO(vl::parsing::xml::XmlDocument)
DECL_TYPE_INFO(vl::parsing::xml::XmlNode::IVisitor)
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(vl::parsing::xml::XmlNode::IVisitor)
void Visit(vl::parsing::xml::XmlText* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::xml::XmlCData* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::xml::XmlAttribute* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::xml::XmlComment* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::xml::XmlElement* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::xml::XmlInstruction* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
void Visit(vl::parsing::xml::XmlDocument* node)override
{
INVOKE_INTERFACE_PROXY(Visit, node);
}
END_INTERFACE_PROXY(vl::parsing::xml::XmlNode::IVisitor)
#endif
extern bool XmlLoadTypes();
}
}
}
#endif
/***********************************************************************
.\PARSING\XML\PARSINGXML_PARSER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingXml.parser.txt
This file is generated by: Vczh Parser Generator
***********************************************************************/
#ifndef VCZH_PARSING_XML_PARSINGXML_PARSER_PARSER
#define VCZH_PARSING_XML_PARSINGXML_PARSER_PARSER
namespace vl
{
namespace parsing
{
namespace xml
{
extern vl::WString XmlGetParserTextBuffer();
extern vl::Ptr<vl::parsing::ParsingTreeCustomBase> XmlConvertParsingTreeNode(vl::Ptr<vl::parsing::ParsingTreeNode> node, const vl::collections::List<vl::regex::RegexToken>& tokens);
extern vl::Ptr<vl::parsing::tabling::ParsingTable> XmlLoadTable();
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseDocumentAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseDocumentAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
extern vl::Ptr<XmlDocument> XmlParseDocument(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
extern vl::Ptr<XmlDocument> XmlParseDocument(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseElementAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
extern vl::Ptr<vl::parsing::ParsingTreeNode> XmlParseElementAsParsingTreeNode(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
extern vl::Ptr<XmlElement> XmlParseElement(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::collections::List<vl::Ptr<vl::parsing::ParsingError>>& errors, vl::vint codeIndex = -1);
extern vl::Ptr<XmlElement> XmlParseElement(const vl::WString& input, vl::Ptr<vl::parsing::tabling::ParsingTable> table, vl::vint codeIndex = -1);
}
}
}
#endif
/***********************************************************************
.\REGEX\REGEXDATA.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::Basic Data Structure
Classes:
***********************************************************************/
#ifndef VCZH_REGEX_REGEXDATA
#define VCZH_REGEX_REGEXDATA
namespace vl
{
namespace regex_internal
{
/***********************************************************************
Data Structure
***********************************************************************/
class CharRange
{
public:
typedef collections::SortedList<CharRange> List;
wchar_t begin;
wchar_t end;
CharRange();
CharRange(wchar_t _begin, wchar_t _end);
bool operator<(CharRange item)const;
bool operator<=(CharRange item)const;
bool operator>(CharRange item)const;
bool operator>=(CharRange item)const;
bool operator==(CharRange item)const;
bool operator!=(CharRange item)const;
bool operator<(wchar_t item)const;
bool operator<=(wchar_t item)const;
bool operator>(wchar_t item)const;
bool operator>=(wchar_t item)const;
bool operator==(wchar_t item)const;
bool operator!=(wchar_t item)const;
};
}
template<>
struct POD<regex_internal::CharRange>
{
static const bool Result=true;
};
}
#endif
/***********************************************************************
.\REGEX\REGEXAUTOMATON.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::RegexAutomaton
Classes:
State : State
Transition : Transation
Automaton : Automaton
Functions:
EpsilonNfaToNfa : Copy and remove epsilon states and transitions from an NFA
NfaToDfa : Convert an NFA to a DFA
***********************************************************************/
#ifndef VCZH_REGEX_REGEXAUTOMATON
#define VCZH_REGEX_REGEXAUTOMATON
namespace vl
{
namespace regex_internal
{
class State;
class Transition;
class Transition
{
public:
enum Type
{
Chars, // Character range transition
Epsilon,
BeginString,
EndString,
Nop, // Non-epsilon transition with no input
Capture, // Begin capture transition
Match, // Capture matching transition
Positive, // Begin positive lookahead
Negative, // Begin negative lookahead
NegativeFail, // Negative lookahead failure
End // For Capture, Position, Negative
};
State* source;
State* target;
CharRange range;
Type type;
vint capture;
vint index;
};
class State
{
public:
collections::List<Transition*> transitions;
collections::List<Transition*> inputs;
bool finalState;
void* userData;
};
class Automaton
{
public:
typedef Ptr<Automaton> Ref;
collections::List<Ptr<State>> states;
collections::List<Ptr<Transition>> transitions;
collections::List<WString> captureNames;
State* startState;
Automaton();
State* NewState();
Transition* NewTransition(State* start, State* end);
Transition* NewChars(State* start, State* end, CharRange range);
Transition* NewEpsilon(State* start, State* end);
Transition* NewBeginString(State* start, State* end);
Transition* NewEndString(State* start, State* end);
Transition* NewNop(State* start, State* end);
Transition* NewCapture(State* start, State* end, vint capture);
Transition* NewMatch(State* start, State* end, vint capture, vint index=-1);
Transition* NewPositive(State* start, State* end);
Transition* NewNegative(State* start, State* end);
Transition* NewNegativeFail(State* start, State* end);
Transition* NewEnd(State* start, State* end);
};
extern bool PureEpsilonChecker(Transition* transition);
extern bool RichEpsilonChecker(Transition* transition);
extern bool AreEqual(Transition* transA, Transition* transB);
extern Automaton::Ref EpsilonNfaToNfa(Automaton::Ref source, bool(*epsilonChecker)(Transition*), collections::Dictionary<State*, State*>& nfaStateMap);
extern Automaton::Ref NfaToDfa(Automaton::Ref source, collections::Group<State*, State*>& dfaStateMap);
}
}
#endif
/***********************************************************************
.\REGEX\REGEXEXPRESSION.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::RegexExpression
Classes:
Expression : Base class of expressions |
CharSetExpression : Character set | a, [a-b], [^a-b0_9], \.rnt\/()+*?{}[]<>^$!=SsDdLlWw, [\rnt-[]\/^$]
LoopExpression : Repeat | a{3}, a{3,}, a{1,3}, a+, a*, a?, LOOP?
SequenceExpression : Sequence of two regex | ab
AlternateExpression : Alternative of two regex | a|b
BeginExpression : <Rich> String begin | ^
EndExpression : <Rich> String end | $
CaptureExpression : <Rich> Capture | (<name>expr), (?expr)
MatchExpression : <Rich> Capture matching | (<$name>), (<$name;i>), (<$i>)
PositiveExpression : <Rich> Positive lookahead | (=expr)
NegativeExpression : <Rich> Negative lookahead | (!expr)
UsingExpression : refer a regex | (<#name1>expr)...(<&name1>)...
RegexExpression : Regular Expression
Functions:
ParseRegexExpression : Regex Syntax Analyzer
***********************************************************************/
#ifndef VCZH_REGEX_REGEXEXPRESSION
#define VCZH_REGEX_REGEXEXPRESSION
namespace vl
{
namespace regex_internal
{
class IRegexExpressionAlgorithm;
/***********************************************************************
Regex Expression AST
***********************************************************************/
class Expression : public Object, private NotCopyable
{
public:
typedef Ptr<Expression> Ref;
typedef collections::Dictionary<WString, Expression::Ref> Map;
virtual void Apply(IRegexExpressionAlgorithm& algorithm)=0;
bool IsEqual(Expression* expression);
bool HasNoExtension();
bool CanTreatAsPure();
void NormalizeCharSet(CharRange::List& subsets);
void CollectCharSet(CharRange::List& subsets);
void ApplyCharSet(CharRange::List& subsets);
Automaton::Ref GenerateEpsilonNfa();
};
class CharSetExpression : public Expression
{
public:
CharRange::List ranges;
bool reverse;
bool AddRangeWithConflict(CharRange range);
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class LoopExpression : public Expression
{
public:
Expression::Ref expression; // The regex to loop
vint min; // Minimum count of looping
vint max; // Maximum count of looping, -1 for infinite
bool preferLong; // Prefer longer matching
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class SequenceExpression : public Expression
{
public:
Expression::Ref left; // First regex to match
Expression::Ref right; // Last regex to match
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class AlternateExpression : public Expression
{
public:
Expression::Ref left; // First regex to match
Expression::Ref right; // Last regex to match
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class BeginExpression: public Expression
{
public:
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class EndExpression : public Expression
{
public:
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class CaptureExpression : public Expression
{
public:
WString name; // Capture name, empty for anonymous capture
Expression::Ref expression; // Regex to match
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class MatchExpression : public Expression
{
public:
WString name; // Capture name, empty for anonymous
vint index; // The index of captured text to match associated the name, -1 for all of them
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class PositiveExpression : public Expression
{
public:
Expression::Ref expression; // Regex to match
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class NegativeExpression : public Expression
{
public:
Expression::Ref expression; // Regex to match
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class UsingExpression : public Expression
{
public:
WString name; // Name of the regex to refer
void Apply(IRegexExpressionAlgorithm& algorithm);
};
class RegexExpression : public Object, private NotCopyable
{
public:
typedef Ptr<RegexExpression> Ref;
Expression::Map definitions; // Named regex to be referred
Expression::Ref expression; // Regex to match
Expression::Ref Merge();
};
/***********************************************************************
Visitor
***********************************************************************/
class IRegexExpressionAlgorithm : public Interface
{
public:
virtual void Visit(CharSetExpression* expression)=0;
virtual void Visit(LoopExpression* expression)=0;
virtual void Visit(SequenceExpression* expression)=0;
virtual void Visit(AlternateExpression* expression)=0;
virtual void Visit(BeginExpression* expression)=0;
virtual void Visit(EndExpression* expression)=0;
virtual void Visit(CaptureExpression* expression)=0;
virtual void Visit(MatchExpression* expression)=0;
virtual void Visit(PositiveExpression* expression)=0;
virtual void Visit(NegativeExpression* expression)=0;
virtual void Visit(UsingExpression* expression)=0;
};
template<typename ReturnType, typename ParameterType=void*>
class RegexExpressionAlgorithm : public Object, public IRegexExpressionAlgorithm
{
private:
ReturnType returnValue;
ParameterType* parameterValue;
public:
ReturnType Invoke(Expression* expression, ParameterType parameter)
{
parameterValue=&parameter;
expression->Apply(*this);
return returnValue;
}
ReturnType Invoke(Expression::Ref expression, ParameterType parameter)
{
parameterValue=&parameter;
expression->Apply(*this);
return returnValue;
}
virtual ReturnType Apply(CharSetExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(LoopExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(SequenceExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(AlternateExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(BeginExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(EndExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(CaptureExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(MatchExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(PositiveExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(NegativeExpression* expression, ParameterType parameter)=0;
virtual ReturnType Apply(UsingExpression* expression, ParameterType parameter)=0;
public:
void Visit(CharSetExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(LoopExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(SequenceExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(AlternateExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(BeginExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(EndExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(CaptureExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(MatchExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(PositiveExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(NegativeExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
void Visit(UsingExpression* expression)
{
returnValue=Apply(expression, *parameterValue);
}
};
template<typename ParameterType>
class RegexExpressionAlgorithm<void, ParameterType> : public Object, public IRegexExpressionAlgorithm
{
private:
ParameterType* parameterValue;
public:
void Invoke(Expression* expression, ParameterType parameter)
{
parameterValue=&parameter;
expression->Apply(*this);
}
void Invoke(Expression::Ref expression, ParameterType parameter)
{
parameterValue=&parameter;
expression->Apply(*this);
}
virtual void Apply(CharSetExpression* expression, ParameterType parameter)=0;
virtual void Apply(LoopExpression* expression, ParameterType parameter)=0;
virtual void Apply(SequenceExpression* expression, ParameterType parameter)=0;
virtual void Apply(AlternateExpression* expression, ParameterType parameter)=0;
virtual void Apply(BeginExpression* expression, ParameterType parameter)=0;
virtual void Apply(EndExpression* expression, ParameterType parameter)=0;
virtual void Apply(CaptureExpression* expression, ParameterType parameter)=0;
virtual void Apply(MatchExpression* expression, ParameterType parameter)=0;
virtual void Apply(PositiveExpression* expression, ParameterType parameter)=0;
virtual void Apply(NegativeExpression* expression, ParameterType parameter)=0;
virtual void Apply(UsingExpression* expression, ParameterType parameter)=0;
public:
void Visit(CharSetExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(LoopExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(SequenceExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(AlternateExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(BeginExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(EndExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(CaptureExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(MatchExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(PositiveExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(NegativeExpression* expression)
{
Apply(expression, *parameterValue);
}
void Visit(UsingExpression* expression)
{
Apply(expression, *parameterValue);
}
};
/***********************************************************************
Helper Functions
***********************************************************************/
extern Ptr<LoopExpression> ParseLoop(const wchar_t*& input);
extern Ptr<Expression> ParseCharSet(const wchar_t*& input);
extern Ptr<Expression> ParseFunction(const wchar_t*& input);
extern Ptr<Expression> ParseUnit(const wchar_t*& input);
extern Ptr<Expression> ParseJoin(const wchar_t*& input);
extern Ptr<Expression> ParseAlt(const wchar_t*& input);
extern Ptr<Expression> ParseExpression(const wchar_t*& input);
extern RegexExpression::Ref ParseRegexExpression(const WString& code);
extern WString EscapeTextForRegex(const WString& literalString);
extern WString UnescapeTextForRegex(const WString& escapedText);
extern WString NormalizeEscapedTextForRegex(const WString& escapedText);
extern bool IsRegexEscapedLiteralString(const WString& regex);
}
}
#endif
/***********************************************************************
.\CONSOLE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
UI::Console
***********************************************************************/
#ifndef VCZH_CONSOLE
#define VCZH_CONSOLE
namespace vl
{
namespace console
{
/// <summary>A Static class for command line window operations.</summary>
class Console abstract
{
public:
/// <summary>Write to the command line window.</summary>
/// <param name="string">Content to write.</param>
/// <param name="length">Size of the content in wchar_t. The zero terminator is not included.</param>
static void Write(const wchar_t* string, vint length);
/// <summary>Write to the command line window.</summary>
/// <param name="string">Content to write.</param>
static void Write(const wchar_t* string);
/// <summary>Write to the command line window.</summary>
/// <param name="string">Content to write.</param>
static void Write(const WString& string);
/// <summary>Write to the command line window with a CRLF.</summary>
/// <param name="string">Content to write.</param>
static void WriteLine(const WString& string);
/// <summary>Read from the command line window.</summary>
/// <returns>The whole line read from the command line window.</returns>
static WString Read();
static void SetColor(bool red, bool green, bool blue, bool light);
static void SetTitle(const WString& string);
};
}
}
#endif
/***********************************************************************
.\FILESYSTEM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::FileSystem
***********************************************************************/
#ifndef VCZH_FILESYSTEM
#define VCZH_FILESYSTEM
namespace vl
{
namespace filesystem
{
/// <summary>A type representing a file path.</summary>
class FilePath : public Object
{
protected:
WString fullPath;
void Initialize();
static void GetPathComponents(WString path, collections::List<WString>& components);
static WString ComponentsToPath(const collections::List<WString>& components);
public:
#if defined VCZH_MSVC
static const wchar_t Delimiter = L'\\';
#elif defined VCZH_GCC
static const wchar_t Delimiter = L'/';
#endif
/// <summary>Create a root path.</summary>
FilePath();
/// <summary>Create a file path.</summary>
/// <param name="_filePath">Content of the file path. If it is a relative path, it will be converted to an absolute path.</param>
FilePath(const WString& _filePath);
/// <summary>Create a file path.</summary>
/// <param name="_filePath">Content of the file path. If it is a relative path, it will be converted to an absolute path.</param>
FilePath(const wchar_t* _filePath);
/// <summary>Copy a file path.</summary>
/// <param name="_filePath">The file path to copy.</param>
FilePath(const FilePath& _filePath);
~FilePath();
static vint Compare(const FilePath& a, const FilePath& b);
bool operator==(const FilePath& filePath)const{ return Compare(*this, filePath) == 0; }
bool operator!=(const FilePath& filePath)const{ return Compare(*this, filePath) != 0; }
bool operator< (const FilePath& filePath)const{ return Compare(*this, filePath) < 0; }
bool operator<=(const FilePath& filePath)const{ return Compare(*this, filePath) <= 0; }
bool operator> (const FilePath& filePath)const{ return Compare(*this, filePath) > 0; }
bool operator>=(const FilePath& filePath)const{ return Compare(*this, filePath) >= 0; }
/// <summary>Concat an absolute path and a relative path.</summary>
/// <returns>The result absolute path.</returns>
/// <param name="relativePath">The relative path to concat.</param>
FilePath operator/(const WString& relativePath)const;
/// <summary>Test if the file path is a file.</summary>
/// <returns>Returns true if the file path is a file.</returns>
bool IsFile()const;
/// <summary>Test if the file path is a folder.</summary>
/// <returns>Returns true if the file path is a folder.</returns>
bool IsFolder()const;
/// <summary>Test if the file path is a the root of all file system objects.</summary>
/// <returns>Returns true if the file path is the root of all file system objects.</returns>
bool IsRoot()const;
/// <summary>Get the last piece of names in the file path.</summary>
/// <returns>The last piece of names in the file path.</returns>
WString GetName()const;
/// <summary>Get the containing folder of this file path.</summary>
/// <returns>The containing folder.</returns>
FilePath GetFolder()const;
/// <summary>Get the content of the file path.</summary>
/// <returns>The content of the file path.</returns>
WString GetFullPath()const;
/// <summary>Calculate the relative path using a referencing folder.</summary>
/// <returns>The relative path.</returns>
/// <param name="_filePath">The referencing folder.</param>
WString GetRelativePathFor(const FilePath& _filePath);
};
/// <summary>Representing a file reference.</summary>
class File : public Object
{
private:
FilePath filePath;
public:
/// <summary>Create an empty reference.</summary>
File();
/// <summary>Create a reference to a specified file.</summary>
/// <param name="_filePath">The specified file.</param>
File(const FilePath& _filePath);
~File();
/// <summary>Get the file path of the file.</summary>
/// <returns>The file path.</returns>
const FilePath& GetFilePath()const;
/// <summary>Get the content of the file as text with encoding testing.</summary>
/// <returns>Returns false if this operation succeeded.</returns>
/// <param name="text">The content of the file.</param>
/// <param name="encoding">The encoding.</param>
/// <param name="containsBom">True if there is BOM.</param>
bool ReadAllTextWithEncodingTesting(WString& text, stream::BomEncoder::Encoding& encoding, bool& containsBom);
/// <summary>Get the content of the file as text.</summary>
/// <returns>The content of the file.</returns>
WString ReadAllTextByBom()const;
/// <summary>Get the content of the file as text.</summary>
/// <returns>Returns false if this operation succeeded.</returns>
/// <param name="text">The content of the file.</param>
bool ReadAllTextByBom(WString& text)const;
/// <summary>Get the content of the file as text.</summary>
/// <returns>Returns false if this operation succeeded.</returns>
/// <param name="lines">The content of the file.</param>
bool ReadAllLinesByBom(collections::List<WString>& lines)const;
/// <summary>Write text to the file.</summary>
/// <returns>Returns false if this operation succeeded.</returns>
/// <param name="text">The text to write.</param>
/// <param name="bom">Set to true to add a corresponding BOM at the beginning of the file according to the encoding.</param>
/// <param name="encoding">The text encoding.</param>
bool WriteAllText(const WString& text, bool bom = true, stream::BomEncoder::Encoding encoding = stream::BomEncoder::Utf16);
/// <summary>Write text to the file.</summary>
/// <returns>Returns false if this operation succeeded.</returns>
/// <param name="lines">The text to write.</param>
/// <param name="bom">Set to true to add a corresponding BOM at the beginning of the file according to the encoding.</param>
/// <param name="encoding">The text encoding.</param>
bool WriteAllLines(collections::List<WString>& lines, bool bom = true, stream::BomEncoder::Encoding encoding = stream::BomEncoder::Utf16);
/// <summary>Test does the file exist or not.</summary>
/// <returns>Returns true if the file exists.</returns>
bool Exists()const;
/// <summary>Delete the file.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
bool Delete()const;
/// <summary>Rename the file in the same folder.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="newName">The new file name.</param>
bool Rename(const WString& newName)const;
};
/// <summary>Representing a folder reference.</summary>
class Folder : public Object
{
private:
FilePath filePath;
public:
/// <summary>Create a root reference.</summary>
Folder();
/// <summary>Create a reference to a specified folder.</summary>
/// <param name="_filePath">The specified folder.</param>
Folder(const FilePath& _filePath);
~Folder();
/// <summary>Get the file path of the folder.</summary>
/// <returns>The file path.</returns>
const FilePath& GetFilePath()const;
/// <summary>Get all folders in this folder.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="folders">All folders.</param>
bool GetFolders(collections::List<Folder>& folders)const;
/// <summary>Get all files in this folder.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="files">All files.</param>
bool GetFiles(collections::List<File>& files)const;
/// <summary>Test does the folder exist or not.</summary>
/// <returns>Returns true if the folder exists.</returns>
bool Exists()const;
/// <summary>Create the folder.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="recursively">Set to true to create all parent folders if necessary.</param>
bool Create(bool recursively)const;
/// <summary>Delete the folder.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="recursively">Set to true to delete everything in the folder.</param>
bool Delete(bool recursively)const;
/// <summary>Rename the folder in the same folder.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="newName">The new folder name.</param>
bool Rename(const WString& newName)const;
};
}
}
#endif
/***********************************************************************
.\STREAM\FILESTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::FileStream
Interfaces:
FileStream : File stream
***********************************************************************/
#ifndef VCZH_STREAM_FILESTREAM
#define VCZH_STREAM_FILESTREAM
#include <stdio.h>
namespace vl
{
namespace stream
{
/// <summary>A file stream. It is readable when you use [F:vl.stream.FileStream.AccessRight.ReadOnly] or [F:vl.stream.FileStream.AccessRight.ReadWrite] to create the stream. It is writable when you use [F:vl.stream.FileStream.AccessRight.WriteOnly] or [F:vl.stream.FileStream.AccessRight.ReadWrite] to create the stream.</summary>
class FileStream : public Object, public virtual IStream
{
public:
/// <summary>Access to the file.</summary>
enum AccessRight
{
/// <summary>The file is opened to read.</summary>
ReadOnly,
/// <summary>The file is opened to write.</summary>
WriteOnly,
/// <summary>The file is opened to both read and write.</summary>
ReadWrite
};
protected:
AccessRight accessRight;
FILE* file;
public:
/// <summary>Create a stream.</summary>
/// <param name="fileName">File to operate.</param>
/// <param name="_accessRight">Operations want to perform on the file.</param>
FileStream(const WString& fileName, AccessRight _accessRight);
~FileStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
}
}
#endif
/***********************************************************************
.\GLOBALSTORAGE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Global Storage
Classes:
GlobalStorage : Global storage accessable by name, each storage will be initialized on the first access, and all storages will be released by FinalizeGlobalStorage
***********************************************************************/
#ifndef VCZH_GLOBALSTORAGE
#define VCZH_GLOBALSTORAGE
namespace vl
{
/// <summary><![CDATA[
/// Base type of all global storages. A global storage is a value with a key to store some information. In order to create a global storage, you should do the following in a cpp file:
/// BEGIN_GLOBAL_STOREGE_CLASS(<put the key here, it should be a legal C++ identifier>)
/// <put all variables here>
/// INITIALIZE_GLOBAL_STORAGE_CLASS
/// <initialize all variables>
/// FINALIZE_GLOBAL_STORAGE_CLASS
/// <clear all resources because the program is about to exit>
/// END_GLOBAL_STORAGE_CLASS
/// Then you have a global storage. You can only use this global storage in the current cpp file. [M:vl.InitializeGlobalStorage] should be called before using any global storage. [M:vl.FinalizeGlobalStorage] is encouraged to call if you think you will not use any global storages anymore. It will reduce noices when you want to detect memory leaks.
/// If the key of the global variable is called Key, and the variable you want to access is called Variable, then you can use GetKey()->Variable to access that variable. The GetKey function is created in the macro calls before.
/// ]]></summary>
class GlobalStorage : public Object, private NotCopyable
{
private:
bool cleared;
public:
GlobalStorage(const wchar_t* key);
~GlobalStorage();
bool Cleared();
virtual void ClearResource()=0;
};
extern GlobalStorage* GetGlobalStorage(const wchar_t* key);
extern GlobalStorage* GetGlobalStorage(const WString& key);
/// <summary>Initialize the global storage.</summary>
extern void InitializeGlobalStorage();
/// <summary>Finalize the global storage.</summary>
extern void FinalizeGlobalStorage();
}
#define BEGIN_GLOBAL_STORAGE_CLASS(NAME)\
class NAME : public vl::GlobalStorage\
{\
public:\
NAME()\
:vl::GlobalStorage(L ## #NAME)\
{\
InitializeClearResource();\
}\
~NAME()\
{\
if(!Cleared())ClearResource();\
}\
#define INITIALIZE_GLOBAL_STORAGE_CLASS\
void InitializeClearResource()\
{\
#define FINALIZE_GLOBAL_STORAGE_CLASS\
}\
void ClearResource()\
{\
#define END_GLOBAL_STORAGE_CLASS(NAME)\
}\
};\
NAME& Get##NAME()\
{\
static NAME __global_storage_##NAME;\
return __global_storage_##NAME;\
}\
#define EXTERN_GLOBAL_STORAGE_CLASS(NAME)\
class NAME;\
extern NAME& Get##NAME();\
#endif
/***********************************************************************
.\HTTPUTILITY.H
***********************************************************************/
#ifndef VCZH_HTTPUTILITY
#define VCZH_HTTPUTILITY
#ifdef VCZH_MSVC
namespace vl
{
/***********************************************************************
HTTP Utility
***********************************************************************/
/// <summary>A type representing an http requiest.</summary>
class HttpRequest
{
typedef collections::Array<char> BodyBuffer;
typedef collections::List<WString> StringList;
typedef collections::Dictionary<WString, WString> HeaderMap;
public:
/// <summary>Name of the server, like "gaclib.net".</summary>
WString server;
/// <summary>Port of the server, like 80.</summary>
vint port;
/// <summary>Query of the request, like "/GettingStart.html".</summary>
WString query;
/// <summary>Set to true if the request uses SSL.</summary>
bool secure;
/// <summary>User name to authorize. Set to empty if you don't want to provide it.</summary>
WString username;
/// <summary>Password to authorize. Set to empty if you don't want to provide it.</summary>
WString password;
/// <summary>HTTP method, like "GET", "POST", "PUT", "DELETE", etc.</summary>
WString method;
/// <summary>Cookie. Set to empty if you don't want to provide it.</summary>
WString cookie;
/// <summary>Request body. This is a binary array using an array container to char.</summary>
BodyBuffer body;
/// <summary>Content type, like "text/xml".</summary>
WString contentType;
/// <summary>Accept type list, elements of it like "text/xml".</summary>
StringList acceptTypes;
/// <summary>A dictionary to contain extra headers.</summary>
HeaderMap extraHeaders;
/// <summary>Create an empty request.</summary>
HttpRequest();
/// <summary>Set <see cref="server"/>, <see cref="port"/>, <see cref="query"/> and <see cref="secure"/> fields for you using an URL.</summary>
/// <returns>Returns true if this operation succeeded.</returns>
/// <param name="inputQuery">The URL.</param>
bool SetHost(const WString& inputQuery);
/// <summary>Fill the body with a text using UTF-8 encoding.</summary>
/// <param name="bodyString">The text to fill.</param>
void SetBodyUtf8(const WString& bodyString);
};
/// <summary>A type representing an http response.</summary>
class HttpResponse
{
typedef collections::Array<char> BodyBuffer;
public:
/// <summary>Status code, like 200.</summary>
vint statusCode;
/// <summary>Response body. This is a binary array using an array container to char.</summary>
BodyBuffer body;
/// <summary>Returned cookie from the server.</summary>
WString cookie;
HttpResponse();
/// <summary>If you believe the server returns a text in UTF-8, use it to decode the body.</summary>
/// <returns>The response body as text.</returns>
WString GetBodyUtf8();
};
/// <summary>Send an http request and receive a response.</summary>
/// <returns>Returns true if this operation succeeded. Even the server returns 404 will be treated as success, because you get the response.</returns>
/// <param name="request">The request.</param>
/// <param name="response">The response.</param>
extern bool HttpQuery(const HttpRequest& request, HttpResponse& response);
/// <summary>Encode a text as part of the url. This function can be used to create arguments in an URL.</summary>
/// <returns>The encoded text.</returns>
/// <param name="query">The text to encode.</param>
extern WString UrlEncodeQuery(const WString& query);
}
#endif
#endif
/***********************************************************************
.\COLLECTIONS\PARTIALORDERING.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Data Structure::Partial Ordering
***********************************************************************/
#ifndef VCZH_COLLECTIONS_PARTIALORDERING
#define VCZH_COLLECTIONS_PARTIALORDERING
namespace vl
{
namespace collections
{
/***********************************************************************
Partial Ordering
***********************************************************************/
namespace po
{
struct Node
{
bool visited = false;
vint component = -1;
const List<vint>* ins = nullptr; // all nodes that this node depends on
const List<vint>* outs = nullptr; // all nodes that depend on this node
const vint* firstSubClassItem = nullptr; // index of the first item in this sub class node
vint subClassItemCount = 0; // the number of items in this sub class node
};
struct Component
{
const vint* firstNode = nullptr;
vint nodeCount = 0;
};
}
}
namespace collections
{
/// <summary>
/// Partial ordering item sorter.
/// This class sorts items in a partial order using the given dependency information.
/// Node stored in this class using the index of items.
/// If a depends on b, then a.ins->Contains(b) &amp;&amp; b.outs->Contains(a).
/// The sorting result is a list of strong connected components in order.
/// If a depends on b, then the component containing a appears after the component containing b.
/// Node could represent a sub class if InitWithSubClass is called.
/// </summary>
class PartialOrderingProcessor : public Object
{
template<typename TList>
using GroupOf = Group<typename TList::ElementType, typename TList::ElementType>;
protected:
List<vint> emptyList;
Group<vint, vint> ins;
Group<vint, vint> outs;
Array<vint> firstNodesBuffer;
Array<vint> subClassItemsBuffer;
void InitNodes(vint itemCount);
void VisitUnvisitedNode(po::Node& node, Array<vint>& reversedOrder, vint& used);
void AssignUnassignedNode(po::Node& node, vint componentIndex, vint& used);
public:
/// <summary>Nodes.</summary>
Array<po::Node> nodes;
/// <summary>Strong connected components in order.</summary>
List<po::Component> components;
/// <summary>Sort. This method can only be called once.</summary>
void Sort();
/// <summary>Initialize the processor, specifying dependency relationships as a group.</summary>
/// <typeparam name="TList">Type of the first parameter.</typeparam>
/// <param name="items">Items.</param>
/// <param name="depGroup">Dependences. If a depends on b, then depGroups[a].Contains(b) == true.</param>
template<typename TList>
void InitWithGroup(const TList& items, const GroupOf<TList>& depGroup)
{
CHECK_ERROR(nodes.Count() == 0, L"PartialOrdering::InitWithGroup(items, depGroup)#Initializing twice is not allowed.");
for (vint i = 0; i < depGroup.Count(); i++)
{
vint fromNode = items.IndexOf(KeyType<typename TList::ElementType>::GetKeyValue(depGroup.Keys()[i]));
CHECK_ERROR(fromNode != -1, L"PartialOrdering::InitWithGroup(items, depGroup)#The key in outsGroup does not exist in items.");
auto& edges = depGroup.GetByIndex(i);
for (vint j = 0; j < edges.Count(); j++)
{
vint toNode = items.IndexOf(KeyType<typename TList::ElementType>::GetKeyValue(edges[j]));
CHECK_ERROR(toNode != -1, L"PartialOrdering::InitWithGroup(items, depGroup)#The value in outsGroup does not exist in items.");
ins.Add(fromNode, toNode);
outs.Add(toNode, fromNode);
}
}
InitNodes(items.Count());
}
/// <summary>Initialize the processor, specifying dependency relationships as a callback function.</summary>
/// <typeparam name="TList">Type of the first parameter.</typeparam>
/// <typeparam name="TFunc">Type of the second parameter.</typeparam>
/// <param name="items">Items.</param>
/// <param name="depFunc">Dependences. If a depends on b, then depFunc(a, b) == true.</param>
template<typename TList, typename TFunc>
void InitWithFunc(const TList& items, TFunc&& depFunc)
{
GroupOf<TList> depGroup;
for (vint i = 0; i < items.Count(); i++)
{
for (vint j = 0; j < items.Count(); j++)
{
if (depFunc(items[i], items[j]))
{
depGroup.Add(items[i], items[j]);
}
}
}
InitWithGroup(items, depGroup);
}
/// <summary>Initialize the processor, specifying dependency relationships and sub class classification as two groups.</summary>
/// <typeparam name="TList">Type of the first parameter.</typeparam>
/// <typeparam name="TSubClass">Type of the sub class.</typeparam>
/// <param name="items">Items.</param>
/// <param name="depGroup">Dependences. If a depends on b, then depGroups[a].Contains(b) == true.</param>
/// <param name="subClasses">To put multiple items in a node to represent a sub class, use these items as keys, use a unique value as a value, and put them in subClasses.</param>
template<typename TList, typename TSubClass>
void InitWithSubClass(const TList& items, const GroupOf<TList>& depGroup, const Dictionary<typename TList::ElementType, TSubClass>& subClasses)
{
CHECK_ERROR(nodes.Count() == 0, L"PartialOrdering::InitWithSubClass(items, degGroup, subClasses)#Initializing twice is not allowed.");
using ElementType = typename TList::ElementType;
using ElementKeyType = KeyType<ElementType>;
Group<TSubClass, ElementType> scItems;
SortedList<ElementType> singleItems;
for (vint i = 0; i < subClasses.Count(); i++)
{
const auto& key = subClasses.Keys()[i];
const auto& value = subClasses.Values()[i];
scItems.Add(value, key);
}
for (vint i = 0; i < items.Count(); i++)
{
const auto& item = items[i];
if (!subClasses.Keys().Contains(ElementKeyType::GetKeyValue(item)))
{
singleItems.Add(item);
}
}
auto getSubClass = [&](const ElementType& item)
{
vint index = subClasses.Keys().IndexOf(ElementKeyType::GetKeyValue(item));
if (index != -1)
{
index = scItems.Keys().IndexOf(KeyType<TSubClass>::GetKeyValue(subClasses.Values()[index]));
CHECK_ERROR(index != -1, L"PartialOrdering::InitWithSubClass(items, degGroup, subClasses)#Internal Error.");
return index;
}
else
{
index = singleItems.IndexOf(ElementKeyType::GetKeyValue(item));
CHECK_ERROR(index != -1, L"PartialOrdering::InitWithSubClass(items, degGroup, subClasses)#Internal Error.");
return scItems.Count() + index;
}
};
for (vint i = 0; i < depGroup.Count(); i++)
{
const auto& key = depGroup.Keys()[i];
vint keyIndex = getSubClass(key);
const auto& values = depGroup.GetByIndex(i);
for (vint j = 0; j < values.Count(); j++)
{
const auto& value = values[j];
vint valueIndex = getSubClass(value);
if (!ins.Contains(keyIndex, valueIndex))
{
ins.Add(keyIndex, valueIndex);
}
}
}
for (vint i = 0; i < ins.Count(); i++)
{
vint key = ins.Keys()[i];
const auto& values = ins.GetByIndex(i);
for (vint j = 0; j < values.Count(); j++)
{
outs.Add(values[j], key);
}
}
InitNodes(scItems.Count() + singleItems.Count());
subClassItemsBuffer.Resize(items.Count());
vint used = 0;
vint scItemCount = scItems.Keys().Count();
for (vint i = 0; i < nodes.Count(); i++)
{
auto& node = nodes[i];
node.firstSubClassItem = &subClassItemsBuffer[used];
if (i < scItemCount)
{
const auto& values = scItems.GetByIndex(i);
for (vint j = 0; j < values.Count(); j++)
{
subClassItemsBuffer[used++] = items.IndexOf(ElementKeyType::GetKeyValue(values[j]));
}
node.subClassItemCount = values.Count();
}
else
{
subClassItemsBuffer[used++] = items.IndexOf(ElementKeyType::GetKeyValue(singleItems[i - scItemCount]));
node.subClassItemCount = 1;
}
}
}
};
}
}
#endif
/***********************************************************************
.\PARSING\JSON\PARSINGJSON.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingJson_Parser
***********************************************************************/
#ifndef VCZH_PARSING_JSON_PARSINGJSON
#define VCZH_PARSING_JSON_PARSINGJSON
namespace vl
{
namespace parsing
{
namespace json
{
extern void JsonEscapeString(const WString& text, stream::TextWriter& writer);
extern void JsonUnescapeString(const WString& text, stream::TextWriter& writer);
extern void JsonPrint(Ptr<JsonNode> node, stream::TextWriter& writer);
extern WString JsonToString(Ptr<JsonNode> node);
}
}
}
#endif
/***********************************************************************
.\PARSING\XML\PARSINGXML.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Parser::ParsingXml
***********************************************************************/
#ifndef VCZH_PARSING_XML_PARSINGXML
#define VCZH_PARSING_XML_PARSINGXML
namespace vl
{
namespace parsing
{
namespace xml
{
extern WString XmlEscapeValue(const WString& value);
extern WString XmlUnescapeValue(const WString& value);
extern WString XmlEscapeCData(const WString& value);
extern WString XmlUnescapeCData(const WString& value);
extern WString XmlEscapeComment(const WString& value);
extern WString XmlUnescapeComment(const WString& value);
extern void XmlPrint(Ptr<XmlNode> node, stream::TextWriter& writer);
extern void XmlPrintContent(Ptr<XmlElement> element, stream::TextWriter& writer);
extern WString XmlToString(Ptr<XmlNode> node);
extern Ptr<XmlAttribute> XmlGetAttribute(Ptr<XmlElement> element, const WString& name);
extern Ptr<XmlElement> XmlGetElement(Ptr<XmlElement> element, const WString& name);
extern collections::LazyList<Ptr<XmlElement>> XmlGetElements(Ptr<XmlElement> element);
extern collections::LazyList<Ptr<XmlElement>> XmlGetElements(Ptr<XmlElement> element, const WString& name);
extern WString XmlGetValue(Ptr<XmlElement> element);
extern Ptr<XmlAttribute> XmlGetAttribute(XmlElement* element, const WString& name);
extern Ptr<XmlElement> XmlGetElement(XmlElement* element, const WString& name);
extern collections::LazyList<Ptr<XmlElement>> XmlGetElements(XmlElement* element);
extern collections::LazyList<Ptr<XmlElement>> XmlGetElements(XmlElement* element, const WString& name);
extern WString XmlGetValue(XmlElement* element);
class XmlElementWriter : public Object
{
protected:
Ptr<XmlElement> element;
const XmlElementWriter* previousWriter;
public:
XmlElementWriter(Ptr<XmlElement> _element, const XmlElementWriter* _previousWriter=0);
~XmlElementWriter();
const XmlElementWriter& Attribute(const WString& name, const WString& value)const;
XmlElementWriter Element(const WString& name)const;
const XmlElementWriter& End()const;
const XmlElementWriter& Text(const WString& value)const;
const XmlElementWriter& CData(const WString& value)const;
const XmlElementWriter& Comment(const WString& value)const;
};
}
}
}
#endif
/***********************************************************************
.\REGEX\REGEXPURE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::RegexInterpretor
Classes:
PureInterpretor : Pure regular expression interpretor
***********************************************************************/
#ifndef VCZH_REGEX_REGEXPURE
#define VCZH_REGEX_REGEXPURE
namespace vl
{
namespace regex_internal
{
class PureResult
{
public:
vint start;
vint length;
vint finalState;
vint terminateState;
};
class PureInterpretor : public Object
{
protected:
#if defined VCZH_MSVC
static const vint SupportedCharCount = 0x10000; // UTF-16
#elif defined VCZH_GCC
static const vint SupportedCharCount = 0x110000; // UTF-32
#endif
vint charMap[SupportedCharCount]; // char -> char set index
vint** transition; // (state * char set index) -> state*
bool* finalState; // state -> bool
vint* relatedFinalState; // sate -> (finalState or -1)
vint stateCount;
vint charSetCount;
vint startState;
public:
PureInterpretor(Automaton::Ref dfa, CharRange::List& subsets);
~PureInterpretor();
bool MatchHead(const wchar_t* input, const wchar_t* start, PureResult& result);
bool Match(const wchar_t* input, const wchar_t* start, PureResult& result);
vint GetStartState();
vint Transit(wchar_t input, vint state);
bool IsFinalState(vint state);
bool IsDeadState(vint state);
void PrepareForRelatedFinalStateTable();
vint GetRelatedFinalState(vint state);
};
}
}
#endif
/***********************************************************************
.\REGEX\REGEXRICH.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::RegexInterpretor
Classes:
RichInterpretor : Rich regular expression interpretor
***********************************************************************/
#ifndef VCZH_REGEX_REGEXRICH
#define VCZH_REGEX_REGEXRICH
namespace vl
{
namespace regex_internal
{
class CaptureRecord
{
public:
vint capture;
vint start;
vint length;
bool operator==(const CaptureRecord& record)const;
};
}
template<>
struct POD<regex_internal::CaptureRecord>
{
static const bool Result=true;
};
namespace regex_internal
{
class RichResult
{
public:
vint start;
vint length;
collections::List<CaptureRecord> captures;
};
class RichInterpretor : public Object
{
public:
protected:
class UserData
{
public:
bool NeedKeepState;
};
Automaton::Ref dfa;
UserData* datas;
public:
RichInterpretor(Automaton::Ref _dfa);
~RichInterpretor();
bool MatchHead(const wchar_t* input, const wchar_t* start, RichResult& result);
bool Match(const wchar_t* input, const wchar_t* start, RichResult& result);
const collections::List<WString>& CaptureNames();
};
};
}
#endif
/***********************************************************************
.\REGEX\REGEXWRITER.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Regex::RegexWriter
Classes:
***********************************************************************/
#ifndef VCZH_REGEX_REGEXWRITER
#define VCZH_REGEX_REGEXWRITER
namespace vl
{
namespace regex
{
class RegexNode : public Object
{
public:
vl::regex_internal::Expression::Ref expression;
RegexNode(vl::regex_internal::Expression::Ref _expression);
RegexNode Some()const;
RegexNode Any()const;
RegexNode Opt()const;
RegexNode Loop(vint min, vint max)const;
RegexNode AtLeast(vint min)const;
RegexNode operator+(const RegexNode& node)const;
RegexNode operator|(const RegexNode& node)const;
RegexNode operator+()const;
RegexNode operator-()const;
RegexNode operator!()const;
RegexNode operator%(const RegexNode& node)const;
};
extern RegexNode rCapture(const WString& name, const RegexNode& node);
extern RegexNode rUsing(const WString& name);
extern RegexNode rMatch(const WString& name, vint index=-1);
extern RegexNode rMatch(vint index);
extern RegexNode rBegin();
extern RegexNode rEnd();
extern RegexNode rC(wchar_t a, wchar_t b=L'\0');
extern RegexNode r_d();
extern RegexNode r_l();
extern RegexNode r_w();
extern RegexNode rAnyChar();
}
}
#endif
/***********************************************************************
.\STREAM\BROADCASTSTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::BroadcastStream
Interfaces:
BroadcastStream : Stream that copy the written data to multiple streams
***********************************************************************/
#ifndef VCZH_STREAM_BROADCASTSTREAM
#define VCZH_STREAM_BROADCASTSTREAM
namespace vl
{
namespace stream
{
/// <summary>A writable stream that copy written content to multiple target streams.</summary>
class BroadcastStream : public Object, public virtual IStream
{
typedef collections::List<IStream*> StreamList;
protected:
bool closed;
pos_t position;
StreamList streams;
public:
/// <summary>Create a strema.</summary>
BroadcastStream();
~BroadcastStream();
/// <summary>Get the list of target streams. You can add streams to this list, or remove streams from this list.</summary>
/// <returns>The list of target streams.</returns>
StreamList& Targets();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
}
}
#endif
/***********************************************************************
.\STREAM\CACHESTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::CacheStream
Interfaces:
CacheStream : Stream that provide a cache for reading and writing
***********************************************************************/
#ifndef VCZH_STREAM_CACHESTREAM
#define VCZH_STREAM_CACHESTREAM
namespace vl
{
namespace stream
{
/// <summary>
/// A cache stream. Features (readable, writable, seekable, peekable) are enabled according to the target stream.
/// When you read from the cache strema, it will read a specified size of content from the target stream first and cache, reducing the numbers of operations on the target stream.
/// When you write to the cache strema, it will save them to a buffer, and write to the target stream until the buffer reaches a specified size, reducing the numbers of operations on the target stream.
/// </summary>
class CacheStream : public Object, public virtual IStream
{
protected:
IStream* target;
vint block;
pos_t start;
pos_t position;
char* buffer;
vint dirtyStart;
vint dirtyLength;
vint availableLength;
pos_t operatedSize;
void Flush();
void Load(pos_t _position);
vint InternalRead(void* _buffer, vint _size);
vint InternalWrite(void* _buffer, vint _size);
public:
/// <summary>Create a cache stream using a target stream.</summary>
/// <param name="_target">The target stream.</param>
/// <param name="_block">Size of the cache.</param>
CacheStream(IStream& _target, vint _block=65536);
~CacheStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
}
}
#endif
/***********************************************************************
.\STREAM\RECORDERSTREAM.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Stream::RecorderStream
Interfaces:
RecorderStream : A readable stream that will copy the data to another stream on the fly
***********************************************************************/
#ifndef VCZH_STREAM_RECORDERSTREAM
#define VCZH_STREAM_RECORDERSTREAM
namespace vl
{
namespace stream
{
/// <summary>A readable stream that, read from an stream, and write everything that is read to another stream.</summary>
class RecorderStream : public Object, public virtual IStream
{
protected:
IStream* in;
IStream* out;
public:
/// <summary>Create a stream.</summary>
/// <param name="_in">The stream to read.</param>
/// <param name="_out">The stream to write what is read from "_in".</param>
RecorderStream(IStream& _in, IStream& _out);
~RecorderStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
}
}
#endif
/***********************************************************************
.\UNITTEST\UNITTEST.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
UI::Console
***********************************************************************/
#ifndef VCZH_UNITTEST
#define VCZH_UNITTEST
class UnitTestError
{
};
namespace vl
{
namespace unittest
{
/// <summary><![CDATA[
/// A static class containing all unit test operations. In order to run test cases, you should do the following:
/// 1) Write test cases in cpp files like this
/// TEST_CASE(<Name of the test case, which should be a legal C++ identifier>)
/// {
/// <Use TEST_ASSERT(condition) to test>
/// <Use TEST_ERROR(expression) if you know "expression" will cause a fatal error by using the CHECK_ERROR macro.>
/// <Use TEST_EXCEPTION(expression, exceptionType, assertFunction) if you know "expression" will throw an expression of "exceptionType", and then you can provide "assertFunction" to check the information provided in the exception.>
/// <Use TEST_PRINT(message) to print whatever to the command line window.>
/// }
/// You should call [M:vl.unittest.UnitTest.RunAndDisposeTests] in your main function to run all test cases.
/// ]]></summary>
class UnitTest abstract
{
public:
typedef void(*TestProc)();
/// <summary>Print a green message.</summary>
/// <param name="string">The content.</param>
static void PrintMessage(const WString& string);
/// <summary>Print a white information.</summary>
/// <param name="string">The content.</param>
static void PrintInfo(const WString& string);
/// <summary>Print a red error.</summary>
/// <param name="string">The content.</param>
static void PrintError(const WString& string);
static void PushTest(TestProc testProc);
/// <summary>Run all test cases.</summary>
static void RunAndDisposeTests();
};
#define TEST_CHECK_ERROR(CONDITION,DESCRIPTION) do{if(!(CONDITION))throw Error(DESCRIPTION);}while(0)
#define TEST_ASSERT(CONDITION) do{TEST_CHECK_ERROR(CONDITION,L"");}while(0)
#define TEST_ERROR(CONDITION) do{try{CONDITION;throw UnitTestError();}catch(const Error&){}catch(const UnitTestError&){TEST_CHECK_ERROR(false,L"");}}while(0)
#define TEST_CASE(NAME)\
extern void TESTCASE_##NAME(); \
namespace vl_unittest_executors \
{ \
class TESTCASE_RUNNER_##NAME \
{ \
public: \
static void RunUnitTest() \
{ \
vl::unittest::UnitTest::PrintMessage(L_(#NAME)); \
TESTCASE_##NAME(); \
} \
TESTCASE_RUNNER_##NAME() \
{ \
vl::unittest::UnitTest::PushTest(&TESTCASE_RUNNER_##NAME::RunUnitTest); \
} \
} TESTCASE_RUNNER_##NAME##_INSTANCE; \
} \
void TESTCASE_##NAME()
#define TEST_PRINT(x) vl::unittest::UnitTest::PrintInfo(x)
#define TEST_EXCEPTION(STATEMENT,EXCEPTION,ASSERT_FUNCTION) try{STATEMENT; TEST_ASSERT(false);}catch(const EXCEPTION& e){ASSERT_FUNCTION(e);}
}
}
#endif
/***********************************************************************
.\LAZY.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Lazy Evaluation
Classes:
Lazy<T> : Object with lazy evaluation
***********************************************************************/
#ifndef VCZH_LAZY
#define VCZH_LAZY
namespace vl
{
/// <summary>A type representing a lazy evaluation.</summary>
/// <typeparam name="T">The type of the evaluation result.</typeparam>
template<typename T>
class Lazy : public Object
{
protected:
class Internal
{
public:
Func<T()> evaluator;
T value;
bool evaluated;
};
Ptr<Internal> internalValue;
public:
/// <summary>Create an empty evaluation.</summary>
Lazy()
{
}
/// <summary>Create an evaluation using a function.</summary>
/// <param name="evaluator">The function.</param>
Lazy(const Func<T()>& evaluator)
{
internalValue=new Internal;
internalValue->evaluated=false;
internalValue->evaluator=evaluator;
}
/// <summary>Create an evaluation using the result directly.</summary>
/// <param name="value">The result that you have already known.</param>0
Lazy(const T& value)
{
internalValue=new Internal;
internalValue->evaluated=true;
internalValue->value=value;
}
/// <summary>Copy an evaluation.</summary>
/// <param name="lazy">The evaluation to copy.</param>
Lazy(const Lazy<T>& lazy)
:internalValue(lazy.internalValue)
{
}
Lazy<T>& operator=(const Func<T()>& evaluator)
{
internalValue=new Internal;
internalValue->evaluated=false;
internalValue->evaluator=evaluator;
return *this;
}
Lazy<T>& operator=(const T& value)
{
internalValue=new Internal;
internalValue->evaluated=true;
internalValue->value=value;
return *this;
}
Lazy<T>& operator=(const Lazy<T>& lazy)
{
internalValue=lazy.internalValue;
return *this;
}
/// <summary>Get the evaluation result. If it has not been calculated yet, it will run the evaluation and cache the result. You will not need to calculate for the second time.</summary>
/// <returns>The evaluation result.</returns>
const T& Value()const
{
if(!internalValue->evaluated)
{
internalValue->evaluated=true;
internalValue->value=internalValue->evaluator();
internalValue->evaluator=Func<T()>();
}
return internalValue->value;
}
/// <summary>Test if it has already been evaluated or not.</summary>
/// <returns>Returns true if it has already been evaluated.</returns>
const bool IsEvaluated()const
{
return internalValue->evaluated;
}
/// <summary>Test if it is an empty evaluation or not.</summary>
/// <returns>Returns true if it is not empty.</returns>
const bool IsAvailable()const
{
return internalValue;
}
};
}
#endif
/***********************************************************************
.\TUPLE.H
***********************************************************************/
/***********************************************************************
Vczh Library++ 3.0
Developer: Zihan Chen(vczh)
Framework::Tuple
This file is generated by: Vczh Functional Macro
***********************************************************************/
#ifndef VCZH_TUPLE
#define VCZH_TUPLE
namespace vl
{
class TupleNullItem
{
};
template<typename T0 = TupleNullItem,typename T1 = TupleNullItem,typename T2 = TupleNullItem,typename T3 = TupleNullItem,typename T4 = TupleNullItem,typename T5 = TupleNullItem,typename T6 = TupleNullItem,typename T7 = TupleNullItem,typename T8 = TupleNullItem,typename T9 = TupleNullItem,typename T10 = TupleNullItem>
class Tuple
{
};
/***********************************************************************
vl::Tuple<T0>
***********************************************************************/
template<typename T0>
class Tuple<T0> : public Object
{
public:
T0 f0;
Tuple()
{
}
Tuple(T0 p0)
:f0(p0)
{
}
static int Compare(const Tuple<T0>& a, const Tuple<T0>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;
return 0;
}
bool operator==(const Tuple<T0>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1>
***********************************************************************/
template<typename T0,typename T1>
class Tuple<T0,T1> : public Object
{
public:
T0 f0;T1 f1;
Tuple()
{
}
Tuple(T0 p0,T1 p1)
:f0(p0),f1(p1)
{
}
static int Compare(const Tuple<T0,T1>& a, const Tuple<T0,T1>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2>
***********************************************************************/
template<typename T0,typename T1,typename T2>
class Tuple<T0,T1,T2> : public Object
{
public:
T0 f0;T1 f1;T2 f2;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2)
:f0(p0),f1(p1),f2(p2)
{
}
static int Compare(const Tuple<T0,T1,T2>& a, const Tuple<T0,T1,T2>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3>
class Tuple<T0,T1,T2,T3> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3)
:f0(p0),f1(p1),f2(p2),f3(p3)
{
}
static int Compare(const Tuple<T0,T1,T2,T3>& a, const Tuple<T0,T1,T2,T3>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3,T4>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3,typename T4>
class Tuple<T0,T1,T2,T3,T4> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;T4 f4;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3,T4 p4)
:f0(p0),f1(p1),f2(p2),f3(p3),f4(p4)
{
}
static int Compare(const Tuple<T0,T1,T2,T3,T4>& a, const Tuple<T0,T1,T2,T3,T4>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;if (a.f4 < b.f4) return -1; else if (a.f4 > b.f4) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3,T4>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3,T4>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3,T4>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3,T4>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3,T4>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3,T4>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3,T4,T5>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5>
class Tuple<T0,T1,T2,T3,T4,T5> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;T4 f4;T5 f5;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3,T4 p4,T5 p5)
:f0(p0),f1(p1),f2(p2),f3(p3),f4(p4),f5(p5)
{
}
static int Compare(const Tuple<T0,T1,T2,T3,T4,T5>& a, const Tuple<T0,T1,T2,T3,T4,T5>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;if (a.f4 < b.f4) return -1; else if (a.f4 > b.f4) return 1;if (a.f5 < b.f5) return -1; else if (a.f5 > b.f5) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3,T4,T5>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3,T4,T5>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3,T4,T5>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3,T4,T5>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3,T4,T5>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3,T4,T5>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3,T4,T5,T6>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6>
class Tuple<T0,T1,T2,T3,T4,T5,T6> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;T4 f4;T5 f5;T6 f6;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3,T4 p4,T5 p5,T6 p6)
:f0(p0),f1(p1),f2(p2),f3(p3),f4(p4),f5(p5),f6(p6)
{
}
static int Compare(const Tuple<T0,T1,T2,T3,T4,T5,T6>& a, const Tuple<T0,T1,T2,T3,T4,T5,T6>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;if (a.f4 < b.f4) return -1; else if (a.f4 > b.f4) return 1;if (a.f5 < b.f5) return -1; else if (a.f5 > b.f5) return 1;if (a.f6 < b.f6) return -1; else if (a.f6 > b.f6) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3,T4,T5,T6>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3,T4,T5,T6>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3,T4,T5,T6>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3,T4,T5,T6>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3,T4,T5,T6>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3,T4,T5,T6>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3,T4,T5,T6,T7>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7>
class Tuple<T0,T1,T2,T3,T4,T5,T6,T7> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;T4 f4;T5 f5;T6 f6;T7 f7;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3,T4 p4,T5 p5,T6 p6,T7 p7)
:f0(p0),f1(p1),f2(p2),f3(p3),f4(p4),f5(p5),f6(p6),f7(p7)
{
}
static int Compare(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& a, const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;if (a.f4 < b.f4) return -1; else if (a.f4 > b.f4) return 1;if (a.f5 < b.f5) return -1; else if (a.f5 > b.f5) return 1;if (a.f6 < b.f6) return -1; else if (a.f6 > b.f6) return 1;if (a.f7 < b.f7) return -1; else if (a.f7 > b.f7) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7,typename T8>
class Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;T4 f4;T5 f5;T6 f6;T7 f7;T8 f8;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3,T4 p4,T5 p5,T6 p6,T7 p7,T8 p8)
:f0(p0),f1(p1),f2(p2),f3(p3),f4(p4),f5(p5),f6(p6),f7(p7),f8(p8)
{
}
static int Compare(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& a, const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;if (a.f4 < b.f4) return -1; else if (a.f4 > b.f4) return 1;if (a.f5 < b.f5) return -1; else if (a.f5 > b.f5) return 1;if (a.f6 < b.f6) return -1; else if (a.f6 > b.f6) return 1;if (a.f7 < b.f7) return -1; else if (a.f7 > b.f7) return 1;if (a.f8 < b.f8) return -1; else if (a.f8 > b.f8) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>& value)const{ return Compare(*this, value) >= 0; }
};
/***********************************************************************
vl::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
***********************************************************************/
template<typename T0,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7,typename T8,typename T9>
class Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> : public Object
{
public:
T0 f0;T1 f1;T2 f2;T3 f3;T4 f4;T5 f5;T6 f6;T7 f7;T8 f8;T9 f9;
Tuple()
{
}
Tuple(T0 p0,T1 p1,T2 p2,T3 p3,T4 p4,T5 p5,T6 p6,T7 p7,T8 p8,T9 p9)
:f0(p0),f1(p1),f2(p2),f3(p3),f4(p4),f5(p5),f6(p6),f7(p7),f8(p8),f9(p9)
{
}
static int Compare(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& a, const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& b)
{
if (a.f0 < b.f0) return -1; else if (a.f0 > b.f0) return 1;if (a.f1 < b.f1) return -1; else if (a.f1 > b.f1) return 1;if (a.f2 < b.f2) return -1; else if (a.f2 > b.f2) return 1;if (a.f3 < b.f3) return -1; else if (a.f3 > b.f3) return 1;if (a.f4 < b.f4) return -1; else if (a.f4 > b.f4) return 1;if (a.f5 < b.f5) return -1; else if (a.f5 > b.f5) return 1;if (a.f6 < b.f6) return -1; else if (a.f6 > b.f6) return 1;if (a.f7 < b.f7) return -1; else if (a.f7 > b.f7) return 1;if (a.f8 < b.f8) return -1; else if (a.f8 > b.f8) return 1;if (a.f9 < b.f9) return -1; else if (a.f9 > b.f9) return 1;
return 0;
}
bool operator==(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& value)const{ return Compare(*this, value) == 0; }
bool operator!=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& value)const{ return Compare(*this, value) != 0; }
bool operator< (const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& value)const{ return Compare(*this, value) < 0; }
bool operator<=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& value)const{ return Compare(*this, value) <= 0; }
bool operator> (const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& value)const{ return Compare(*this, value) > 0; }
bool operator>=(const Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>& value)const{ return Compare(*this, value) >= 0; }
};
}
#endif