From c5dcef180c38317bcb39ef1859ca33d299d62107 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 30 Jul 2021 17:30:11 -0700 Subject: [PATCH] fixes/improvements to AzCore Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/std/string/conversions.h | 47 +++++++++-- .../AzCore/AzCore/std/string/utf8/unchecked.h | 79 +++++++++++++------ .../WinAPI/AzCore/Utils/Utils_WinAPI.cpp | 9 ++- Code/Framework/AzCore/Tests/AZStd/String.cpp | 9 --- 4 files changed, 104 insertions(+), 40 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index 4dc5bbd547..cb90881933 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -35,11 +35,11 @@ namespace AZStd { if constexpr (Size == 2) { - Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size()); } else { @@ -54,11 +54,29 @@ namespace AZStd { if constexpr (Size == 2) { - Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size()); + } + else + { + // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter + using StringType = AZStd::basic_string; + static_assert(!AZStd::is_same_v, "only wchar_t types of size 2 or 4 can be converted to utf8"); + } + } + + static inline void to_string(char* dest, size_t destSize, const wchar_t* first, const wchar_t* last) + { + if constexpr (Size == 2) + { + Utf8::Unchecked::utf16to8(first, last, dest, destSize); + } + else if constexpr (Size == 4) + { + Utf8::Unchecked::utf32to8(first, last, dest, destSize); } else { @@ -73,11 +91,11 @@ namespace AZStd { if constexpr (Size == 2) { - Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size()); } else { @@ -92,11 +110,11 @@ namespace AZStd { if constexpr (Size == 2) { - Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest)); + Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size()); } else { @@ -326,6 +344,19 @@ namespace AZStd return to_string(dest, src.c_str(), src.length()); } + inline void to_string(char* dest, size_t destSize, const wchar_t* str, size_t srcLen = 0) + { + if (srcLen == 0) + { + srcLen = wcslen(str) + 1; + } + + if (srcLen > 0) + { + Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen + 1); // copy null terminator + } + } + template int stoi(const AZStd::basic_string& str, AZStd::size_t* idx = 0, int base = 10) { diff --git a/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h b/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h index 9608ff897b..cfc917ddc4 100644 --- a/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h +++ b/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h @@ -92,33 +92,58 @@ namespace Utf8::Unchecked return temp; } - static Iterator to_utf8_sequence(AZ::u32 cp, Iterator result) + static Iterator to_utf8_sequence(AZ::u32 cp, Iterator& result, size_t& resultMaxSize) { if (cp < 0x80) { // one octet + resultMaxSize -= 1; // no need to check the calling function will exit the loop *(result++) = static_cast(cp); } else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); + if (resultMaxSize >= 2) + { + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + resultMaxSize -= 2; + } + else + { + resultMaxSize = 0; + } } else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); + if (resultMaxSize >= 3) + { + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + resultMaxSize -= 3; + } + else + { + resultMaxSize = 0; + } } else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); + if (resultMaxSize >= 4) + { + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + resultMaxSize -= 4; + } + else + { + resultMaxSize = 0; + } } return result; } @@ -155,9 +180,9 @@ namespace Utf8::Unchecked }; template - Utf8Iterator utf16to8(u16bit_iterator start, u16bit_iterator end, Utf8Iterator result) + Utf8Iterator utf16to8(u16bit_iterator start, u16bit_iterator end, Utf8Iterator result, size_t resultMaxSize) { - while (start != end) + while (start != end && resultMaxSize > 0) { AZ::u32 cp = Utf8::Internal::mask16(*start++); // Take care of surrogate pairs first @@ -166,52 +191,62 @@ namespace Utf8::Unchecked AZ::u32 trail_surrogate = Utf8::Internal::mask16(*start++); cp = (cp << 10) + trail_surrogate + Internal::SURROGATE_OFFSET; } - octet_iterator::to_utf8_sequence(cp, result); + octet_iterator::to_utf8_sequence(cp, result, resultMaxSize); } return result; } template - u16bit_iterator utf8to16(Utf8Iterator start, Utf8Iterator end, u16bit_iterator result) + u16bit_iterator utf8to16(Utf8Iterator start, Utf8Iterator end, u16bit_iterator result, size_t resultMaxSize) { octet_iterator utf8Start(start); octet_iterator utf8Last(end); - while (utf8Start != utf8Last) + while (utf8Start != utf8Last && resultMaxSize > 0) { AZ::u32 cp = *utf8Start++; if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + Internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + Internal::TRAIL_SURROGATE_MIN); + if (resultMaxSize >= 2) + { + *result++ = static_cast((cp >> 10) + Internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + Internal::TRAIL_SURROGATE_MIN); + resultMaxSize -= 2; + } + else + { + resultMaxSize = 0; + } } else { *result++ = static_cast(cp); + resultMaxSize -= 1; } } return result; } template - Utf8Iterator utf32to8(u32bit_iterator start, u32bit_iterator end, Utf8Iterator result) + Utf8Iterator utf32to8(u32bit_iterator start, u32bit_iterator end, Utf8Iterator result, size_t resultMaxSize) { - while (start != end) + while (start != end && resultMaxSize > 0) { - octet_iterator::to_utf8_sequence(*start++, result); + octet_iterator::to_utf8_sequence(*start++, result, resultMaxSize); } return result; } template - u32bit_iterator utf8to32(Utf8Iterator start, Utf8Iterator end, u32bit_iterator result) + u32bit_iterator utf8to32(Utf8Iterator start, Utf8Iterator end, u32bit_iterator result, size_t resultMaxSize) { octet_iterator utf8Start(start); octet_iterator utf8Last(end); - while (utf8Start != utf8Last) + while (utf8Start != utf8Last && resultMaxSize > 0) { *result++ = *utf8Start++; + --resultMaxSize; } return result; diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp index 66257735b4..c57f2b31f6 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -29,7 +30,9 @@ namespace AZ result.m_pathIncludesFilename = true; // Platform specific get exe path: http://stackoverflow.com/a/1024937 // https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea - const DWORD pathLen = GetModuleFileNameA(nullptr, exeStorageBuffer, static_cast(exeStorageSize)); + AZStd::wstring pathBuffer; + pathBuffer.resize(exeStorageSize); + const DWORD pathLen = GetModuleFileName(nullptr, pathBuffer.data(), static_cast(exeStorageSize)); const DWORD errorCode = GetLastError(); if (pathLen == exeStorageSize && errorCode == ERROR_INSUFFICIENT_BUFFER) { @@ -39,6 +42,10 @@ namespace AZ { result.m_pathStored = ExecutablePathResult::GeneralError; } + else + { + AZStd::to_string(exeStorageBuffer, exeStorageSize, pathBuffer.c_str()); + } return result; } diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp index 0e6ea4727c..2d2602e456 100644 --- a/Code/Framework/AzCore/Tests/AZStd/String.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp @@ -628,10 +628,6 @@ namespace UnitTest } } -#if defined(AZ_COMPILER_MSVC) -# pragma warning(push) -# pragma warning( disable: 4428 ) // universal-character-name encountered in source -#endif // AZ_COMPILER_MSVC TEST_F(String, Algorithms) { string str = string::format("%s %d", "BlaBla", 5); @@ -1114,11 +1110,6 @@ namespace UnitTest EXPECT_FALSE(other2.Valid()); } - // StringAlgorithmTest-End -#if defined(AZ_COMPILER_MSVC) -# pragma warning(pop) -#endif // AZ_COMPILER_MSVC - TEST_F(String, ConstString) { string_view cstr1;