SFML/test/System/String.test.cpp

684 lines
27 KiB
C++
Raw Normal View History

#include <SFML/System/String.hpp>
2023-01-17 21:51:08 -07:00
#include <catch2/catch_test_macros.hpp>
2023-03-22 21:40:17 -06:00
#include <GraphicsUtil.hpp>
#include <array>
#include <iomanip>
#include <sstream>
#include <type_traits>
2023-04-24 14:13:52 +02:00
#include <cassert>
2023-03-22 21:40:17 -06:00
namespace
{
// Return either argument depending on whether wchar_t is 16 or 32 bits
// Lets us write tests that work on both Windows where wchar_t is 16 bits
// and elsewhere where it is 32. Otherwise the tests would only work on
// one OS or the other.
template <typename T>
auto select(const std::basic_string<T>& string16, const std::basic_string<T>& string32)
{
assert(string16 != string32 && "Invalid to select between identical inputs");
2023-03-22 21:40:17 -06:00
if constexpr (sizeof(wchar_t) == 2)
return string16;
else
return string32;
}
auto toHex(const char32_t character)
{
std::ostringstream stream;
stream << "[\\x" << std::uppercase << std::hex << std::uint32_t{character} << ']';
return stream.str();
}
2023-03-22 21:40:17 -06:00
} // namespace
// Specialize StringMaker for alternative std::basic_string<T> specializations
// std::string's string conversion cannot be specialized but all other string types get special treatment
2023-01-17 21:51:08 -07:00
// https://github.com/catchorg/Catch2/blob/devel/docs/tostring.md#catchstringmaker-specialisation
namespace Catch
2023-03-22 21:40:17 -06:00
{
2023-01-17 21:51:08 -07:00
template <>
struct StringMaker<sf::U8String>
2023-03-22 21:40:17 -06:00
{
static std::string convert(const sf::U8String& string)
2023-03-22 21:40:17 -06:00
{
2023-01-17 21:51:08 -07:00
std::ostringstream output;
2023-03-22 21:40:17 -06:00
for (const auto character : string)
{
if (character >= 32 && character < 127)
2023-01-17 21:51:08 -07:00
output << std::string(1, static_cast<char>(character));
2023-03-22 21:40:17 -06:00
else
2023-01-17 21:51:08 -07:00
output << toHex(character);
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
return output.str();
}
};
2023-01-17 21:51:08 -07:00
} // namespace Catch
2023-03-22 21:40:17 -06:00
TEST_CASE("[System] sf::U8StringCharTraits")
{
SECTION("Type traits")
{
STATIC_CHECK(std::is_trivially_copy_constructible_v<sf::U8StringCharTraits>);
STATIC_CHECK(std::is_trivially_copy_assignable_v<sf::U8StringCharTraits>);
2025-01-31 14:43:01 -07:00
STATIC_CHECK(std::is_trivially_move_constructible_v<sf::U8StringCharTraits>);
STATIC_CHECK(std::is_trivially_move_assignable_v<sf::U8StringCharTraits>);
}
SECTION("assign(char_type&, const char_type&)")
{
sf::U8StringCharTraits::char_type c1 = 'a';
const sf::U8StringCharTraits::char_type c2 = 'b';
sf::U8StringCharTraits::assign(c1, c2);
CHECK(c1 == 'b');
CHECK(c2 == 'b');
}
SECTION("assign(char_type*, std::size_t, char_type)")
{
2024-10-16 13:27:49 -06:00
std::array<sf::U8StringCharTraits::char_type, 4> s = {'a', 'b', 'c', '\0'};
CHECK(sf::U8StringCharTraits::assign(s.data(), 2, 'd') == s.data());
CHECK(s[0] == 'd');
CHECK(s[1] == 'd');
CHECK(s[2] == 'c');
}
SECTION("eq()")
{
CHECK(sf::U8StringCharTraits::eq(0, 0));
CHECK(!sf::U8StringCharTraits::eq(1, 0));
CHECK(!sf::U8StringCharTraits::eq(0, 1));
CHECK(sf::U8StringCharTraits::eq(1, 1));
}
SECTION("lt()")
{
CHECK(!sf::U8StringCharTraits::lt(0, 0));
CHECK(!sf::U8StringCharTraits::lt(1, 0));
CHECK(sf::U8StringCharTraits::lt(0, 1));
CHECK(!sf::U8StringCharTraits::lt(1, 1));
}
SECTION("move()")
{
2024-10-16 13:27:49 -06:00
std::array<sf::U8StringCharTraits::char_type, 4> s1 = {'a', 'b', 'c', '\0'};
const std::array<sf::U8StringCharTraits::char_type, 4> s2 = {'d', 'e', 'f', '\0'};
CHECK(sf::U8StringCharTraits::move(s1.data(), s2.data(), s2.size()) == s1.data());
CHECK(s1[0] == 'd');
CHECK(s1[1] == 'e');
CHECK(s1[2] == 'f');
CHECK(s2[0] == 'd');
CHECK(s2[1] == 'e');
CHECK(s2[2] == 'f');
}
SECTION("copy()")
{
2024-10-16 13:27:49 -06:00
std::array<sf::U8StringCharTraits::char_type, 4> s1 = {'a', 'b', 'c', '\0'};
const std::array<sf::U8StringCharTraits::char_type, 4> s2 = {'d', 'e', 'f', '\0'};
CHECK(sf::U8StringCharTraits::copy(s1.data(), s2.data(), s2.size()) == s1.data());
CHECK(s1[0] == 'd');
CHECK(s1[1] == 'e');
CHECK(s1[2] == 'f');
CHECK(s2[0] == 'd');
CHECK(s2[1] == 'e');
CHECK(s2[2] == 'f');
}
SECTION("compare()")
{
2024-10-16 13:27:49 -06:00
const std::array<sf::U8StringCharTraits::char_type, 4> s1 = {'a', 'b', 'c', '\0'};
const std::array<sf::U8StringCharTraits::char_type, 4> s2 = {'a', 'b', 'c', '\0'};
const std::array<sf::U8StringCharTraits::char_type, 4> s3 = {'d', 'e', 'f', '\0'};
CHECK(sf::U8StringCharTraits::compare(s1.data(), s2.data(), s1.size()) == 0);
CHECK(sf::U8StringCharTraits::compare(s1.data(), s3.data(), s1.size()) < 0);
CHECK(sf::U8StringCharTraits::compare(s3.data(), s1.data(), s3.size()) > 0);
}
SECTION("length()")
{
2024-10-16 13:27:49 -06:00
const std::array<sf::U8StringCharTraits::char_type, 2> s1 = {'a', '\0'};
const std::array<sf::U8StringCharTraits::char_type, 6> s2 = {'a', 'b', 'c', 'd', 'e', '\0'};
CHECK(sf::U8StringCharTraits::length(s1.data()) == 1);
CHECK(sf::U8StringCharTraits::length(s2.data()) == 5);
}
SECTION("find()")
{
2024-10-16 13:27:49 -06:00
const std::array<sf::U8StringCharTraits::char_type, 5> s = {'a', 'b', 'c', 'd', 'e'};
CHECK(*sf::U8StringCharTraits::find(s.data(), s.size(), 'a') == 'a');
CHECK(sf::U8StringCharTraits::find(s.data(), s.size(), 'f') == nullptr);
}
SECTION("to_char_type()")
{
CHECK(sf::U8StringCharTraits::to_char_type(sf::U8StringCharTraits::int_type{0}) ==
sf::U8StringCharTraits::char_type{0});
CHECK(sf::U8StringCharTraits::to_char_type(sf::U8StringCharTraits::int_type{1}) ==
sf::U8StringCharTraits::char_type{1});
CHECK(sf::U8StringCharTraits::to_char_type(sf::U8StringCharTraits::int_type{10}) ==
sf::U8StringCharTraits::char_type{10});
}
SECTION("to_int_type()")
{
CHECK(sf::U8StringCharTraits::to_int_type(sf::U8StringCharTraits::char_type{0}) ==
sf::U8StringCharTraits::int_type{0});
CHECK(sf::U8StringCharTraits::to_int_type(sf::U8StringCharTraits::char_type{1}) ==
sf::U8StringCharTraits::int_type{1});
CHECK(sf::U8StringCharTraits::to_int_type(sf::U8StringCharTraits::char_type{10}) ==
sf::U8StringCharTraits::int_type{10});
}
SECTION("eq_int_type()")
{
CHECK(sf::U8StringCharTraits::eq_int_type(sf::U8StringCharTraits::int_type{0}, sf::U8StringCharTraits::int_type{0}));
CHECK(sf::U8StringCharTraits::eq_int_type(sf::U8StringCharTraits::int_type{1}, sf::U8StringCharTraits::int_type{1}));
CHECK(sf::U8StringCharTraits::eq_int_type(sf::U8StringCharTraits::int_type{10},
sf::U8StringCharTraits::int_type{10}));
}
SECTION("eof()")
{
CHECK(sf::U8StringCharTraits::eof() == ~sf::U8StringCharTraits::int_type{0});
}
SECTION("not_eof()")
{
CHECK(sf::U8StringCharTraits::not_eof(sf::U8StringCharTraits::int_type{0}) == sf::U8StringCharTraits::int_type{0});
CHECK(sf::U8StringCharTraits::not_eof(sf::U8StringCharTraits::int_type{1}) == sf::U8StringCharTraits::int_type{1});
CHECK(sf::U8StringCharTraits::not_eof(sf::U8StringCharTraits::int_type{10}) == sf::U8StringCharTraits::int_type{10});
CHECK(sf::U8StringCharTraits::not_eof(sf::U8StringCharTraits::eof()) != sf::U8StringCharTraits::eof());
}
}
2023-03-22 21:40:17 -06:00
TEST_CASE("[System] sf::String")
{
using namespace std::string_literals;
2025-02-03 11:45:40 -07:00
using namespace std::string_view_literals;
2023-03-22 21:40:17 -06:00
2023-01-17 21:51:08 -07:00
SECTION("Type traits")
{
STATIC_CHECK(!std::is_constructible_v<sf::String, std::nullptr_t>);
STATIC_CHECK(!std::is_constructible_v<sf::String, std::nullptr_t, const std::locale&>);
2023-01-17 21:51:08 -07:00
STATIC_CHECK(std::is_copy_constructible_v<sf::String>);
STATIC_CHECK(std::is_copy_assignable_v<sf::String>);
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::String>);
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::String>);
}
SECTION("Construction")
2023-03-22 21:40:17 -06:00
{
2023-01-17 21:51:08 -07:00
SECTION("Default constructor")
2023-03-22 21:40:17 -06:00
{
const sf::String string;
CHECK(std::string(string).empty());
CHECK(std::wstring(string).empty());
CHECK(string.toAnsiString().empty());
CHECK(string.toWideString().empty());
2023-01-17 21:51:08 -07:00
CHECK(string.toUtf8().empty());
CHECK(string.toUtf16().empty());
CHECK(string.toUtf32().empty());
2023-03-22 21:40:17 -06:00
CHECK(string.getSize() == 0);
CHECK(string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-01-17 21:51:08 -07:00
SECTION("ANSI character constructor")
2023-03-22 21:40:17 -06:00
{
const sf::String string = 'a';
2023-03-22 21:40:17 -06:00
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() == sf::U8String{'a'});
CHECK(string.toUtf16() == u"a"s);
CHECK(string.toUtf32() == U"a"s);
2023-03-22 21:40:17 -06:00
CHECK(string.getSize() == 1);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-01-17 21:51:08 -07:00
SECTION("ANSI C string constructor")
2023-03-22 21:40:17 -06:00
{
{
const sf::String string = static_cast<char*>(nullptr);
CHECK(std::string(string).empty());
CHECK(std::wstring(string).empty());
CHECK(string.toAnsiString().empty());
CHECK(string.toWideString().empty());
CHECK(string.toUtf8().empty());
CHECK(string.toUtf16().empty());
CHECK(string.toUtf32().empty());
CHECK(string.getSize() == 0);
CHECK(string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
2025-02-03 11:45:40 -07:00
const sf::String string = "Escargot";
CHECK(std::string(string) == "Escargot"s);
CHECK(std::wstring(string) == L"Escargot"s);
CHECK(string.toAnsiString() == "Escargot"s);
CHECK(string.toWideString() == L"Escargot"s);
CHECK(string.toUtf8() == sf::U8String{'E', 's', 'c', 'a', 'r', 'g', 'o', 't'});
CHECK(string.toUtf16() == u"Escargot"s);
CHECK(string.toUtf32() == U"Escargot"s);
CHECK(string.getSize() == 8);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
SECTION("ANSI string constructor")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
const sf::String string = "Csiga"s;
CHECK(std::string(string) == "Csiga"s);
CHECK(std::wstring(string) == L"Csiga"s);
CHECK(string.toAnsiString() == "Csiga"s);
CHECK(string.toWideString() == L"Csiga"s);
CHECK(string.toUtf8() == sf::U8String{'C', 's', 'i', 'g', 'a'});
CHECK(string.toUtf16() == u"Csiga"s);
CHECK(string.toUtf32() == U"Csiga"s);
CHECK(string.getSize() == 5);
2023-03-22 21:40:17 -06:00
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-01-17 21:51:08 -07:00
SECTION("Wide character constructor")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
{
const sf::String string = L'ú';
CHECK(std::string(string) == select("\xFA"s, "\0"s));
CHECK(std::wstring(string) == L"ú"s);
CHECK(string.toAnsiString() == select("\xFA"s, "\0"s));
CHECK(string.toWideString() == L"ú"s);
CHECK(string.toUtf8() == sf::U8String{0xC3, 0xBA});
CHECK(string.toUtf16() == u"ú"s);
CHECK(string.toUtf32() == U"ú"s);
CHECK(string.getSize() == 1);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
const sf::String string = L'Ǻ';
CHECK(std::string(string) == "\0"s);
CHECK(std::wstring(string) == L"Ǻ"s);
CHECK(string.toAnsiString() == "\0"s);
CHECK(string.toWideString() == L"Ǻ"s);
CHECK(string.toUtf8() == sf::U8String{0xC7, 0xBA});
CHECK(string.toUtf16() == u"Ǻ"s);
CHECK(string.toUtf32() == U"Ǻ"s);
CHECK(string.getSize() == 1);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
SECTION("Wide C string constructor")
2023-03-22 21:40:17 -06:00
{
{
const sf::String string = static_cast<wchar_t*>(nullptr);
CHECK(std::string(string).empty());
CHECK(std::wstring(string).empty());
CHECK(string.toAnsiString().empty());
CHECK(string.toWideString().empty());
CHECK(string.toUtf8().empty());
CHECK(string.toUtf16().empty());
CHECK(string.toUtf32().empty());
CHECK(string.getSize() == 0);
CHECK(string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
2025-02-03 11:45:40 -07:00
const sf::String string = L"Улитка";
CHECK(std::string(string) == "\0\0\0\0\0\0"s);
CHECK(std::wstring(string) == L"Улитка"s);
CHECK(string.toAnsiString() == "\0\0\0\0\0\0"s);
CHECK(string.toWideString() == L"Улитка"s);
CHECK(string.toUtf8() ==
sf::U8String{0xD0, 0xA3, 0xD0, 0xBB, 0xD0, 0xB8, 0xD1, 0x82, 0xD0, 0xBA, 0xD0, 0xB0});
CHECK(string.toUtf16() == u"Улитка"s);
CHECK(string.toUtf32() == U"Улитка"s);
CHECK(string.getSize() == 6);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
SECTION("Wide string constructor")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
const sf::String string = L"Полжав"s;
CHECK(std::string(string) == "\0\0\0\0\0\0"s);
CHECK(std::wstring(string) == L"Полжав"s);
CHECK(string.toAnsiString() == "\0\0\0\0\0\0"s);
CHECK(string.toWideString() == L"Полжав"s);
CHECK(string.toUtf8() == sf::U8String{0xD0, 0x9F, 0xD0, 0xBE, 0xD0, 0xBB, 0xD0, 0xB6, 0xD0, 0xB0, 0xD0, 0xB2});
CHECK(string.toUtf16() == u"Полжав"s);
CHECK(string.toUtf32() == U"Полжав"s);
CHECK(string.getSize() == 6);
2023-03-22 21:40:17 -06:00
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-01-17 21:51:08 -07:00
SECTION("UTF-32 character constructor")
2023-03-22 21:40:17 -06:00
{
2025-02-02 23:25:18 -07:00
const sf::String string = U'🐌';
2023-03-22 21:40:17 -06:00
CHECK(std::string(string) == "\0"s);
2025-02-02 23:25:18 -07:00
CHECK(std::wstring(string) == select(L""s, L"🐌"s));
2023-03-22 21:40:17 -06:00
CHECK(string.toAnsiString() == "\0"s);
2025-02-02 23:25:18 -07:00
CHECK(string.toWideString() == select(L""s, L"🐌"s));
CHECK(string.toUtf8() == sf::U8String{0xF0, 0x9F, 0x90, 0x8C});
CHECK(string.toUtf16() == u"🐌"s);
CHECK(string.toUtf32() == U"🐌"s);
2023-03-22 21:40:17 -06:00
CHECK(string.getSize() == 1);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-01-17 21:51:08 -07:00
SECTION("UTF-32 C string constructor")
2023-03-22 21:40:17 -06:00
{
{
const sf::String string = static_cast<char32_t*>(nullptr);
CHECK(std::string(string).empty());
CHECK(std::wstring(string).empty());
CHECK(string.toAnsiString().empty());
CHECK(string.toWideString().empty());
CHECK(string.toUtf8().empty());
CHECK(string.toUtf16().empty());
CHECK(string.toUtf32().empty());
CHECK(string.getSize() == 0);
CHECK(string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
2025-02-03 11:45:40 -07:00
const sf::String string = U"カタツムリ";
CHECK(std::string(string) == "\0\0\0\0\0"s);
CHECK(std::wstring(string) == L"カタツムリ"s);
CHECK(string.toAnsiString() == "\0\0\0\0\0"s);
CHECK(string.toWideString() == L"カタツムリ"s);
CHECK(string.toUtf8() ==
sf::U8String{0xE3, 0x82, 0xAB, 0xE3, 0x82, 0xBF, 0xE3, 0x83, 0x84, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0xAA});
CHECK(string.toUtf16() == u"カタツムリ"s);
CHECK(string.toUtf32() == U"カタツムリ"s);
CHECK(string.getSize() == 5);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
const sf::String string = U"🐌🐚";
CHECK(std::string(string) == "\0\0"s);
CHECK(std::wstring(string) == select(L""s, L"🐌🐚"s));
CHECK(string.toAnsiString() == "\0\0"s);
CHECK(string.toWideString() == select(L""s, L"🐌🐚"s));
CHECK(string.toUtf8() == sf::U8String{0xF0, 0x9F, 0x90, 0x8C, 0xF0, 0x9F, 0x90, 0x9A});
CHECK(string.toUtf16() == u"🐌🐚"s);
CHECK(string.toUtf32() == U"🐌🐚"s);
CHECK(string.getSize() == 2);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
SECTION("UTF-32 string constructor")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
const sf::String string = U"گھونگا"s;
CHECK(std::string(string) == "\0\0\0\0\0\0"s);
CHECK(std::wstring(string) == L"گھونگا"s);
CHECK(string.toAnsiString() == "\0\0\0\0\0\0"s);
CHECK(string.toWideString() == L"گھونگا"s);
CHECK(string.toUtf8() == sf::U8String{0xDA, 0xAF, 0xDA, 0xBE, 0xD9, 0x88, 0xD9, 0x86, 0xDA, 0xAF, 0xD8, 0xA7});
CHECK(string.toUtf16() == u"گھونگا"s);
CHECK(string.toUtf32() == U"گھونگا"s);
CHECK(string.getSize() == 6);
2023-03-22 21:40:17 -06:00
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
}
2023-01-17 21:51:08 -07:00
SECTION("fromUtf8()")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
{
constexpr std::array<std::uint8_t, 1> characters{251};
const sf::String string = sf::String::fromUtf8(characters.begin(), characters.end());
CHECK(string.getSize() == 1);
CHECK(string[0] == 0);
}
{
constexpr std::array<std::uint8_t, 4> characters{'w', 'x', 'y', 'z'};
const sf::String string = sf::String::fromUtf8(characters.begin(), characters.end());
CHECK(std::string(string) == "wxyz"s);
CHECK(std::wstring(string) == L"wxyz"s);
CHECK(string.toAnsiString() == "wxyz"s);
CHECK(string.toWideString() == L"wxyz"s);
CHECK(string.toUtf8() == sf::U8String{'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);
}
{
2025-02-03 11:45:40 -07:00
constexpr std::array<std::uint8_t, 4> characters{0xF0, 0x9F, 0x90, 0x8C};
const sf::String string = sf::String::fromUtf8(characters.begin(), characters.end());
2025-02-03 11:45:40 -07:00
CHECK(std::string(string) == "\0"s);
CHECK(std::wstring(string) == select(L""s, L"🐌"s));
CHECK(string.toAnsiString() == "\0"s);
CHECK(string.toWideString() == select(L""s, L"🐌"s));
CHECK(string.toUtf8() == sf::U8String{0xF0, 0x9F, 0x90, 0x8C});
CHECK(string.toUtf16() == u"🐌"s);
CHECK(string.toUtf32() == U"🐌"s);
CHECK(string.getSize() == 1);
2025-02-03 11:45:40 -07:00
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
SECTION("fromUtf16()")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
{
constexpr std::u16string_view characters = u"SFML!"sv;
const sf::String string = sf::String::fromUtf16(characters.begin(), characters.end());
CHECK(std::string(string) == "SFML!"s);
CHECK(std::wstring(string) == L"SFML!"s);
CHECK(string.toAnsiString() == "SFML!"s);
CHECK(string.toWideString() == L"SFML!"s);
CHECK(string.toUtf8() == sf::U8String{'S', 'F', 'M', 'L', '!'});
CHECK(string.toUtf16() == u"SFML!"s);
CHECK(string.toUtf32() == U"SFML!"s);
CHECK(string.getSize() == 5);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
constexpr std::u16string_view characters = u"piñata"sv;
const sf::String string = sf::String::fromUtf16(characters.begin(), characters.end());
CHECK(std::string(string) == select("pi\xF1"
"ata"s,
"pi\0ata"s));
CHECK(std::wstring(string) == L"piñata"s);
CHECK(string.toAnsiString() == select("pi\xF1"
"ata"s,
"pi\0ata"s));
CHECK(string.toWideString() == L"piñata"s);
CHECK(string.toUtf8() == sf::U8String{'p', 'i', 0xC3, 0xB1, 'a', 't', 'a'});
CHECK(string.toUtf16() == u"piñata"s);
CHECK(string.toUtf32() == U"piñata"s);
CHECK(string.getSize() == 6);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
{
constexpr std::u16string_view characters = u"달팽이"sv;
const sf::String string = sf::String::fromUtf16(characters.begin(), characters.end());
CHECK(std::string(string) == "\0\0\0"s);
CHECK(std::wstring(string) == L"달팽이"s);
CHECK(string.toAnsiString() == "\0\0\0"s);
CHECK(string.toWideString() == L"달팽이"s);
CHECK(string.toUtf8() == sf::U8String{0xEB, 0x8B, 0xAC, 0xED, 0x8C, 0xBD, 0xEC, 0x9D, 0xB4});
CHECK(string.toUtf16() == u"달팽이"s);
CHECK(string.toUtf32() == U"달팽이"s);
CHECK(string.getSize() == 3);
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-03-22 21:40:17 -06:00
}
2023-01-17 21:51:08 -07:00
SECTION("fromUtf32()")
2023-03-22 21:40:17 -06:00
{
2025-02-03 11:45:40 -07:00
constexpr std::u32string_view characters = U"👍+👎=🤷"sv;
const sf::String string = sf::String::fromUtf32(characters.begin(), characters.end());
CHECK(std::string(string) == "\0+\0=\0"s);
CHECK(std::wstring(string) == select(L"+="s, L"👍+👎=🤷"s));
CHECK(string.toAnsiString() == "\0+\0=\0"s);
CHECK(string.toWideString() == select(L"+="s, L"👍+👎=🤷"s));
CHECK(string.toUtf8() ==
sf::U8String{0xF0, 0x9F, 0x91, 0x8D, '+', 0xF0, 0x9F, 0x91, 0x8E, '=', 0xF0, 0x9F, 0xA4, 0xB7});
CHECK(string.toUtf16() == u"👍+👎=🤷"s);
CHECK(string.toUtf32() == U"👍+👎=🤷"s);
CHECK(string.getSize() == 5);
2023-03-22 21:40:17 -06:00
CHECK(!string.isEmpty());
CHECK(string.getData() != nullptr);
}
2023-01-17 21:51:08 -07:00
SECTION("clear()")
2023-03-22 21:40:17 -06:00
{
sf::String string("you'll never guess what happens when you call clear()");
string.clear();
2025-02-03 11:45:40 -07:00
CHECK(string.isEmpty());
2023-03-22 21:40:17 -06:00
CHECK(string.getSize() == 0);
}
2023-01-17 21:51:08 -07:00
SECTION("erase()")
2023-03-22 21:40:17 -06:00
{
sf::String string("what if i want a shorter string?");
string.erase(0, 8);
string.erase(string.getSize() - 1, 1);
CHECK(string == "i want a shorter string");
CHECK(string.getSize() == 23);
}
2023-01-17 21:51:08 -07:00
SECTION("insert()")
2023-03-22 21:40:17 -06:00
{
sf::String string("please insert text");
string.insert(7, "don't ");
CHECK(string == "please don't insert text");
CHECK(string.getSize() == 24);
}
2023-01-17 21:51:08 -07:00
SECTION("find()")
2023-03-22 21:40:17 -06:00
{
const sf::String string("a little bit of this and a little bit of that");
CHECK(string.find("a little bit") == 0);
CHECK(string.find("a little bit", 15) == 25);
CHECK(string.find("a little bit", 1'000) == sf::String::InvalidPos);
CHECK(string.find("no way you find this") == sf::String::InvalidPos);
}
2023-01-17 21:51:08 -07:00
SECTION("replace()")
2023-03-22 21:40:17 -06:00
{
sf::String string("sfml is the worst");
string.replace(12, 5, "best!");
CHECK(string == "sfml is the best!");
string.replace("the", "THE");
CHECK(string == "sfml is THE best!");
}
2023-01-17 21:51:08 -07:00
SECTION("substring()")
2023-03-22 21:40:17 -06:00
{
const sf::String string("let's get some substrings");
CHECK(string.substring(0) == "let's get some substrings");
CHECK(string.substring(10) == "some substrings");
CHECK(string.substring(10, 4) == "some");
CHECK_THROWS_AS((void)string.substring(1'000), std::out_of_range);
CHECK_THROWS_AS((void)string.substring(420, 69), std::out_of_range);
}
2023-01-17 21:51:08 -07:00
SECTION("begin() and end() const")
2023-03-22 21:40:17 -06:00
{
const sf::String string("let's test the const iterators");
CHECK(*string.begin() == 'l');
CHECK(*(string.end() - 1) == 's');
for (const auto character : string)
CHECK(character != 0);
}
2023-01-17 21:51:08 -07:00
SECTION("begin() and end()")
2023-03-22 21:40:17 -06:00
{
sf::String string("let's test the iterators");
CHECK(*string.begin() == 'l');
CHECK(*(string.end() - 1) == 's');
for (auto& character : string)
character = 'x';
CHECK(string == "xxxxxxxxxxxxxxxxxxxxxxxx");
}
2023-01-17 21:51:08 -07:00
SECTION("Operators")
2023-03-22 21:40:17 -06:00
{
2023-01-17 21:51:08 -07:00
SECTION("operator+=")
2023-03-22 21:40:17 -06:00
{
sf::String string;
string += sf::String("xyz");
CHECK(string.toAnsiString() == "xyz"s);
}
2023-01-17 21:51:08 -07:00
SECTION("operator[] const")
2023-03-22 21:40:17 -06:00
{
const sf::String string("the quick brown fox");
CHECK(string[0] == 't');
CHECK(string[10] == 'b');
}
2023-01-17 21:51:08 -07:00
SECTION("operator[]")
2023-03-22 21:40:17 -06:00
{
sf::String string("the quick brown fox");
CHECK(string[0] == 't');
string[1] = 'x';
CHECK(string[1] == 'x');
}
2023-01-17 21:51:08 -07:00
SECTION("operator==")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String() == sf::String());
CHECK_FALSE(sf::String() == sf::String(' '));
}
2023-01-17 21:51:08 -07:00
SECTION("operator!=")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String() != sf::String(' '));
CHECK_FALSE(sf::String() != sf::String());
}
2023-01-17 21:51:08 -07:00
SECTION("operator<")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String('a') < sf::String('b'));
CHECK_FALSE(sf::String() < sf::String());
}
2023-01-17 21:51:08 -07:00
SECTION("operator>")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String('b') > sf::String('a'));
CHECK_FALSE(sf::String() > sf::String());
}
2023-01-17 21:51:08 -07:00
SECTION("operator<=")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String() <= sf::String());
CHECK(sf::String('a') <= sf::String('b'));
}
2023-01-17 21:51:08 -07:00
SECTION("operator>=")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String() >= sf::String());
CHECK(sf::String('b') >= sf::String('a'));
}
2023-01-17 21:51:08 -07:00
SECTION("operator+")
2023-03-22 21:40:17 -06:00
{
CHECK(sf::String() + sf::String() == sf::String());
CHECK(sf::String("abc") + sf::String("def") == sf::String("abcdef"));
}
}
}