Implement sf::String in terms of std::u32string

This commit is contained in:
Chris Thrasher 2023-03-25 22:02:29 -06:00
parent 93a8506498
commit f371a99b39
8 changed files with 81 additions and 71 deletions

View File

@ -48,15 +48,15 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Types // Types
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
using Iterator = std::basic_string<std::uint32_t>::iterator; //!< Iterator type using Iterator = std::u32string::iterator; //!< Iterator type
using ConstIterator = std::basic_string<std::uint32_t>::const_iterator; //!< Read-only iterator type using ConstIterator = std::u32string::const_iterator; //!< Read-only iterator type
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Static member data // Static member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// NOLINTBEGIN(readability-identifier-naming) // NOLINTBEGIN(readability-identifier-naming)
/// Represents an invalid position in the string /// Represents an invalid position in the string
static const std::size_t InvalidPos{std::basic_string<std::uint32_t>::npos}; static const std::size_t InvalidPos{std::u32string::npos};
// NOLINTEND(readability-identifier-naming) // NOLINTEND(readability-identifier-naming)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -93,7 +93,7 @@ public:
/// \param utf32Char UTF-32 character to convert /// \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 /// \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 /// \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 /// \brief Construct from an UTF-32 string
@ -149,7 +149,7 @@ public:
/// \param utf32String UTF-32 string to assign /// \param utf32String UTF-32 string to assign
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String(const std::basic_string<std::uint32_t>& utf32String); String(const std::u32string& utf32String);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new sf::String from a UTF-8 encoded string /// \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 /// \brief Create a new sf::String from a UTF-32 encoded string
/// ///
/// This function is provided for consistency, it is equivalent to /// This function is provided for consistency, it is equivalent to
/// using the constructors that takes a const std::uint32_t* or /// using the constructors that takes a const char32_t* or
/// a std::basic_string<std::uint32_t>. /// a std::u32string.
/// ///
/// \param begin Forward iterator to the beginning of the UTF-32 sequence /// \param begin Forward iterator to the beginning of the UTF-32 sequence
/// \param end Forward iterator to the end 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 /// \see toUtf8, toUtf32
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<std::uint16_t> toUtf16() const; std::u16string toUtf16() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-32 string /// \brief Convert the Unicode string to a UTF-32 string
@ -290,7 +290,7 @@ public:
/// \see toUtf8, toUtf16 /// \see toUtf8, toUtf16
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<std::uint32_t> toUtf32() const; std::u32string toUtf32() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Overload of += operator to append an UTF-32 string /// \brief Overload of += operator to append an UTF-32 string
@ -313,7 +313,7 @@ public:
/// \return Character at position \a index /// \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 /// \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 /// \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 /// \brief Clear the string
@ -450,7 +450,7 @@ public:
/// \return Read-only pointer to the array of characters /// \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 /// \brief Return an iterator to the beginning of the string
@ -507,7 +507,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<std::uint32_t> m_string; //!< Internal string of UTF-32 characters std::u32string m_string; //!< Internal string of UTF-32 characters
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -381,7 +381,7 @@ Packet& Packet::operator>>(String& data)
{ {
std::uint32_t character = 0; std::uint32_t character = 0;
*this >> character; *this >> character;
data += character; data += static_cast<char32_t>(character);
} }
} }

View File

@ -57,7 +57,7 @@ String::String(wchar_t wideChar)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String::String(std::uint32_t utf32Char) String::String(char32_t utf32Char)
{ {
m_string += 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) if (utf32String)
m_string = utf32String; m_string = utf32String;
@ -118,7 +118,7 @@ String::String(const std::uint32_t* utf32String)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String::String(const std::basic_string<std::uint32_t>& utf32String) : m_string(utf32String) String::String(const std::u32string& utf32String) : m_string(utf32String)
{ {
} }
@ -180,10 +180,10 @@ std::basic_string<std::uint8_t> String::toUtf8() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<std::uint16_t> String::toUtf16() const std::u16string String::toUtf16() const
{ {
// Prepare the output string // Prepare the output string
std::basic_string<std::uint16_t> output; std::u16string output;
output.reserve(m_string.length()); output.reserve(m_string.length());
// Convert // Convert
@ -194,7 +194,7 @@ std::basic_string<std::uint16_t> String::toUtf16() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<std::uint32_t> String::toUtf32() const std::u32string String::toUtf32() const
{ {
return m_string; 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]; 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]; 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(); return m_string.c_str();
} }

View File

@ -690,7 +690,7 @@ String HIDInputManager::getDescription(Keyboard::Scancode code)
// Phase 2: Try to convert the key to unicode // Phase 2: Try to convert the key to unicode
UniChar unicode = toUnicode(localize(code)); UniChar unicode = toUnicode(localize(code));
if (unicode != 0x00) if (unicode != 0x00)
return String(static_cast<std::uint32_t>(unicode)); return String(static_cast<char32_t>(unicode));
} }
// Phase 3: Return final fallback // Phase 3: Return final fallback

View File

@ -30,7 +30,7 @@
namespace sf::priv namespace sf::priv
{ {
std::uint32_t keysymToUnicode(KeySym keysym) char32_t keysymToUnicode(KeySym keysym)
{ {
// clang-format off // clang-format off
switch (keysym) switch (keysym)

View File

@ -49,6 +49,6 @@ namespace sf::priv
/// \return corresponding UTF-32 /// \return corresponding UTF-32
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::uint32_t keysymToUnicode(KeySym keysym); char32_t keysymToUnicode(KeySym keysym);
} // namespace sf::priv } // namespace sf::priv

View File

@ -672,7 +672,7 @@ String KeyboardImpl::getDescription(Keyboard::Scancode code)
if (checkInput) if (checkInput)
{ {
KeySym keysym = scancodeToKeySym(code); KeySym keysym = scancodeToKeySym(code);
std::uint32_t unicode = keysymToUnicode(keysym); char32_t unicode = keysymToUnicode(keysym);
if (unicode != 0) if (unicode != 0)
return String(unicode); return String(unicode);

View File

@ -28,6 +28,14 @@ auto select(const std::basic_string<T>& string16, const std::basic_string<T>& st
else else
return string32; return string32;
} }
template <typename CharT>
auto toHex(const CharT character)
{
std::ostringstream stream;
stream << "[\\x" << std::uppercase << std::hex << static_cast<std::uint32_t>(character) << ']';
return stream.str();
}
} // namespace } // namespace
// Specialize StringMaker for alternative std::basic_string<T> specializations // Specialize StringMaker for alternative std::basic_string<T> specializations
@ -38,13 +46,6 @@ namespace doctest
template <typename CharT> template <typename CharT>
struct StringMaker<std::basic_string<CharT>> struct StringMaker<std::basic_string<CharT>>
{ {
static std::string toHex(const CharT character)
{
std::ostringstream stream;
stream << "[\\x" << std::uppercase << std::hex << static_cast<std::uint32_t>(character) << ']';
return stream.str();
}
static String convert(const std::basic_string<CharT>& string) static String convert(const std::basic_string<CharT>& string)
{ {
doctest::String output; doctest::String output;
@ -58,6 +59,15 @@ struct StringMaker<std::basic_string<CharT>>
return output; return output;
} }
}; };
template <>
struct StringMaker<char32_t>
{
static String convert(const char32_t character)
{
return toHex(character).c_str();
}
};
} // namespace doctest } // namespace doctest
TEST_CASE("[System] sf::String") TEST_CASE("[System] sf::String")
@ -74,8 +84,8 @@ TEST_CASE("[System] sf::String")
CHECK(string.toAnsiString() == ""s); CHECK(string.toAnsiString() == ""s);
CHECK(string.toWideString() == L""s); CHECK(string.toWideString() == L""s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>()); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>());
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>()); CHECK(string.toUtf16() == u""s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>()); CHECK(string.toUtf32() == U""s);
CHECK(string.getSize() == 0); CHECK(string.getSize() == 0);
CHECK(string.isEmpty()); CHECK(string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -83,14 +93,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("ANSI character constructor") SUBCASE("ANSI character constructor")
{ {
const sf::String string('a'); const sf::String string = 'a';
CHECK(std::string(string) == "a"s); CHECK(std::string(string) == "a"s);
CHECK(std::wstring(string) == L"a"s); CHECK(std::wstring(string) == L"a"s);
CHECK(string.toAnsiString() == "a"s); CHECK(string.toAnsiString() == "a"s);
CHECK(string.toWideString() == L"a"s); CHECK(string.toWideString() == L"a"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'a'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'a'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'a'}); CHECK(string.toUtf16() == u"a"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'a'}); CHECK(string.toUtf32() == U"a"s);
CHECK(string.getSize() == 1); CHECK(string.getSize() == 1);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -98,14 +108,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("ANSI C string constructor") SUBCASE("ANSI C string constructor")
{ {
const sf::String string("def"); const sf::String string = "def";
CHECK(std::string(string) == "def"s); CHECK(std::string(string) == "def"s);
CHECK(std::wstring(string) == L"def"s); CHECK(std::wstring(string) == L"def"s);
CHECK(string.toAnsiString() == "def"s); CHECK(string.toAnsiString() == "def"s);
CHECK(string.toWideString() == L"def"s); CHECK(string.toWideString() == L"def"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'d', 'e', 'f'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'d', 'e', 'f'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'d', 'e', 'f'}); CHECK(string.toUtf16() == u"def"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'d', 'e', 'f'}); CHECK(string.toUtf32() == U"def"s);
CHECK(string.getSize() == 3); CHECK(string.getSize() == 3);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -113,14 +123,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("ANSI string constructor") SUBCASE("ANSI string constructor")
{ {
const sf::String string("ghi"s); const sf::String string = "ghi"s;
CHECK(std::string(string) == "ghi"s); CHECK(std::string(string) == "ghi"s);
CHECK(std::wstring(string) == L"ghi"s); CHECK(std::wstring(string) == L"ghi"s);
CHECK(string.toAnsiString() == "ghi"s); CHECK(string.toAnsiString() == "ghi"s);
CHECK(string.toWideString() == L"ghi"s); CHECK(string.toWideString() == L"ghi"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'g', 'h', 'i'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'g', 'h', 'i'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'g', 'h', 'i'}); CHECK(string.toUtf16() == u"ghi"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'g', 'h', 'i'}); CHECK(string.toUtf32() == U"ghi"s);
CHECK(string.getSize() == 3); CHECK(string.getSize() == 3);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -128,14 +138,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("Wide character constructor") 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::string(string) == select("\xFA"s, "\0"s));
CHECK(std::wstring(string) == L"\xFA"s); CHECK(std::wstring(string) == L"\xFA"s);
CHECK(string.toAnsiString() == select("\xFA"s, "\0"s)); CHECK(string.toAnsiString() == select("\xFA"s, "\0"s));
CHECK(string.toWideString() == L"\xFA"s); CHECK(string.toWideString() == L"\xFA"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xC3, 0xBA}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xC3, 0xBA});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{0xFA}); CHECK(string.toUtf16() == u"\xFA"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{0xFA}); CHECK(string.toUtf32() == U"\xFA"s);
CHECK(string.getSize() == 1); CHECK(string.getSize() == 1);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -143,14 +153,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("Wide C string constructor") 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::string(string) == select("j\xFAl"s, "j\0l"s));
CHECK(std::wstring(string) == L"j\xFAl"s); CHECK(std::wstring(string) == L"j\xFAl"s);
CHECK(string.toAnsiString() == select("j\xFAl"s, "j\0l"s)); CHECK(string.toAnsiString() == select("j\xFAl"s, "j\0l"s));
CHECK(string.toWideString() == L"j\xFAl"s); CHECK(string.toWideString() == L"j\xFAl"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'j', 0xC3, 0xBA, 'l'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'j', 0xC3, 0xBA, 'l'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'j', 0xFA, 'l'}); CHECK(string.toUtf16() == u"j\xFAl"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'j', 0xFA, 'l'}); CHECK(string.toUtf32() == U"j\xFAl"s);
CHECK(string.getSize() == 3); CHECK(string.getSize() == 3);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -158,14 +168,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("Wide string constructor") 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::string(string) == select("mno\xFA"s, "mno\0"s));
CHECK(std::wstring(string) == L"mno\xFA"s); CHECK(std::wstring(string) == L"mno\xFA"s);
CHECK(string.toAnsiString() == select("mno\xFA"s, "mno\0"s)); CHECK(string.toAnsiString() == select("mno\xFA"s, "mno\0"s));
CHECK(string.toWideString() == L"mno\xFA"s); CHECK(string.toWideString() == L"mno\xFA"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'m', 'n', 'o', 0xC3, 0XBA}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'m', 'n', 'o', 0xC3, 0XBA});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'m', 'n', 'o', 0xFA}); CHECK(string.toUtf16() == u"mno\xFA"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'m', 'n', 'o', 0xFA}); CHECK(string.toUtf32() == U"mno\xFA"s);
CHECK(string.getSize() == 4); CHECK(string.getSize() == 4);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -173,14 +183,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("UTF-32 character constructor") 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::string(string) == "\0"s);
CHECK(std::wstring(string) == select(L""s, L"\U0010AFAF"s)); CHECK(std::wstring(string) == select(L""s, L"\U0010AFAF"s));
CHECK(string.toAnsiString() == "\0"s); CHECK(string.toAnsiString() == "\0"s);
CHECK(string.toWideString() == select(L""s, L"\U0010AFAF"s)); CHECK(string.toWideString() == select(L""s, L"\U0010AFAF"s));
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xF4, 0x8A, 0xBE, 0xAF}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xF4, 0x8A, 0xBE, 0xAF});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{0xDBEB, 0xDFAF}); CHECK(string.toUtf16() == u"\U0010AFAF"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{0x10AFAF}); CHECK(string.toUtf32() == U"\U0010AFAF"s);
CHECK(string.getSize() == 1); CHECK(string.getSize() == 1);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -188,14 +198,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("UTF-32 C string constructor") SUBCASE("UTF-32 C string constructor")
{ {
const sf::String string(reinterpret_cast<const std::uint32_t*>(U"\U0010ABCDrs")); const sf::String string = U"\U0010ABCDrs";
CHECK(std::string(string) == "\0rs"s); CHECK(std::string(string) == "\0rs"s);
CHECK(std::wstring(string) == select(L"rs"s, L"\U0010ABCDrs"s)); CHECK(std::wstring(string) == select(L"rs"s, L"\U0010ABCDrs"s));
CHECK(string.toAnsiString() == "\0rs"s); CHECK(string.toAnsiString() == "\0rs"s);
CHECK(string.toWideString() == select(L"rs"s, L"\U0010ABCDrs"s)); CHECK(string.toWideString() == select(L"rs"s, L"\U0010ABCDrs"s));
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xF4, 0x8A, 0xAF, 0x8D, 'r', 's'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xF4, 0x8A, 0xAF, 0x8D, 'r', 's'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{0xDBEA, 0xDFCD, 'r', 's'}); CHECK(string.toUtf16() == u"\U0010ABCDrs"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{0x10ABCD, 'r', 's'}); CHECK(string.toUtf32() == U"\U0010ABCDrs"s);
CHECK(string.getSize() == 3); CHECK(string.getSize() == 3);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -203,14 +213,14 @@ TEST_CASE("[System] sf::String")
SUBCASE("UTF-32 string constructor") SUBCASE("UTF-32 string constructor")
{ {
const sf::String string(std::basic_string<std::uint32_t>{'t', 'u', 'v', 0x104321}); const sf::String string = U"tuv\U00104321"s;
CHECK(std::string(string) == "tuv\0"s); CHECK(std::string(string) == "tuv\0"s);
CHECK(std::wstring(string) == select(L"tuv"s, L"tuv\U00104321"s)); CHECK(std::wstring(string) == select(L"tuv"s, L"tuv\U00104321"s));
CHECK(string.toAnsiString() == "tuv\0"s); CHECK(string.toAnsiString() == "tuv\0"s);
CHECK(string.toWideString() == select(L"tuv"s, L"tuv\U00104321"s)); CHECK(string.toWideString() == select(L"tuv"s, L"tuv\U00104321"s));
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'t', 'u', 'v', 0xF4, 0x84, 0x8C, 0xA1}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'t', 'u', 'v', 0xF4, 0x84, 0x8C, 0xA1});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'t', 'u', 'v', 0xDBD0, 0xDF21}); CHECK(string.toUtf16() == u"tuv\U00104321"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'t', 'u', 'v', 0x104321}); CHECK(string.toUtf32() == U"tuv\U00104321"s);
CHECK(string.getSize() == 4); CHECK(string.getSize() == 4);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -226,8 +236,8 @@ TEST_CASE("[System] sf::String")
CHECK(string.toAnsiString() == "wxyz"s); CHECK(string.toAnsiString() == "wxyz"s);
CHECK(string.toWideString() == L"wxyz"s); CHECK(string.toWideString() == L"wxyz"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'w', 'x', 'y', 'z'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'w', 'x', 'y', 'z'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'w', 'x', 'y', 'z'}); CHECK(string.toUtf16() == u"wxyz"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'w', 'x', 'y', 'z'}); CHECK(string.toUtf32() == U"wxyz"s);
CHECK(string.getSize() == 4); CHECK(string.getSize() == 4);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -242,8 +252,8 @@ TEST_CASE("[System] sf::String")
CHECK(string.toAnsiString() == select("\xF1xyz"s, "\0xyz"s)); CHECK(string.toAnsiString() == select("\xF1xyz"s, "\0xyz"s));
CHECK(string.toWideString() == L"\xF1xyz"s); CHECK(string.toWideString() == L"\xF1xyz"s);
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xC3, 0xB1, 'x', 'y', 'z'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{0xC3, 0xB1, 'x', 'y', 'z'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{0xF1, 'x', 'y', 'z'}); CHECK(string.toUtf16() == u"\xF1xyz"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{0xF1, 'x', 'y', 'z'}); CHECK(string.toUtf32() == U"\xF1xyz"s);
CHECK(string.getSize() == 4); CHECK(string.getSize() == 4);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);
@ -258,8 +268,8 @@ TEST_CASE("[System] sf::String")
CHECK(string.toAnsiString() == "w\0yz"s); CHECK(string.toAnsiString() == "w\0yz"s);
CHECK(string.toWideString() == select(L"wyz"s, L"w\U00104321yz"s)); CHECK(string.toWideString() == select(L"wyz"s, L"w\U00104321yz"s));
CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'w', 0xF4, 0x84, 0x8C, 0xA1, 'y', 'z'}); CHECK(string.toUtf8() == std::basic_string<std::uint8_t>{'w', 0xF4, 0x84, 0x8C, 0xA1, 'y', 'z'});
CHECK(string.toUtf16() == std::basic_string<std::uint16_t>{'w', 0xDBD0, 0xDF21, 'y', 'z'}); CHECK(string.toUtf16() == u"w\U00104321yz"s);
CHECK(string.toUtf32() == std::basic_string<std::uint32_t>{'w', 0x104321, 'y', 'z'}); CHECK(string.toUtf32() == U"w\U00104321yz"s);
CHECK(string.getSize() == 4); CHECK(string.getSize() == 4);
CHECK(!string.isEmpty()); CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr); CHECK(string.getData() != nullptr);