Files
GacUI/Import/Vlpp.cpp
2023-04-30 02:21:30 -07:00

1498 lines
42 KiB
C++

/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "Vlpp.h"
/***********************************************************************
.\BASIC.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
namespace vl
{
/***********************************************************************
Error
***********************************************************************/
Error::Error(const wchar_t* _description)
{
description=_description;
}
const wchar_t* Error::Description()const
{
return description;
}
}
/***********************************************************************
.\CONSOLE.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
namespace vl
{
namespace console
{
/***********************************************************************
Console
***********************************************************************/
void Console::Write(const wchar_t* string)
{
Write(string, wcslen(string));
}
void Console::Write(const WString& string)
{
Write(string.Buffer(), string.Length());
}
void Console::WriteLine(const WString& string)
{
Write(string);
Write(L"\r\n");
}
}
}
/***********************************************************************
.\EXCEPTION.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
namespace vl
{
/***********************************************************************
Exception
***********************************************************************/
Exception::Exception(const WString& _message)
:message(_message)
{
}
const WString& Exception::Message()const
{
return message;
}
/***********************************************************************
ArgumentException
***********************************************************************/
ArgumentException::ArgumentException(const WString& _message, const WString& _function, const WString& _name)
:Exception(_message)
,function(_function)
,name(_name)
{
}
const WString& ArgumentException::GetFunction()const
{
return function;
}
const WString& ArgumentException::GetName()const
{
return name;
}
}
/***********************************************************************
.\GLOBALSTORAGE.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
namespace vl
{
using namespace collections;
/***********************************************************************
Helper Functions
***********************************************************************/
GlobalStorageDescriptor* firstGlobalStorageDescriptor = nullptr;
GlobalStorageDescriptor** lastGlobalStorageDescriptor = &firstGlobalStorageDescriptor;
void RegisterStorageDescriptor(GlobalStorageDescriptor* globalStorageDescriptor)
{
*lastGlobalStorageDescriptor = globalStorageDescriptor;
lastGlobalStorageDescriptor = &globalStorageDescriptor->next;
}
void FinalizeGlobalStorage()
{
auto current = firstGlobalStorageDescriptor;
while (current)
{
current->globalStorage->EnsureFinalized();
current = current->next;
}
}
/***********************************************************************
GlobalStorage
***********************************************************************/
GlobalStorage::GlobalStorage()
{
}
GlobalStorage::~GlobalStorage()
{
}
bool GlobalStorage::IsInitialized()
{
return initialized;
}
void GlobalStorage::EnsureInitialized()
{
if (!initialized)
{
initialized = true;
InitializeResource();
}
}
void GlobalStorage::EnsureFinalized()
{
if (initialized)
{
initialized = false;
FinalizeResource();
}
}
}
/***********************************************************************
.\COLLECTIONS\PARTIALORDERING.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
namespace vl
{
namespace collections
{
using namespace po;
/***********************************************************************
PartialOrderingProcessor
***********************************************************************/
void PartialOrderingProcessor::InitNodes(vint itemCount)
{
nodes.Resize(itemCount);
for (vint i = 0; i < itemCount; i++)
{
auto& node = nodes[i];
node.ins = &emptyList;
node.outs = &emptyList;
vint inIndex = ins.Keys().IndexOf(i);
vint outIndex = outs.Keys().IndexOf(i);
if (inIndex != -1)
{
node.ins = &ins.GetByIndex(inIndex);
}
if (outIndex != -1)
{
node.outs = &outs.GetByIndex(outIndex);
}
}
}
void PartialOrderingProcessor::VisitUnvisitedNode(po::Node& node, Array<vint>& reversedOrder, vint& used)
{
node.visited = true;
for (vint i = node.outs->Count() - 1; i >= 0; i--)
{
auto& outNode = nodes[node.outs->Get(i)];
if (!outNode.visited)
{
VisitUnvisitedNode(outNode, reversedOrder, used);
}
}
reversedOrder[used++] = (vint)(&node - &nodes[0]);
}
void PartialOrderingProcessor::AssignUnassignedNode(po::Node& node, vint componentIndex, vint& used)
{
node.component = componentIndex;
firstNodesBuffer[used++] = (vint)(&node - &nodes[0]);
for (vint i = 0; i < node.ins->Count(); i++)
{
auto& inNode = nodes[node.ins->Get(i)];
if (inNode.component == -1)
{
AssignUnassignedNode(inNode, componentIndex, used);
}
}
}
void PartialOrderingProcessor::Sort()
{
// Kosaraju's Algorithm
CHECK_ERROR(components.Count() == 0, L"PartialOrdering::Sort()#Sorting twice is not allowed.");
Array<vint> reversedOrder(nodes.Count());
{
vint used = 0;
for (vint i = nodes.Count() - 1; i >= 0; i--)
{
auto& node = nodes[i];
if (!node.visited)
{
VisitUnvisitedNode(node, reversedOrder, used);
}
}
}
firstNodesBuffer.Resize(nodes.Count());
{
vint lastUsed = 0;
vint used = 0;
for (vint i = reversedOrder.Count() - 1; i >= 0; i--)
{
auto& node = nodes[reversedOrder[i]];
if (node.component == -1)
{
AssignUnassignedNode(node, components.Count(), used);
Component component;
component.firstNode = &firstNodesBuffer[lastUsed];
component.nodeCount = used - lastUsed;
lastUsed = used;
components.Add(component);
}
}
}
}
}
}
/***********************************************************************
.\STRINGS\CONVERSION.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#if defined VCZH_GCC
#include <stdio.h>
#include <ctype.h>
#include <wctype.h>
#endif
namespace vl
{
namespace encoding
{
__forceinline bool IsInvalid(char32_t c)
{
return 0xD800U <= c && c <= 0xDFFFU;
}
/***********************************************************************
UtfConversion<wchar_t>
***********************************************************************/
vint UtfConversion<wchar_t>::From32(char32_t source, wchar_t(&dest)[BufferLength])
{
#if defined VCZH_WCHAR_UTF16
return UtfConversion<char16_t>::From32(source, reinterpret_cast<char16_t(&)[BufferLength]>(dest));
#elif defined VCZH_WCHAR_UTF32
dest[0] = static_cast<wchar_t>(source);
return 1;
#endif
}
vint UtfConversion<wchar_t>::To32(const wchar_t* source, vint sourceLength, char32_t& dest)
{
#if defined VCZH_WCHAR_UTF16
return UtfConversion<char16_t>::To32(reinterpret_cast<const char16_t*>(source), sourceLength, dest);
#elif defined VCZH_WCHAR_UTF32
if (sourceLength <= 0) return -1;
dest = static_cast<char32_t>(source[0]);
return 1;
#endif
}
/***********************************************************************
UtfConversion<char8_t>
***********************************************************************/
/*
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
*/
vint UtfConversion<char8_t>::From32(char32_t source, char8_t(&dest)[BufferLength])
{
if (IsInvalid(source)) return -1;
vuint32_t c = static_cast<vuint32_t>(source);
vuint8_t(&ds)[BufferLength] = reinterpret_cast<vuint8_t(&)[BufferLength]>(dest);
if (c <= 0x0000007FUL)
{
ds[0] = static_cast<vuint8_t>(c);
return 1;
}
else if (c <= 0x000007FFUL)
{
ds[0] = static_cast<vuint8_t>((c >> 6) | 0b11000000U);
ds[1] = static_cast<vuint8_t>((c & 0b00111111U) | 0b10000000U);
return 2;
}
else if (c <= 0x0000FFFFUL)
{
ds[0] = static_cast<vuint8_t>((c >> 12) | 0b11100000U);
ds[1] = static_cast<vuint8_t>(((c >> 6) & 0b00111111U) | 0b10000000U);
ds[2] = static_cast<vuint8_t>((c & 0b00111111U) | 0b10000000U);
return 3;
}
else if (c <= 0x001FFFFFUL)
{
ds[0] = static_cast<vuint8_t>((c >> 18) | 0b11110000U);
ds[1] = static_cast<vuint8_t>(((c >> 12) & 0b00111111U) | 0b10000000U);
ds[2] = static_cast<vuint8_t>(((c >> 6) & 0b00111111U) | 0b10000000U);
ds[3] = static_cast<vuint8_t>((c & 0b00111111U) | 0b10000000U);
return 4;
}
else if (c <= 0x03FFFFFFUL)
{
ds[0] = static_cast<vuint8_t>((c >> 24) | 0b11111000U);
ds[1] = static_cast<vuint8_t>(((c >> 18) & 0b00111111U) | 0b10000000U);
ds[2] = static_cast<vuint8_t>(((c >> 12) & 0b00111111U) | 0b10000000U);
ds[3] = static_cast<vuint8_t>(((c >> 6) & 0b00111111U) | 0b10000000U);
ds[4] = static_cast<vuint8_t>((c & 0b00111111U) | 0b10000000U);
return 5;
}
else if (c <= 0x7FFFFFFFUL)
{
ds[0] = static_cast<vuint8_t>((c >> 30) | 0b11111100U);
ds[1] = static_cast<vuint8_t>(((c >> 24) & 0b00111111U) | 0b10000000U);
ds[2] = static_cast<vuint8_t>(((c >> 18) & 0b00111111U) | 0b10000000U);
ds[3] = static_cast<vuint8_t>(((c >> 12) & 0b00111111U) | 0b10000000U);
ds[4] = static_cast<vuint8_t>(((c >> 6) & 0b00111111U) | 0b10000000U);
ds[5] = static_cast<vuint8_t>((c & 0b00111111U) | 0b10000000U);
return 6;
}
else
{
return -1;
}
}
vint UtfConversion<char8_t>::To32(const char8_t* source, vint sourceLength, char32_t& dest)
{
const vuint8_t* cs = reinterpret_cast<const vuint8_t*>(source);
vuint32_t& d = reinterpret_cast<vuint32_t&>(dest);
if (sourceLength <= 0) return -1;
if (cs[0] < 0b10000000U)
{
d = cs[0];
return 1;
}
else if (cs[0] < 0b11100000U)
{
if (sourceLength < 2) return -1;
d = ((static_cast<vuint32_t>(cs[0]) & 0b00011111U) << 6) |
((static_cast<vuint32_t>(cs[1]) & 0b00111111U));
return 2;
}
else if (cs[0] < 0b11110000U)
{
if (sourceLength < 3) return -1;
d = ((static_cast<vuint32_t>(cs[0]) & 0b00001111U) << 12) |
((static_cast<vuint32_t>(cs[1]) & 0b00111111U) << 6) |
((static_cast<vuint32_t>(cs[2]) & 0b00111111U));
return 3;
}
else if (cs[0] < 0b11111000U)
{
if (sourceLength < 4) return -1;
d = ((static_cast<vuint32_t>(cs[0]) & 0b00000111U) << 18) |
((static_cast<vuint32_t>(cs[1]) & 0b00111111U) << 12) |
((static_cast<vuint32_t>(cs[2]) & 0b00111111U) << 6) |
((static_cast<vuint32_t>(cs[3]) & 0b00111111U));
return 4;
}
else if (cs[0] < 0b11111100U)
{
if (sourceLength < 5) return -1;
d = ((static_cast<vuint32_t>(cs[0]) & 0b00000011U) << 24) |
((static_cast<vuint32_t>(cs[1]) & 0b00111111U) << 18) |
((static_cast<vuint32_t>(cs[2]) & 0b00111111U) << 12) |
((static_cast<vuint32_t>(cs[3]) & 0b00111111U) << 6) |
((static_cast<vuint32_t>(cs[4]) & 0b00111111U));
return 5;
}
else
{
if (sourceLength < 6) return -1;
d = ((static_cast<vuint32_t>(cs[0]) & 0b00000001U) << 30) |
((static_cast<vuint32_t>(cs[1]) & 0b00111111U) << 24) |
((static_cast<vuint32_t>(cs[2]) & 0b00111111U) << 18) |
((static_cast<vuint32_t>(cs[3]) & 0b00111111U) << 12) |
((static_cast<vuint32_t>(cs[4]) & 0b00111111U) << 6) |
((static_cast<vuint32_t>(cs[5]) & 0b00111111U));
return 6;
}
if (IsInvalid(dest)) return -1;
return 1;
}
/***********************************************************************
UtfConversion<char16_t>
***********************************************************************/
/*
How UCS-4 translates to UTF-16 Surrogate Pair
U' = yyyyyyyyyyxxxxxxxxxx // U - 0x10000
W1 = 110110yyyyyyyyyy // 0xD800 + yyyyyyyyyy
W2 = 110111xxxxxxxxxx // 0xDC00 + xxxxxxxxxx
*/
vint UtfConversion<char16_t>::From32(char32_t source, char16_t(&dest)[BufferLength])
{
if (IsInvalid(source)) return -1;
vuint32_t c = static_cast<vuint32_t>(source);
vuint16_t(&ds)[BufferLength] = reinterpret_cast<vuint16_t(&)[BufferLength]>(dest);
if (0x000000UL <= c && c <= 0x00D7FFUL)
{
ds[0] = static_cast<vuint16_t>(c);
return 1;
}
else if (0x00E000UL <= c && c <= 0x00FFFFUL)
{
ds[0] = static_cast<vuint16_t>(c);
return 1;
}
else if (0x010000UL <= c && c <= 0x10FFFFUL)
{
c -= 0x010000UL;
ds[0] = static_cast<vuint16_t>((c >> 10) | 0xD800U);
ds[1] = static_cast<vuint16_t>((c & 0x03FFU) | 0xDC00U);
return 2;
}
else
{
return -1;
}
}
vint UtfConversion<char16_t>::To32(const char16_t* source, vint sourceLength, char32_t& dest)
{
const vuint16_t* cs = reinterpret_cast<const vuint16_t* >(source);
vuint32_t& d = reinterpret_cast<vuint32_t&>(dest);
if (sourceLength <= 0) return -1;
if ((cs[0] & 0xFC00U) == 0xD800U)
{
if (sourceLength < 2) return -1;
if ((cs[1] & 0xFC00U) == 0xDC00U)
{
d = 0x010000UL + (
((static_cast<vuint32_t>(cs[0]) & 0x03FF) << 10) |
(static_cast<vuint32_t>(cs[1]) & 0x03FF)
);
if (IsInvalid(dest)) return -1;
return 2;
}
else
{
return -1;
}
}
else
{
d = cs[0];
if (IsInvalid(dest)) return -1;
return 1;
}
}
}
/***********************************************************************
String Conversions (buffer walkthrough)
***********************************************************************/
template<typename TFrom, typename TTo, typename TReader>
vint _utftoutf_reader(const TFrom* s, TTo* d, vint chars)
{
TReader reader(s);
vint size = 0;
if (d == nullptr)
{
while (reader.Read()) size++;
return reader.HasIllegalChar() ? -1 : size + 1;
}
else
{
while (true)
{
if (chars == 0) break;
auto c = reader.Read();
*d++ = c;
size++;
chars--;
if (!c) break;
}
return reader.HasIllegalChar() ? -1 : size;
}
}
template<typename T>
vint _utftou32(const T* s, char32_t* d, vint chars)
{
return _utftoutf_reader<T, char32_t, encoding::UtfStringTo32Reader<T>>(s, d, chars);
}
template<typename T>
vint _u32toutf(const char32_t* s, T* d, vint chars)
{
return _utftoutf_reader<char32_t, T, encoding::UtfStringFrom32Reader<T>>(s, d, chars);
}
template vint _utftou32<wchar_t>(const wchar_t* s, char32_t* d, vint chars);
template vint _utftou32<char8_t>(const char8_t* s, char32_t* d, vint chars);
template vint _utftou32<char16_t>(const char16_t* s, char32_t* d, vint chars);
template vint _u32toutf<wchar_t>(const char32_t* s, wchar_t* d, vint chars);
template vint _u32toutf<char8_t>(const char32_t* s, char8_t* d, vint chars);
template vint _u32toutf<char16_t>(const char32_t* s, char16_t* d, vint chars);
/***********************************************************************
String Conversions (direct)
***********************************************************************/
template<typename TFrom, typename TTo, vint(*Convert)(const TFrom*, TTo*, vint)>
ObjectString<TTo> ConvertStringDirect(const ObjectString<TFrom>& source)
{
vint len = Convert(source.Buffer(), nullptr, 0);
if (len < 1) return {};
TTo* buffer = new TTo[len];
memset(buffer, 0, len * sizeof(TTo));
Convert(source.Buffer(), buffer, len);
return ObjectString<TTo>::TakeOver(buffer, len - 1);
}
AString wtoa (const WString& source) { return ConvertStringDirect<wchar_t, char, _wtoa>(source); }
WString atow (const AString& source) { return ConvertStringDirect<char, wchar_t, _atow>(source); }
#if defined VCZH_WCHAR_UTF16
U32String wtou32 (const WString& source) { return ConvertStringDirect<wchar_t, char32_t, _utftou32<wchar_t>>(source); }
WString u32tow (const U32String& source) { return ConvertStringDirect<char32_t, wchar_t, _u32toutf<wchar_t>>(source); }
#elif defined VCZH_WCHAR_UTF32
U32String wtou32 (const WString& source) { return U32String::UnsafeCastFrom(source); }
WString u32tow (const U32String& source) { return WString::UnsafeCastFrom(source); }
#endif
U32String u8tou32 (const U8String& source) { return ConvertStringDirect<char8_t, char32_t, _utftou32<char8_t>>(source); }
U8String u32tou8 (const U32String& source) { return ConvertStringDirect<char32_t, char8_t, _u32toutf<char8_t>>(source); }
U32String u16tou32(const U16String& source) { return ConvertStringDirect<char16_t, char32_t, _utftou32<char16_t>>(source); }
U16String u32tou16(const U32String& source) { return ConvertStringDirect<char32_t, char16_t, _u32toutf<char16_t>>(source); }
/***********************************************************************
String Conversions (buffer walkthrough indirect)
***********************************************************************/
template<typename TFrom, typename TTo>
vint _utftoutf(const TFrom* s, TTo* d, vint chars)
{
return _utftoutf_reader<TFrom, TTo, encoding::UtfStringToStringReader<TFrom, TTo>>(s, d, chars);
}
template vint _utftoutf<wchar_t, char8_t>(const wchar_t* s, char8_t* d, vint chars);
template vint _utftoutf<wchar_t, char16_t>(const wchar_t* s, char16_t* d, vint chars);
template vint _utftoutf<char8_t, wchar_t>(const char8_t* s, wchar_t* d, vint chars);
template vint _utftoutf<char8_t, char16_t>(const char8_t* s, char16_t* d, vint chars);
template vint _utftoutf<char16_t, wchar_t>(const char16_t* s, wchar_t* d, vint chars);
template vint _utftoutf<char16_t, char8_t>(const char16_t* s, char8_t* d, vint chars);
/***********************************************************************
String Conversions (unicode indirect)
***********************************************************************/
U8String wtou8 (const WString& source) { return ConvertStringDirect<wchar_t, char8_t, _utftoutf<wchar_t, char8_t>>(source); }
WString u8tow (const U8String& source) { return ConvertStringDirect<char8_t, wchar_t, _utftoutf<char8_t, wchar_t>>(source); }
#if defined VCZH_WCHAR_UTF16
U16String wtou16 (const WString& source) { return U16String::UnsafeCastFrom(source); }
WString u16tow (const U16String& source) { return WString::UnsafeCastFrom(source); }
#elif defined VCZH_WCHAR_UTF32
U16String wtou16 (const WString& source) { return ConvertStringDirect<wchar_t, char16_t, _utftoutf<wchar_t, char16_t>>(source); }
WString u16tow (const U16String& source) { return ConvertStringDirect<char16_t, wchar_t, _utftoutf<char16_t, wchar_t>>(source); }
#endif
U16String u8tou16 (const U8String& source) { return ConvertStringDirect<char8_t, char16_t, _utftoutf<char8_t, char16_t>>(source); }
U8String u16tou8 (const U16String& source) { return ConvertStringDirect<char16_t, char8_t, _utftoutf<char16_t, char8_t>>(source); }
}
/***********************************************************************
.\STRINGS\LOREMIPSUM.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#include <time.h>
namespace vl
{
WString LoremIpsum(vint bestLength, LoremIpsumCasing casing)
{
static const wchar_t* words[] =
{
L"lorem", L"ipsum", L"dolor", L"sit", L"amet", L"consectetur", L"adipiscing", L"elit", L"integer",
L"nec", L"odio", L"praesent", L"libero", L"sed", L"cursus", L"ante", L"dapibus", L"diam",
L"sed", L"nisi", L"nulla", L"quis", L"sem", L"at", L"nibh", L"elementum", L"imperdiet", L"duis",
L"sagittis", L"ipsum", L"praesent", L"mauris", L"fusce", L"nec", L"tellus", L"sed", L"augue",
L"semper", L"porta", L"mauris", L"massa", L"vestibulum", L"lacinia", L"arcu", L"eget", L"nulla",
L"class", L"aptent", L"taciti", L"sociosqu", L"ad", L"litora", L"torquent", L"per", L"conubia",
L"nostra", L"per", L"inceptos", L"himenaeos", L"curabitur", L"sodales", L"ligula", L"in",
L"libero", L"sed", L"dignissim", L"lacinia", L"nunc", L"curabitur", L"tortor", L"pellentesque",
L"nibh", L"aenean", L"quam", L"in", L"scelerisque", L"sem", L"at", L"dolor", L"maecenas",
L"mattis", L"sed", L"convallis", L"tristique", L"sem", L"proin", L"ut", L"ligula", L"vel",
L"nunc", L"egestas", L"porttitor", L"morbi", L"lectus", L"risus", L"iaculis", L"vel", L"suscipit",
L"quis", L"luctus", L"non", L"massa", L"fusce", L"ac", L"turpis", L"quis", L"ligula", L"lacinia",
L"aliquet", L"mauris", L"ipsum", L"nulla", L"metus", L"metus", L"ullamcorper", L"vel", L"tincidunt",
L"sed", L"euismod", L"in", L"nibh", L"quisque", L"volutpat", L"condimentum", L"velit", L"class",
L"aptent", L"taciti", L"sociosqu", L"ad", L"litora", L"torquent", L"per", L"conubia", L"nostra",
L"per", L"inceptos", L"himenaeos", L"nam", L"nec", L"ante", L"sed", L"lacinia", L"urna",
L"non", L"tincidunt", L"mattis", L"tortor", L"neque", L"adipiscing", L"diam", L"a", L"cursus",
L"ipsum", L"ante", L"quis", L"turpis", L"nulla", L"facilisi", L"ut", L"fringilla", L"suspendisse",
L"potenti", L"nunc", L"feugiat", L"mi", L"a", L"tellus", L"consequat", L"imperdiet", L"vestibulum",
L"sapien", L"proin", L"quam", L"etiam", L"ultrices", L"suspendisse", L"in", L"justo", L"eu",
L"magna", L"luctus", L"suscipit", L"sed", L"lectus", L"integer", L"euismod", L"lacus", L"luctus",
L"magna", L"quisque", L"cursus", L"metus", L"vitae", L"pharetra", L"auctor", L"sem", L"massa",
L"mattis", L"sem", L"at", L"interdum", L"magna", L"augue", L"eget", L"diam", L"vestibulum",
L"ante", L"ipsum", L"primis", L"in", L"faucibus", L"orci", L"luctus", L"et", L"ultrices",
L"posuere", L"cubilia", L"curae;", L"morbi", L"lacinia", L"molestie", L"dui", L"praesent",
L"blandit", L"dolor", L"sed", L"non", L"quam", L"in", L"vel", L"mi", L"sit", L"amet", L"augue",
L"congue", L"elementum", L"morbi", L"in", L"ipsum", L"sit", L"amet", L"pede", L"facilisis",
L"laoreet", L"donec", L"lacus", L"nunc", L"viverra", L"nec", L"blandit", L"vel", L"egestas",
L"et", L"augue", L"vestibulum", L"tincidunt", L"malesuada", L"tellus", L"ut", L"ultrices",
L"ultrices", L"enim", L"curabitur", L"sit", L"amet", L"mauris", L"morbi", L"in", L"dui",
L"quis", L"est", L"pulvinar", L"ullamcorper", L"nulla", L"facilisi", L"integer", L"lacinia",
L"sollicitudin", L"massa", L"cras", L"metus", L"sed", L"aliquet", L"risus", L"a", L"tortor",
L"integer", L"id", L"quam", L"morbi", L"mi", L"quisque", L"nisl", L"felis", L"venenatis",
L"tristique", L"dignissim", L"in", L"ultrices", L"sit", L"amet", L"augue", L"proin", L"sodales",
L"libero", L"eget", L"ante", L"nulla", L"quam", L"aenean", L"laoreet", L"vestibulum", L"nisi",
L"lectus", L"commodo", L"ac", L"facilisis", L"ac", L"ultricies", L"eu", L"pede", L"ut", L"orci",
L"risus", L"accumsan", L"porttitor", L"cursus", L"quis", L"aliquet", L"eget", L"justo",
L"sed", L"pretium", L"blandit", L"orci", L"ut", L"eu", L"diam", L"at", L"pede", L"suscipit",
L"sodales", L"aenean", L"lectus", L"elit", L"fermentum", L"non", L"convallis", L"id", L"sagittis",
L"at", L"neque", L"nullam", L"mauris", L"orci", L"aliquet", L"et", L"iaculis", L"et", L"viverra",
L"vitae", L"ligula", L"nulla", L"ut", L"felis", L"in", L"purus", L"aliquam", L"imperdiet",
L"maecenas", L"aliquet", L"mollis", L"lectus", L"vivamus", L"consectetuer", L"risus", L"et",
L"tortor"
};
static vint index = 0;
const vint WordCount = sizeof(words) / sizeof(*words);
if (bestLength < 0) bestLength = 0;
vint bufferLength = bestLength + 20;
wchar_t* buffer = new wchar_t[bufferLength + 1];
buffer[0] = 0;
vint used = 0;
wchar_t* writing = buffer;
while (used < bestLength)
{
if (used != 0)
{
*writing++ = L' ';
used++;
}
vint wordSize = (vint)wcslen(words[index]);
wcscpy_s(writing, bufferLength - used, words[index]);
if (casing == LoremIpsumCasing::AllWordsUpperCase || (casing == LoremIpsumCasing::FirstWordUpperCase && used == 0))
{
*writing -= L'a' - L'A';
}
if (used != 0 && used + wordSize > bestLength)
{
vint deltaShort = bestLength - used + 1;
vint deltaLong = used + wordSize - bestLength;
if (deltaShort < deltaLong)
{
*--writing = 0;
used--;
break;
}
}
writing += wordSize;
used += wordSize;
index = (index + 1) % WordCount;
}
WString result = buffer;
delete[] buffer;
return result;
}
WString LoremIpsumTitle(vint bestLength)
{
return LoremIpsum(bestLength, LoremIpsumCasing::AllWordsUpperCase);
}
WString LoremIpsumSentence(vint bestLength)
{
return LoremIpsum(bestLength, LoremIpsumCasing::FirstWordUpperCase) + L".";
}
WString LoremIpsumParagraph(vint bestLength)
{
srand((unsigned)time(0));
auto casing = LoremIpsumCasing::FirstWordUpperCase;
vint comma = 0;
WString result;
while (result.Length() < bestLength)
{
vint offset = bestLength - result.Length();
if (comma == 0)
{
comma = rand() % 4 + 1;
}
vint length = rand() % 45 + 15;
if (offset < 20)
{
comma = 0;
length = offset - 1;
}
else if (length > offset)
{
comma = 0;
length = offset + rand() % 11 - 5;
}
result += LoremIpsum(length, casing);
if (comma == 0)
{
result += L".";
break;
}
else if (comma == 1)
{
result += L". ";
casing = LoremIpsumCasing::FirstWordUpperCase;
}
else
{
result += L", ";
casing = LoremIpsumCasing::AllWordsLowerCase;
}
comma--;
}
return result;
}
}
/***********************************************************************
.\STRINGS\STRING.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#if defined VCZH_MSVC
#elif defined VCZH_GCC
#define _strtoi64 strtoll
#define _strtoui64 strtoull
#define _wcstoi64 wcstoll
#define _wcstoui64 wcstoull
#endif
namespace vl
{
#if defined VCZH_GCC
void _itoa_s(vint32_t value, char* buffer, size_t size, vint radix)
{
sprintf(buffer, "%d", value);
}
void _itow_s(vint32_t value, wchar_t* buffer, size_t size, vint radix)
{
swprintf(buffer, size - 1, L"%d", value);
}
void _i64toa_s(vint64_t value, char* buffer, size_t size, vint radix)
{
sprintf(buffer, "%ld", value);
}
void _i64tow_s(vint64_t value, wchar_t* buffer, size_t size, vint radix)
{
swprintf(buffer, size - 1, L"%ld", value);
}
void _uitoa_s(vuint32_t value, char* buffer, size_t size, vint radix)
{
sprintf(buffer, "%u", value);
}
void _uitow_s(vuint32_t value, wchar_t* buffer, size_t size, vint radix)
{
swprintf(buffer, size - 1, L"%u", value);
}
void _ui64toa_s(vuint64_t value, char* buffer, size_t size, vint radix)
{
sprintf(buffer, "%lu", value);
}
void _ui64tow_s(vuint64_t value, wchar_t* buffer, size_t size, vint radix)
{
swprintf(buffer, size - 1, L"%lu", value);
}
void _gcvt_s(char* buffer, size_t size, double value, vint numberOfDigits)
{
sprintf(buffer, "%f", value);
char* point = strchr(buffer, '.');
if(!point) return;
char* zero = buffer + strlen(buffer);
while(zero[-1] == '0')
{
*--zero = '\0';
}
if(zero[-1] == '.') *--zero = '\0';
}
void _strlwr_s(char* buffer, size_t size)
{
while(*buffer)
{
*buffer=(char)tolower(*buffer);
buffer++;
}
}
void _strupr_s(char* buffer, size_t size)
{
while(*buffer)
{
*buffer=(char)toupper(*buffer);
buffer++;
}
}
void _wcslwr_s(wchar_t* buffer, size_t size)
{
while(*buffer)
{
*buffer=(char)towlower(*buffer);
buffer++;
}
}
void _wcsupr_s(wchar_t* buffer, size_t size)
{
while(*buffer)
{
*buffer=(char)towupper(*buffer);
buffer++;
}
}
void wcscpy_s(wchar_t* buffer, size_t size, const wchar_t* text)
{
wcscpy(buffer, text);
}
#endif
vint atoi_test(const AString& string, bool& success)
{
char* endptr = 0;
vint result = strtol(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && itoa(result) == string;
if (success) success &= (_I32_MIN <= result && result <= _I32_MAX);
return result;
}
vint wtoi_test(const WString& string, bool& success)
{
wchar_t* endptr = 0;
vint result = wcstol(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && itow(result) == string;
if (success) success &= (_I32_MIN <= result && result <= _I32_MAX);
return result;
}
vint64_t atoi64_test(const AString& string, bool& success)
{
char* endptr = 0;
vint64_t result = _strtoi64(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && i64toa(result) == string;
return result;
}
vint64_t wtoi64_test(const WString& string, bool& success)
{
wchar_t* endptr = 0;
vint64_t result = _wcstoi64(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && i64tow(result) == string;
return result;
}
vuint atou_test(const AString& string, bool& success)
{
char* endptr = 0;
vuint result = strtoul(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && utoa(result) == string;
if (success) success &= (result <= _UI32_MAX);
return result;
}
vuint wtou_test(const WString& string, bool& success)
{
wchar_t* endptr = 0;
vuint result = wcstoul(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && utow(result) == string;
if (success) success &= (result <= _UI32_MAX);
return result;
}
vuint64_t atou64_test(const AString& string, bool& success)
{
char* endptr = 0;
vuint64_t result = _strtoui64(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && u64toa(result) == string;
return result;
}
vuint64_t wtou64_test(const WString& string, bool& success)
{
wchar_t* endptr = 0;
vuint64_t result = _wcstoui64(string.Buffer(), &endptr, 10);
success = endptr == string.Buffer() + string.Length() && u64tow(result) == string;
return result;
}
double atof_test(const AString& string, bool& success)
{
char* endptr = 0;
double result = strtod(string.Buffer(), &endptr);
success = endptr == string.Buffer() + string.Length();
return result;
}
double wtof_test(const WString& string, bool& success)
{
wchar_t* endptr = 0;
double result = wcstod(string.Buffer(), &endptr);
success = endptr == string.Buffer() + string.Length();
return result;
}
vint atoi(const AString& string)
{
bool success = false;
vint result = atoi_test(string, success);
return success ? result : 0;
}
vint wtoi(const WString& string)
{
bool success = false;
vint result = wtoi_test(string, success);
return success ? result : 0;
}
vint64_t atoi64(const AString& string)
{
bool success = false;
vint64_t result = atoi64_test(string, success);
return success ? result : 0;
}
vint64_t wtoi64(const WString& string)
{
bool success = false;
vint64_t result = wtoi64_test(string, success);
return success ? result : 0;
}
vuint atou(const AString& string)
{
bool success = false;
vuint result = atou_test(string, success);
return success ? result : 0;
}
vuint wtou(const WString& string)
{
bool success = false;
vuint result = wtou_test(string, success);
return success ? result : 0;
}
vuint64_t atou64(const AString& string)
{
bool success = false;
vuint64_t result = atou64_test(string, success);
return success ? result : 0;
}
vuint64_t wtou64(const WString& string)
{
bool success = false;
vuint64_t result = wtou64_test(string, success);
return success ? result : 0;
}
double atof(const AString& string)
{
bool success = false;
double result = atof_test(string, success);
return success ? result : 0;
}
double wtof(const WString& string)
{
bool success = false;
double result = wtof_test(string, success);
return success ? result : 0;
}
AString itoa(vint number)
{
char buffer[100];
ITOA_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
WString itow(vint number)
{
wchar_t buffer[100];
ITOW_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
AString i64toa(vint64_t number)
{
char buffer[100];
I64TOA_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
WString i64tow(vint64_t number)
{
wchar_t buffer[100];
I64TOW_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
AString utoa(vuint number)
{
char buffer[100];
UITOA_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
WString utow(vuint number)
{
wchar_t buffer[100];
UITOW_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
AString u64toa(vuint64_t number)
{
char buffer[100];
UI64TOA_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
WString u64tow(vuint64_t number)
{
wchar_t buffer[100];
UI64TOW_S(number, buffer, sizeof(buffer) / sizeof(*buffer), 10);
return buffer;
}
AString ftoa(double number)
{
char buffer[320];
_gcvt_s(buffer, 320, number, 30);
vint len = (vint)strlen(buffer);
if (buffer[len - 1] == '.')
{
buffer[len - 1] = '\0';
}
return buffer;
}
WString ftow(double number)
{
return atow(ftoa(number));
}
AString alower(const AString& string)
{
AString result = string.Buffer();
_strlwr_s((char*)result.Buffer(), result.Length() + 1);
return result;
}
WString wlower(const WString& string)
{
WString result = string.Buffer();
_wcslwr_s((wchar_t*)result.Buffer(), result.Length() + 1);
return result;
}
AString aupper(const AString& string)
{
AString result = string.Buffer();
_strupr_s((char*)result.Buffer(), result.Length() + 1);
return result;
}
WString wupper(const WString& string)
{
WString result = string.Buffer();
_wcsupr_s((wchar_t*)result.Buffer(), result.Length() + 1);
return result;
}
}
/***********************************************************************
.\UNITTEST\UNITTEST.CPP
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
namespace vl
{
namespace unittest
{
using namespace vl::console;
/***********************************************************************
UnitTest
***********************************************************************/
namespace execution_impl
{
UnitTestLink* testHead = nullptr;
UnitTestLink** testTail = &testHead;
enum class UnitTestContextKind
{
File,
Category,
Case,
};
struct UnitTestContext
{
UnitTestContext* parent = nullptr;
WString indentation;
UnitTestContextKind kind = UnitTestContextKind::File;
bool failed = false;
};
UnitTestContext* testContext = nullptr;
vint totalFiles = 0;
vint passedFiles = 0;
vint totalCases = 0;
vint passedCases = 0;
bool suppressFailure = false;
template<typename TMessage>
void RecordFailure(TMessage errorMessage)
{
UnitTest::PrintMessage(errorMessage, UnitTest::MessageKind::Error);
auto current = testContext;
while (current)
{
current->failed = true;
current = current->parent;
}
}
template<typename TCallback>
void SuppressCppFailure(TCallback&& callback)
{
try
{
callback();
}
catch (const UnitTestAssertError& e)
{
RecordFailure(e.message);
}
catch (const UnitTestConfigError& e)
{
RecordFailure(e.message);
}
catch (const Error& e)
{
RecordFailure(e.Description());
}
catch (const Exception& e)
{
RecordFailure(e.Message());
}
catch (...)
{
RecordFailure(L"Unknown exception occurred!");
}
}
template<typename TCallback>
void SuppressCFailure(TCallback&& callback)
{
#ifdef VCZH_MSVC
__try
{
SuppressCppFailure(std::forward<TCallback&&>(callback));
}
__except (/*EXCEPTION_EXECUTE_HANDLER*/ 1)
{
RecordFailure(L"Runtime exception occurred!");
}
#else
SuppressCppFailure(callback);
#endif
}
template<typename TCallback>
void ExecuteAndSuppressFailure(TCallback&& callback)
{
if (suppressFailure)
{
SuppressCFailure(std::forward<TCallback&&>(callback));
}
else
{
callback();
}
}
}
using namespace execution_impl;
void UnitTest::PrintMessage(const WString& string, MessageKind kind)
{
if (kind != MessageKind::Error && !testContext)
{
throw UnitTestConfigError(L"Cannot print message when unit test is not running.");
}
switch (kind)
{
case MessageKind::Error:
Console::SetColor(true, false, false, true);
break;
case MessageKind::Info:
Console::SetColor(true, true, true, true);
break;
case MessageKind::File:
Console::SetColor(true, false, true, true);
break;
case MessageKind::Category:
Console::SetColor(true, true, false, true);
break;
case MessageKind::Case:
Console::SetColor(false, true, false, true);
break;
}
Console::WriteLine((testContext ? testContext->indentation : L"") + string);
Console::SetColor(true, true, true, false);
}
int UnitTest::PrintUsages()
{
PrintMessage(L"Usage: [/D | /R]", MessageKind::Error);
return 1;
}
int UnitTest::RunAndDisposeTests(Nullable<WString> option)
{
if (option)
{
if (option.Value() == L"/D")
{
suppressFailure = false;
}
else if (option.Value() == L"/R")
{
suppressFailure = true;
}
else
{
return PrintUsages();
}
}
else if (IsDebuggerAttached())
{
suppressFailure = false;
}
else
{
suppressFailure = true;
}
{
UnitTestContext context;
testContext = &context;
totalFiles = 0;
passedFiles = 0;
totalCases = 0;
passedCases = 0;
if (suppressFailure)
{
PrintMessage(L"Failures are suppressed.", MessageKind::Info);
}
else
{
PrintMessage(L"Failures are not suppressed.", MessageKind::Info);
}
auto current = testHead;
while (current)
{
context.failed = false;
PrintMessage(atow(AString::Unmanaged(current->fileName)), MessageKind::File);
context.indentation = L" ";
ExecuteAndSuppressFailure(current->testProc);
if (!testContext->failed) passedFiles++;
totalFiles++;
context.indentation = L"";
current = current->next;
}
bool passed = totalFiles == passedFiles;
auto messageKind = passed ? MessageKind::Case : MessageKind::Error;
PrintMessage(L"Passed test files: " + itow(passedFiles) + L"/" + itow(totalFiles), messageKind);
PrintMessage(L"Passed test cases: " + itow(passedCases) + L"/" + itow(totalCases), messageKind);
testContext = nullptr;
return passed ? 0 : 1;
}
}
int UnitTest::RunAndDisposeTests(int argc, wchar_t* argv[])
{
if (argc < 3)
{
if (argc == 2)
{
return RunAndDisposeTests({ argv[1] });
}
else
{
return RunAndDisposeTests({});
}
}
else
{
return PrintUsages();
}
}
int UnitTest::RunAndDisposeTests(int argc, char* argv[])
{
if (argc < 3)
{
if (argc == 2)
{
return RunAndDisposeTests({ atow(argv[1]) });
}
else
{
return RunAndDisposeTests({});
}
}
else
{
return PrintUsages();
}
}
void UnitTest::RegisterTestFile(UnitTestLink* link)
{
*testTail = link;
testTail = &link->next;
}
void UnitTest::RunCategoryOrCase(const WString& description, bool isCategory, Func<void()>&& callback)
{
if (!testContext) throw UnitTestConfigError(L"TEST_CATEGORY is not allowed to execute outside of TEST_FILE.");
if (testContext->kind == UnitTestContextKind::Case) throw UnitTestConfigError(
isCategory ?
L"TEST_CATEGORY is not allowed to execute inside TEST_CASE" :
L"TEST_CASE is not allowed to execute inside TEST_CASE");
PrintMessage(description, (isCategory ? MessageKind::Category : MessageKind::Case));
UnitTestContext context;
context.parent = testContext;
context.indentation = testContext->indentation + L" ";
context.kind = isCategory ? UnitTestContextKind::Category : UnitTestContextKind::Case;
testContext = &context;
ExecuteAndSuppressFailure(callback);
if (!isCategory)
{
if (!testContext->failed) passedCases++;
totalCases++;
}
testContext = context.parent;
}
void UnitTest::EnsureLegalToAssert()
{
if (!testContext) throw UnitTestConfigError(L"Assertion is not allowed to execute outside of TEST_CASE.");
if (testContext->kind != UnitTestContextKind::Case) throw UnitTestConfigError(L"Assertion is not allowed to execute outside of TEST_CASE.");
}
}
}