28#include <TGUI/Config.hpp>
43 template <
typename CharT>
44 void encodeCharUtf8(
char32_t input, std::basic_string<CharT>& outStrUtf8)
48 outStrUtf8.push_back(
static_cast<CharT
>(input));
53 if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
57 std::size_t bytestoWrite;
58 std::uint8_t firstByteMask;
64 else if (input < 0x10000)
76 std::array<CharT, 4> bytes;
77 if (bytestoWrite == 4)
79 bytes[3] =
static_cast<CharT
>((input | 0x80) & 0xBF);
82 if (bytestoWrite >= 3)
84 bytes[2] =
static_cast<CharT
>((input | 0x80) & 0xBF);
87 bytes[1] =
static_cast<CharT
>((input | 0x80) & 0xBF);
89 bytes[0] =
static_cast<CharT
>(input | firstByteMask);
92 outStrUtf8.append(bytes.cbegin(), bytes.cbegin() +
static_cast<std::ptrdiff_t
>(bytestoWrite));
102 template <
typename CharIt>
103 CharIt decodeCharUtf8(CharIt inputCharIt, CharIt inputEndIt, std::u32string& outStrUtf32)
105 if (
static_cast<std::uint8_t
>(*inputCharIt) < 128)
107 outStrUtf32.push_back(
static_cast<char32_t>(
static_cast<std::uint8_t
>(*inputCharIt)));
108 return ++inputCharIt;
112 static const std::array<std::uint32_t, 6> offsetsMap = {0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080};
113 static const std::array<std::uint8_t, 128> trailingMap =
114 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
117 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
120 const std::uint8_t trailingBytes = trailingMap[
static_cast<std::uint8_t
>(*inputCharIt) - 128];
121 const std::uint32_t offset = offsetsMap[trailingBytes];
122 const auto remainingBytes = std::distance(inputCharIt, inputEndIt) - 1;
123 if (remainingBytes >=
static_cast<decltype(remainingBytes)
>(trailingBytes))
125 char32_t outputChar = 0;
126 for (std::uint8_t i = 0; i < trailingBytes; ++i)
128 outputChar +=
static_cast<char32_t>(
static_cast<std::uint8_t
>(*inputCharIt++));
132 outputChar +=
static_cast<char32_t>(
static_cast<std::uint8_t
>(*inputCharIt++));
133 outputChar -= offset;
134 outStrUtf32.push_back(outputChar);
137 inputCharIt = inputEndIt;
142#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201811L)
148 [[nodiscard]]
inline std::u8string convertUtf32toUtf8(
const std::u32string& strUtf32)
150 std::u8string outStrUtf8;
151 outStrUtf8.reserve(strUtf32.length() + 1);
152 for (
const char32_t& codepoint : strUtf32)
153 encodeCharUtf8(codepoint, outStrUtf8);
165 template <
typename CharIt>
166 [[nodiscard]] std::u32string convertUtf8toUtf32(CharIt inputBegin, CharIt inputEnd)
168 std::u32string outStrUtf32;
169 outStrUtf32.reserve(
static_cast<std::size_t
>((inputEnd - inputBegin) + 1));
171 auto it = inputBegin;
172 while (it < inputEnd)
173 it = decodeCharUtf8(it, inputEnd, outStrUtf32);
184 template <
typename U16CharIt>
185 [[nodiscard]] std::u32string convertUtf16toUtf32(U16CharIt inputBegin, U16CharIt inputEnd)
187 std::u32string outStrUtf32;
188 outStrUtf32.reserve(
static_cast<std::size_t
>((inputEnd - inputBegin) + 1));
190 auto it = inputBegin;
191 while (it < inputEnd)
193 const char16_t first = *it++;
196 if ((first < 0xD800) || (first > 0xDBFF))
198 outStrUtf32.push_back(
static_cast<char32_t>(first));
206 const char16_t second = *it++;
207 if ((second >= 0xDC00) && (second <= 0xDFFF))
208 outStrUtf32.push_back(
209 ((
static_cast<char32_t>(first) - 0xD800) << 10) + (
static_cast<char32_t>(second) - 0xDC00) + 0x0010000);
220 template <
typename WCharIt>
221 [[nodiscard]] std::u32string convertWidetoUtf32(WCharIt inputBegin, WCharIt inputEnd)
223 std::u32string outStrUtf32;
224 outStrUtf32.reserve(
static_cast<std::size_t
>((inputEnd - inputBegin) + 1));
227 for (
auto it = inputBegin; it != inputEnd; ++it)
228 outStrUtf32.push_back(
static_cast<char32_t>(*it));
238 [[nodiscard]]
inline std::string convertUtf32toStdStringUtf8(
const std::u32string& strUtf32)
240 std::string outStrUtf8;
241 outStrUtf8.reserve(strUtf32.length() + 1);
242 for (
const char32_t codepoint : strUtf32)
243 encodeCharUtf8(codepoint, outStrUtf8);
253 [[nodiscard]]
inline std::wstring convertUtf32toWide(
const std::u32string& strUtf32)
256 outStr.reserve(strUtf32.length() + 1);
258 if constexpr (
sizeof(wchar_t) == 4)
261 for (
const char32_t codepoint : strUtf32)
262 outStr.push_back(
static_cast<wchar_t>(codepoint));
267 for (
const char32_t codepoint : strUtf32)
269 if ((codepoint < 0xD800) || ((codepoint > 0xDFFF) && (codepoint <= 0xFFFF)))
270 outStr.push_back(
static_cast<wchar_t>(codepoint));
282 [[nodiscard]]
inline std::u16string convertUtf32toUtf16(
const std::u32string& strUtf32)
284 std::u16string outStrUtf16;
285 outStrUtf16.reserve(strUtf32.length() + 1);
287 for (
const char32_t codepoint : strUtf32)
290 if (codepoint <= 0xFFFF)
292 if ((codepoint < 0xD800) || (codepoint > 0xDFFF))
293 outStrUtf16.push_back(
static_cast<char16_t>(codepoint));
297 if (codepoint > 0x0010FFFF)
301 outStrUtf16.push_back(
static_cast<char16_t>(((codepoint - 0x0010000) >> 10) + 0xD800));
302 outStrUtf16.push_back(
static_cast<char16_t>(((codepoint - 0x0010000) & 0x3FFUL) + 0xDC00));