/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "Vlpp.h"

/***********************************************************************
.\HTTPUTILITY.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_HTTPUTILITY
#define VCZH_HTTPUTILITY


#ifdef VCZH_MSVC

namespace vl
{

/***********************************************************************
HTTP Utility
***********************************************************************/

	/// <summary>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 = 0;
		/// <summary>Query of the request, like "/index.html".</summary>
		WString				query;
		/// <summary>Set to true if the request uses SSL, or https.</summary>
		bool				secure = false;
		/// <summary>User name to authorize. Set to empty if authorization is not needed.</summary>
		WString				username;
		/// <summary>Password to authorize. Set to empty if authorization is not needed.</summary>
		WString				password;
		/// <summary>HTTP method, like "GET", "POST", "PUT", "DELETE", etc.</summary>
		WString				method;
		/// <summary>Cookie. Set to empty if cookie is not needed.</summary>
		WString				cookie;
		/// <summary>Request body. This is a byte array.</summary>
		BodyBuffer			body;
		/// <summary>Content type, like "text/xml".</summary>
		WString				contentType;
		/// <summary>Accept type list, elements like "text/xml".</summary>
		StringList			acceptTypes;
		/// <summary>A dictionary to contain extra headers.</summary>
		HeaderMap			extraHeaders;

		/// <summary>Create an empty request.</summary>
		HttpRequest() = default;

		/// <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 text body in UTF-8.</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 = 0;
		/// <summary>Response body. This is a byte array.</summary>
		BodyBuffer			body;
		/// <summary>Returned cookie from the server.</summary>
		WString				cookie;

		HttpResponse() = default;

		/// <summary>Get the text body, encoding is assumed to be UTF-8.</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 when the server returns 404.</returns>
	/// <param name="request">The request to send.</param>
	/// <param name="response">Returns the response.</param>
	/// <remarks>
	/// <p>
	/// This function will block the calling thread until the respons is returned.
	/// </p>
	/// <p>
	/// This function is only available in Windows.
	/// </p>
	/// </remarks>
	/// <example><![CDATA[
	/// int main()
	/// {
	///     HttpRequest request;
	///     HttpResponse response;
	///     request.SetHost(L"http://www.msftncsi.com/ncsi.txt");
	///     HttpQuery(request, response);
	///     Console::WriteLine(L"Status:" + itow(response.statusCode));
	///     Console::WriteLine(L"Body:" + response.GetBodyUtf8());
	/// }
	/// ]]></example>
	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>
	/// <remarks>
	/// <p>
	/// When a character is not a digit or a letter,
	/// it is first encoded to UTF-8,
	/// then each byte is written as "%" with two hex digits.
	/// </p>
	/// <p>
	/// This function is only available in Windows.
	/// </p>
	///</remarks>
	extern WString			UrlEncodeQuery(const WString& query);
}

#endif

#endif


/***********************************************************************
.\LOCALE.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_LOCALE
#define VCZH_LOCALE


namespace vl
{
/***********************************************************************
Locale
***********************************************************************/

	/// <summary>Locale awared operations. Macro "INVLOC" is a shortcut to get a invariant locale.</summary>
	/// <remarks>
	/// <p>
	/// For all string operations that the normalization does not set to <b>None</b>,
	/// and all non-string operations,
	/// the result is platform-dependent.
	/// This class is designed to process human-readable text,
	/// do not rely on the result.
	/// </p>
	/// <p>
	/// In Linux and macOS, only en-US is supported, with a hard-coded set of date and time formats,
	/// and string operations only support <b>None</b> and <b>IgnoreCase</b> for normalization.
	/// </p>
	/// </remarks>
	class Locale : public Object
	{
	protected:
		WString						localeName;

	public:
		/// <summary>Create a locale with a specified local name.</summary>
		/// <param name="_localeName">The name of the locale. If it is not provided, it becomes the invariant locale.</param>
		/// <remarks>
		/// In Windows, the specified locale need to be installed in order to take effect.
		/// In Linux and macOS, only en-US is supported.
		/// </remarks>
		Locale() = default;
		Locale(const Locale&) = default;
		Locale(Locale&&) = default;
		~Locale() = default;

		Locale& operator=(const Locale&) = default;
		Locale& operator=(Locale&&) = default;

		Locale(const WString& _localeName);

		std::strong_ordering		operator<=>(const Locale& locale)const { return localeName <=> locale.localeName; }
		bool						operator==(const Locale& locale)const { return localeName == locale.localeName; }

		/// <summary>Get the invariant locale. An invariant locale is neutral, it is not awared of any language specified thing.</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 settings and UI language.</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 this locale.</summary>
		/// <returns>The name of this locale.</returns>
		const WString&				GetName()const;

		/// <summary>Get all short date formats for this locale.</summary>
		/// <param name="formats">Returns all formats.</param>
		void						GetShortDateFormats(collections::List<WString>& formats)const;
		/// <summary>Get all long date formats for this locale.</summary>
		/// <param name="formats">Returns all formats.</param>
		void						GetLongDateFormats(collections::List<WString>& formats)const;
		/// <summary>Get all Year-Month date formats for this locale.</summary>
		/// <param name="formats">Returns all formats.</param>
		void						GetYearMonthDateFormats(collections::List<WString>& formats)const;
		/// <summary>Get all long time formats for this locale.</summary>
		/// <param name="formats">Returns all formats.</param>
		void						GetLongTimeFormats(collections::List<WString>& formats)const;
		/// <summary>Get all short time formats for this locale.</summary>
		/// <param name="formats">Returns all 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>
		/// <remarks>
		/// The value of the "format" argument must come from any of the following functions.
		/// Otherwise the behavior is undefined.
		/// <ul>
		///   <li><see cref="GetShortDateFormats"/></li>
		///   <li><see cref="GetLongDateFormats"/></li>
		///   <li><see cref="GetYearMonthDateFormats"/></li>
		/// </ul>
		/// </remarks>
		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>
		/// <remarks>
		/// The value of the "format" argument must come from any of the following functions.
		/// Otherwise the behavior is undefined.
		/// <ul>
		///   <li><see cref="GetLongTimeFormats"/></li>
		///   <li><see cref="GetShortTimeFormats"/></li>
		/// </ul>
		/// </remarks>
		WString						FormatTime(const WString& format, DateTime time)const;

		/// <summary>Convert a number to a formatted string according to the locale.</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 according to the locale.</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 according to the locale.</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 according to the locale.</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 according to the locale.</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 according to the locale.</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>
		/// <remarks>This function is only available in Windows.</remarks>
		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>
		/// <remarks>This function is only available in Windows.</remarks>
		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>
		/// <remarks>This function is only available in Windows.</remarks>
		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>
		/// <remarks>This function is only available in Windows.</remarks>
		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>
		/// <remarks>This function is only available in Windows.</remarks>
		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>
		/// <remarks>This function is only available in Windows.</remarks>
		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>
		/// <remarks>This function is only available in Windows.</remarks>
		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. This value is only available in Windows.</summary>
			IgnoreCaseLinguistic=2,
			/// <summary>Ignore the difference between between hiragana and katakana characters. This value is only available in Windows.</summary>
			IgnoreKanaType=4,
			/// <summary>Ignore nonspacing characters. This value is only available in Windows.</summary>
			IgnoreNonSpace=8,
			/// <summary>Ignore symbols and punctuation. This value is only available in Windows.</summary>
			IgnoreSymbol=16,
			/// <summary>Ignore the difference between half-width and full-width characters. This value is only available in Windows.</summary>
			IgnoreWidth=32,
			/// <summary>Treat digits as numbers during sorting. This value is only available in Windows.</summary>
			DigitsAsNumbers=64,
			/// <summary>Treat punctuation the same as symbols. This value is only available in Windows.</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.</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>
		/// <remarks>For any normalization that is not <b>None</b>, the found sub string could be different to the string you want to find.</remarks>
		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.</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>
		/// <remarks>For any normalization that is not <b>None</b>, the found sub string could be different to the string you want to find.</remarks>
		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>
		/// <remarks>For any normalization that is not <b>None</b>, the found prefix could be different to the string you want to find.</remarks>
		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>
		/// <remarks>For any normalization that is not <b>None</b>, the postfix could be different to the string you want to find.</remarks>
		bool									EndsWith(const WString& text, const WString& find, Normalization normalization)const;
	};

#define INVLOC vl::Locale::Invariant()

/***********************************************************************
ILocaleImpl
***********************************************************************/

	/// <summary>Platform-specific locale implementation interface.</summary>
	class ILocaleImpl : public virtual feature_injection::IFeatureImpl
	{
	public:
		virtual Locale							Invariant() const = 0;
		virtual Locale							SystemDefault() const = 0;
		virtual Locale							UserDefault() const = 0;
		virtual void							Enumerate(collections::List<Locale>& locales) const = 0;

		virtual void							GetShortDateFormats(const WString& localeName, collections::List<WString>& formats) const = 0;
		virtual void							GetLongDateFormats(const WString& localeName, collections::List<WString>& formats) const = 0;
		virtual void							GetYearMonthDateFormats(const WString& localeName, collections::List<WString>& formats) const = 0;
		virtual void							GetLongTimeFormats(const WString& localeName, collections::List<WString>& formats) const = 0;
		virtual void							GetShortTimeFormats(const WString& localeName, collections::List<WString>& formats) const = 0;

		virtual WString							FormatDate(const WString& localeName, const WString& format, DateTime date) const = 0;
		virtual WString							FormatTime(const WString& localeName, const WString& format, DateTime time) const = 0;
		virtual WString							FormatNumber(const WString& localeName, const WString& number) const = 0;
		virtual WString							FormatCurrency(const WString& localeName, const WString& currency) const = 0;

		virtual WString							GetShortDayOfWeekName(const WString& localeName, vint dayOfWeek) const = 0;
		virtual WString							GetLongDayOfWeekName(const WString& localeName, vint dayOfWeek) const = 0;
		virtual WString							GetShortMonthName(const WString& localeName, vint month) const = 0;
		virtual WString							GetLongMonthName(const WString& localeName, vint month) const = 0;

		virtual WString							ToLower(const WString& localeName, const WString& str) const = 0;
		virtual WString							ToUpper(const WString& localeName, const WString& str) const = 0;
		virtual WString							ToLinguisticLower(const WString& localeName, const WString& str) const = 0;
		virtual WString							ToLinguisticUpper(const WString& localeName, const WString& str) const = 0;

		virtual vint							Compare(const WString& localeName, const WString& s1, const WString& s2, Locale::Normalization normalization) const = 0;
		virtual vint							CompareOrdinal(const WString& s1, const WString& s2) const = 0;
		virtual vint							CompareOrdinalIgnoreCase(const WString& s1, const WString& s2) const = 0;
		virtual collections::Pair<vint, vint>	FindFirst(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const = 0;
		virtual collections::Pair<vint, vint>	FindLast(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const = 0;
		virtual bool							StartsWith(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const = 0;
		virtual bool							EndsWith(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const = 0;
	};
	
	extern void									InjectLocaleImpl(ILocaleImpl* impl);
	extern void									EjectLocaleImpl(ILocaleImpl* impl);

/***********************************************************************
EnUsLocaleImpl
***********************************************************************/

	/// <summary>A platform independent implementation that only supports en-US.</summary>
	class EnUsLocaleImpl : public feature_injection::FeatureImpl<ILocaleImpl>
	{
	public:
		Locale									Invariant() const override;
		Locale									SystemDefault() const override;
		Locale									UserDefault() const override;
		void									Enumerate(collections::List<Locale>& locales) const override;

		void									GetShortDateFormats(const WString& localeName, collections::List<WString>& formats) const override;
		void									GetLongDateFormats(const WString& localeName, collections::List<WString>& formats) const override;
		void									GetYearMonthDateFormats(const WString& localeName, collections::List<WString>& formats) const override;
		void									GetLongTimeFormats(const WString& localeName, collections::List<WString>& formats) const override;
		void									GetShortTimeFormats(const WString& localeName, collections::List<WString>& formats) const override;

		WString									FormatDate(const WString& localeName, const WString& format, DateTime date) const override;
		WString									FormatTime(const WString& localeName, const WString& format, DateTime time) const override;
		WString									FormatNumber(const WString& localeName, const WString& number) const override;
		WString									FormatCurrency(const WString& localeName, const WString& currency) const override;

		WString									GetShortDayOfWeekName(const WString& localeName, vint dayOfWeek) const override;
		WString									GetLongDayOfWeekName(const WString& localeName, vint dayOfWeek) const override;
		WString									GetShortMonthName(const WString& localeName, vint month) const override;
		WString									GetLongMonthName(const WString& localeName, vint month) const override;

		WString									ToLower(const WString& localeName, const WString& str) const override;
		WString									ToUpper(const WString& localeName, const WString& str) const override;
		WString									ToLinguisticLower(const WString& localeName, const WString& str) const override;
		WString									ToLinguisticUpper(const WString& localeName, const WString& str) const override;

		vint									Compare(const WString& localeName, const WString& s1, const WString& s2, Locale::Normalization normalization) const override;
		vint									CompareOrdinal(const WString& s1, const WString& s2) const override;
		vint									CompareOrdinalIgnoreCase(const WString& s1, const WString& s2) const override;
		collections::Pair<vint, vint>			FindFirst(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override;
		collections::Pair<vint, vint>			FindLast(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override;
		bool									StartsWith(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override;
		bool									EndsWith(const WString& localeName, const WString& text, const WString& find, Locale::Normalization normalization) const override;
	};
}

#endif

/***********************************************************************
.\THREADING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#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
	{
#if defined VCZH_MSVC
	private:
		threading_internal::WaitableData*			waitableData;
	protected:
		WaitableObject();
		void										SetData(threading_internal::WaitableData* data);
	public:
		NOT_COPYABLE(WaitableObject);

		/// <summary>Test if the object has already been created. Some of the synchronization objects should initialize itself after the constructor.</summary>
		/// <returns>Returns true if the object has already been created.</returns>
		/// <remarks>This function is only available in Windows.</remarks>
		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.</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>
		/// <remarks>This function is only available in Windows.</remarks>
		bool										WaitForTime(vint ms);
		
		/// <summary>Wait for multiple objects.</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>
		/// <remarks>This function is only available in Windows.</remarks>
		static bool									WaitAll(WaitableObject** objects, vint count);
		/// <summary>Wait for multiple objects for a period of time.</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>
		/// <remarks>This function is only available in Windows.</remarks>
		static bool									WaitAllForTime(WaitableObject** objects, vint count, vint ms);
		/// <summary>Wait for one of the objects.</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>
		/// <remarks>This function is only available in Windows.</remarks>
		static vint									WaitAny(WaitableObject** objects, vint count, bool* abandoned);
		/// <summary>Wait for one of the objects for a period of time.</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>
		/// <remarks>This function is only available in Windows.</remarks>
		static vint									WaitAnyForTime(WaitableObject** objects, vint count, vint ms, bool* abandoned);
#elif defined VCZH_GCC
		virtual bool								Wait() = 0;
#endif
	};

	/// <summary>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 recommended 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 recommended 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. <see cref="Create"/> or <see cref="Open"/> is required to initialize a 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.</param>
		bool										Open(bool inheritable, const WString& name);

		/// <summary>
		/// Release the mutex.
		/// In 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. <see cref="Create"/> or <see cref="Open"/> is required to initialize a 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.</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. <see cref="CreateAutoUnsignal"/> or <see cref="CreateManualUnsignal"/> is required to initialize an 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>
	/// Critical section.
	/// The macro "CS_LOCK" is recommended instead of calling [M:vl.CriticalSection.Enter] and [M:vl.CriticalSection.Leave] like this:
	/// <program><code><![CDATA[
	/// CS_LOCK(yourCriticalSection)
	/// {
	///     // do something
	/// }
	/// ]]></code></program>
	/// </summary>
	/// <remarks>
	/// In Windows, enter a owned critical section will not result in dead lock.
	/// In Linux and macOS, it works like a mutex.
	/// </remarks>
	class CriticalSection : public Object
	{
	private:
		friend class ConditionVariable;
		threading_internal::CriticalSectionData*	internalData;
	public:
		NOT_COPYABLE(CriticalSection);
		/// <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
		{
		private:
			CriticalSection*						criticalSection;
		public:
			NOT_COPYABLE(Scope);
			Scope(CriticalSection& _criticalSection);
			~Scope();
		};
	};
	
	/// <summary>
	/// Reader writer lock.
	/// The macro "READER_LOCK" and "WRITER_LOCK" are recommended instead of calling [M:vl.ReaderWriterLock.EnterReader], [M:vl.ReaderWriterLock.LeaveReader], [M:vl.ReaderWriterLock.EnterWriter] and [M:vl.ReaderWriterLock.LeaveWriter] like this:
	/// <program><code><![CDATA[
	/// READER_LOCK(yourLock)
	/// {
	///     // do something
	/// }
	/// ]]></code></program>
	/// or
	/// <program><code><![CDATA[
	/// WRITER_LOCK(yourLock)
	/// {
	///     // do something
	/// }
	/// ]]></code></program>
	/// </summary>
	class ReaderWriterLock : public Object
	{
	private:
		friend class ConditionVariable;
		threading_internal::ReaderWriterLockData*	internalData;
	public:
		NOT_COPYABLE(ReaderWriterLock);
		/// <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
		{
		private:
			ReaderWriterLock*						lock;
		public:
			NOT_COPYABLE(ReaderScope);
			ReaderScope(ReaderWriterLock& _lock);
			~ReaderScope();
		};
		
		class WriterScope : public Object
		{
		private:
			ReaderWriterLock*						lock;
		public:
			NOT_COPYABLE(WriterScope);
			WriterScope(ReaderWriterLock& _lock);
			~WriterScope();
		};
	};

	/// <summary>Conditional variable.</summary>
	class ConditionVariable : public Object
	{
	private:
		threading_internal::ConditionVariableData*	internalData;
	public:
		NOT_COPYABLE(ConditionVariable);
		/// <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.</summary>
		/// <returns>Returns true if this operation succeeded.</returns>
		/// <param name="cs">The critical section.</param>
		/// <param name="ms">Time in milliseconds.</param>
		/// <remarks>This function is only available in Windows.</remarks>
		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.</summary>
		/// <returns>Returns true if this operation succeeded.</returns>
		/// <param name="lock">The reader lock.</param>
		/// <remarks>This function is only available in Windows.</remarks>
		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.</summary>
		/// <returns>Returns true if this operation succeeded.</returns>
		/// <param name="lock">The reader lock.</param>
		/// <param name="ms">Time in milliseconds.</param>
		/// <remarks>This function is only available in Windows.</remarks>
		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.</summary>
		/// <returns>Returns true if this operation succeeded.</returns>
		/// <param name="lock">The writer lock.</param>
		/// <remarks>This function is only available in Windows.</remarks>
		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.</summary>
		/// <returns>Returns true if this operation succeeded.</returns>
		/// <param name="lock">The writer lock.</param>
		/// <param name="ms">Time in milliseconds.</param>
		/// <remarks>This function is only available in Windows.</remarks>
		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
***********************************************************************/
	
	/// <summary>
	/// Spin lock. It is similar to mutex, but it does not occupy resource in the system.
	/// The macro "SPIN_LOCK" is recommended instead of calling [M:vl.SpinLock.Enter] and [M:vl.SpinLock.Leave] like this:
	/// <program><code><![CDATA[
	/// SPIN_LOCK(yourLock)
	/// {
	///     // do something
	/// }
	/// ]]></code></program>
	/// </summary>
	class SpinLock : public Object
	{
	protected:
		atomic_vint									token = 0;
	public:
		NOT_COPYABLE(SpinLock);
		/// <summary>Create a spin lock.</summary>
		SpinLock() = default;
		~SpinLock() = default;
		
		/// <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
		{
		private:
			SpinLock*								spinLock;
		public:
			NOT_COPYABLE(Scope);
			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
***********************************************************************/

	/// <summary>Thread local storage operations.</summary>
	/// <remarks>
	/// This class is designed to define global variables.
	/// Dynamically allocation will result in undefined behavior.
	/// </remarks>
	class ThreadLocalStorage : public Object
	{
		typedef void(*Destructor)(void*);
	protected:
		vuint64_t								key;
		Destructor								destructor;
		volatile bool							disposed = false;
		
		static void								PushStorage(ThreadLocalStorage* storage);
	public:
		NOT_COPYABLE(ThreadLocalStorage);
		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 for detecting memory leaks.</summary>
		static void								DisposeStorages();
	};

	/// <summary>Thread local variable. 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>
	/// <remarks>
	/// This class is designed to define global variables.
	/// Dynamically allocation will result in undefined behavior.
	/// </remarks>
	template<typename T>
	class ThreadVariable : public Object
	{
	protected:
		ThreadLocalStorage						storage;

		static void Destructor(void* data)
		{
			if (data)
			{
				delete (T*)data;
			}
		}
	public:
		NOT_COPYABLE(ThreadVariable);

		/// <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
	{
	protected:
		ThreadLocalStorage						storage;

	public:
		NOT_COPYABLE(ThreadVariable);

		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 because:
	/// <ul>
	///   <li>Task execution is single threaded.</li>
	///   <li>If you queue a task, it will override all unexecuted queued tasks.</li>
	/// </ul>
	/// </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.</summary>
		/// <param name="input">The argument to run a task.</param>
		/// <remarks>
		/// <p>
		/// When there is a running task, queuing a new task will cancel all unexecuted queued tasks.
		/// When there is no running task, queuing a task will execute this task immediately.
		/// </p>
		/// </remarks>
		void SubmitTask(const T& input)
		{
			SPIN_LOCK(inputLock)
			{
				inputData=input;
				inputDataAvailable=true;
			}
			if(!executing)
			{
				executing=true;
				executingEvent.Enter();
				ThreadPoolLite::Queue(&ExecutingProc, this);
			}
		}
	};
}
#endif


/***********************************************************************
.\STREAM\INTERFACES.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_INTERFACES
#define VCZH_STREAM_INTERFACES


namespace vl
{
	namespace stream
	{
		/// <summary>
		/// <p>
		/// Interface for streams.
		/// </p>
		/// <p>
		/// Please notice that, even if you get a stream object, if [M:vl.stream.IStream.IsAvailable] returns false, all other methods cannot be used.
		/// </p>
		/// <p>
		/// Not all methods are available for all types of streams.
		/// Feature testing functions must be called before calling other methods, if it is not sure that what kind of stream is being operated against:
		/// </p>
		/// <p>
		///   <ul>
		///     <li><b>Readable</b>: A stream is readable if [M:vl.stream.IStream.CanRead] returns true.</li>
		///     <li><b>Peekable</b>: A stream is peekable if [M:vl.stream.IStream.CanPeek] returns true.</li>
		///     <li><b>Writable</b>: A stream is writable if [M:vl.stream.IStream.CanWrite] returns true.</li>
		///     <li><b>Seekable</b>: A stream is readable if [M:vl.stream.IStream.CanSeek] returns true.</li>
		///     <li><b>Finite</b>: A stream is finite if [M:vl.stream.IStream.IsLimited] returns true.</li>
		///   </ul>
		/// </p>
		/// </summary>
		class IStream : public virtual Interface
		{
		public:
			/// <summary>Test if the stream is <b>readable</b>.</summary>
			/// <returns>Returns true if the stream is <b>readable</b>.</returns>
			virtual bool					CanRead()const=0;
			/// <summary>Test if the stream is <b>writable</b>.</summary>
			/// <returns>Returns true if the stream is <b>writable</b>.</returns>
			virtual bool					CanWrite()const=0;
			/// <summary>Test if the stream is <b>seekable</b>.</summary>
			/// <returns>Returns true if the stream is <b>seekable</b>.</returns>
			virtual bool					CanSeek()const=0;
			/// <summary>Test if the stream is <b>peekable</b>.</summary>
			/// <returns>Returns true if the stream is <b>peekable</b>.</returns>
			virtual bool					CanPeek()const=0;
			/// <summary>Test if the content of the stream is <b>finite</b>. A writable stream can also be limited, it means that you can only write limited content to the stream.</summary>
			/// <returns>Returns true if the content of the stream is <b>finite</b>.</returns>
			virtual bool					IsLimited()const=0;
			/// <summary>Test if the stream is <b>available</b>. 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 <b>available</b>.</returns>
			virtual bool					IsAvailable()const=0;
			/// <summary>Close the stream, making the stream <b>unavailable</b>.</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 <b>unavailable</b>.</returns>
			virtual pos_t					Position()const=0;
			/// <summary>Get the size of the content in this stream.</summary>
			/// <returns>The size of the content in this stream. Returns -1 if the size is <b>unsizable</b> or <b>unavailable</b>.</returns>
			virtual pos_t					Size()const=0;
			/// <summary>Step forward or backward from the current position. It will crash if the stream is <b>unseekable</b> or <b>unavailable</b>.</summary>
			/// <param name="_size">The length to step forward if it is a positive number. The length to step backward if it is a negative number</param>
			virtual void					Seek(pos_t _size)=0;
			/// <summary>Step forward from the beginning. It will crash if the stream is <b>unseekable</b> or <b>unavailable</b>.</summary>
			/// <param name="_size">The length to step forward.</param>
			virtual void					SeekFromBegin(pos_t _size)=0;
			/// <summary>Step backward from the end. It will crash if the stream is <b>unseekable</b> or <b>unavailable</b>.</summary>
			/// <param name="_size">The length to step backward.</param>
			virtual void					SeekFromEnd(pos_t _size)=0;
			/// <summary>Read from the current position and step forward. It will crash if the stream is <b>unreadable</b> or <b>unavailable</b>.</summary>
			/// <returns>Returns the actual size of the content that has read. Returns 0 if a stream has no more data to 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;
			/// <summary>Write to the current position and step forward. It will crash if the stream is <b>unwritable</b> or <b>unavailable</b>.</summary>
			/// <returns>Returns the actual size of the content that has written. Returns 0 if a stream has not enough space to write.</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 without stepping forward. It will crash if the stream is <b>unpeekable</b> or <b>unavailable</b>.</summary>
			/// <returns>Returns the actual size of the content that is read. Returns 0 if a stream has no more data to 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					Peek(void* _buffer, vint _size)=0;
		};
	}
}

#endif

/***********************************************************************
.\ENCODING\ENCODING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_ENCODING
#define VCZH_STREAM_ENCODING_ENCODING


namespace vl
{
	namespace stream
	{
/***********************************************************************
IEncoder and IDecoder
***********************************************************************/

		/// <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 <b>writable</b> stream to receive data. <see cref="Write"/> transforms the content and write to this tream.</summary>
			/// <param name="_stream">The target <b>writable</b> stream.</param>
			virtual void					Setup(IStream* _stream)=0;
			/// <summary>Stop the transformation, ensuring all content is written to the target stream.</summary>
			virtual	void					Close()=0;
			/// <summary>
			/// Transform content and write to the target stream.
			/// This function could use caching to improve performance.
			/// Please do not expect that all transformed content will be written to the target stream immediately.
			/// </summary>
			/// <returns>
			/// Returns the actual size of the content that has written <b>before</b> transforming.
			/// A successful write operation may only cache the data without actually write anything to the target stream.
			/// </returns>
			/// <param name="_buffer">A buffer storing the content to transform.</param>
			/// <param name="_size">The expected size of the content in bytes in "_buffer" to use.</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 <b>readable</b> stream.
			/// <see cref="Read"/> reads from this tream and transform the content.
			/// </summary>
			/// <param name="_stream">The target <b>readable</b> 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 has read after transforming.</returns>
			/// <param name="_buffer">A buffer to store the content.</param>
			/// <param name="_size">The expected size of the content in bytes in "_buffer" to receive.</param>
			virtual vint					Read(void* _buffer, vint _size)=0;
		};

/***********************************************************************
EncoderBase and DecoderBase
***********************************************************************/

		/// <summary>Basic implementation of IEncoder.</summary>
		class EncoderBase : public Object, public IEncoder
		{
		protected:
			IStream*						stream = nullptr;

		public:

			void							Setup(IStream* _stream) override;
			void							Close() override;
		};
		
		/// <summary>Basic implementation of IDecoder.</summary>
		class DecoderBase : public Object, public IDecoder
		{
		protected:
			IStream*						stream = nullptr;

		public:

			void							Setup(IStream* _stream) override;
			void							Close() override;
		};
	}
}

#endif

/***********************************************************************
.\ENCODING\BASE64ENCODING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_BASE64ENCODING
#define VCZH_STREAM_ENCODING_BASE64ENCODING


namespace vl
{
	namespace stream
	{
		constexpr const vint Base64CycleBytes = 3;
		constexpr const vint Base64CycleChars = 4;

/***********************************************************************
Utf8Base64Encoder
***********************************************************************/

		class Utf8Base64Encoder : public EncoderBase
		{
		protected:
			uint8_t					cache[Base64CycleBytes];
			vint					cacheSize = 0;

			void					WriteBytesToCharArray(uint8_t* fromBytes, char8_t(&toChars)[Base64CycleChars], vint bytes);
			bool					WriteCycle(uint8_t*& reading, vint& _size);
			bool					WriteCache(uint8_t*& reading, vint& _size);
		public:
			vint					Write(void* _buffer, vint _size) override;
			void					Close() override;
		};

/***********************************************************************
Utf8Base64Decoder
***********************************************************************/

		class Utf8Base64Decoder : public DecoderBase
		{
		protected:
			uint8_t					cache[Base64CycleBytes];
			vint					cacheSize = 0;

			vint					ReadBytesFromCharArray(char8_t(&fromChars)[Base64CycleChars], uint8_t* toBytes);
			vint					ReadCycle(uint8_t*& writing, vint& _size);
			void					ReadCache(uint8_t*& writing, vint& _size);
		public:
			vint					Read(void* _buffer, vint _size) override;
		};
	}
}

#endif


/***********************************************************************
.\ENCODING\CHARFORMAT\BOMENCODING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_CHARFORMAT_BOMENCODING
#define VCZH_STREAM_ENCODING_CHARFORMAT_BOMENCODING


namespace vl
{
	namespace stream
	{
/***********************************************************************
Bom
***********************************************************************/
		
		/// <summary>Encoder to write text in a specified encoding. 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. EF, BB, BF will be written before writing any text.</summary>
				Utf8,
				/// <summary>UTF-16. FF FE will be written before writing any text.</summary>
				Utf16,
				/// <summary>Big endian UTF-16. FE FF, BF will be written before writing any text.</summary>
				Utf16BE
			};
		protected:
			Encoding						encoding;
			IEncoder*						encoder;
		public:
			/// <summary>Create an encoder with a specified encoding.</summary>
			/// <param name="_encoding">The specified encoding.</param>
			BomEncoder(Encoding _encoding);
			~BomEncoder();

			void							Setup(IStream* _stream);
			void							Close();
			vint							Write(void* _buffer, vint _size);
		};
		
		/// <summary>Decoder to read text. This decoder depends on BOM 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, BOM will be consumed before reading any text.</summary>
			BomDecoder();
			~BomDecoder();

			void							Setup(IStream* _stream);
			void							Close();
			vint							Read(void* _buffer, vint _size);
		};
	}
}

#endif


/***********************************************************************
.\ENCODING\CHARFORMAT\MBCSENCODING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_CHARFORMAT_MBCSENCODING
#define VCZH_STREAM_ENCODING_CHARFORMAT_MBCSENCODING


namespace vl
{
	namespace stream
	{
/***********************************************************************
MbcsEncoder
***********************************************************************/

		/// <summary>Encoder to write text in the local code page.</summary>
		class MbcsEncoder : public EncoderBase
		{
		protected:
			vuint8_t						cacheBuffer[sizeof(char32_t)];
			vint							cacheSize = 0;

			vint							WriteString(wchar_t* _buffer, vint chars);
		public:

			vint							Write(void* _buffer, vint _size) override;
		};

/***********************************************************************
MbcsDecoder
***********************************************************************/

		/// <summary>Decoder to read text in the local code page.</summary>
		class MbcsDecoder : public DecoderBase
		{
		protected:
			vuint8_t						cacheBuffer[sizeof(wchar_t)];
			vint							cacheSize = 0;

			vint							ReadString(wchar_t* _buffer, vint chars);
		public:

			vint							Read(void* _buffer, vint _size) override;
		};
	}
}

#endif


/***********************************************************************
.\ENCODING\CHARFORMAT\UTFENCODING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_CHARFORMAT_UTFENCODING
#define VCZH_STREAM_ENCODING_CHARFORMAT_UTFENCODING


namespace vl
{
	namespace stream
	{

/***********************************************************************
UtfStreamConsumer<T>
***********************************************************************/

		template<typename T>
		class UtfStreamConsumer : public Object
		{
		protected:
			IStream*				stream = nullptr;

			T Consume()
			{
				T c;
				vint size = stream->Read(&c, sizeof(c));
				if (size != sizeof(c)) return 0;
				return c;
			}
		public:
			void Setup(IStream* _stream)
			{
				stream = _stream;
			}

			bool HasIllegalChar() const
			{
				return false;
			}
		};

		template<typename T>
		class UtfStreamConsumerApiRedirection : public Object
		{
		private:
			T&						internalConsumer;

		public:
			UtfStreamConsumerApiRedirection(T& _internalConsumer)
				: internalConsumer(_internalConsumer)
			{
			}

			void Setup(IStream* _stream)
			{
				internalConsumer.Setup(_stream);
			}

			encoding::UtfCharCluster SourceCluster() const
			{
				return internalConsumer.SourceCluster();
			}
		};

/***********************************************************************
UtfStreamToStreamReader<TFrom, TTo>
***********************************************************************/

		template<typename TFrom, typename TTo>
		using UtfStreamToStreamReader = encoding::UtfToUtfReaderBase<TFrom, TTo, UtfStreamConsumer<TFrom>, UtfStreamConsumerApiRedirection>;

/***********************************************************************
Unicode General
***********************************************************************/

		template<typename T>
		struct MaxPossibleCodePoints
		{
			static const vint		Value = encoding::UtfConversion<T>::BufferLength;
		};

		template<>
		struct MaxPossibleCodePoints<char32_t>
		{
			static const vint		Value = 1;
		};

		template<typename TNative, typename TExpect>
		class UtfGeneralEncoder : public EncoderBase
		{
			using TStringRangeReader = encoding::UtfStringRangeToStringRangeReader<TExpect, TNative>;
		protected:
			vuint8_t						cacheBuffer[sizeof(TExpect) * MaxPossibleCodePoints<TExpect>::Value];
			vint							cacheSize = 0;

		public:

			vint							Write(void* _buffer, vint _size) override;
		};

		template<typename TNative, typename TExpect>
		class UtfGeneralDecoder : public DecoderBase
		{
			using TStreamReader = UtfStreamToStreamReader<TNative, TExpect>;
		protected:
			vuint8_t						cacheBuffer[sizeof(TExpect)];
			vint							cacheSize = 0;
			TStreamReader					reader;

		public:

			void							Setup(IStream* _stream) override;
			vint							Read(void* _buffer, vint _size) override;
		};

/***********************************************************************
Unicode General (without conversion)
***********************************************************************/

		template<typename T>
		class UtfGeneralEncoder<T, T> : public EncoderBase
		{
		public:
			vint							Write(void* _buffer, vint _size) override;
		};

		template<typename T>
		class UtfGeneralDecoder<T, T> : public DecoderBase
		{
		public:
			vint							Read(void* _buffer, vint _size) override;
		};

#if defined VCZH_WCHAR_UTF16

		template<>
		class UtfGeneralEncoder<char16_t, wchar_t> : public UtfGeneralEncoder<wchar_t, wchar_t> {};

		template<>
		class UtfGeneralEncoder<wchar_t, char16_t> : public UtfGeneralEncoder<wchar_t, wchar_t> {};

#elif defined VCZH_WCHAR_UTF32

		template<>
		class UtfGeneralEncoder<char32_t, wchar_t> : public UtfGeneralEncoder<wchar_t, wchar_t> {};

		template<>
		class UtfGeneralEncoder<wchar_t, char32_t> : public UtfGeneralEncoder<wchar_t, wchar_t> {};

#endif

/***********************************************************************
Unicode General (extern templates)
***********************************************************************/

		extern template class UtfGeneralEncoder<wchar_t, wchar_t>;
		extern template class UtfGeneralEncoder<wchar_t, char8_t>;
		extern template class UtfGeneralEncoder<wchar_t, char16_t>;
		extern template class UtfGeneralEncoder<wchar_t, char16be_t>;
		extern template class UtfGeneralEncoder<wchar_t, char32_t>;

		extern template class UtfGeneralEncoder<char8_t, wchar_t>;
		extern template class UtfGeneralEncoder<char8_t, char8_t>;
		extern template class UtfGeneralEncoder<char8_t, char16_t>;
		extern template class UtfGeneralEncoder<char8_t, char16be_t>;
		extern template class UtfGeneralEncoder<char8_t, char32_t>;

		extern template class UtfGeneralEncoder<char16_t, wchar_t>;
		extern template class UtfGeneralEncoder<char16_t, char8_t>;
		extern template class UtfGeneralEncoder<char16_t, char16_t>;
		extern template class UtfGeneralEncoder<char16_t, char16be_t>;
		extern template class UtfGeneralEncoder<char16_t, char32_t>;

		extern template class UtfGeneralEncoder<char16be_t, wchar_t>;
		extern template class UtfGeneralEncoder<char16be_t, char8_t>;
		extern template class UtfGeneralEncoder<char16be_t, char16_t>;
		extern template class UtfGeneralEncoder<char16be_t, char16be_t>;
		extern template class UtfGeneralEncoder<char16be_t, char32_t>;

		extern template class UtfGeneralEncoder<char32_t, wchar_t>;
		extern template class UtfGeneralEncoder<char32_t, char8_t>;
		extern template class UtfGeneralEncoder<char32_t, char16_t>;
		extern template class UtfGeneralEncoder<char32_t, char16be_t>;
		extern template class UtfGeneralEncoder<char32_t, char32_t>;

		extern template class UtfGeneralDecoder<wchar_t, wchar_t>;
		extern template class UtfGeneralDecoder<wchar_t, char8_t>;
		extern template class UtfGeneralDecoder<wchar_t, char16_t>;
		extern template class UtfGeneralDecoder<wchar_t, char16be_t>;
		extern template class UtfGeneralDecoder<wchar_t, char32_t>;

		extern template class UtfGeneralDecoder<char8_t, wchar_t>;
		extern template class UtfGeneralDecoder<char8_t, char8_t>;
		extern template class UtfGeneralDecoder<char8_t, char16_t>;
		extern template class UtfGeneralDecoder<char8_t, char16be_t>;
		extern template class UtfGeneralDecoder<char8_t, char32_t>;

		extern template class UtfGeneralDecoder<char16_t, wchar_t>;
		extern template class UtfGeneralDecoder<char16_t, char8_t>;
		extern template class UtfGeneralDecoder<char16_t, char16_t>;
		extern template class UtfGeneralDecoder<char16_t, char16be_t>;
		extern template class UtfGeneralDecoder<char16_t, char32_t>;

		extern template class UtfGeneralDecoder<char16be_t, wchar_t>;
		extern template class UtfGeneralDecoder<char16be_t, char8_t>;
		extern template class UtfGeneralDecoder<char16be_t, char16_t>;
		extern template class UtfGeneralDecoder<char16be_t, char16be_t>;
		extern template class UtfGeneralDecoder<char16be_t, char32_t>;

		extern template class UtfGeneralDecoder<char32_t, wchar_t>;
		extern template class UtfGeneralDecoder<char32_t, char8_t>;
		extern template class UtfGeneralDecoder<char32_t, char16_t>;
		extern template class UtfGeneralDecoder<char32_t, char16be_t>;
		extern template class UtfGeneralDecoder<char32_t, char32_t>;
	}
}

#endif


/***********************************************************************
.\ENCODING\CHARFORMAT\CHARFORMAT.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_CHARFORMAT
#define VCZH_STREAM_ENCODING_CHARFORMAT


namespace vl
{
	namespace stream
	{
/***********************************************************************
Utf-8
***********************************************************************/
		
		/// <summary>Encoder to write UTF-8 text.</summary>
		class Utf8Encoder : public UtfGeneralEncoder<char8_t, wchar_t> {};
		/// <summary>Decoder to read UTF-8 text.</summary>
		class Utf8Decoder : public UtfGeneralDecoder<char8_t, wchar_t> {};

/***********************************************************************
Utf-16
***********************************************************************/
		
		/// <summary>Encoder to write UTF-16 text.</summary>
		class Utf16Encoder : public UtfGeneralEncoder<char16_t, wchar_t> {};
		/// <summary>Decoder to read UTF-16 text.</summary>
		class Utf16Decoder : public UtfGeneralDecoder<char16_t, wchar_t> {};

/***********************************************************************
Utf-16BE
***********************************************************************/

		/// <summary>Encoder to write big endian UTF-16 to.</summary>
		class Utf16BEEncoder : public UtfGeneralEncoder<char16be_t, wchar_t> {};
		/// <summary>Decoder to read big endian UTF-16 text.</summary>
		class Utf16BEDecoder : public UtfGeneralDecoder<char16be_t, wchar_t> {};

/***********************************************************************
Utf-32
***********************************************************************/

		/// <summary>Encoder to write UTF-8 text.</summary>
		class Utf32Encoder : public UtfGeneralEncoder<char32_t, wchar_t> {};
		/// <summary>Decoder to read UTF-8 text.</summary>
		class Utf32Decoder : public UtfGeneralDecoder<char32_t, wchar_t> {};

/***********************************************************************
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);
	}
}

#endif


/***********************************************************************
.\ENCODING\LZWENCODING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODING_LZWENCODING
#define VCZH_STREAM_ENCODING_LZWENCODING


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 data using the Lzw algorithm.</summary>
		/// <remarks>
		/// You are not recommended to compress data more than 1 mega bytes at once using the encoder directly.
		/// <see cref="CompressStream"/> and <see cref="DecompressStream"/> is recommended.
		/// </remarks>
		class LzwEncoder : public LzwBase, public EncoderBase
		{
		protected:
			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, specifying what bytes will never appear in the data to compress.</summary>
			/// <param name="existingBytes">
			/// A filter array
			/// If existingBytes[x] == true, it means x will possibly appear.
			/// If existingBytes[x] == false, it means x will never appear.
			/// </param>
			/// <remarks>
			/// The behavior is undefined, if existingBytes[x] == false, but byte x is actually in the data to compress.
			/// </remarks>
			LzwEncoder(bool (&existingBytes)[256]);
			~LzwEncoder();

			void									Close()override;
			vint									Write(void* _buffer, vint _size)override;
		};
		
		/// <summary>An decoder to decompress data using the Lzw algorithm.</summary>
		/// <remarks>
		/// You are not recommended to compress data more than 1 mega bytes at once using the encoder directly.
		/// <see cref="CompressStream"/> and <see cref="DecompressStream"/> is recommended.
		/// </remarks>
		class LzwDecoder :public LzwBase, public DecoderBase
		{
		protected:
			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 a decoder.</summary>
			LzwDecoder();
			/// <summary>Create an encoder, specifying what bytes will never appear in the decompressed data.</summary>
			/// <param name="existingBytes">
			/// A filter array
			/// If existingBytes[x] == true, it means x will possibly appear.
			/// If existingBytes[x] == false, it means x will never appear.
			/// </param>
			/// <remarks>
			/// The array "existingBytes" should exactly match the one given to <see cref="LzwEncoder"/>.
			/// </remarks>
			LzwDecoder(bool (&existingBytes)[256]);
			~LzwDecoder();

			vint									Read(void* _buffer, vint _size)override;
		};

/***********************************************************************
Helper Functions
***********************************************************************/

		/// <summary>Copy data from a <b>readable</b> input stream to a <b>writable</b> output stream.</summary>
		/// <returns>Data copied in bytes.</returns>
		/// <param name="inputStream">The <b>readable</b> input stream.</param>
		/// <param name="outputStream">The <b>writable</b> output stream.</param>
		extern vint						CopyStream(stream::IStream& inputStream, stream::IStream& outputStream);

		/// <summary>Compress data from a <b>readable</b> input stream to a <b>writable</b> output stream.</summary>
		/// <returns>Data copied in bytes.</returns>
		/// <param name="inputStream">The <b>readable</b> input stream.</param>
		/// <param name="outputStream">The <b>writable</b> output stream.</param>
		/// <remarks>
		/// Data is compressed in multiple batches,
		/// the is expected output stream to have data in multiple parts.
		/// In each part, the first 4 bytes is the data before compression in bytes.
		/// the rest is the compressed data.
		/// </remarks>
		/// <example><![CDATA[
		/// int main()
		/// {
		///     MemoryStream textStream, compressedStream, decompressedStream;
		///     {
		///         Utf8Encoder encoder;
		///         EncoderStream encoderStream(textStream, encoder);
		///         StreamWriter writer(encoderStream);
		///         writer.WriteString(L"Some text to compress.");
		///     }
		///     textStream.SeekFromBegin(0);
		///
		///     CompressStream(textStream, compressedStream);
		///     compressedStream.SeekFromBegin(0);
		///     DecompressStream(compressedStream, decompressedStream);
		///     decompressedStream.SeekFromBegin(0);
		///
		///     Utf8Decoder decoder;
		///     DecoderStream decoderStream(decompressedStream, decoder);
		///     StreamReader reader(decoderStream);
		///     Console::WriteLine(reader.ReadToEnd());
		/// }
		/// ]]></example>
		extern void						CompressStream(stream::IStream& inputStream, stream::IStream& outputStream);

		/// <summary>Decompress data from a <b>readable</b> input stream (with compressed data) to a <b>writable</b> output stream (with uncompressed data).</summary>
		/// <returns>Data copied in bytes.</returns>
		/// <param name="inputStream">The <b>readable</b> input stream.</param>
		/// <param name="outputStream">The <b>writable</b> output stream.</param>
		/// <remarks>
		/// Data is compressed in multiple batches,
		/// the is expected input stream to have data in multiple parts.
		/// In each part, the first 4 bytes is the data before compression in bytes.
		/// the rest is the compressed data.
		/// </remarks>
		/// <example><![CDATA[
		/// int main()
		/// {
		///     MemoryStream textStream, compressedStream, decompressedStream;
		///     {
		///         Utf8Encoder encoder;
		///         EncoderStream encoderStream(textStream, encoder);
		///         StreamWriter writer(encoderStream);
		///         writer.WriteString(L"Some text to compress.");
		///     }
		///     textStream.SeekFromBegin(0);
		///
		///     CompressStream(textStream, compressedStream);
		///     compressedStream.SeekFromBegin(0);
		///     DecompressStream(compressedStream, decompressedStream);
		///     decompressedStream.SeekFromBegin(0);
		///
		///     Utf8Decoder decoder;
		///     DecoderStream decoderStream(decompressedStream, decoder);
		///     StreamReader reader(decoderStream);
		///     Console::WriteLine(reader.ReadToEnd());
		/// }
		/// ]]></example>
		extern void						DecompressStream(stream::IStream& inputStream, stream::IStream& outputStream);
	}
}

#endif

/***********************************************************************
.\STREAM\BROADCASTSTREAM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_BROADCASTSTREAM
#define VCZH_STREAM_BROADCASTSTREAM


namespace vl
{
	namespace stream
	{
		/// <summary>A <b>writable</b> stream that copy the written content to multiple output streams.</summary>
		/// <remarks>
		/// When writing happens, the boreadcast stream will only performance one write attempt to each output stream.
		/// </remarks>
		class BroadcastStream : public Object, public virtual IStream
		{
			typedef collections::List<IStream*>		StreamList;
		protected:
			bool					closed;
			pos_t					position;
			StreamList				streams;
		public:
			/// <summary>Create a boradcast stream.</summary>
			BroadcastStream();
			~BroadcastStream();

			/// <summary>
			/// Get the list of output streams.
			/// You can change this list to subscribe or unsubscribe.
			/// </summary>
			/// <returns>The list of output 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
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_CACHESTREAM
#define VCZH_STREAM_CACHESTREAM


namespace vl
{
	namespace stream
	{
		/// <summary>
		/// <p>
		/// A potentially <b>readable</b>, <b>peekable</b>, <b>writable</b>, <b>seekable</b> and <b>finite</b> stream that creates on another stream.
		/// Each feature is available if the target stream has the same feature.
		/// </p>
		/// <p>
		/// When you read from the cache strema,
		/// it will read a specified size of content from the target stream at once and cache,
		/// reducing the number of operations on the target stream.
		/// </p>
		/// <p>
		/// When you write to the cache stream,
		/// it will cache all the data to write,
		/// and write to the target stream after the cache is full,
		/// reducing the number of operations on the target stream.
		/// </p>
		/// </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 from 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\ENCODINGSTREAM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_ENCODINGSTREAM
#define VCZH_STREAM_ENCODINGSTREAM


namespace vl
{
	namespace stream
	{
/***********************************************************************
Encoding Related
***********************************************************************/

		/// <summary>Encoder stream, a <b>writable</b> and potentially <b>finite</b> stream using [T:vl.stream.IEncoder] to transform content.</summary>
		class EncoderStream : public virtual IStream
		{
		protected:
			IStream*					stream;
			IEncoder*					encoder;
			pos_t						position;

		public:
			/// <summary>Create en encoder stream.</summary>
			/// <param name="_stream">The output 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 <b>readable</b> and potentially <b>finite</b> stream using [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 decoder stream.</summary>
			/// <param name="_stream">The input 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);
		};
	}
}

#endif

/***********************************************************************
.\STREAM\FILESTREAM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_FILESTREAM
#define VCZH_STREAM_FILESTREAM

#include <stdio.h>

namespace vl
{
	namespace stream
	{
		/// <summary>Platform-specific file stream implementation interface.</summary>
		class IFileStreamImpl : public virtual Interface
		{
		public:
			virtual bool			Open() = 0;
			virtual void			Close() = 0;
			virtual pos_t			Position() const = 0;
			virtual pos_t			Size() const = 0;
			virtual void			Seek(pos_t _size) = 0;
			virtual void			SeekFromBegin(pos_t _size) = 0;
			virtual void			SeekFromEnd(pos_t _size) = 0;
			virtual vint			Read(void* _buffer, vint _size) = 0;
			virtual vint			Write(void* _buffer, vint _size) = 0;
			virtual vint			Peek(void* _buffer, vint _size) = 0;
		};

		/// <summary>A file stream. If the given file name is not working, the stream could be <b>unavailable</b>.</summary>
		class FileStream : public Object, public virtual IStream
		{
		public:
			/// <summary>Access to the file.</summary>
			enum AccessRight
			{
				/// <summary>The file is opened to read, making this stream <b>readable</b>,  <b>seekable</b> and <b>finite</b>.</summary>
				ReadOnly,
				/// <summary>The file is opened to write, making this stream <b>writable</b>.</summary>
				WriteOnly,
				/// <summary>The file is opened to both read and write, making this stream <b>readable</b>, <b>seekable</b> and <b>writable</b>.</summary>
				ReadWrite
			};
		protected:
			AccessRight				accessRight;
			Ptr<IFileStreamImpl>	impl;
		public:
			/// <summary>Create a file stream from a given file name.</summary>
			/// <param name="fileName">The file to operate.</param>
			/// <param name="_accessRight">Expected operations 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

/***********************************************************************
.\FILESYSTEM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_FILESYSTEM
#define VCZH_FILESYSTEM


namespace vl
{
	namespace filesystem
	{
		/// <summary>Absolute file path.</summary>
		class FilePath : public Object
		{
			friend class LinuxFileSystemImpl;
			friend class WindowsFileSystemImpl;
		protected:
			WString						fullPath;

			static void					NormalizeDelimiters(collections::Array<wchar_t>& buffer);
			static void					TrimLastDelimiter(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
			/// <summary>The delimiter character used in a file path</summary>
			/// <remarks>
			/// In Windows, it is "\".
			/// In Linux and macOS, it is "/".
			/// But you can always use "/", it is also supported in Windows.
			/// </remarks>
			static constexpr wchar_t	Delimiter = L'\\';
#elif defined VCZH_GCC
			static constexpr wchar_t	Delimiter = L'/';
#endif

			/// <summary>Create a root path.</summary>
			/// <remarks><see cref="GetFullPath"/> returns different values for root path on different platforms. Do not rely on the value.</remarks>
			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() = default;

			std::strong_ordering		operator<=>(const FilePath& path)const { return fullPath <=> path.fullPath; }
			bool						operator==(const FilePath& path)const { return fullPath == path.fullPath; }

			/// <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>
			/// <remarks>In Windows, a drive is also considered a folder.</remarks>
			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 based on a specified referencing folder.</summary>
			/// <returns>The relative path.</returns>
			/// <param name="_filePath">The referencing folder.</param>
			WString						GetRelativePathFor(const FilePath& _filePath)const;

		};

		/// <summary>A file.</summary>
		class File : public Object
		{
		private:
			FilePath					filePath;

		public:
			/// <summary>Create an empty reference. An empty reference does not refer to any file.</summary>
			File() = default;
			/// <summary>Create a reference to a specified file. The file is not required to exist.</summary>
			/// <param name="_filePath">The specified file.</param>
			File(const FilePath& _filePath);
			~File() = default;

			/// <summary>Get the file path of the file.</summary>
			/// <returns>The file path.</returns>
			const FilePath&				GetFilePath()const;

			/// <summary>Get the content of a text file with encoding testing.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <param name="text">Returns the content of the file.</param>
			/// <param name="encoding">Returns the encoding of the file.</param>
			/// <param name="containsBom">Returns true if there is a BOM in the file.</param>
			bool						ReadAllTextWithEncodingTesting(WString& text, stream::BomEncoder::Encoding& encoding, bool& containsBom);
			/// <summary>Get the content of a text file. If there is no BOM in the file, the encoding is assumed to be aligned to the current code page.</summary>
			/// <returns>The content of the file.</returns>
			WString						ReadAllTextByBom()const;
			/// <summary>Get the content of a text file.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <param name="text">The content of the file.</param>
			bool						ReadAllTextByBom(WString& text)const;
			/// <summary>Get the content of a text file by lines.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <param name="lines">The content of the file by lines.</param>
			/// <remarks>
			/// Lines could be separated by either CRLF or LF.
			/// A text file is not required to ends with CRLF.
			/// If the last character of the file is LF,
			/// the last line is the line before LF.
			/// </remarks>
			bool						ReadAllLinesByBom(collections::List<WString>& lines)const;

			/// <summary>Write text to the file.</summary>
			/// <returns>Returns true 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, the default value is true.</param>
			/// <param name="encoding">The text encoding, the default encoding is UTF-16.</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 true if this operation succeeded.</returns>
			/// <param name="lines">The text to write, with CRLF appended after all lines.</param>
			/// <param name="bom">Set to true to add a corresponding BOM at the beginning of the file according to the encoding, the default value is true.</param>
			/// <param name="encoding">The text encoding, the default encoding is UTF-16.</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>
			/// <remarks>This function could return before the file is actually deleted.</remarks>
			bool						Delete()const;
			/// <summary>Rename the file.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <param name="newName">The new file name.</param>
			bool						Rename(const WString& newName)const;
		};
		
		/// <summary>A folder.</summary>
		/// <remarks>In Windows, a drive is also considered a folder.</remarks>
		class Folder : public Object
		{
		private:
			FilePath					filePath;

			bool						CreateNonRecursively()const;
			bool						DeleteNonRecursively()const;
		public:
			/// <summary>Create a reference to the root folder.</summary>
			Folder() = default;
			/// <summary>Create a reference to a specified folder. The folder is not required to exist.</summary>
			/// <param name="_filePath">The specified folder.</param>
			Folder(const FilePath& _filePath);
			~Folder() = default;
			
			/// <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>
			/// <remarks>In Windows, drives are considered sub folders in the root folder.</remarks>
			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 levels of containing folders if they do not exist.</param>
			/// <remarks>
			/// This function could return before the folder is actually created.
			/// If "recursively" is false, this function will only attempt to create the specified folder directly,
			/// it fails if the containing folder does not exist.
			/// </remarks>
			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>
			/// <remarks>This function could return before the folder is actually deleted.</remarks>
			bool						Delete(bool recursively)const;
			/// <summary>Rename the folder.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <param name="newName">The new folder name.</param>
			bool						Rename(const WString& newName)const;
		};

		/// <summary>Platform-specific file system implementation interface.</summary>
		class IFileSystemImpl : public virtual feature_injection::IFeatureImpl
		{
		public:
			// FilePath operations
			virtual void Initialize(WString& fullPath) const = 0;
			virtual bool IsFile(const WString& fullPath) const = 0;
			virtual bool IsFolder(const WString& fullPath) const = 0;
			virtual bool IsRoot(const WString& fullPath) const = 0;
			virtual WString GetRelativePathFor(const WString& fromPath, const WString& toPath) const = 0;
			
			// File operations
			virtual bool FileDelete(const FilePath& filePath) const = 0;
			virtual bool FileRename(const FilePath& filePath, const WString& newName) const = 0;
			
			// Folder operations
			virtual bool GetFolders(const FilePath& folderPath, collections::List<Folder>& folders) const = 0;
			virtual bool GetFiles(const FilePath& folderPath, collections::List<File>& files) const = 0;
			virtual bool CreateFolder(const FilePath& folderPath) const = 0;
			virtual bool DeleteFolder(const FilePath& folderPath) const = 0;
			virtual bool FolderRename(const FilePath& folderPath, const WString& newName) const = 0;
			
			// Stream operations
			virtual Ptr<stream::IFileStreamImpl> GetFileStreamImpl(const WString& fileName, stream::FileStream::AccessRight accessRight) const = 0;
		};

		extern void InjectFileSystemImpl(IFileSystemImpl* impl);
		extern void EjectFileSystemImpl(IFileSystemImpl* impl);
	}
}

#endif


/***********************************************************************
.\STREAM\MEMORYSTREAM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_MEMORYSTREAM
#define VCZH_STREAM_MEMORYSTREAM


namespace vl
{
	namespace stream
	{
		/// <summary>A <b>readable</b>, <b>peekable</b>, <b>writable</b> and <b>seekable</b> stream that creates on a buffer.</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 memory stream.</summary>
			/// <param name="_block">
			/// Size for each allocation.
			/// When the allocated buffer is not big enough for writing,
			/// the buffer will be rebuilt with an extension of "_block" in bytes.
			/// </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\ACCESSOR.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#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 whatever in the input stream.</summary>
		/// <typeparam name="T">The character type.</typeparam>
		template<typename T>
		class TextReader_ : public Object
		{
		public:
			NOT_COPYABLE(TextReader_);
			TextReader_() = default;

			/// <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 T					ReadChar()=0;
			/// <summary>Read a string of a specified size in characters.</summary>
			/// <returns>The read string. It could be shorter than the expected length if the reader reaches the end.</returns>
			/// <param name="length">Expected length of the string to read.</param>
			virtual ObjectString<T>		ReadString(vint length);
			/// <summary>Read a string until a line breaks is reached.</summary>
			/// <returns>The string without the line break. If the reader reaches the end, it returns an empty string.</returns>
			virtual ObjectString<T>		ReadLine();
			/// <summary>Read everying remain.</summary>
			/// <returns>The read string.</returns>
			virtual ObjectString<T>		ReadToEnd();
		};
		
		/// <summary>Text writer.</summary>
		/// <typeparam name="T">The character type.</typeparam>
		template<typename T>
		class TextWriter_ : public Object
		{
		public:
			NOT_COPYABLE(TextWriter_);
			TextWriter_() = default;

			/// <summary>Write a single character.</summary>
			/// <param name="c">The character to write.</param>
			virtual void				WriteChar(T c)=0;
			/// <summary>Write a string.</summary>
			/// <param name="string">Buffer of the string to write.</param>
			/// <param name="charCount">Size of the string in characters, not including the zero terminator.</param>
			virtual void				WriteString(const T* string, vint charCount);
			/// <summary>Write a string.</summary>
			/// <param name="string">Buffer of the zero terminated string to write.</param>
			virtual void				WriteString(const T* string);
			/// <summary>Write a string.</summary>
			/// <param name="string">The string to write.</param>
			virtual void				WriteString(const ObjectString<T>& 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 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 T* string);
			/// <summary>Write a string with a CRLF.</summary>
			/// <param name="string">The string to write.</param>
			virtual void				WriteLine(const ObjectString<T>& string);
		};

		/// <summary>Text reader from a string.</summary>
		/// <typeparam name="T">The character type.</typeparam>
		template<typename T>
		class StringReader_ : public TextReader_<T>
		{
		protected:
			ObjectString<T>				string;
			vint						current;
			bool						lastCallIsReadLine;

			void						PrepareIfLastCallIsReadLine();
		public:
			/// <summary>Create a text reader.</summary>
			/// <param name="_string">The string to read.</param>
			StringReader_(const ObjectString<T>& _string);

			bool						IsEnd();
			T							ReadChar();
			ObjectString<T>				ReadString(vint length);
			ObjectString<T>				ReadLine();
			ObjectString<T>				ReadToEnd();
		};

		/// <summary>
		/// Text reader from a stream storing characters in code point.
		/// </summary>
		/// <typeparam name="T">The character type.</typeparam>
		/// <remarks>
		/// To specify the encoding in the input stream,
		/// you are recommended to create a <see cref="DecoderStream"/> with a <see cref="UtfGeneralDecoder"/> implementation,
		/// like <see cref="BomDecoder"/>, <see cref="MbcsDecoder"/>, <see cref="Utf16Decoder"/>, <see cref="Utf16BEDecoder"/> or <see cref="Utf8Decoder"/>.
		/// </remarks>
		/// <example output="false"><![CDATA[
		/// int main()
		/// {
		///     FileStream fileStream(L"C:/a.txt", FileStream::ReadOnly);
		///     Utf8Decoder decoder;
		///     DecoderStream decoderStream(fileStream, decoder);
		///     StreamReader reader(decoderStream);
		///     Console::WriteLine(reader.ReadToEnd());
		/// }
		/// ]]></example>
		template<typename T>
		class StreamReader_ : public TextReader_<T>
		{
		protected:
			IStream*					stream;
		public:
			/// <summary>Create a text reader.</summary>
			/// <param name="_stream">The stream to read.</param>
			StreamReader_(IStream& _stream);

			bool						IsEnd();
			T							ReadChar();
		};

		/// <summary>
		/// Text reader from a stream storing characters in code point.
		/// </summary>
		/// <typeparam name="T">The character type.</typeparam>
		/// <remarks>
		/// To specify the encoding in the input stream,
		/// you are recommended to create a <see cref="EncoderStream"/> with a <see cref="UtfGeneralEncoder"/> implementation,
		/// like <see cref="BomEncoder"/>, <see cref="MbcsEncoder"/>, <see cref="Utf16Encoder"/>, <see cref="Utf16BEEncoder"/> or <see cref="Utf8Encoder"/>.
		/// </remarks>
		/// <example output="false"><![CDATA[
		/// int main()
		/// {
		///     FileStream fileStream(L"C:/a.txt", FileStream::WriteOnly);
		///     Utf8Encoder encoder;
		///     EncoderStream encoderStream(fileStream, encoder);
		///     StreamWriter writer(encoderStream);
		///     writer.Write(L"Hello, world!");
		/// }
		/// ]]></example>
		template<typename T>
		class StreamWriter_ : public TextWriter_<T>
		{
		protected:
			IStream* stream;
		public:
			/// <summary>Create a text writer.</summary>
			/// <param name="_stream">The stream to write.</param>
			StreamWriter_(IStream& _stream);
			using TextWriter_<T>::WriteString;

			void						WriteChar(T c);
			void						WriteString(const T* string, vint charCount);
		};

/***********************************************************************
Extern Templates
***********************************************************************/

		extern template class TextReader_<wchar_t>;
		extern template class TextReader_<char8_t>;
		extern template class TextReader_<char16_t>;
		extern template class TextReader_<char32_t>;

		extern template class TextWriter_<wchar_t>;
		extern template class TextWriter_<char8_t>;
		extern template class TextWriter_<char16_t>;
		extern template class TextWriter_<char32_t>;

		extern template class StringReader_<wchar_t>;
		extern template class StringReader_<char8_t>;
		extern template class StringReader_<char16_t>;
		extern template class StringReader_<char32_t>;

		extern template class StreamReader_<wchar_t>;
		extern template class StreamReader_<char8_t>;
		extern template class StreamReader_<char16_t>;
		extern template class StreamReader_<char32_t>;

		extern template class StreamWriter_<wchar_t>;
		extern template class StreamWriter_<char8_t>;
		extern template class StreamWriter_<char16_t>;
		extern template class StreamWriter_<char32_t>;

/***********************************************************************
Helper Functions
***********************************************************************/

		using TextReader = TextReader_<wchar_t>;
		using TextWriter = TextWriter_<wchar_t>;
		using StringReader = StringReader_<wchar_t>;
		using StreamReader = StreamReader_<wchar_t>;
		using StreamWriter = StreamWriter_<wchar_t>;

		void WriteMonospacedEnglishTable(TextWriter& writer, collections::Array<WString>& tableByRow, vint rows, vint columns);

		/// <summary>
		/// Build a big string using <see cref="StreamWriter"/>.
		/// </summary>
		/// <typeparam name="TCallback">The type of the callback.</typeparam>
		/// <returns>The built big string.</returns>
		/// <param name="callback">
		/// The callback to receive a big string.
		/// The argument is a reference to a <see cref="StreamWriter"/>.
		/// After the callback is executed, everything written to the writer will be returned from "GenerateToStream".
		/// </param>
		/// <param name="block">Size of the cache in bytes.</param>
		/// <example><![CDATA[
		/// int main()
		/// {
		///     Console::Write(GenerateToStream([](StreamWriter& writer)
		///     {
		///         writer.WriteLine(L"Hello, world!");
		///         writer.WriteLine(L"Welcome to Gaclib!");
		///     }));
		/// }
		/// ]]></example>
		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\MEMORYWRAPPERSTREAM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_MEMORYWRAPPERSTREAM
#define VCZH_STREAM_MEMORYWRAPPERSTREAM


namespace vl
{
	namespace stream
	{
		/// <summary>A <b>readable</b>, <b>peekable</b>, <b>writable</b>, <b>seekable</b> and <b>finite</b> stream that creates on a buffer.</summary>
		class MemoryWrapperStream : public Object, public virtual IStream
		{
		protected:
			char*					buffer;
			vint						size;
			vint						position;
		public:
			/// <summary>Create a memory wrapper stream.</summary>
			/// <param name="_buffer">The buffer to operate.</param>
			/// <param name="_size">Size of the buffer in bytes.</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\RECORDERSTREAM.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_RECORDERSTREAM
#define VCZH_STREAM_RECORDERSTREAM


namespace vl
{
	namespace stream
	{
		/// <summary>
		/// A readable stream that, reads from one stream, and copy everything that is read to another stream.
		/// The stream is <b>unavailable</b> if one of the input stream or the output stream is <b>unavailable</b>.
		/// The stream is <b>readable</b>, and potentially <b>finite</b>.
		/// </summary>
		/// <remarks>
		/// When reading happens, the recorder stream will only performance one write attempt to the output stream.
		/// </remarks>
		class RecorderStream : public Object, public virtual IStream
		{
		protected:
			IStream*				in;
			IStream*				out;
		public:
			/// <summary>Create a recorder stream.</summary>
			/// <param name="_in">
			/// The input stream.
			/// This recorder stream is <b>readable</b> only when the input stream is <b>readable</b>
			/// This recorder stream is <b>finite</b> only when the input stream is <b>finite</b>
			/// </param>
			/// <param name="_out">
			/// The output stream.
			/// </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

/***********************************************************************
.\STREAM\SERIALIZATION.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_STREAM_SERIALIZATION
#define VCZH_STREAM_SERIALIZATION


namespace vl
{
	namespace stream
	{
/***********************************************************************
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;
			}

/***********************************************************************
Serialization (integers)
***********************************************************************/

			template<typename T>
			struct Serialization_POD
			{
				template<typename TContext>
				static void IO(Reader<TContext>& reader, 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, T& value)
				{
					if (writer.output.Write(&value, sizeof(value)) != sizeof(value))
					{
						CHECK_FAIL(L"Serialization failed.");
					}
				}
			};

			template<typename TValue, typename TData>
			struct Serialization_DefaultConversion
			{
				static TValue ToValue(TData data)
				{
					return (TValue)data;
				}

				static TData FromValue(TValue value)
				{
					return (TData)value;
				}
			};

			template<typename TValue, typename TData, typename TConversion = Serialization_DefaultConversion<TValue, TData>>
			struct Serialization_Conversion
			{
				template<typename TContext>
				static void IO(Reader<TContext>& reader, TValue& value)
				{
					TData data;
					Serialization<TData>::IO(reader, data);
					value = TConversion::ToValue(data);
				}

				template<typename TContext>
				static void IO(Writer<TContext>& writer, TValue& value)
				{
					TData data = TConversion::FromValue(value);
					Serialization<TData>::IO(writer, data);
				}
			};

			template<>
			struct Serialization<vint64_t> : Serialization_POD<vint64_t> {};

			template<>
			struct Serialization<vuint64_t> : Serialization_POD<vuint64_t> {};

			template<>
			struct Serialization<vint32_t> : Serialization_Conversion<vint32_t, vint64_t> {};

			template<>
			struct Serialization<vuint32_t> : Serialization_Conversion<vuint32_t, vuint64_t> {};

			template<>
			struct Serialization<vint16_t> : Serialization_POD<vint16_t> {};

			template<>
			struct Serialization<vuint16_t> : Serialization_POD<vuint16_t> {};

			template<>
			struct Serialization<vint8_t> : Serialization_POD<vint8_t> {};

			template<>
			struct Serialization<vuint8_t> : Serialization_POD<vuint8_t> {};

/***********************************************************************
Serialization (chars)
***********************************************************************/

			template<>
			struct Serialization<char> : Serialization_Conversion<char, vint64_t> {};

			template<>
			struct Serialization<wchar_t> : Serialization_Conversion<wchar_t, vint64_t> {};

			template<>
			struct Serialization<char8_t> : Serialization_Conversion<char8_t, vint64_t> {};

			template<>
			struct Serialization<char16_t> : Serialization_Conversion<char16_t, vint64_t> {};

			template<>
			struct Serialization<char32_t> : Serialization_Conversion<char32_t, vint64_t> {};

/***********************************************************************
Serialization (floats)
***********************************************************************/

			template<>
			struct Serialization<double> : Serialization_POD<double> {};

			template<>
			struct Serialization<float> : Serialization_POD<float> {};

			template<>
			struct Serialization<bool> : Serialization_Conversion<bool, vint8_t, Serialization<bool>>
			{
				static bool ToValue(vint8_t data)
				{
					return data == -1;
				}

				static vint8_t FromValue(bool value)
				{
					return value ? -1 : 0;
				}
			};

/***********************************************************************
Serialization (enum)
***********************************************************************/

			template<typename T>
				requires(std::is_enum_v<T>)
			struct Serialization<T> : Serialization_Conversion<T, vint64_t> {};

/***********************************************************************
Serialization (strings)
***********************************************************************/

			template<>
			struct Serialization<U8String>
			{
				template<typename TContext>
				static void IO(Reader<TContext>& reader, U8String& value)
				{
					vint count = -1;
					reader << count;
					if (count > 0)
					{
						char8_t* buffer = new char8_t[count + 1];
						MemoryWrapperStream stream(buffer, count);
						reader << (IStream&)stream;
						buffer[count] = 0;
						value = U8String::TakeOver(buffer, count);
					}
					else
					{
						value = {};
					}
				}

				template<typename TContext>
				static void IO(Writer<TContext>& writer, U8String& value)
				{
					vint count = value.Length();
					writer << count;
					if (count > 0)
					{
						MemoryWrapperStream stream((void*)value.Buffer(), count);
						writer << (IStream&)stream;
					}
				}
			};

			template<>
			struct Serialization<WString> : Serialization_Conversion<WString, U8String, Serialization<WString>>
			{
				static WString ToValue(const U8String& data)
				{
					return u8tow(data);
				}

				static U8String FromValue(const WString& value)
				{
					return wtou8(value);
				}
			};

			template<>
			struct Serialization<U16String> : Serialization_Conversion<U16String, U8String, Serialization<U16String>>
			{
				static U16String ToValue(const U8String& data)
				{
					return u8tou16(data);
				}

				static U8String FromValue(const U16String& value)
				{
					return u16tou8(value);
				}
			};

			template<>
			struct Serialization<U32String> : Serialization_Conversion<U32String, U8String, Serialization<U32String>>
			{
				static U32String ToValue(const U8String& data)
				{
					return u8tou32(data);
				}

				static U8String FromValue(const U32String& value)
				{
					return u32tou8(value);
				}
			};

/***********************************************************************
Serialization (generic types)
***********************************************************************/

			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 = Ptr(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);
					}
				}
			};

/***********************************************************************
Serialization (collections)
***********************************************************************/

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

/***********************************************************************
Serialization (MISC)
***********************************************************************/

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

/***********************************************************************
Serialization (macros)
***********************************************************************/

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

		}
	}
}

#endif

