#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); always_check(CCharType); always_check(CCharType); always_check(CCharType); always_check(CCharType); always_check(CCharType); always_check(CCharType); } auto Test = [](TInPlaceType) { always_check(TChar::IsASCII(LITERAL(T, '0'))); always_check(TChar::IsASCII(LITERAL(T, 'A'))); always_check(TChar::IsASCII(LITERAL(T, 'a'))); always_check(TChar::IsASCII(LITERAL(T, 'A'))); always_check(TChar::IsASCII(LITERAL(T, '0'))); always_check(TChar::IsASCII(LITERAL(T, '\n'))); always_check(TChar::IsASCII(LITERAL(T, '!'))); always_check(TChar::IsASCII(LITERAL(T, '\t'))); always_check(TChar::IsASCII(LITERAL(T, ' '))); always_check(TChar::IsASCII(LITERAL(T, '#'))); always_check(TChar::IsASCII(LITERAL(T, '['))); always_check(TChar::IsAlnum(LITERAL(T, '0'))); always_check(TChar::IsAlpha(LITERAL(T, 'A'))); always_check(TChar::IsLower(LITERAL(T, 'a'))); always_check(TChar::IsUpper(LITERAL(T, 'A'))); always_check(TChar::IsDigit(LITERAL(T, '0'))); always_check(TChar::IsCntrl(LITERAL(T, '\n'))); always_check(TChar::IsGraph(LITERAL(T, '!'))); always_check(TChar::IsSpace(LITERAL(T, '\t'))); always_check(TChar::IsBlank(LITERAL(T, ' '))); always_check(TChar::IsPrint(LITERAL(T, '#'))); always_check(TChar::IsPunct(LITERAL(T, '['))); always_check(!TChar::IsAlnum(LITERAL(T, '$'))); always_check(!TChar::IsAlpha(LITERAL(T, '0'))); always_check(!TChar::IsLower(LITERAL(T, 'A'))); always_check(!TChar::IsUpper(LITERAL(T, 'a'))); always_check(!TChar::IsDigit(LITERAL(T, 'I'))); always_check(!TChar::IsCntrl(LITERAL(T, '_'))); always_check(!TChar::IsGraph(LITERAL(T, ' '))); always_check(!TChar::IsSpace(LITERAL(T, '='))); always_check(!TChar::IsBlank(LITERAL(T, '+'))); always_check(!TChar::IsPrint(LITERAL(T, '\n'))); always_check(!TChar::IsPunct(LITERAL(T, 'H'))); always_check( TChar::IsDigit(LITERAL(T, 'F'), 16)); always_check(!TChar::IsDigit(LITERAL(T, 'G'), 16)); always_check(TChar::ToLower(LITERAL(T, 'i')) == LITERAL(T, 'i')); always_check(TChar::ToUpper(LITERAL(T, 'l')) == LITERAL(T, 'L')); always_check(0x0 == TChar::ToDigit(LITERAL(T, '0'))); always_check(0xF == TChar::ToDigit(LITERAL(T, 'f'))); always_check(0xF == TChar::ToDigit(LITERAL(T, 'F'))); always_check(0x0 == TChar::ToDigit(LITERAL(T, '0'), false)); always_check(0xF != TChar::ToDigit(LITERAL(T, 'f'), false)); always_check(0xF == TChar::ToDigit(LITERAL(T, 'F'), false)); always_check(0x0 == TChar::ToDigit(LITERAL(T, '0'), true)); always_check(0xF == TChar::ToDigit(LITERAL(T, 'f'), true)); always_check(0xF != TChar::ToDigit(LITERAL(T, 'F'), true)); always_check(LITERAL(T, '0') == TChar::FromDigit(0x0)); always_check(LITERAL(T, 'f') != TChar::FromDigit(0xF)); always_check(LITERAL(T, 'F') == TChar::FromDigit(0xF)); always_check(LITERAL(T, '0') == TChar::FromDigit(0x0, false)); always_check(LITERAL(T, 'f') != TChar::FromDigit(0xF, false)); always_check(LITERAL(T, 'F') == TChar::FromDigit(0xF, false)); always_check(LITERAL(T, '0') == TChar::FromDigit(0x0, true)); always_check(LITERAL(T, 'f') == TChar::FromDigit(0xF, true)); always_check(LITERAL(T, 'F') != TChar::FromDigit(0xF, true)); }; Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); } void TestStringView() { auto Test = [](TInPlaceType) { { TStringView 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(10)); always_check(!LITERAL_VIEW(T, "\u4E38\u8FA3").template IsInteger(10)); always_check(!LITERAL_VIEW(T, "0123456789AB").template IsInteger(10)); always_check( LITERAL_VIEW(T, "0123456789AB").template IsInteger(16)); } }; Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); } void TestString() { auto Test = [](TInPlaceType) { { TString Empty; always_check(Empty.IsEmpty()); always_check(TStringView(*Empty) == LITERAL(T, "")); TString 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(*StrA) == LITERAL(T, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); always_check(TStringView(*StrB) == LITERAL(T, "ABC")); always_check(TStringView(*StrC) == LITERAL(T, "ABCDEFG")); always_check(TStringView(*StrD) == LITERAL(T, "ABCDEFG")); always_check(TStringView(*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(LITERAL(T, "A"))); always_check(Str == LITERAL(T, 'A') ); always_check(Str == LITERAL(T, 'A') ); always_check(TString(LITERAL(T, "A")) == Str); always_check( LITERAL(T, 'A') == Str); always_check( LITERAL(T, "A") == Str); always_check(Str != TString(LITERAL(T, "B"))); always_check(Str != LITERAL(T, 'B') ); always_check(Str != LITERAL(T, "B") ); always_check(TString(LITERAL(T, "B")) != Str); always_check( LITERAL(T, 'B') != Str); always_check( LITERAL(T, "B") != Str); always_check(Str < TString(LITERAL(T, "B"))); always_check(Str < LITERAL(T, 'B') ); always_check(Str < LITERAL(T, "B") ); always_check(TString(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); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); } void TestConvert() { auto Test = [](TInPlaceType) { auto CheckParseArithmetic = [](TStringView View, U Result) { U Object; if constexpr (CSameAs) always_check(View.Parse(Object)); else if constexpr (CIntegral) always_check(View.Parse(Object)); else if constexpr (CFloatingPoint) always_check(View.Parse(Object)); if constexpr (CFloatingPoint) { 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 = [&](TInPlaceType) { CheckParseArithmetic(LITERAL(T, "+0"), static_cast(+0.0)); CheckParseArithmetic(LITERAL(T, " 0"), static_cast( 0.0)); CheckParseArithmetic(LITERAL(T, "-0"), static_cast(-0.0)); CheckParseArithmetic(LITERAL(T, "+42"), static_cast( +42)); CheckParseArithmetic(LITERAL(T, "+052"), static_cast( +052)); CheckParseArithmetic(LITERAL(T, "+0x2A"), static_cast( +0x2A)); CheckParseArithmetic(LITERAL(T, "+0b101010"), static_cast(+0b101010)); CheckParseArithmetic(LITERAL(T, "42"), static_cast( 42)); CheckParseArithmetic(LITERAL(T, "052"), static_cast( 052)); CheckParseArithmetic(LITERAL(T, "0x2A"), static_cast( 0x2A)); CheckParseArithmetic(LITERAL(T, "0b101010"), static_cast(0b101010)); CheckParseArithmetic(LITERAL(T, "-42"), static_cast( -42)); CheckParseArithmetic(LITERAL(T, "-052"), static_cast( -052)); CheckParseArithmetic(LITERAL(T, "-0x2A"), static_cast( -0x2A)); CheckParseArithmetic(LITERAL(T, "-0b101010"), static_cast(-0b101010)); }; CheckParseInt(InPlaceType); CheckParseInt(InPlaceType); CheckParseInt(InPlaceType); CheckParseInt(InPlaceType); auto CheckParseFloat = [&](TInPlaceType) { CheckParseArithmetic(LITERAL(T, "+3.14"), static_cast( +3.14)); CheckParseArithmetic(LITERAL(T, "+3.14e2"), static_cast( +3.14e2)); CheckParseArithmetic(LITERAL(T, "+3.14e-2"), static_cast( +3.14e-2)); CheckParseArithmetic(LITERAL(T, "+0x1.91eb86p1"), static_cast(+0x1.91eb86p1)); CheckParseArithmetic(LITERAL(T, "3.14"), static_cast( 3.14)); CheckParseArithmetic(LITERAL(T, "3.14e2"), static_cast( 3.14e2)); CheckParseArithmetic(LITERAL(T, "3.14e-2"), static_cast( 3.14e-2)); CheckParseArithmetic(LITERAL(T, "0x1.91eb86p1"), static_cast(0x1.91eb86p1)); CheckParseArithmetic(LITERAL(T, "-3.14"), static_cast( -3.14)); CheckParseArithmetic(LITERAL(T, "-3.14e2"), static_cast( -3.14e2)); CheckParseArithmetic(LITERAL(T, "-3.14e-2"), static_cast( -3.14e-2)); CheckParseArithmetic(LITERAL(T, "-0x1.91eb86p1"), static_cast(-0x1.91eb86p1)); CheckParseArithmetic(LITERAL(T, "+Infinity"), +TNumericLimits::Infinity()); CheckParseArithmetic(LITERAL(T, " Infinity"), +TNumericLimits::Infinity()); CheckParseArithmetic(LITERAL(T, "-Infinity"), -TNumericLimits::Infinity()); CheckParseArithmetic(LITERAL(T, "+NaN"), +TNumericLimits::QuietNaN()); CheckParseArithmetic(LITERAL(T, " NaN"), +TNumericLimits::QuietNaN()); CheckParseArithmetic(LITERAL(T, "-NaN"), -TNumericLimits::QuietNaN()); }; CheckParseFloat(InPlaceType); CheckParseFloat(InPlaceType); { 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); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); } void TestStringConversion() { auto Test = [](TInPlaceType) { always_check(TString::Format(LITERAL(T, "#{}#"), true ) == LITERAL(T, "#True#" )); always_check(TString::Format(LITERAL(T, "#{}#"), false) == LITERAL(T, "#False#")); always_check(TString::Format(LITERAL(T, "#{}#"), +0) == LITERAL(T, "#0#")); always_check(TString::Format(LITERAL(T, "#{}#"), 0) == LITERAL(T, "#0#")); always_check(TString::Format(LITERAL(T, "#{}#"), -0) == LITERAL(T, "#0#")); always_check(TString::Format(LITERAL(T, "#{}#"), 42) == LITERAL(T, "#42#")); always_check(TString::Format(LITERAL(T, "#{}#"), +0.0) == LITERAL(T, "#0.000000#")); always_check(TString::Format(LITERAL(T, "#{}#"), 0.0) == LITERAL(T, "#0.000000#")); always_check(TString::Format(LITERAL(T, "#{}#"), -0.0) == LITERAL(T, "#-0.000000#")); always_check(TString::Format(LITERAL(T, "#{}#"), 3.14) == LITERAL(T, "#3.140000#")); always_check(TString::Format(LITERAL(T, "#{}#"), +TNumericLimits::Infinity()) == LITERAL(T, "#Infinity#")); always_check(TString::Format(LITERAL(T, "#{}#"), -TNumericLimits::Infinity()) == LITERAL(T, "#-Infinity#")); always_check(TString::Format(LITERAL(T, "#{}#"), +TNumericLimits::QuietNaN()) == LITERAL(T, "#NaN#")); always_check(TString::Format(LITERAL(T, "#{}#"), -TNumericLimits::QuietNaN()) == LITERAL(T, "#-NaN#")); { always_check(TString::FromBool(true ) == LITERAL(T, "True" )); always_check(TString::FromBool(false) == LITERAL(T, "False")); } { always_check(TString::FromInt(42) == LITERAL(T, "42" )); always_check(TString::FromInt(255, 16) == LITERAL(T, "FF" )); always_check(TString::FromInt(-42) == LITERAL(T, "-42" )); always_check(TString::FromInt(0) == LITERAL(T, "0" )); always_check(TString::FromInt(1234567890) == LITERAL(T, "1234567890")); always_check(TString::FromInt(255, 2) == LITERAL(T, "11111111" )); always_check(TString::FromInt(255, 8) == LITERAL(T, "377" )); always_check(TString::FromInt(255, 36) == LITERAL(T, "73" )); } { always_check(TString::FromFloat(3.14f) == LITERAL(T, "3.14" )); always_check(TString::FromFloat(0.0f) == LITERAL(T, "0" )); always_check(TString::FromFloat(-3.14f) == LITERAL(T, "-3.14" )); always_check(TString::FromFloat(3.14f, true, false) == LITERAL(T, "3.14" )); always_check(TString::FromFloat(3.14f, false, true) == LITERAL(T, "3.14e+00")); always_check(TString::FromFloat(3.14f, false, false, 2) == LITERAL(T, "1.92p+1" )); always_check(TString::FromFloat(1.0f / 3.0f, true, false, 5) == LITERAL(T, "0.33333" )); } }; Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); Test(InPlaceType); } 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