/***********************************************************************
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
***********************************************************************/
///
/// This function will block the calling thread until the respons is returned.
///
/// This function is only available in Windows.
///
/// 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.
///
/// This function is only available in Windows.
///
/// For all string operations that the normalization does not set to None,
/// 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.
///
/// In Linux and macOS, only en-US is supported, with a hard-coded set of date and time formats,
/// and string operations only support None and IgnoreCase for normalization.
///
/// 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.
///
/// Interface for streams.
///
/// Please notice that, even if you get a stream object, if [M:vl.stream.IStream.IsAvailable] returns false, all other methods cannot be used.
///
/// 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:
///
///
///
///
///
///
///
///
///
///
/// A potentially readable, peekable, writable, seekable and finite stream that creates on another stream. /// Each feature is available if the target stream has the same feature. ///
////// 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. ///
////// 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. ///
/// CodeAllocator;
typedef collections::ByteObjectMap::Allocator MapAllocator;
vuint8_t byte = 0;
vint code = -1;
Code* parent = 0;
vint size = 0;
collections::ByteObjectMap 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();
};
/// An encoder to compress data using the Lzw algorithm.
///
/// You are not recommended to compress data more than 1 mega bytes at once using the encoder directly.
/// and is recommended.
///
class LzwEncoder : public LzwBase, public IEncoder
{
protected:
IStream* stream = 0;
vuint8_t buffer[lzw::BufferSize];
vint bufferUsedBits = 0;
lzw::Code* prefix;
void Flush();
void WriteNumber(vint number, vint bitSize);
public:
/// Create an encoder.
LzwEncoder();
/// Create an encoder, specifying what bytes will never appear in the data to compress.
///
/// A filter array
/// If existingBytes[x] == true, it means x will possibly appear.
/// If existingBytes[x] == false, it means x will never appear.
///
///
/// The behavior is undefined, if existingBytes[x] == false, but byte x is actually in the data to compress.
///
LzwEncoder(bool (&existingBytes)[256]);
~LzwEncoder();
void Setup(IStream* _stream)override;
void Close()override;
vint Write(void* _buffer, vint _size)override;
};
/// An decoder to decompress data using the Lzw algorithm.
///
/// You are not recommended to compress data more than 1 mega bytes at once using the encoder directly.
/// and is recommended.
///
class LzwDecoder :public LzwBase, public IDecoder
{
protected:
IStream* stream = 0;
collections::List dictionary;
lzw::Code* lastCode = 0;
vuint8_t inputBuffer[lzw::BufferSize];
vint inputBufferSize = 0;
vint inputBufferUsedBits = 0;
collections::Array outputBuffer;
vint outputBufferSize = 0;
vint outputBufferUsedBytes = 0;
bool ReadNumber(vint& number, vint bitSize);
void PrepareOutputBuffer(vint size);
void ExpandCodeToOutputBuffer(lzw::Code* code);
public:
/// Create a decoder.
LzwDecoder();
/// Create an encoder, specifying what bytes will never appear in the decompressed data.
///
/// A filter array
/// If existingBytes[x] == true, it means x will possibly appear.
/// If existingBytes[x] == false, it means x will never appear.
///
///
/// The array "existingBytes" should exactly match the one given to .
///
LzwDecoder(bool (&existingBytes)[256]);
~LzwDecoder();
void Setup(IStream* _stream)override;
void Close()override;
vint Read(void* _buffer, vint _size)override;
};
/***********************************************************************
Helper Functions
***********************************************************************/
/// Copy data from a readable input stream to a writable output stream.
/// Data copied in bytes.
/// The readable input stream.
/// The writable output stream.
extern vint CopyStream(stream::IStream& inputStream, stream::IStream& outputStream);
/// Compress data from a readable input stream to a writable output stream.
/// Data copied in bytes.
/// The readable input stream.
/// The writable output stream.
///
/// 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.
///
///
extern void CompressStream(stream::IStream& inputStream, stream::IStream& outputStream);
/// Decompress data from a readable input stream (with compressed data) to a writable output stream (with uncompressed data).
/// Data copied in bytes.
/// The readable input stream.
/// The writable output stream.
///
/// 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.
///
///
extern void DecompressStream(stream::IStream& inputStream, stream::IStream& outputStream);
}
}
#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
namespace vl
{
namespace stream
{
/// A file stream. If the given file name is not working, the stream could be unavailable.
class FileStream : public Object, public virtual IStream
{
public:
/// Access to the file.
enum AccessRight
{
/// The file is opened to read, making this stream readable, seekable and finite.
ReadOnly,
/// The file is opened to write, making this stream writable.
WriteOnly,
/// The file is opened to both read and write, making this stream readable, seekable and writable.
ReadWrite
};
protected:
AccessRight accessRight;
FILE* file;
public:
/// Create a file stream from a given file name.
/// The file to operate.
/// Expected operations on the file.
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
/***********************************************************************
.\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
{
/// A readable, peekable, writable and seekable stream that creates on a buffer.
class MemoryStream : public Object, public virtual IStream
{
protected:
vint block;
char* buffer;
vint size;
vint position;
vint capacity;
void PrepareSpace(vint totalSpace);
public:
/// Create a memory stream.
///
/// 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.
///
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
***********************************************************************/
/// Text reader. All line breaks are normalized to CRLF regardless whatever in the input stream.
class TextReader : public Object, private NotCopyable
{
public:
/// Test does the reader reach the end or not.
/// Returns true if the reader reaches the end.
virtual bool IsEnd()=0;
/// Read a single character.
/// The character.
virtual wchar_t ReadChar()=0;
/// Read a string of a specified size in characters.
/// The read string. It could be shorter than the expected length if the reader reaches the end.
/// Expected length of the string to read.
virtual WString ReadString(vint length);
/// Read a string until a line breaks is reached.
/// The string without the line break. If the reader reaches the end, it returns an empty string.
virtual WString ReadLine();
/// Read everying remain.
/// The read string.
virtual WString ReadToEnd();
};
/// Text writer.
class TextWriter : public Object, private NotCopyable
{
public:
/// Write a single character.
/// The character to write.
virtual void WriteChar(wchar_t c)=0;
/// Write a string.
/// Buffer of the string to write.
/// Size of the string in characters, not including the zero terminator.
virtual void WriteString(const wchar_t* string, vint charCount);
/// Write a string.
/// Buffer of the zero terminated string to write.
virtual void WriteString(const wchar_t* string);
/// Write a string.
/// The string to write.
virtual void WriteString(const WString& string);
/// Write a string with a CRLF.
/// Buffer to the string to write.
/// Size of the string in characters, not including the zero terminator.
virtual void WriteLine(const wchar_t* string, vint charCount);
/// Write a string with a CRLF.
/// Buffer to the zero terminated string to write.
virtual void WriteLine(const wchar_t* string);
/// Write a string with a CRLF.
/// The string to write.
virtual void WriteLine(const WString& string);
virtual void WriteMonospacedEnglishTable(collections::Array& tableByRow, vint rows, vint columns);
};
/// Text reader from a string.
class StringReader : public TextReader
{
protected:
WString string;
vint current;
bool lastCallIsReadLine;
void PrepareIfLastCallIsReadLine();
public:
/// Create a text reader.
/// The string to read.
StringReader(const WString& _string);
bool IsEnd();
wchar_t ReadChar();
WString ReadString(vint length);
WString ReadLine();
WString ReadToEnd();
};
///
/// Text reader from a stream storing characters in wchar_t.
///
///
/// To specify the encoding in the input stream,
/// you are recommended to create a with a ,
/// like , , , or .
///
///
class StreamReader : public TextReader
{
protected:
IStream* stream;
public:
/// Create a text reader.
/// The stream to read.
StreamReader(IStream& _stream);
bool IsEnd();
wchar_t ReadChar();
};
///
/// Text reader from a stream storing characters in wchar_t.
///
///
/// To specify the encoding in the input stream,
/// you are recommended to create a with a ,
/// like , , , or .
///
///
class StreamWriter : public TextWriter
{
protected:
IStream* stream;
public:
/// Create a text writer.
/// The stream to write.
StreamWriter(IStream& _stream);
using TextWriter::WriteString;
void WriteChar(wchar_t c);
void WriteString(const wchar_t* string, vint charCount);
};
/***********************************************************************
Encoding Related
***********************************************************************/
/// Encoder stream, a writable and potentially finite stream using [T:vl.stream.IEncoder] to transform content.
class EncoderStream : public virtual IStream
{
protected:
IStream* stream;
IEncoder* encoder;
pos_t position;
public:
/// Create en encoder stream.
/// The output stream to write.
/// The encoder to transform content.
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);
};
/// Decoder stream, a readable and potentially finite stream using [T:vl.stream.IDecoder] to transform content.
class DecoderStream : public virtual IStream
{
protected:
IStream* stream;
IDecoder* decoder;
pos_t position;
public:
/// Create a decoder stream.
/// The input stream to read.
/// The decoder to transform content.
DecoderStream(IStream& _stream, IDecoder& _decoder);
~DecoderStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
/***********************************************************************
Helper Functions
***********************************************************************/
///
/// Build a big string using .
///
/// The type of the callback.
/// The built big string.
///
/// The callback to receive a big string.
/// The argument is a reference to a .
/// After the callback is executed, everything written to the writer will be returned from "GenerateToStream".
///
/// Size of the cache in bytes.
///
template
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
{
/// A readable, peekable, writable, seekable and finite stream that creates on a buffer.
class MemoryWrapperStream : public Object, public virtual IStream
{
protected:
char* buffer;
vint size;
vint position;
public:
/// Create a memory wrapper stream.
/// The buffer to operate.
/// Size of the buffer in bytes.
MemoryWrapperStream(void* _buffer, vint _size);
~MemoryWrapperStream();
bool CanRead()const;
bool CanWrite()const;
bool CanSeek()const;
bool CanPeek()const;
bool IsLimited()const;
bool IsAvailable()const;
void Close();
pos_t Position()const;
pos_t Size()const;
void Seek(pos_t _size);
void SeekFromBegin(pos_t _size);
void SeekFromEnd(pos_t _size);
vint Read(void* _buffer, vint _size);
vint Write(void* _buffer, vint _size);
vint Peek(void* _buffer, vint _size);
};
}
}
#endif
/***********************************************************************
.\STREAM\CHARFORMAT.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_STREAM_CHARFORMAT
#define VCZH_STREAM_CHARFORMAT
namespace vl
{
namespace stream
{
/*
How UCS-4 translates to UTF-8
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
BOM:
FFFE =Unicode
FEFF =Unicode Big Endian
EFBBBF =UTF-8
other =MBCS(GBK)
*/
/***********************************************************************
Char Encoder and Decoder
***********************************************************************/
/// Base type of all character encoder.
class CharEncoder : public Object, public IEncoder
{
protected:
IStream* stream;
vuint8_t cacheBuffer[sizeof(wchar_t)];
vint cacheSize;
virtual vint WriteString(wchar_t* _buffer, vint chars)=0;
public:
CharEncoder();
void Setup(IStream* _stream);
void Close();
vint Write(void* _buffer, vint _size);
};
/// Base type of all character decoder.
class CharDecoder : public Object, public IDecoder
{
protected:
IStream* stream;
vuint8_t cacheBuffer[sizeof(wchar_t)];
vint cacheSize;
virtual vint ReadString(wchar_t* _buffer, vint chars)=0;
public:
CharDecoder();
void Setup(IStream* _stream);
void Close();
vint Read(void* _buffer, vint _size);
};
/***********************************************************************
Mbcs
***********************************************************************/
/// Encoder to write text in the local code page.
class MbcsEncoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// Decoder to read text in the local code page.
class MbcsDecoder : public CharDecoder
{
protected:
vint ReadString(wchar_t* _buffer, vint chars);
};
/***********************************************************************
Utf-16
***********************************************************************/
/// Encoder to write UTF-16 text.
class Utf16Encoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// Decoder to read UTF-16 text.
class Utf16Decoder : public CharDecoder
{
protected:
vint ReadString(wchar_t* _buffer, vint chars);
};
/***********************************************************************
Utf-16-be
***********************************************************************/
/// Encoder to write big endian UTF-16 to.
class Utf16BEEncoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// Decoder to read big endian UTF-16 text.
class Utf16BEDecoder : public CharDecoder
{
protected:
vint ReadString(wchar_t* _buffer, vint chars);
};
/***********************************************************************
Utf-8
***********************************************************************/
/// Encoder to write UTF-8 text.
class Utf8Encoder : public CharEncoder
{
protected:
vint WriteString(wchar_t* _buffer, vint chars);
};
/// Decoder to read UTF-8 text.
class Utf8Decoder : public CharDecoder
{
protected:
#if defined VCZH_MSVC
wchar_t cache;
bool cacheAvailable;
#endif
vint ReadString(wchar_t* _buffer, vint chars);
public:
Utf8Decoder();
};
/***********************************************************************
Bom
***********************************************************************/
/// Encoder to write text in a specified encoding. A BOM will be added at the beginning.
class BomEncoder : public Object, public IEncoder
{
public:
/// Text encoding.
enum Encoding
{
/// Multi-bytes character string.
Mbcs,
/// UTF-8. EF, BB, BF will be written before writing any text.
Utf8,
/// UTF-16. FF FE will be written before writing any text.
Utf16,
/// Big endian UTF-16. FE FF, BF will be written before writing any text.
Utf16BE
};
protected:
Encoding encoding;
IEncoder* encoder;
public:
/// Create an encoder with a specified encoding.
/// The specified encoding.
BomEncoder(Encoding _encoding);
~BomEncoder();
void Setup(IStream* _stream);
void Close();
vint Write(void* _buffer, vint _size);
};
/// Decoder to read text. This decoder depends on BOM at the beginning to decide the format of the input.
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:
/// Create an decoder, BOM will be consumed before reading any text.
BomDecoder();
~BomDecoder();
void Setup(IStream* _stream);
void Close();
vint Read(void* _buffer, vint _size);
};
/***********************************************************************
Encoding Test
***********************************************************************/
/// Guess the text encoding in a buffer.
/// The buffer to guess.
/// Size of the buffer in bytes.
/// Returns the most possible encoding.
/// Returns true if the BOM information is at the beginning of the buffer.
extern void TestEncoding(unsigned char* buffer, vint size, BomEncoder::Encoding& encoding, bool& containsBom);
/***********************************************************************
Serialization
***********************************************************************/
namespace internal
{
template
struct Reader
{
stream::IStream& input;
T context;
Reader(stream::IStream& _input)
:input(_input)
, context(nullptr)
{
}
};
template
struct Writer
{
stream::IStream& output;
T context;
Writer(stream::IStream& _output)
:output(_output)
, context(nullptr)
{
}
};
using ContextFreeReader = Reader;
using ContextFreeWriter = Writer;
template
struct Serialization
{
template
static void IO(TIO& io, T& value);
};
template
Reader& operator<<(Reader& reader, TValue& value)
{
Serialization::IO(reader, value);
return reader;
}
template
Writer& operator<<(Writer& writer, TValue& value)
{
Serialization::IO(writer, value);
return writer;
}
//---------------------------------------------
template<>
struct Serialization
{
template
static void IO(Reader& reader, vint64_t& value)
{
if (reader.input.Read(&value, sizeof(value)) != sizeof(value))
{
CHECK_FAIL(L"Deserialization failed.");
}
}
template
static void IO(Writer& writer, vint64_t& value)
{
if (writer.output.Write(&value, sizeof(value)) != sizeof(value))
{
CHECK_FAIL(L"Serialization failed.");
}
}
};
template<>
struct Serialization
{
template
static void IO(Reader& reader, vint32_t& value)
{
vint64_t v = 0;
Serialization::IO(reader, v);
value = (vint32_t)v;
}
template
static void IO(Writer& writer, vint32_t& value)
{
vint64_t v = (vint64_t)value;
Serialization::IO(writer, v);
}
};
template<>
struct Serialization
{
template
static void IO(Reader& reader, bool& value)
{
vint8_t v = 0;
if (reader.input.Read(&v, sizeof(v)) != sizeof(v))
{
CHECK_FAIL(L"Deserialization failed.");
}
else
{
value = v == -1;
}
}
template
static void IO(Writer& writer, bool& value)
{
vint8_t v = value ? -1 : 0;
if (writer.output.Write(&v, sizeof(v)) != sizeof(v))
{
CHECK_FAIL(L"Serialization failed.");
}
}
};
template
struct Serialization>
{
template
static void IO(Reader& reader, Ptr& value)
{
bool notNull = false;
reader << notNull;
if (notNull)
{
value = new T;
Serialization::IO(reader, *value.Obj());
}
else
{
value = 0;
}
}
template
static void IO(Writer& writer, Ptr& value)
{
bool notNull = value;
writer << notNull;
if (notNull)
{
Serialization::IO(writer, *value.Obj());
}
}
};
template
struct Serialization>
{
template
static void IO(Reader& reader, Nullable& value)
{
bool notNull = false;
reader << notNull;
if (notNull)
{
T data;
Serialization::IO(reader, data);
value = Nullable(data);
}
else
{
value = Nullable();
}
}
template
static void IO(Writer& writer, Nullable& value)
{
bool notNull = value;
writer << notNull;
if (notNull)
{
T data = value.Value();
Serialization::IO(writer, data);
}
}
};
template<>
struct Serialization
{
template
static void IO(Reader& reader, WString& value)
{
vint count = -1;
reader << count;
if (count > 0)
{
MemoryStream stream;
reader << (IStream&)stream;
Utf8Decoder decoder;
decoder.Setup(&stream);
collections::Array stringBuffer(count + 1);
vint stringSize = decoder.Read(&stringBuffer[0], count * sizeof(wchar_t));
stringBuffer[stringSize / sizeof(wchar_t)] = 0;
value = &stringBuffer[0];
}
else
{
value = L"";
}
}
template
static void IO(Writer& writer, WString& value)
{
vint count = value.Length();
writer << count;
if (count > 0)
{
MemoryStream stream;
{
Utf8Encoder encoder;
encoder.Setup(&stream);
encoder.Write((void*)value.Buffer(), count * sizeof(wchar_t));
}
writer << (IStream&)stream;
}
}
};
template
struct Serialization>
{
template
static void IO(Reader& reader, collections::List& value)
{
vint32_t count = -1;
reader << count;
value.Clear();
for (vint i = 0; i < count; i++)
{
T t;
reader << t;
value.Add(t);
}
}
template
static void IO(Writer& writer, collections::List& value)
{
vint32_t count = (vint32_t)value.Count();
writer << count;
for (vint i = 0; i < count; i++)
{
writer << value[i];
}
}
};
template
struct Serialization>
{
template
static void IO(Reader& reader, collections::Array& value)
{
vint32_t count = -1;
reader << count;
value.Resize(count);
for (vint i = 0; i < count; i++)
{
reader << value[i];
}
}
template
static void IO(Writer& writer, collections::Array& value)
{
vint32_t count = (vint32_t)value.Count();
writer << count;
for (vint i = 0; i < count; i++)
{
writer << value[i];
}
}
};
template
struct Serialization>
{
template
static void IO(Reader& reader, collections::Dictionary& 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
static void IO(Writer& writer, collections::Dictionary& 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
struct Serialization>
{
template
static void IO(Reader& reader, collections::Group& value)
{
vint32_t count = -1;
reader << count;
value.Clear();
for (vint i = 0; i < count; i++)
{
K k;
collections::List v;
reader << k << v;
for (vint j = 0; j < v.Count(); j++)
{
value.Add(k, v[j]);
}
}
}
template
static void IO(Writer& writer, collections::Group& 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 = const_cast&>(value.GetByIndex(i));
writer << k << v;
}
}
};
template<>
struct Serialization
{
template
static void IO(Reader& reader, stream::IStream& value)
{
vint32_t count = 0;
reader.input.Read(&count, sizeof(count));
if (count > 0)
{
vint length = 0;
collections::Array 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
static void IO(Writer& 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 buffer(count);
value.SeekFromBegin(0);
length = value.Read(&buffer[0], count);
if (length != count)
{
CHECK_FAIL(L"Serialization failed.");
}
length = writer.output.Write(&buffer[0], count);
if (length != count)
{
CHECK_FAIL(L"Serialization failed.");
}
value.SeekFromBegin(0);
}
}
};
//---------------------------------------------
#define BEGIN_SERIALIZATION(TYPE)\
template<>\
struct Serialization\
{\
template\
static void IO(TIO& op, TYPE& value)\
{\
op\
#define SERIALIZE(FIELD)\
<< value.FIELD\
#define END_SERIALIZATION\
;\
}\
};\
#define SERIALIZE_ENUM(TYPE)\
template<>\
struct Serialization\
{\
template\
static void IO(Reader& reader, TYPE& value)\
{\
vint32_t v = 0;\
Serialization::IO(reader, v);\
value = (TYPE)v;\
}\
template\
static void IO(Writer& writer, TYPE& value)\
{\
vint32_t v = (vint32_t)value;\
Serialization::IO(writer, v);\
}\
};\
}
}
}
#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
{
/// Absolute file path.
class FilePath : public Object
{
protected:
WString fullPath;
void Initialize();
static void GetPathComponents(WString path, collections::List& components);
static WString ComponentsToPath(const collections::List& components);
public:
#if defined VCZH_MSVC
/// The delimiter character used in a file path
///
/// In Windows, it is "\".
/// In Linux and macOS, it is "/".
/// But you can always use "/", it is also supported in Windows.
///
static const wchar_t Delimiter = L'\\';
#elif defined VCZH_GCC
static const wchar_t Delimiter = L'/';
#endif
/// Create a root path.
/// returns different values for root path on different platforms. Do not rely on the value.
FilePath();
/// Create a file path.
/// Content of the file path. If it is a relative path, it will be converted to an absolute path.
FilePath(const WString& _filePath);
/// Create a file path.
/// Content of the file path. If it is a relative path, it will be converted to an absolute path.
FilePath(const wchar_t* _filePath);
/// Copy a file path.
/// The file path to copy.
FilePath(const FilePath& _filePath);
~FilePath();
static vint Compare(const FilePath& a, const FilePath& b);
bool operator==(const FilePath& filePath)const{ return Compare(*this, filePath) == 0; }
bool operator!=(const FilePath& filePath)const{ return Compare(*this, filePath) != 0; }
bool operator< (const FilePath& filePath)const{ return Compare(*this, filePath) < 0; }
bool operator<=(const FilePath& filePath)const{ return Compare(*this, filePath) <= 0; }
bool operator> (const FilePath& filePath)const{ return Compare(*this, filePath) > 0; }
bool operator>=(const FilePath& filePath)const{ return Compare(*this, filePath) >= 0; }
/// Concat an absolute path and a relative path.
/// The result absolute path.
/// The relative path to concat.
FilePath operator/(const WString& relativePath)const;
/// Test if the file path is a file.
/// Returns true if the file path is a file.
bool IsFile()const;
/// Test if the file path is a folder.
/// Returns true if the file path is a folder.
/// In Windows, a drive is also considered a folder.
bool IsFolder()const;
/// Test if the file path is a the root of all file system objects.
/// Returns true if the file path is the root of all file system objects.
bool IsRoot()const;
/// Get the last piece of names in the file path.
/// The last piece of names in the file path.
WString GetName()const;
/// Get the containing folder of this file path.
/// The containing folder.
FilePath GetFolder()const;
/// Get the content of the file path.
/// The content of the file path.
WString GetFullPath()const;
/// Calculate the relative path based on a specified referencing folder.
/// The relative path.
/// The referencing folder.
WString GetRelativePathFor(const FilePath& _filePath);
};
/// A file.
class File : public Object
{
private:
FilePath filePath;
public:
/// Create an empty reference. An empty reference does not refer to any file.
File();
/// Create a reference to a specified file. The file is not required to exist.
/// The specified file.
File(const FilePath& _filePath);
~File();
/// Get the file path of the file.
/// The file path.
const FilePath& GetFilePath()const;
/// Get the content of a text file with encoding testing.
/// Returns true if this operation succeeded.
/// Returns the content of the file.
/// Returns the encoding of the file.
/// Returns true if there is a BOM in the file.
bool ReadAllTextWithEncodingTesting(WString& text, stream::BomEncoder::Encoding& encoding, bool& containsBom);
/// 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.
/// The content of the file.
WString ReadAllTextByBom()const;
/// Get the content of a text file.
/// Returns true if this operation succeeded.
/// The content of the file.
bool ReadAllTextByBom(WString& text)const;
/// Get the content of a text file by lines.
/// Returns true if this operation succeeded.
/// The content of the file by lines.
///
/// 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.
///
bool ReadAllLinesByBom(collections::List& lines)const;
/// Write text to the file.
/// Returns true if this operation succeeded.
/// The text to write.
/// Set to true to add a corresponding BOM at the beginning of the file according to the encoding, the default value is true.
/// The text encoding, the default encoding is UTF-16.
bool WriteAllText(const WString& text, bool bom = true, stream::BomEncoder::Encoding encoding = stream::BomEncoder::Utf16);
/// Write text to the file.
/// Returns true if this operation succeeded.
/// The text to write, with CRLF appended after all lines.
/// Set to true to add a corresponding BOM at the beginning of the file according to the encoding, the default value is true.
/// The text encoding, the default encoding is UTF-16.
bool WriteAllLines(collections::List& lines, bool bom = true, stream::BomEncoder::Encoding encoding = stream::BomEncoder::Utf16);
/// Test does the file exist or not.
/// Returns true if the file exists.
bool Exists()const;
/// Delete the file.
/// Returns true if this operation succeeded.
/// This function could return before the file is actually deleted.
bool Delete()const;
/// Rename the file.
/// Returns true if this operation succeeded.
/// The new file name.
bool Rename(const WString& newName)const;
};
/// A folder.
/// In Windows, a drive is also considered a folder.
class Folder : public Object
{
private:
FilePath filePath;
public:
/// Create a reference to the root folder.
Folder();
/// Create a reference to a specified folder. The folder is not required to exist.
/// The specified folder.
Folder(const FilePath& _filePath);
~Folder();
/// Get the file path of the folder.
/// The file path.
const FilePath& GetFilePath()const;
/// Get all folders in this folder.
/// Returns true if this operation succeeded.
/// All folders.
/// In Windows, drives are considered sub folders in the root folder.
bool GetFolders(collections::List& folders)const;
/// Get all files in this folder.
/// Returns true if this operation succeeded.
/// All files.
bool GetFiles(collections::List& files)const;
/// Test does the folder exist or not.
/// Returns true if the folder exists.
bool Exists()const;
/// Create the folder.
/// Returns true if this operation succeeded.
/// Set to true to create all levels of containing folders if they do not exist.
///
/// 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.
///
bool Create(bool recursively)const;
/// Delete the folder.
/// Returns true if this operation succeeded.
/// Set to true to delete everything in the folder.
/// This function could return before the folder is actually deleted.
bool Delete(bool recursively)const;
/// Rename the folder.
/// Returns true if this operation succeeded.
/// The new folder name.
bool Rename(const WString& newName)const;
};
}
}
#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
{
///
/// A readable stream that, reads from one stream, and copy everything that is read to another stream.
/// The stream is unavailable if one of the input stream or the output stream is unavailable.
/// The stream is readable, and potentially finite.
///
///
/// When reading happens, the recorder stream will only performance one write attempt to the output stream.
///
class RecorderStream : public Object, public virtual IStream
{
protected:
IStream* in;
IStream* out;
public:
/// Create a recorder stream.
///
/// The input stream.
/// This recorder stream is readable only when the input stream is readable
/// This recorder stream is finite only when the input stream is finite
///
///
/// The output stream.
///
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