diff --git a/include/SFML/System/String.hpp b/include/SFML/System/String.hpp index a217539d..5d79e30a 100644 --- a/include/SFML/System/String.hpp +++ b/include/SFML/System/String.hpp @@ -48,15 +48,15 @@ public: //////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////// - using Iterator = std::basic_string::iterator; //!< Iterator type - using ConstIterator = std::basic_string::const_iterator; //!< Read-only iterator type + using Iterator = std::u32string::iterator; //!< Iterator type + using ConstIterator = std::u32string::const_iterator; //!< Read-only iterator type //////////////////////////////////////////////////////////// // Static member data //////////////////////////////////////////////////////////// // NOLINTBEGIN(readability-identifier-naming) /// Represents an invalid position in the string - static const std::size_t InvalidPos{std::basic_string::npos}; + static const std::size_t InvalidPos{std::u32string::npos}; // NOLINTEND(readability-identifier-naming) //////////////////////////////////////////////////////////// @@ -93,7 +93,7 @@ public: /// \param utf32Char UTF-32 character to convert /// //////////////////////////////////////////////////////////// - String(std::uint32_t utf32Char); + String(char32_t utf32Char); //////////////////////////////////////////////////////////// /// \brief Construct from a null-terminated C-style ANSI string and a locale @@ -141,7 +141,7 @@ public: /// \param utf32String UTF-32 string to assign /// //////////////////////////////////////////////////////////// - String(const std::uint32_t* utf32String); + String(const char32_t* utf32String); //////////////////////////////////////////////////////////// /// \brief Construct from an UTF-32 string @@ -149,7 +149,7 @@ public: /// \param utf32String UTF-32 string to assign /// //////////////////////////////////////////////////////////// - String(const std::basic_string& utf32String); + String(const std::u32string& utf32String); //////////////////////////////////////////////////////////// /// \brief Create a new sf::String from a UTF-8 encoded string @@ -183,8 +183,8 @@ public: /// \brief Create a new sf::String from a UTF-32 encoded string /// /// This function is provided for consistency, it is equivalent to - /// using the constructors that takes a const std::uint32_t* or - /// a std::basic_string. + /// using the constructors that takes a const char32_t* or + /// a std::u32string. /// /// \param begin Forward iterator to the beginning of the UTF-32 sequence /// \param end Forward iterator to the end of the UTF-32 sequence @@ -277,7 +277,7 @@ public: /// \see toUtf8, toUtf32 /// //////////////////////////////////////////////////////////// - std::basic_string toUtf16() const; + std::u16string toUtf16() const; //////////////////////////////////////////////////////////// /// \brief Convert the Unicode string to a UTF-32 string @@ -290,7 +290,7 @@ public: /// \see toUtf8, toUtf16 /// //////////////////////////////////////////////////////////// - std::basic_string toUtf32() const; + std::u32string toUtf32() const; //////////////////////////////////////////////////////////// /// \brief Overload of += operator to append an UTF-32 string @@ -313,7 +313,7 @@ public: /// \return Character at position \a index /// //////////////////////////////////////////////////////////// - std::uint32_t operator[](std::size_t index) const; + char32_t operator[](std::size_t index) const; //////////////////////////////////////////////////////////// /// \brief Overload of [] operator to access a character by its position @@ -326,7 +326,7 @@ public: /// \return Reference to the character at position \a index /// //////////////////////////////////////////////////////////// - std::uint32_t& operator[](std::size_t index); + char32_t& operator[](std::size_t index); //////////////////////////////////////////////////////////// /// \brief Clear the string @@ -450,7 +450,7 @@ public: /// \return Read-only pointer to the array of characters /// //////////////////////////////////////////////////////////// - const std::uint32_t* getData() const; + const char32_t* getData() const; //////////////////////////////////////////////////////////// /// \brief Return an iterator to the beginning of the string @@ -507,7 +507,7 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - std::basic_string m_string; //!< Internal string of UTF-32 characters + std::u32string m_string; //!< Internal string of UTF-32 characters }; //////////////////////////////////////////////////////////// diff --git a/src/SFML/Network/Packet.cpp b/src/SFML/Network/Packet.cpp index 1fc05ca1..3f41038d 100644 --- a/src/SFML/Network/Packet.cpp +++ b/src/SFML/Network/Packet.cpp @@ -381,7 +381,7 @@ Packet& Packet::operator>>(String& data) { std::uint32_t character = 0; *this >> character; - data += character; + data += static_cast(character); } } diff --git a/src/SFML/System/String.cpp b/src/SFML/System/String.cpp index 2524fbf2..f0ef7ab6 100644 --- a/src/SFML/System/String.cpp +++ b/src/SFML/System/String.cpp @@ -57,7 +57,7 @@ String::String(wchar_t wideChar) //////////////////////////////////////////////////////////// -String::String(std::uint32_t utf32Char) +String::String(char32_t utf32Char) { m_string += utf32Char; } @@ -110,7 +110,7 @@ String::String(const std::wstring& wideString) //////////////////////////////////////////////////////////// -String::String(const std::uint32_t* utf32String) +String::String(const char32_t* utf32String) { if (utf32String) m_string = utf32String; @@ -118,7 +118,7 @@ String::String(const std::uint32_t* utf32String) //////////////////////////////////////////////////////////// -String::String(const std::basic_string& utf32String) : m_string(utf32String) +String::String(const std::u32string& utf32String) : m_string(utf32String) { } @@ -180,10 +180,10 @@ std::basic_string String::toUtf8() const //////////////////////////////////////////////////////////// -std::basic_string String::toUtf16() const +std::u16string String::toUtf16() const { // Prepare the output string - std::basic_string output; + std::u16string output; output.reserve(m_string.length()); // Convert @@ -194,7 +194,7 @@ std::basic_string String::toUtf16() const //////////////////////////////////////////////////////////// -std::basic_string String::toUtf32() const +std::u32string String::toUtf32() const { return m_string; } @@ -209,14 +209,14 @@ String& String::operator+=(const String& right) //////////////////////////////////////////////////////////// -std::uint32_t String::operator[](std::size_t index) const +char32_t String::operator[](std::size_t index) const { return m_string[index]; } //////////////////////////////////////////////////////////// -std::uint32_t& String::operator[](std::size_t index) +char32_t& String::operator[](std::size_t index) { return m_string[index]; } @@ -295,7 +295,7 @@ String String::substring(std::size_t position, std::size_t length) const //////////////////////////////////////////////////////////// -const std::uint32_t* String::getData() const +const char32_t* String::getData() const { return m_string.c_str(); } diff --git a/src/SFML/Window/OSX/HIDInputManager.mm b/src/SFML/Window/OSX/HIDInputManager.mm index d9c41af6..95c75f7a 100644 --- a/src/SFML/Window/OSX/HIDInputManager.mm +++ b/src/SFML/Window/OSX/HIDInputManager.mm @@ -690,7 +690,7 @@ String HIDInputManager::getDescription(Keyboard::Scancode code) // Phase 2: Try to convert the key to unicode UniChar unicode = toUnicode(localize(code)); if (unicode != 0x00) - return String(static_cast(unicode)); + return String(static_cast(unicode)); } // Phase 3: Return final fallback diff --git a/src/SFML/Window/Unix/KeySymToUnicodeMapping.cpp b/src/SFML/Window/Unix/KeySymToUnicodeMapping.cpp index 01f333b4..40d3d259 100644 --- a/src/SFML/Window/Unix/KeySymToUnicodeMapping.cpp +++ b/src/SFML/Window/Unix/KeySymToUnicodeMapping.cpp @@ -30,7 +30,7 @@ namespace sf::priv { -std::uint32_t keysymToUnicode(KeySym keysym) +char32_t keysymToUnicode(KeySym keysym) { // clang-format off switch (keysym) diff --git a/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp b/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp index ba05c75c..42c28833 100644 --- a/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp +++ b/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp @@ -49,6 +49,6 @@ namespace sf::priv /// \return corresponding UTF-32 /// //////////////////////////////////////////////////////////// -std::uint32_t keysymToUnicode(KeySym keysym); +char32_t keysymToUnicode(KeySym keysym); } // namespace sf::priv diff --git a/src/SFML/Window/Unix/KeyboardImpl.cpp b/src/SFML/Window/Unix/KeyboardImpl.cpp index c4dc9dd0..f4628a3d 100644 --- a/src/SFML/Window/Unix/KeyboardImpl.cpp +++ b/src/SFML/Window/Unix/KeyboardImpl.cpp @@ -671,8 +671,8 @@ String KeyboardImpl::getDescription(Keyboard::Scancode code) if (checkInput) { - KeySym keysym = scancodeToKeySym(code); - std::uint32_t unicode = keysymToUnicode(keysym); + KeySym keysym = scancodeToKeySym(code); + char32_t unicode = keysymToUnicode(keysym); if (unicode != 0) return String(unicode); diff --git a/test/System/String.test.cpp b/test/System/String.test.cpp index d923c54a..f18ec0f4 100644 --- a/test/System/String.test.cpp +++ b/test/System/String.test.cpp @@ -28,6 +28,14 @@ auto select(const std::basic_string& string16, const std::basic_string& st else return string32; } + +template +auto toHex(const CharT character) +{ + std::ostringstream stream; + stream << "[\\x" << std::uppercase << std::hex << static_cast(character) << ']'; + return stream.str(); +} } // namespace // Specialize StringMaker for alternative std::basic_string specializations @@ -38,13 +46,6 @@ namespace doctest template struct StringMaker> { - static std::string toHex(const CharT character) - { - std::ostringstream stream; - stream << "[\\x" << std::uppercase << std::hex << static_cast(character) << ']'; - return stream.str(); - } - static String convert(const std::basic_string& string) { doctest::String output; @@ -58,6 +59,15 @@ struct StringMaker> return output; } }; + +template <> +struct StringMaker +{ + static String convert(const char32_t character) + { + return toHex(character).c_str(); + } +}; } // namespace doctest TEST_CASE("[System] sf::String") @@ -74,8 +84,8 @@ TEST_CASE("[System] sf::String") CHECK(string.toAnsiString() == ""s); CHECK(string.toWideString() == L""s); CHECK(string.toUtf8() == std::basic_string()); - CHECK(string.toUtf16() == std::basic_string()); - CHECK(string.toUtf32() == std::basic_string()); + CHECK(string.toUtf16() == u""s); + CHECK(string.toUtf32() == U""s); CHECK(string.getSize() == 0); CHECK(string.isEmpty()); CHECK(string.getData() != nullptr); @@ -83,14 +93,14 @@ TEST_CASE("[System] sf::String") SUBCASE("ANSI character constructor") { - const sf::String string('a'); + const sf::String string = 'a'; CHECK(std::string(string) == "a"s); CHECK(std::wstring(string) == L"a"s); CHECK(string.toAnsiString() == "a"s); CHECK(string.toWideString() == L"a"s); CHECK(string.toUtf8() == std::basic_string{'a'}); - CHECK(string.toUtf16() == std::basic_string{'a'}); - CHECK(string.toUtf32() == std::basic_string{'a'}); + CHECK(string.toUtf16() == u"a"s); + CHECK(string.toUtf32() == U"a"s); CHECK(string.getSize() == 1); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -98,14 +108,14 @@ TEST_CASE("[System] sf::String") SUBCASE("ANSI C string constructor") { - const sf::String string("def"); + const sf::String string = "def"; CHECK(std::string(string) == "def"s); CHECK(std::wstring(string) == L"def"s); CHECK(string.toAnsiString() == "def"s); CHECK(string.toWideString() == L"def"s); CHECK(string.toUtf8() == std::basic_string{'d', 'e', 'f'}); - CHECK(string.toUtf16() == std::basic_string{'d', 'e', 'f'}); - CHECK(string.toUtf32() == std::basic_string{'d', 'e', 'f'}); + CHECK(string.toUtf16() == u"def"s); + CHECK(string.toUtf32() == U"def"s); CHECK(string.getSize() == 3); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -113,14 +123,14 @@ TEST_CASE("[System] sf::String") SUBCASE("ANSI string constructor") { - const sf::String string("ghi"s); + const sf::String string = "ghi"s; CHECK(std::string(string) == "ghi"s); CHECK(std::wstring(string) == L"ghi"s); CHECK(string.toAnsiString() == "ghi"s); CHECK(string.toWideString() == L"ghi"s); CHECK(string.toUtf8() == std::basic_string{'g', 'h', 'i'}); - CHECK(string.toUtf16() == std::basic_string{'g', 'h', 'i'}); - CHECK(string.toUtf32() == std::basic_string{'g', 'h', 'i'}); + CHECK(string.toUtf16() == u"ghi"s); + CHECK(string.toUtf32() == U"ghi"s); CHECK(string.getSize() == 3); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -128,14 +138,14 @@ TEST_CASE("[System] sf::String") SUBCASE("Wide character constructor") { - const sf::String string(L'\xFA'); + const sf::String string = L'\xFA'; CHECK(std::string(string) == select("\xFA"s, "\0"s)); CHECK(std::wstring(string) == L"\xFA"s); CHECK(string.toAnsiString() == select("\xFA"s, "\0"s)); CHECK(string.toWideString() == L"\xFA"s); CHECK(string.toUtf8() == std::basic_string{0xC3, 0xBA}); - CHECK(string.toUtf16() == std::basic_string{0xFA}); - CHECK(string.toUtf32() == std::basic_string{0xFA}); + CHECK(string.toUtf16() == u"\xFA"s); + CHECK(string.toUtf32() == U"\xFA"s); CHECK(string.getSize() == 1); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -143,14 +153,14 @@ TEST_CASE("[System] sf::String") SUBCASE("Wide C string constructor") { - const sf::String string(L"j\xFAl"); + const sf::String string = L"j\xFAl"; CHECK(std::string(string) == select("j\xFAl"s, "j\0l"s)); CHECK(std::wstring(string) == L"j\xFAl"s); CHECK(string.toAnsiString() == select("j\xFAl"s, "j\0l"s)); CHECK(string.toWideString() == L"j\xFAl"s); CHECK(string.toUtf8() == std::basic_string{'j', 0xC3, 0xBA, 'l'}); - CHECK(string.toUtf16() == std::basic_string{'j', 0xFA, 'l'}); - CHECK(string.toUtf32() == std::basic_string{'j', 0xFA, 'l'}); + CHECK(string.toUtf16() == u"j\xFAl"s); + CHECK(string.toUtf32() == U"j\xFAl"s); CHECK(string.getSize() == 3); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -158,14 +168,14 @@ TEST_CASE("[System] sf::String") SUBCASE("Wide string constructor") { - const sf::String string(L"mno\xFA"s); + const sf::String string = L"mno\xFA"s; CHECK(std::string(string) == select("mno\xFA"s, "mno\0"s)); CHECK(std::wstring(string) == L"mno\xFA"s); CHECK(string.toAnsiString() == select("mno\xFA"s, "mno\0"s)); CHECK(string.toWideString() == L"mno\xFA"s); CHECK(string.toUtf8() == std::basic_string{'m', 'n', 'o', 0xC3, 0XBA}); - CHECK(string.toUtf16() == std::basic_string{'m', 'n', 'o', 0xFA}); - CHECK(string.toUtf32() == std::basic_string{'m', 'n', 'o', 0xFA}); + CHECK(string.toUtf16() == u"mno\xFA"s); + CHECK(string.toUtf32() == U"mno\xFA"s); CHECK(string.getSize() == 4); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -173,14 +183,14 @@ TEST_CASE("[System] sf::String") SUBCASE("UTF-32 character constructor") { - const sf::String string(U'\U0010AFAF'); + const sf::String string = U'\U0010AFAF'; CHECK(std::string(string) == "\0"s); CHECK(std::wstring(string) == select(L""s, L"\U0010AFAF"s)); CHECK(string.toAnsiString() == "\0"s); CHECK(string.toWideString() == select(L""s, L"\U0010AFAF"s)); CHECK(string.toUtf8() == std::basic_string{0xF4, 0x8A, 0xBE, 0xAF}); - CHECK(string.toUtf16() == std::basic_string{0xDBEB, 0xDFAF}); - CHECK(string.toUtf32() == std::basic_string{0x10AFAF}); + CHECK(string.toUtf16() == u"\U0010AFAF"s); + CHECK(string.toUtf32() == U"\U0010AFAF"s); CHECK(string.getSize() == 1); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -188,14 +198,14 @@ TEST_CASE("[System] sf::String") SUBCASE("UTF-32 C string constructor") { - const sf::String string(reinterpret_cast(U"\U0010ABCDrs")); + const sf::String string = U"\U0010ABCDrs"; CHECK(std::string(string) == "\0rs"s); CHECK(std::wstring(string) == select(L"rs"s, L"\U0010ABCDrs"s)); CHECK(string.toAnsiString() == "\0rs"s); CHECK(string.toWideString() == select(L"rs"s, L"\U0010ABCDrs"s)); CHECK(string.toUtf8() == std::basic_string{0xF4, 0x8A, 0xAF, 0x8D, 'r', 's'}); - CHECK(string.toUtf16() == std::basic_string{0xDBEA, 0xDFCD, 'r', 's'}); - CHECK(string.toUtf32() == std::basic_string{0x10ABCD, 'r', 's'}); + CHECK(string.toUtf16() == u"\U0010ABCDrs"s); + CHECK(string.toUtf32() == U"\U0010ABCDrs"s); CHECK(string.getSize() == 3); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -203,14 +213,14 @@ TEST_CASE("[System] sf::String") SUBCASE("UTF-32 string constructor") { - const sf::String string(std::basic_string{'t', 'u', 'v', 0x104321}); + const sf::String string = U"tuv\U00104321"s; CHECK(std::string(string) == "tuv\0"s); CHECK(std::wstring(string) == select(L"tuv"s, L"tuv\U00104321"s)); CHECK(string.toAnsiString() == "tuv\0"s); CHECK(string.toWideString() == select(L"tuv"s, L"tuv\U00104321"s)); CHECK(string.toUtf8() == std::basic_string{'t', 'u', 'v', 0xF4, 0x84, 0x8C, 0xA1}); - CHECK(string.toUtf16() == std::basic_string{'t', 'u', 'v', 0xDBD0, 0xDF21}); - CHECK(string.toUtf32() == std::basic_string{'t', 'u', 'v', 0x104321}); + CHECK(string.toUtf16() == u"tuv\U00104321"s); + CHECK(string.toUtf32() == U"tuv\U00104321"s); CHECK(string.getSize() == 4); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -226,8 +236,8 @@ TEST_CASE("[System] sf::String") CHECK(string.toAnsiString() == "wxyz"s); CHECK(string.toWideString() == L"wxyz"s); CHECK(string.toUtf8() == std::basic_string{'w', 'x', 'y', 'z'}); - CHECK(string.toUtf16() == std::basic_string{'w', 'x', 'y', 'z'}); - CHECK(string.toUtf32() == std::basic_string{'w', 'x', 'y', 'z'}); + CHECK(string.toUtf16() == u"wxyz"s); + CHECK(string.toUtf32() == U"wxyz"s); CHECK(string.getSize() == 4); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -242,8 +252,8 @@ TEST_CASE("[System] sf::String") CHECK(string.toAnsiString() == select("\xF1xyz"s, "\0xyz"s)); CHECK(string.toWideString() == L"\xF1xyz"s); CHECK(string.toUtf8() == std::basic_string{0xC3, 0xB1, 'x', 'y', 'z'}); - CHECK(string.toUtf16() == std::basic_string{0xF1, 'x', 'y', 'z'}); - CHECK(string.toUtf32() == std::basic_string{0xF1, 'x', 'y', 'z'}); + CHECK(string.toUtf16() == u"\xF1xyz"s); + CHECK(string.toUtf32() == U"\xF1xyz"s); CHECK(string.getSize() == 4); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr); @@ -258,8 +268,8 @@ TEST_CASE("[System] sf::String") CHECK(string.toAnsiString() == "w\0yz"s); CHECK(string.toWideString() == select(L"wyz"s, L"w\U00104321yz"s)); CHECK(string.toUtf8() == std::basic_string{'w', 0xF4, 0x84, 0x8C, 0xA1, 'y', 'z'}); - CHECK(string.toUtf16() == std::basic_string{'w', 0xDBD0, 0xDF21, 'y', 'z'}); - CHECK(string.toUtf32() == std::basic_string{'w', 0x104321, 'y', 'z'}); + CHECK(string.toUtf16() == u"w\U00104321yz"s); + CHECK(string.toUtf32() == U"w\U00104321yz"s); CHECK(string.getSize() == 4); CHECK(!string.isEmpty()); CHECK(string.getData() != nullptr);