/*********************************************************************** 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& 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 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); } } } } } } /*********************************************************************** .\PRIMITIVES\DATETIME.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { extern IDateTimeImpl* GetOSDateTimeImpl(); feature_injection::FeatureInjection& GetDateTimeInjection() { static feature_injection::FeatureInjection injection(GetOSDateTimeImpl()); return injection; } void InjectDateTimeImpl(IDateTimeImpl* impl) { GetDateTimeInjection().Inject(impl); } void EjectDateTimeImpl(IDateTimeImpl* impl) { if (impl == nullptr) { GetDateTimeInjection().EjectAll(); } else { GetDateTimeInjection().Eject(impl); } } /*********************************************************************** DateTime ***********************************************************************/ DateTime DateTime::LocalTime() { return GetDateTimeInjection().Get()->FromOSInternal(GetDateTimeInjection().Get()->LocalTime()); } DateTime DateTime::UtcTime() { return GetDateTimeInjection().Get()->FromOSInternal(GetDateTimeInjection().Get()->UtcTime()); } DateTime DateTime::FromDateTime(vint _year, vint _month, vint _day, vint _hour, vint _minute, vint _second, vint _milliseconds) { return GetDateTimeInjection().Get()->FromDateTime(_year, _month, _day, _hour, _minute, _second, _milliseconds); } DateTime DateTime::FromOSInternal(vuint64_t _osInternal) { return GetDateTimeInjection().Get()->FromOSInternal(_osInternal); } DateTime DateTime::ToLocalTime() { return GetDateTimeInjection().Get()->FromOSInternal(GetDateTimeInjection().Get()->UtcToLocalTime(osInternal)); } DateTime DateTime::ToUtcTime() { return GetDateTimeInjection().Get()->FromOSInternal(GetDateTimeInjection().Get()->LocalToUtcTime(osInternal)); } DateTime DateTime::Forward(vuint64_t milliseconds) { return GetDateTimeInjection().Get()->FromOSInternal(GetDateTimeInjection().Get()->Forward(osInternal, milliseconds)); } DateTime DateTime::Backward(vuint64_t milliseconds) { return GetDateTimeInjection().Get()->FromOSInternal(GetDateTimeInjection().Get()->Backward(osInternal, milliseconds)); } } /*********************************************************************** .\STRINGS\CONVERSION.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ #if defined VCZH_GCC #include #include #include #endif namespace vl { namespace encoding { __forceinline bool IsInvalid(char32_t c) { return 0xD800U <= c && c <= 0xDFFFU; } /*********************************************************************** UtfConversion ***********************************************************************/ vint UtfConversion::From32(char32_t source, wchar_t(&dest)[BufferLength]) { #if defined VCZH_WCHAR_UTF16 return UtfConversion::From32(source, reinterpret_cast(dest)); #elif defined VCZH_WCHAR_UTF32 dest[0] = static_cast(source); return 1; #endif } vint UtfConversion::To32(const wchar_t* source, vint sourceLength, char32_t& dest) { #if defined VCZH_WCHAR_UTF16 return UtfConversion::To32(reinterpret_cast(source), sourceLength, dest); #elif defined VCZH_WCHAR_UTF32 if (sourceLength <= 0) return -1; dest = static_cast(source[0]); return 1; #endif } /*********************************************************************** UtfConversion ***********************************************************************/ /* 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::From32(char32_t source, char8_t(&dest)[BufferLength]) { if (IsInvalid(source)) return -1; vuint32_t c = static_cast(source); vuint8_t(&ds)[BufferLength] = reinterpret_cast(dest); if (c <= 0x0000007FUL) { ds[0] = static_cast(c); return 1; } else if (c <= 0x000007FFUL) { ds[0] = static_cast((c >> 6) | 0b11000000U); ds[1] = static_cast((c & 0b00111111U) | 0b10000000U); return 2; } else if (c <= 0x0000FFFFUL) { ds[0] = static_cast((c >> 12) | 0b11100000U); ds[1] = static_cast(((c >> 6) & 0b00111111U) | 0b10000000U); ds[2] = static_cast((c & 0b00111111U) | 0b10000000U); return 3; } else if (c <= 0x001FFFFFUL) { ds[0] = static_cast((c >> 18) | 0b11110000U); ds[1] = static_cast(((c >> 12) & 0b00111111U) | 0b10000000U); ds[2] = static_cast(((c >> 6) & 0b00111111U) | 0b10000000U); ds[3] = static_cast((c & 0b00111111U) | 0b10000000U); return 4; } else if (c <= 0x03FFFFFFUL) { ds[0] = static_cast((c >> 24) | 0b11111000U); ds[1] = static_cast(((c >> 18) & 0b00111111U) | 0b10000000U); ds[2] = static_cast(((c >> 12) & 0b00111111U) | 0b10000000U); ds[3] = static_cast(((c >> 6) & 0b00111111U) | 0b10000000U); ds[4] = static_cast((c & 0b00111111U) | 0b10000000U); return 5; } else if (c <= 0x7FFFFFFFUL) { ds[0] = static_cast((c >> 30) | 0b11111100U); ds[1] = static_cast(((c >> 24) & 0b00111111U) | 0b10000000U); ds[2] = static_cast(((c >> 18) & 0b00111111U) | 0b10000000U); ds[3] = static_cast(((c >> 12) & 0b00111111U) | 0b10000000U); ds[4] = static_cast(((c >> 6) & 0b00111111U) | 0b10000000U); ds[5] = static_cast((c & 0b00111111U) | 0b10000000U); return 6; } else { return -1; } } vint UtfConversion::To32(const char8_t* source, vint sourceLength, char32_t& dest) { const vuint8_t* cs = reinterpret_cast(source); vuint32_t& d = reinterpret_cast(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(cs[0]) & 0b00011111U) << 6) | ((static_cast(cs[1]) & 0b00111111U)); return 2; } else if (cs[0] < 0b11110000U) { if (sourceLength < 3) return -1; d = ((static_cast(cs[0]) & 0b00001111U) << 12) | ((static_cast(cs[1]) & 0b00111111U) << 6) | ((static_cast(cs[2]) & 0b00111111U)); return 3; } else if (cs[0] < 0b11111000U) { if (sourceLength < 4) return -1; d = ((static_cast(cs[0]) & 0b00000111U) << 18) | ((static_cast(cs[1]) & 0b00111111U) << 12) | ((static_cast(cs[2]) & 0b00111111U) << 6) | ((static_cast(cs[3]) & 0b00111111U)); return 4; } else if (cs[0] < 0b11111100U) { if (sourceLength < 5) return -1; d = ((static_cast(cs[0]) & 0b00000011U) << 24) | ((static_cast(cs[1]) & 0b00111111U) << 18) | ((static_cast(cs[2]) & 0b00111111U) << 12) | ((static_cast(cs[3]) & 0b00111111U) << 6) | ((static_cast(cs[4]) & 0b00111111U)); return 5; } else { if (sourceLength < 6) return -1; d = ((static_cast(cs[0]) & 0b00000001U) << 30) | ((static_cast(cs[1]) & 0b00111111U) << 24) | ((static_cast(cs[2]) & 0b00111111U) << 18) | ((static_cast(cs[3]) & 0b00111111U) << 12) | ((static_cast(cs[4]) & 0b00111111U) << 6) | ((static_cast(cs[5]) & 0b00111111U)); return 6; } if (IsInvalid(dest)) return -1; return 1; } /*********************************************************************** UtfConversion ***********************************************************************/ /* How UCS-4 translates to UTF-16 Surrogate Pair U' = yyyyyyyyyyxxxxxxxxxx // U - 0x10000 W1 = 110110yyyyyyyyyy // 0xD800 + yyyyyyyyyy W2 = 110111xxxxxxxxxx // 0xDC00 + xxxxxxxxxx */ vint UtfConversion::From32(char32_t source, char16_t(&dest)[BufferLength]) { if (IsInvalid(source)) return -1; vuint32_t c = static_cast(source); vuint16_t(&ds)[BufferLength] = reinterpret_cast(dest); if (0x000000UL <= c && c <= 0x00D7FFUL) { ds[0] = static_cast(c); return 1; } else if (0x00E000UL <= c && c <= 0x00FFFFUL) { ds[0] = static_cast(c); return 1; } else if (0x010000UL <= c && c <= 0x10FFFFUL) { c -= 0x010000UL; ds[0] = static_cast((c >> 10) | 0xD800U); ds[1] = static_cast((c & 0x03FFU) | 0xDC00U); return 2; } else { return -1; } } vint UtfConversion::To32(const char16_t* source, vint sourceLength, char32_t& dest) { const vuint16_t* cs = reinterpret_cast(source); vuint32_t& d = reinterpret_cast(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(cs[0]) & 0x03FF) << 10) | (static_cast(cs[1]) & 0x03FF) ); if (IsInvalid(dest)) return -1; return 2; } else { return -1; } } else { d = cs[0]; if (IsInvalid(dest)) return -1; return 1; } } /*********************************************************************** UtfConversion ***********************************************************************/ vint UtfConversion::From32(char32_t source, char16be_t(&dest)[BufferLength]) { char16_t destle[BufferLength]; vint result = UtfConversion::From32(source, destle); SwapByteForUtf16BE(destle[0]); SwapByteForUtf16BE(destle[1]); dest[0].value = destle[0]; dest[1].value = destle[1]; return result; } vint UtfConversion::To32(const char16be_t* source, vint sourceLength, char32_t& dest) { char16_t destle[BufferLength]; if (sourceLength >= 1) destle[0] = source[0].value; if (sourceLength >= 2) destle[1] = source[1].value; SwapByteForUtf16BE(destle[0]); SwapByteForUtf16BE(destle[1]); return UtfConversion::To32(destle, sourceLength, dest); } } /*********************************************************************** String Conversions (buffer walkthrough) ***********************************************************************/ template vint _utftoutf_reader(const TFrom* s, TTo* d, vint chars) { TReader reader(s); vint size = 0; if (d == nullptr) { while (reader.Read()) size++; return size + 1; } else { while (true) { if (chars == 0) break; auto c = reader.Read(); *d++ = c; size++; chars--; if (!c) break; } return size; } } template vint _utftoutf(const TFrom* s, TTo* d, vint chars) { return _utftoutf_reader>(s, d, chars); } template vint _utftoutf(const wchar_t* s, char8_t* d, vint chars); template vint _utftoutf(const wchar_t* s, char16_t* d, vint chars); template vint _utftoutf(const char8_t* s, wchar_t* d, vint chars); template vint _utftoutf(const char8_t* s, char16_t* d, vint chars); template vint _utftoutf(const char16_t* s, wchar_t* d, vint chars); template vint _utftoutf(const char16_t* s, char8_t* d, vint chars); template vint _utftoutf(const char32_t* s, char8_t* d, vint chars); template vint _utftoutf(const char32_t* s, char16_t* d, vint chars); template vint _utftoutf(const char32_t* s, wchar_t* d, vint chars); template vint _utftoutf(const char8_t* s, char32_t* d, vint chars); template vint _utftoutf(const char16_t* s, char32_t* d, vint chars); template vint _utftoutf(const wchar_t* s, char32_t* d, vint chars); /*********************************************************************** String Conversions (ObjectString) ***********************************************************************/ template ObjectString ConvertStringDirect(const ObjectString& 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::TakeOver(buffer, len - 1); } template ObjectString ConvertUtfString(const ObjectString& source) { return ConvertStringDirect>(source); } #if defined VCZH_WCHAR_UTF16 template<> ObjectString ConvertUtfString(const ObjectString& source) { return ObjectString::UnsafeCastFrom(source); } template<> ObjectString ConvertUtfString(const ObjectString& source) { return ObjectString::UnsafeCastFrom(source); } template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); #elif defined VCZH_WCHAR_UTF32 template<> ObjectString ConvertUtfString(const ObjectString& source) { return ObjectString::UnsafeCastFrom(source); } template<> ObjectString ConvertUtfString(const ObjectString& source) { return ObjectString::UnsafeCastFrom(source); } template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); #endif template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template ObjectString ConvertUtfString(const ObjectString& source); template void ConvertUtfString(const ObjectString& source, ObjectString& dest) { dest = ConvertUtfString(source); } template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); template void ConvertUtfString(const ObjectString& source, ObjectString& dest); /*********************************************************************** String Conversions (direct) ***********************************************************************/ #if defined VCZH_WCHAR_UTF16 U32String wtou32 (const WString& source) { return ConvertStringDirect>(source); } WString u32tow (const U32String& source) { return ConvertStringDirect>(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>(source); } U8String u32tou8 (const U32String& source) { return ConvertStringDirect>(source); } U32String u16tou32(const U16String& source) { return ConvertStringDirect>(source); } U16String u32tou16(const U32String& source) { return ConvertStringDirect>(source); } /*********************************************************************** String Conversions (unicode indirect) ***********************************************************************/ AString wtoa (const WString& source) { return ConvertStringDirect(source); } WString atow (const AString& source) { return ConvertStringDirect(source); } U8String wtou8 (const WString& source) { return ConvertStringDirect>(source); } WString u8tow (const U8String& source) { return ConvertStringDirect>(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>(source); } WString u16tow (const U16String& source) { return ConvertStringDirect>(source); } #endif U16String u8tou16 (const U8String& source) { return ConvertStringDirect>(source); } U8String u16tou8 (const U16String& source) { return ConvertStringDirect>(source); } } /*********************************************************************** .\STRINGS\LOREMIPSUM.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ #include 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 { template class ObjectString; template class ObjectString; template class ObjectString; template class ObjectString; template class ObjectString; #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 ***********************************************************************/ #ifdef VCZH_GCC #define _wcsnicmp wcsncasecmp #endif namespace vl { /*********************************************************************** MatchWildcardNaive ***********************************************************************/ static vint WildcardNextToken(const wchar_t*& wildcard) { wchar_t c = *wildcard; if (c == L'\0') { return -3; } else if (c == L'?') { wildcard++; return -2; } else if (c == L'*') { vint questionCount = 0; while (true) { if (c == L'?') { questionCount++; } else if (c != L'*') { break; } c = *++wildcard; } return questionCount; } else { while (c != L'\0' && c != L'?' && c != L'*') { c = *++wildcard; } return -1; } } bool MatchWildcardNaive(const wchar_t* wildcard, const wchar_t* text, bool caseSensitive) { #define ERROR_MESSAGE_PREFIX L"vl::MatchWildcardNaive(const wchar_t*, const wchar_t*, bool)#" CHECK_ERROR(wildcard != nullptr, ERROR_MESSAGE_PREFIX L"wildcard cannot be nullptr"); CHECK_ERROR(text != nullptr, ERROR_MESSAGE_PREFIX L"text cannot be nullptr"); while (true) { const wchar_t* tokenStart = wildcard; vint tokenType = WildcardNextToken(wildcard); switch (tokenType) { case -3: return *text == L'\0'; case -2: if (*text == L'\0') return false; text++; break; case -1: { vint literalLen = wildcard - tokenStart; vint cmpResult = caseSensitive ? wcsncmp(tokenStart, text, literalLen) : _wcsnicmp(tokenStart, text, literalLen); if (cmpResult != 0) return false; text += literalLen; } break; default: { vint minSkip = tokenType; for (vint i = 0; i < minSkip; i++) { if (*text++ == L'\0') return false; } while (true) { if (MatchWildcardNaive(wildcard, text, caseSensitive)) { return true; } if (*text++ == L'\0') return false; } } } } #undef ERROR_MESSAGE_PREFIX } namespace unittest { using namespace vl::console; using namespace vl::collections; /*********************************************************************** 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; UnitTest::FailureMode failureMode = UnitTest::FailureMode::NotRunning; template void RecordFailure(TMessage errorMessage) { UnitTest::PrintMessage(errorMessage, UnitTest::MessageKind::Error); auto current = testContext; while (current) { current->failed = true; current = current->parent; } } template void SuppressCppFailure(TCallback&& callback) { try { callback(); } catch (const UnitTestAssertError& e) { RecordFailure(e.message); if (failureMode == UnitTest::FailureMode::Copilot) { throw UnitTestJustCrashError{}; } } catch (const UnitTestConfigError& e) { RecordFailure(e.message); if (failureMode == UnitTest::FailureMode::Copilot) { throw UnitTestJustCrashError{}; } } catch (const Error& e) { RecordFailure(e.Description()); if (failureMode == UnitTest::FailureMode::Copilot) { throw UnitTestJustCrashError{}; } } catch (const Exception& e) { RecordFailure(e.Message()); if (failureMode == UnitTest::FailureMode::Copilot) { throw UnitTestJustCrashError{}; } } catch (const UnitTestJustCrashError&) { throw; } catch (...) { RecordFailure(L"Unknown exception occurred!"); if (failureMode == UnitTest::FailureMode::Copilot) { throw UnitTestJustCrashError{}; } } } template void SuppressCFailure(TCallback&& callback) { #ifdef VCZH_MSVC __try { SuppressCppFailure(std::forward(callback)); } __except (/*EXCEPTION_EXECUTE_HANDLER*/ 1) { RecordFailure(L"Runtime exception occurred!"); } #else SuppressCppFailure(callback); #endif } template void ExecuteAndSuppressFailure(TCallback&& callback) { switch (failureMode) { case UnitTest::FailureMode::Release: SuppressCFailure(std::forward(callback)); break; case UnitTest::FailureMode::Copilot: SuppressCppFailure(std::forward(callback)); break; default: callback(); } } } using namespace execution_impl; UnitTest::FailureMode UnitTest::GetFailureMode() { return execution_impl::failureMode; } 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 | /C] {/F:TestFile}", MessageKind::Error); return 1; } int UnitTest::RunAndDisposeTests(const collections::Array& options) { #ifdef VCZH_MSVC _set_abort_behavior(0, _WRITE_ABORT_MSG); #endif bool unrecognized = false; bool _D = false; bool _R = false; bool _C = false; List _Fs; for (auto&& option : From(options)) { if (option == L"/D") { _D = true; } else if (option == L"/R") { _R = true; } else if (option == L"/C") { _C = true; } else if (option.Length() > 3 && option.Left(3) == L"/F:") { _Fs.Add(wtoa(option.Sub(3, option.Length() - 3))); } else { unrecognized = true; } } vint modeCount = 0; if (_D) modeCount++; if (_R) modeCount++; if (_C) modeCount++; if (unrecognized || modeCount > 1) { return PrintUsages(); } if (_D) { failureMode = FailureMode::Debug; } else if (_R) { failureMode = FailureMode::Release; } else if (_C) { failureMode = FailureMode::Copilot; } else { failureMode = IsDebuggerAttached() ? FailureMode::Debug : FailureMode::Release; } { UnitTestContext context; testContext = &context; totalFiles = 0; passedFiles = 0; totalCases = 0; passedCases = 0; switch (failureMode) { case FailureMode::Debug: PrintMessage(L"Failures are not suppressed.", MessageKind::Info); break; case FailureMode::Release: PrintMessage(L"Failures are suppressed.", MessageKind::Info); break; case FailureMode::Copilot: PrintMessage(L"Failures cause immediate exit.", MessageKind::Info); break; default:; } auto current = testHead; while (current) { bool skipped = false; context.failed = false; if (_Fs.Count() > 0) { skipped = true; // Extract the filename from the full path const char* fullPath = current->fileName; const char* fileNameStart = fullPath; for (const char* p = fullPath; *p != '\0'; p++) { if (*p == '/' || *p == '\\') { fileNameStart = p + 1; } } auto currentFileName = atow(AString::Unmanaged(fileNameStart)); // Check if any wildcard pattern matches the filename for (auto pattern : From(_Fs)) { auto widePattern = atow(pattern); if (MatchWildcardNaive(widePattern.Buffer(), currentFileName.Buffer(), false)) { skipped = false; break; } } } if (skipped) { PrintMessage(atow(AString::Unmanaged(current->fileName)) + WString::Unmanaged(L" [SKIPPED]"), MessageKind::File); } else { 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 < 2) { return RunAndDisposeTests({}); } else { Array options(argc - 1); for (int i = 1; i < argc; i++) { options[i - 1] = WString::Unmanaged(argv[i]); } return RunAndDisposeTests(options); } } int UnitTest::RunAndDisposeTests(int argc, char* argv[]) { if (argc < 2) { return RunAndDisposeTests({}); } else { Array options(argc - 1); for (int i = 1; i < argc; i++) { options[i - 1] = atow(argv[i]); } return RunAndDisposeTests(options); } } void UnitTest::RegisterTestFile(UnitTestLink* link) { *testTail = link; testTail = &link->next; } void UnitTest::RunCategoryOrCase(const WString& description, bool isCategory, Func&& 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."); } } }