Redcraft/Redcraft.Utility/Source/Private/Testing/Strings.cpp

643 lines
24 KiB
C++

#include "Testing/Testing.h"
#include "Strings/Char.h"
#include "Memory/Memory.h"
#include "Numerics/Numerics.h"
#include "Strings/String.h"
#include "Strings/StringView.h"
#include "Strings/Convert.h"
#include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(Testing)
NAMESPACE_PRIVATE_BEGIN
void TestChar()
{
{
always_check(!CCharType<int>);
always_check(CCharType<char>);
always_check(CCharType<wchar>);
always_check(CCharType<u8char>);
always_check(CCharType<u16char>);
always_check(CCharType<u32char>);
always_check(CCharType<unicodechar>);
}
auto Test = []<typename T>(TInPlaceType<T>)
{
always_check(TChar<T>::IsASCII(LITERAL(T, '0')));
always_check(TChar<T>::IsASCII(LITERAL(T, 'A')));
always_check(TChar<T>::IsASCII(LITERAL(T, 'a')));
always_check(TChar<T>::IsASCII(LITERAL(T, 'A')));
always_check(TChar<T>::IsASCII(LITERAL(T, '0')));
always_check(TChar<T>::IsASCII(LITERAL(T, '\n')));
always_check(TChar<T>::IsASCII(LITERAL(T, '!')));
always_check(TChar<T>::IsASCII(LITERAL(T, '\t')));
always_check(TChar<T>::IsASCII(LITERAL(T, ' ')));
always_check(TChar<T>::IsASCII(LITERAL(T, '#')));
always_check(TChar<T>::IsASCII(LITERAL(T, '[')));
always_check(TChar<T>::IsAlnum(LITERAL(T, '0')));
always_check(TChar<T>::IsAlpha(LITERAL(T, 'A')));
always_check(TChar<T>::IsLower(LITERAL(T, 'a')));
always_check(TChar<T>::IsUpper(LITERAL(T, 'A')));
always_check(TChar<T>::IsDigit(LITERAL(T, '0')));
always_check(TChar<T>::IsCntrl(LITERAL(T, '\n')));
always_check(TChar<T>::IsGraph(LITERAL(T, '!')));
always_check(TChar<T>::IsSpace(LITERAL(T, '\t')));
always_check(TChar<T>::IsBlank(LITERAL(T, ' ')));
always_check(TChar<T>::IsPrint(LITERAL(T, '#')));
always_check(TChar<T>::IsPunct(LITERAL(T, '[')));
always_check(!TChar<T>::IsAlnum(LITERAL(T, '$')));
always_check(!TChar<T>::IsAlpha(LITERAL(T, '0')));
always_check(!TChar<T>::IsLower(LITERAL(T, 'A')));
always_check(!TChar<T>::IsUpper(LITERAL(T, 'a')));
always_check(!TChar<T>::IsDigit(LITERAL(T, 'I')));
always_check(!TChar<T>::IsCntrl(LITERAL(T, '_')));
always_check(!TChar<T>::IsGraph(LITERAL(T, ' ')));
always_check(!TChar<T>::IsSpace(LITERAL(T, '=')));
always_check(!TChar<T>::IsBlank(LITERAL(T, '+')));
always_check(!TChar<T>::IsPrint(LITERAL(T, '\n')));
always_check(!TChar<T>::IsPunct(LITERAL(T, 'H')));
always_check( TChar<T>::IsDigit(LITERAL(T, 'F'), 16));
always_check(!TChar<T>::IsDigit(LITERAL(T, 'G'), 16));
always_check(TChar<T>::ToLower(LITERAL(T, 'i')) == LITERAL(T, 'i'));
always_check(TChar<T>::ToUpper(LITERAL(T, 'l')) == LITERAL(T, 'L'));
always_check(0x0 == TChar<T>::ToDigit(LITERAL(T, '0')));
always_check(0xF == TChar<T>::ToDigit(LITERAL(T, 'f')));
always_check(0xF == TChar<T>::ToDigit(LITERAL(T, 'F')));
always_check(0x0 == TChar<T>::ToDigit(LITERAL(T, '0'), false));
always_check(0xF != TChar<T>::ToDigit(LITERAL(T, 'f'), false));
always_check(0xF == TChar<T>::ToDigit(LITERAL(T, 'F'), false));
always_check(0x0 == TChar<T>::ToDigit(LITERAL(T, '0'), true));
always_check(0xF == TChar<T>::ToDigit(LITERAL(T, 'f'), true));
always_check(0xF != TChar<T>::ToDigit(LITERAL(T, 'F'), true));
always_check(LITERAL(T, '0') == TChar<T>::FromDigit(0x0));
always_check(LITERAL(T, 'f') != TChar<T>::FromDigit(0xF));
always_check(LITERAL(T, 'F') == TChar<T>::FromDigit(0xF));
always_check(LITERAL(T, '0') == TChar<T>::FromDigit(0x0, false));
always_check(LITERAL(T, 'f') != TChar<T>::FromDigit(0xF, false));
always_check(LITERAL(T, 'F') == TChar<T>::FromDigit(0xF, false));
always_check(LITERAL(T, '0') == TChar<T>::FromDigit(0x0, true));
always_check(LITERAL(T, 'f') == TChar<T>::FromDigit(0xF, true));
always_check(LITERAL(T, 'F') != TChar<T>::FromDigit(0xF, true));
};
Test(InPlaceType<char>);
Test(InPlaceType<wchar>);
Test(InPlaceType<u8char>);
Test(InPlaceType<u16char>);
Test(InPlaceType<u32char>);
Test(InPlaceType<unicodechar>);
}
void TestStringView()
{
auto Test = []<typename T>(TInPlaceType<T>)
{
{
TStringView<T> Empty;
always_check(Empty == LITERAL(T, ""));
TStringView ViewI = LITERAL(T, "#Hello, World! Goodbye, World!#");
ViewI.RemovePrefix(1);
ViewI.RemoveSuffix(1);
T Buffer[64];
Memory::Memzero(Buffer);
ViewI.Copy(Buffer);
TStringView ViewII = Buffer;
always_check(ViewI == LITERAL(T, "Hello, World! Goodbye, World!"));
always_check(ViewII == LITERAL(T, "Hello, World! Goodbye, World!"));
TStringView ViewA(ViewI.Begin(), 13);
TStringView ViewB(ViewI.Begin(), ViewI.End());
TStringView ViewC(&Buffer[0], 13);
TStringView ViewD(&Buffer[0]);
always_check(ViewA == LITERAL(T, "Hello, World!"));
always_check(ViewB == LITERAL(T, "Hello, World! Goodbye, World!"));
always_check(ViewC == LITERAL(T, "Hello, World!"));
always_check(ViewD == LITERAL(T, "Hello, World! Goodbye, World!"));
}
{
TStringView View = LITERAL(T, "Hello, World! Goodbye, World!");
always_check( View.StartsWith(LITERAL(T, "Hello, World!")));
always_check(!View.StartsWith(LITERAL(T, "Goodbye, World!")));
always_check( View.StartsWith(LITERAL(T, 'H')));
always_check(!View.StartsWith(LITERAL(T, 'G')));
always_check(!View.EndsWith(LITERAL(T, "Hello, World!")));
always_check( View.EndsWith(LITERAL(T, "Goodbye, World!")));
always_check( View.EndsWith(LITERAL(T, '!')));
always_check(!View.EndsWith(LITERAL(T, '?')));
always_check( View.Contains(LITERAL(T, "Hello, World!")));
always_check( View.Contains(LITERAL(T, "Goodbye, World!")));
always_check( View.Contains(LITERAL(T, '!')));
always_check(!View.Contains(LITERAL(T, '?')));
}
{
TStringView View = LITERAL(T, "Hello, World! Goodbye, World!");
always_check(View.Find(LITERAL(T, "")) == 0);
always_check(View.Find(LITERAL(T, "World")) == 7);
always_check(View.Find(LITERAL(T, 'l')) == 2);
always_check(View.RFind(LITERAL(T, "")) == 29);
always_check(View.RFind(LITERAL(T, "World")) == 23);
always_check(View.RFind(LITERAL(T, 'l')) == 26);
always_check(View.Find(LITERAL(T, ""), 13) == 13);
always_check(View.Find(LITERAL(T, "World"), 13) == 23);
always_check(View.Find(LITERAL(T, 'l'), 13) == 26);
always_check(View.RFind(LITERAL(T, ""), 13) == 13);
always_check(View.RFind(LITERAL(T, "World"), 13) == 7);
always_check(View.RFind(LITERAL(T, 'l'), 13) == 10);
always_check(View.FindFirstOf(LITERAL(T, "eor")) == 1);
always_check(View.FindFirstOf(LITERAL(T, 'l')) == 2);
always_check(View.FindLastOf(LITERAL(T, "eor")) == 25);
always_check(View.FindLastOf(LITERAL(T, 'l')) == 26);
always_check(View.FindFirstNotOf(LITERAL(T, "Hello! Goodbye!")) == 5);
always_check(View.FindFirstNotOf(LITERAL(T, '!')) == 0);
always_check(View.FindLastNotOf(LITERAL(T, "Hello! Goodbye!")) == 25);
always_check(View.FindLastNotOf(LITERAL(T, '!')) == 27);
}
{
always_check(LITERAL_VIEW(T, " ABC ").TrimStart() == LITERAL(T, "ABC "));
always_check(LITERAL_VIEW(T, " ABC ").TrimEnd() == LITERAL(T, " ABC" ));
always_check(LITERAL_VIEW(T, " ABC ").TrimStartAndEnd() == LITERAL(T, "ABC" ));
always_check(LITERAL_VIEW(T, " A\0C ").TrimToNullTerminator() == LITERAL(T, " A"));
}
{
always_check( LITERAL_VIEW(T, "012345678900").IsASCII());
always_check(!LITERAL_VIEW(T, "\u4E38\u8FA3").IsASCII());
always_check( LITERAL_VIEW(T, "012345678900").template IsInteger<uint64>(10));
always_check(!LITERAL_VIEW(T, "\u4E38\u8FA3").template IsInteger<uint64>(10));
always_check(!LITERAL_VIEW(T, "0123456789AB").template IsInteger<uint64>(10));
always_check( LITERAL_VIEW(T, "0123456789AB").template IsInteger<uint64>(16));
}
};
Test(InPlaceType<char>);
Test(InPlaceType<wchar>);
Test(InPlaceType<u8char>);
Test(InPlaceType<u16char>);
Test(InPlaceType<u32char>);
Test(InPlaceType<unicodechar>);
}
void TestString()
{
auto Test = []<typename T>(TInPlaceType<T>)
{
{
TString<T> Empty;
always_check(Empty.IsEmpty());
always_check(TStringView<T>(*Empty) == LITERAL(T, ""));
TString<T> StrA(32, LITERAL(T, 'A'));
TString StrB(LITERAL(T, "ABCDEFG"), 3);
TString StrC(LITERAL(T, "ABCDEFG"));
TString StrD(TStringView(LITERAL(T, "ABCDEFG")));
TString StrE({ LITERAL(T, 'A'), LITERAL(T, 'B'), LITERAL(T, 'C') });
always_check(TStringView<T>(*StrA) == LITERAL(T, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
always_check(TStringView<T>(*StrB) == LITERAL(T, "ABC"));
always_check(TStringView<T>(*StrC) == LITERAL(T, "ABCDEFG"));
always_check(TStringView<T>(*StrD) == LITERAL(T, "ABCDEFG"));
always_check(TStringView<T>(*StrE) == LITERAL(T, "ABC"));
TString StrI(StrC);
TString StrII(MoveTemp(StrC));
TString StrIII = Empty;
TString StrIV = Empty;
StrIII = StrD;
StrIV = MoveTemp(StrD);
always_check(TStringView(StrI ) == LITERAL(T, "ABCDEFG"));
always_check(TStringView(StrII ) == LITERAL(T, "ABCDEFG"));
always_check(TStringView(StrIII) == LITERAL(T, "ABCDEFG"));
always_check(TStringView(StrIV ) == LITERAL(T, "ABCDEFG"));
always_check(StrC == LITERAL(T, ""));
always_check(StrD == LITERAL(T, ""));
StrA.Reset();
always_check(StrA.IsEmpty());
always_check(StrA == LITERAL(T, ""));
}
{
TString Str = LITERAL(T, "A");
always_check(!Str.IsEmpty());
always_check(Str.Num() == 1);
always_check(Str == TString<T>(LITERAL(T, "A")));
always_check(Str == LITERAL(T, 'A') );
always_check(Str == LITERAL(T, 'A') );
always_check(TString<T>(LITERAL(T, "A")) == Str);
always_check( LITERAL(T, 'A') == Str);
always_check( LITERAL(T, "A") == Str);
always_check(Str != TString<T>(LITERAL(T, "B")));
always_check(Str != LITERAL(T, 'B') );
always_check(Str != LITERAL(T, "B") );
always_check(TString<T>(LITERAL(T, "B")) != Str);
always_check( LITERAL(T, 'B') != Str);
always_check( LITERAL(T, "B") != Str);
always_check(Str < TString<T>(LITERAL(T, "B")));
always_check(Str < LITERAL(T, 'B') );
always_check(Str < LITERAL(T, "B") );
always_check(TString<T>(LITERAL(T, "B")) > Str);
always_check( LITERAL(T, 'B') > Str);
always_check( LITERAL(T, "B") > Str);
}
{
TString Str = LITERAL(T, "##");
Str.Insert(1, LITERAL(T, 'A'));
always_check(Str == LITERAL(T, "#A#"));
Str.Insert(2, LITERAL(T, "BCD"));
always_check(Str == LITERAL(T, "#ABCD#"));
Str.Insert(3, 3, LITERAL(T, '*'));
always_check(Str == LITERAL(T, "#AB***CD#"));
Str.Erase(4);
always_check(Str == LITERAL(T, "#AB**CD#"));
}
{
TString Str = LITERAL(T, "A");
Str.PushBack(LITERAL(T, 'B'));
always_check(Str == LITERAL(T, "AB"));
Str.PopBack();
always_check(Str == LITERAL(T, "A"));
Str.Append(2, LITERAL(T, 'B'));
always_check(Str == LITERAL(T, "ABB"));
Str.Append(LITERAL(T, "CD"));
always_check(Str == LITERAL(T, "ABBCD"));
Str.Append({ LITERAL(T, 'E'), LITERAL(T, 'F') });
always_check(Str == LITERAL(T, "ABBCDEF"));
Str = LITERAL(T, "A");
Str += LITERAL(T, 'B');
always_check(Str == LITERAL(T, "AB"));
Str += LITERAL(T, "CD");
always_check(Str == LITERAL(T, "ABCD"));
Str += { LITERAL(T, 'E'), LITERAL(T, 'F') };
always_check(Str == LITERAL(T, "ABCDEF"));
}
{
TString StrA = LITERAL(T, "A");
TString StrB = LITERAL(T, "B");
always_check(StrA + StrB == LITERAL(T, "AB"));
always_check(StrA + LITERAL(T, 'B') == LITERAL(T, "AB"));
always_check(StrA + LITERAL(T, "BCD") == LITERAL(T, "ABCD"));
always_check(LITERAL(T, 'B') + StrB == LITERAL(T, "BB"));
always_check(LITERAL(T, "BCD") + StrB == LITERAL(T, "BCDB"));
StrA = LITERAL(T, "A"); StrB = LITERAL(T, "B");
always_check(MoveTemp(StrA) + MoveTemp(StrB) == LITERAL(T, "AB"));
StrA = LITERAL(T, "A"); StrB = LITERAL(T, "B");
always_check(MoveTemp(StrA) + LITERAL(T, 'B') == LITERAL(T, "AB"));
StrA = LITERAL(T, "A"); StrB = LITERAL(T, "B");
always_check(MoveTemp(StrA) + LITERAL(T, "BCD") == LITERAL(T, "ABCD"));
StrA = LITERAL(T, "A"); StrB = LITERAL(T, "B");
always_check(LITERAL(T, 'B') + MoveTemp(StrB) == LITERAL(T, "BB"));
StrA = LITERAL(T, "A"); StrB = LITERAL(T, "B");
always_check(LITERAL(T, "BCD") + MoveTemp(StrB) == LITERAL(T, "BCDB"));
}
{
TString Str = LITERAL(T, "Hello, World! Goodbye, World!");
always_check( Str.StartsWith(LITERAL(T, "Hello, World!")));
always_check(!Str.StartsWith(LITERAL(T, "Goodbye, World!")));
always_check( Str.StartsWith(LITERAL(T, 'H')));
always_check(!Str.StartsWith(LITERAL(T, 'G')));
always_check(!Str.EndsWith(LITERAL(T, "Hello, World!")));
always_check( Str.EndsWith(LITERAL(T, "Goodbye, World!")));
always_check( Str.EndsWith(LITERAL(T, '!')));
always_check(!Str.EndsWith(LITERAL(T, '?')));
always_check( Str.Contains(LITERAL(T, "Hello, World!")));
always_check( Str.Contains(LITERAL(T, "Goodbye, World!")));
always_check( Str.Contains(LITERAL(T, '!')));
always_check(!Str.Contains(LITERAL(T, '?')));
}
{
TString Str = LITERAL(T, "#AB**CD#");
always_check(Str.Replace(3, 2, 3, LITERAL(T, '^')) == LITERAL(T, "#AB^^^CD#"));
always_check(Str.Replace(3, 3, LITERAL(T, "123")) == LITERAL(T, "#AB123CD#"));
always_check(Str.Substr(3, 3) == LITERAL(T, "123"));
always_check(Str.Substr(3) == LITERAL(T, "123CD#"));
}
{
TString Str = LITERAL(T, "Hello, World! Goodbye, World!");
always_check(Str.Find(LITERAL(T, "")) == 0);
always_check(Str.Find(LITERAL(T, "World")) == 7);
always_check(Str.Find(LITERAL(T, 'l')) == 2);
always_check(Str.RFind(LITERAL(T, "")) == 29);
always_check(Str.RFind(LITERAL(T, "World")) == 23);
always_check(Str.RFind(LITERAL(T, 'l')) == 26);
always_check(Str.Find(LITERAL(T, ""), 13) == 13);
always_check(Str.Find(LITERAL(T, "World"), 13) == 23);
always_check(Str.Find(LITERAL(T, 'l'), 13) == 26);
always_check(Str.RFind(LITERAL(T, ""), 13) == 13);
always_check(Str.RFind(LITERAL(T, "World"), 13) == 7);
always_check(Str.RFind(LITERAL(T, 'l'), 13) == 10);
always_check(Str.FindFirstOf(LITERAL(T, "eor")) == 1);
always_check(Str.FindFirstOf(LITERAL(T, 'l')) == 2);
always_check(Str.FindLastOf(LITERAL(T, "eor")) == 25);
always_check(Str.FindLastOf(LITERAL(T, 'l')) == 26);
always_check(Str.FindFirstNotOf(LITERAL(T, "Hello! Goodbye!")) == 5);
always_check(Str.FindFirstNotOf(LITERAL(T, '!')) == 0);
always_check(Str.FindLastNotOf(LITERAL(T, "Hello! Goodbye!")) == 25);
always_check(Str.FindLastNotOf(LITERAL(T, '!')) == 27);
}
{
always_check(TString(LITERAL(T, " ABC ")).TrimStart() == LITERAL(T, "ABC "));
always_check(TString(LITERAL(T, " ABC ")).TrimEnd() == LITERAL(T, " ABC" ));
always_check(TString(LITERAL(T, " ABC ")).TrimStartAndEnd() == LITERAL(T, "ABC" ));
always_check(TString(LITERAL(T, " A\0C ")).TrimToNullTerminator() == LITERAL(T, " A"));
}
{
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToString() == TEXT("\u4E38\u8FA3"));
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToWString() == WTEXT("\u4E38\u8FA3"));
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToU8String() == U8TEXT("\u4E38\u8FA3"));
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToU16String() == U16TEXT("\u4E38\u8FA3"));
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToU32String() == U32TEXT("\u4E38\u8FA3"));
always_check(TString(LITERAL(T, "\u4E38\u8FA3")).ToUnicodeString() == UNICODETEXT("\u4E38\u8FA3"));
}
};
Test(InPlaceType<char>);
Test(InPlaceType<wchar>);
Test(InPlaceType<u8char>);
Test(InPlaceType<u16char>);
Test(InPlaceType<u32char>);
Test(InPlaceType<unicodechar>);
}
void TestConvert()
{
auto Test = []<typename T>(TInPlaceType<T>)
{
auto CheckParseArithmetic = []<typename U>(TStringView<T> View, U Result)
{
U Object;
if constexpr (CSameAs<U, bool>) always_check(View.Parse(Object));
else if constexpr (CIntegral<U>) always_check(View.Parse(Object));
else if constexpr (CFloatingPoint<U>) always_check(View.Parse(Object));
if constexpr (CFloatingPoint<U>)
{
always_check(Math::IsInfinity(Result) == Math::IsInfinity(Object));
always_check(Math::IsNaN(Result) == Math::IsNaN(Object));
always_check(Math::IsNegative(Result) == Math::IsNegative(Object));
if (Math::IsInfinity(Result) || Math::IsNaN(Result)) return;
always_check(Math::IsNearlyEqual(Object, Result, 1e-4));
}
else always_check(Object == Result);
};
CheckParseArithmetic(LITERAL(T, "true" ), true );
CheckParseArithmetic(LITERAL(T, "false"), false);
auto CheckParseInt = [&]<typename U>(TInPlaceType<U>)
{
CheckParseArithmetic(LITERAL(T, "+0"), static_cast<U>(+0.0));
CheckParseArithmetic(LITERAL(T, " 0"), static_cast<U>( 0.0));
CheckParseArithmetic(LITERAL(T, "-0"), static_cast<U>(-0.0));
CheckParseArithmetic(LITERAL(T, "+42"), static_cast<U>( +42));
CheckParseArithmetic(LITERAL(T, "+052"), static_cast<U>( +052));
CheckParseArithmetic(LITERAL(T, "+0x2A"), static_cast<U>( +0x2A));
CheckParseArithmetic(LITERAL(T, "+0b101010"), static_cast<U>(+0b101010));
CheckParseArithmetic(LITERAL(T, "42"), static_cast<U>( 42));
CheckParseArithmetic(LITERAL(T, "052"), static_cast<U>( 052));
CheckParseArithmetic(LITERAL(T, "0x2A"), static_cast<U>( 0x2A));
CheckParseArithmetic(LITERAL(T, "0b101010"), static_cast<U>(0b101010));
CheckParseArithmetic(LITERAL(T, "-42"), static_cast<U>( -42));
CheckParseArithmetic(LITERAL(T, "-052"), static_cast<U>( -052));
CheckParseArithmetic(LITERAL(T, "-0x2A"), static_cast<U>( -0x2A));
CheckParseArithmetic(LITERAL(T, "-0b101010"), static_cast<U>(-0b101010));
};
CheckParseInt(InPlaceType<int8>);
CheckParseInt(InPlaceType<int16>);
CheckParseInt(InPlaceType<int32>);
CheckParseInt(InPlaceType<int64>);
auto CheckParseFloat = [&]<typename U>(TInPlaceType<U>)
{
CheckParseArithmetic(LITERAL(T, "+3.14"), static_cast<U>( +3.14));
CheckParseArithmetic(LITERAL(T, "+3.14e2"), static_cast<U>( +3.14e2));
CheckParseArithmetic(LITERAL(T, "+3.14e-2"), static_cast<U>( +3.14e-2));
CheckParseArithmetic(LITERAL(T, "+0x1.91eb86p1"), static_cast<U>(+0x1.91eb86p1));
CheckParseArithmetic(LITERAL(T, "3.14"), static_cast<U>( 3.14));
CheckParseArithmetic(LITERAL(T, "3.14e2"), static_cast<U>( 3.14e2));
CheckParseArithmetic(LITERAL(T, "3.14e-2"), static_cast<U>( 3.14e-2));
CheckParseArithmetic(LITERAL(T, "0x1.91eb86p1"), static_cast<U>(0x1.91eb86p1));
CheckParseArithmetic(LITERAL(T, "-3.14"), static_cast<U>( -3.14));
CheckParseArithmetic(LITERAL(T, "-3.14e2"), static_cast<U>( -3.14e2));
CheckParseArithmetic(LITERAL(T, "-3.14e-2"), static_cast<U>( -3.14e-2));
CheckParseArithmetic(LITERAL(T, "-0x1.91eb86p1"), static_cast<U>(-0x1.91eb86p1));
CheckParseArithmetic(LITERAL(T, "+Infinity"), +TNumericLimits<U>::Infinity());
CheckParseArithmetic(LITERAL(T, " Infinity"), +TNumericLimits<U>::Infinity());
CheckParseArithmetic(LITERAL(T, "-Infinity"), -TNumericLimits<U>::Infinity());
CheckParseArithmetic(LITERAL(T, "+NaN"), +TNumericLimits<U>::QuietNaN());
CheckParseArithmetic(LITERAL(T, " NaN"), +TNumericLimits<U>::QuietNaN());
CheckParseArithmetic(LITERAL(T, "-NaN"), -TNumericLimits<U>::QuietNaN());
};
CheckParseFloat(InPlaceType<float>);
CheckParseFloat(InPlaceType<double>);
{
always_check( LITERAL_VIEW(T, "true" ).ToBool());
always_check(!LITERAL_VIEW(T, "false").ToBool());
always_check( LITERAL_VIEW(T, "True" ).ToBool());
always_check(!LITERAL_VIEW(T, "False").ToBool());
}
{
always_check(LITERAL_VIEW(T, "42" ).ToInt() == 42 );
always_check(LITERAL_VIEW(T, "FF" ).ToInt(16) == 255);
always_check(LITERAL_VIEW(T, "-42").ToInt() == -42);
always_check(LITERAL_VIEW(T, "0" ).ToInt() == 0 );
}
{
always_check(LITERAL_VIEW(T, "3.14" ).ToFloat() == 3.14f);
always_check(LITERAL_VIEW(T, "3.14e+00").ToFloat() == 3.14f);
always_check(LITERAL_VIEW(T, "-3.14" ).ToFloat() == -3.14f);
always_check(LITERAL_VIEW(T, "0.0" ).ToFloat() == 0.0f);
}
};
Test(InPlaceType<char>);
Test(InPlaceType<wchar>);
Test(InPlaceType<u8char>);
Test(InPlaceType<u16char>);
Test(InPlaceType<u32char>);
Test(InPlaceType<unicodechar>);
}
void TestStringConversion()
{
auto Test = []<typename T>(TInPlaceType<T>)
{
always_check(TString<T>::Format(LITERAL(T, "#{}#"), true ) == LITERAL(T, "#True#" ));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), false) == LITERAL(T, "#False#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), +0) == LITERAL(T, "#0#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), 0) == LITERAL(T, "#0#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), -0) == LITERAL(T, "#0#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), 42) == LITERAL(T, "#42#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), +0.0) == LITERAL(T, "#0.000000#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), 0.0) == LITERAL(T, "#0.000000#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), -0.0) == LITERAL(T, "#-0.000000#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), 3.14) == LITERAL(T, "#3.140000#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), +TNumericLimits<float>::Infinity()) == LITERAL(T, "#Infinity#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), -TNumericLimits<float>::Infinity()) == LITERAL(T, "#-Infinity#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), +TNumericLimits<float>::QuietNaN()) == LITERAL(T, "#NaN#"));
always_check(TString<T>::Format(LITERAL(T, "#{}#"), -TNumericLimits<float>::QuietNaN()) == LITERAL(T, "#-NaN#"));
{
always_check(TString<T>::FromBool(true ) == LITERAL(T, "True" ));
always_check(TString<T>::FromBool(false) == LITERAL(T, "False"));
}
{
always_check(TString<T>::FromInt(42) == LITERAL(T, "42" ));
always_check(TString<T>::FromInt(255, 16) == LITERAL(T, "FF" ));
always_check(TString<T>::FromInt(-42) == LITERAL(T, "-42" ));
always_check(TString<T>::FromInt(0) == LITERAL(T, "0" ));
always_check(TString<T>::FromInt(1234567890) == LITERAL(T, "1234567890"));
always_check(TString<T>::FromInt(255, 2) == LITERAL(T, "11111111" ));
always_check(TString<T>::FromInt(255, 8) == LITERAL(T, "377" ));
always_check(TString<T>::FromInt(255, 36) == LITERAL(T, "73" ));
}
{
always_check(TString<T>::FromFloat(3.14f) == LITERAL(T, "3.14" ));
always_check(TString<T>::FromFloat(0.0f) == LITERAL(T, "0" ));
always_check(TString<T>::FromFloat(-3.14f) == LITERAL(T, "-3.14" ));
always_check(TString<T>::FromFloat(3.14f, true, false) == LITERAL(T, "3.14" ));
always_check(TString<T>::FromFloat(3.14f, false, true) == LITERAL(T, "3.14e+00"));
always_check(TString<T>::FromFloat(3.14f, false, false, 2) == LITERAL(T, "1.92p+1" ));
always_check(TString<T>::FromFloat(1.0f / 3.0f, true, false, 5) == LITERAL(T, "0.33333" ));
}
};
Test(InPlaceType<char>);
Test(InPlaceType<wchar>);
Test(InPlaceType<u8char>);
Test(InPlaceType<u16char>);
Test(InPlaceType<u32char>);
Test(InPlaceType<unicodechar>);
}
NAMESPACE_PRIVATE_END
void TestString()
{
NAMESPACE_PRIVATE::TestChar();
NAMESPACE_PRIVATE::TestStringView();
NAMESPACE_PRIVATE::TestString();
NAMESPACE_PRIVATE::TestConvert();
NAMESPACE_PRIVATE::TestStringConversion();
}
NAMESPACE_END(Testing)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END