add u32 string specialization

This commit is contained in:
Fabrice de Gans 2025-02-08 15:09:07 -08:00
parent 220aa758e6
commit f6be6ac126
3 changed files with 123 additions and 8 deletions

View File

@ -4,5 +4,7 @@ emulator. The original SFML library can be found at http://www.sfml-dev.org/
This uses SFML 2.6.2 as a basis, with the following modifications: This uses SFML 2.6.2 as a basis, with the following modifications:
* Upstream commit [9022d956](https://github.com/SFML/SFML/commit/9022d956) was * Upstream commit [9022d956](https://github.com/SFML/SFML/commit/9022d956) was
partially backported to fix a compilation failure with modern Clang. partially backported to fix a compilation failure with modern Clang.
* Added `U32StringCharTraits` in `include\SFML\System\String.hpp` to work around
a compilation failure on macOS.
* `<timeapi.h>` was added as an include in `src\SFML\System\Win32\SleepImpl.cpp` * `<timeapi.h>` was added as an include in `src\SFML\System\Win32\SleepImpl.cpp`
to fix a compilation failure with MSVC. to fix a compilation failure with MSVC.

View File

@ -76,6 +76,44 @@ struct SFML_SYSTEM_API U8StringCharTraits
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
using U8String = std::basic_string<std::uint8_t, U8StringCharTraits>; using U8String = std::basic_string<std::uint8_t, U8StringCharTraits>;
////////////////////////////////////////////////////////////
/// \brief Character traits for std::uint32_t
///
////////////////////////////////////////////////////////////
struct SFML_SYSTEM_API U32StringCharTraits
{
// NOLINTBEGIN(readability-identifier-naming)
using char_type = std::uint32_t;
using int_type = std::char_traits<char>::int_type;
using off_type = std::char_traits<char>::off_type;
using pos_type = std::char_traits<char>::pos_type;
using state_type = std::char_traits<char>::state_type;
static void assign(char_type& c1, char_type c2) noexcept;
static char_type* assign(char_type* s, std::size_t n, char_type c);
static bool eq(char_type c1, char_type c2) noexcept;
static bool lt(char_type c1, char_type c2) noexcept;
static char_type* move(char_type* s1, const char_type* s2, std::size_t n);
static char_type* copy(char_type* s1, const char_type* s2, std::size_t n);
static int compare(const char_type* s1, const char_type* s2, std::size_t n);
static std::size_t length(const char_type* s);
static const char_type* find(const char_type* s, std::size_t n, const char_type& c);
static char_type to_char_type(int_type i) noexcept;
static int_type to_int_type(char_type c) noexcept;
static bool eq_int_type(int_type i1, int_type i2) noexcept;
static int_type eof() noexcept;
static int_type not_eof(int_type i) noexcept;
// NOLINTEND(readability-identifier-naming)
};
////////////////////////////////////////////////////////////
/// \brief Portable replacement for std::basic_string<std::uint32_t>
///
/// While all major C++ implementations happen to define this
/// as of early 2024, this specialization is not strictly speaking
/// standard C++. Thus we can't depend on its continued existence.
///
////////////////////////////////////////////////////////////
using U32String = std::basic_string<std::uint32_t, U32StringCharTraits>;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Utility string class that automatically handles /// \brief Utility string class that automatically handles
/// conversions between types and encodings /// conversions between types and encodings
@ -88,8 +126,8 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Types // Types
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
typedef std::basic_string<Uint32>::iterator Iterator; //!< Iterator type typedef sf::U32String::iterator Iterator; //!< Iterator type
typedef std::basic_string<Uint32>::const_iterator ConstIterator; //!< Read-only iterator type typedef sf::U32String::const_iterator ConstIterator; //!< Read-only iterator type
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Static member data // Static member data
@ -186,7 +224,7 @@ public:
/// \param utf32String UTF-32 string to assign /// \param utf32String UTF-32 string to assign
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String(const std::basic_string<Uint32>& utf32String); String(const sf::U32String& utf32String);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Copy constructor /// \brief Copy constructor
@ -335,7 +373,7 @@ public:
/// \see toUtf8, toUtf16 /// \see toUtf8, toUtf16
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<Uint32> toUtf32() const; sf::U32String toUtf32() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator /// \brief Overload of assignment operator
@ -563,7 +601,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<Uint32> m_string; //!< Internal string of UTF-32 characters sf::U32String m_string; //!< Internal string of UTF-32 characters
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -108,9 +108,84 @@ U8StringCharTraits::int_type U8StringCharTraits::not_eof(int_type i) noexcept
return std::char_traits<char>::not_eof(i); return std::char_traits<char>::not_eof(i);
} }
////////////////////////////////////////////////////////////
void U32StringCharTraits::assign(char_type& c1, char_type c2) noexcept
{
c1 = c2;
}
////////////////////////////////////////////////////////////
U32StringCharTraits::char_type* U32StringCharTraits::assign(char_type* s, std::size_t n, char_type c)
{
return reinterpret_cast<U32StringCharTraits::char_type*>(
std::char_traits<char>::assign(reinterpret_cast<char*>(s), n, static_cast<char>(c)));
}
////////////////////////////////////////////////////////////
bool U32StringCharTraits::eq(char_type c1, char_type c2) noexcept
{
return c1 == c2;
}
////////////////////////////////////////////////////////////
bool U32StringCharTraits::lt(char_type c1, char_type c2) noexcept
{
return c1 < c2;
}
////////////////////////////////////////////////////////////
U32StringCharTraits::char_type* U32StringCharTraits::move(char_type* s1, const char_type* s2, std::size_t n)
{
std::memmove(s1, s2, n);
return s1;
}
////////////////////////////////////////////////////////////
U32StringCharTraits::char_type* U32StringCharTraits::copy(char_type* s1, const char_type* s2, std::size_t n)
{
std::memcpy(s1, s2, n);
return s1;
}
////////////////////////////////////////////////////////////
int U32StringCharTraits::compare(const char_type* s1, const char_type* s2, std::size_t n)
{
return std::memcmp(s1, s2, n);
}
////////////////////////////////////////////////////////////
std::size_t U32StringCharTraits::length(const char_type* s)
{
return std::strlen(reinterpret_cast<const char*>(s));
}
////////////////////////////////////////////////////////////
const U32StringCharTraits::char_type* U32StringCharTraits::find(const char_type* s, std::size_t n, const char_type& c)
{
return reinterpret_cast<const U32StringCharTraits::char_type*>(
std::char_traits<char>::find(reinterpret_cast<const char*>(s), n, static_cast<char>(c)));
}
////////////////////////////////////////////////////////////
U32StringCharTraits::char_type U32StringCharTraits::to_char_type(int_type i) noexcept
{
return static_cast<U32StringCharTraits::char_type>(std::char_traits<char>::to_char_type(i));
}
////////////////////////////////////////////////////////////
U32StringCharTraits::int_type U32StringCharTraits::to_int_type(char_type c) noexcept
{
return std::char_traits<char>::to_int_type(static_cast<char>(c));
}
////////////////////////////////////////////////////////////
bool U32StringCharTraits::eq_int_type(int_type i1, int_type i2) noexcept
{
return i1 == i2;
}
////////////////////////////////////////////////////////////
U32StringCharTraits::int_type U32StringCharTraits::eof() noexcept
{
return std::char_traits<char>::eof();
}
////////////////////////////////////////////////////////////
U32StringCharTraits::int_type U32StringCharTraits::not_eof(int_type i) noexcept
{
return std::char_traits<char>::not_eof(i);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos; const std::size_t String::InvalidPos = sf::U32String::npos;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -195,7 +270,7 @@ String::String(const Uint32* utf32String)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String::String(const std::basic_string<Uint32>& utf32String) : String::String(const sf::U32String& utf32String) :
m_string(utf32String) m_string(utf32String)
{ {
} }
@ -279,7 +354,7 @@ std::basic_string<Uint16> String::toUtf16() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::basic_string<Uint32> String::toUtf32() const sf::U32String String::toUtf32() const
{ {
return m_string; return m_string;
} }