#pragma once #include #include #include #include namespace unicode { constexpr char32_t UReplacement = U'\uFFFD'; constexpr char32_t UInvalid = U'\uFFFF'; template struct EncodingTag {}; size_t decode(EncodingTag, char32_t& out, const char8_t* in, size_t nRemainingBytes, bool strict); size_t decode(EncodingTag, char32_t& out, const char16_t* in, size_t nRemainingBytes, bool strict); size_t decode(EncodingTag, char32_t& out, const char32_t* in, size_t nRemainingBytes, bool strict); size_t decode(EncodingTag, char32_t& out, const char* in, size_t nRemainingBytes, bool strict); size_t decode(EncodingTag, char32_t& out, const wchar_t* in, size_t nRemainingBytes, bool strict); template inline size_t decode(char32_t& out, const T* in, size_t nRemainingBytes, bool strict = true) { return decode(EncodingTag(), out, in, nRemainingBytes, strict); } size_t encode(EncodingTag, char8_t* ptr, char32_t c, bool strict); size_t encode(EncodingTag, char16_t* ptr, char32_t c, bool strict); size_t encode(EncodingTag, char32_t* ptr, char32_t c, bool strict); size_t encode(EncodingTag, char* ptr, char32_t c, bool strict); size_t encode(EncodingTag, wchar_t* ptr, char32_t c, bool strict); template inline size_t encode(T* ptr, char32_t c, bool strict = true) { return encode(EncodingTag(), ptr, c, strict); } template> inline TTo& convert(TTo& out, const std::basic_string_view& in, bool strict = true) { out.reserve(out.size() + in.size() * 4 / sizeof(in[0]) / sizeof(out[0])); char32_t c{}; for (size_t decLen = 0, decIdx = 0; decIdx < in.size() && (decLen = unicode::decode(c, &in[decIdx], in.size() - decIdx, strict)); decIdx += decLen) { const auto encIdx = out.size(); const auto encLen = unicode::encode(nullptr, c, strict); out.resize(encIdx + encLen); unicode::encode(&out[encIdx], c, strict); } return out; } template, class TFromAlloc = std::allocator> inline TTo& convert(TTo& out, const std::basic_string& in, bool strict = true) { return convert(out, std::basic_string_view(in), strict); } template>> inline TTo& convert(TTo& out, const TFromElem* in, size_t length = (std::numeric_limits::max)(), bool strict = true) { if (length == (std::numeric_limits::max)()) length = std::char_traits::length(in); return convert(out, std::basic_string_view(in, length), strict); } template> inline TTo convert(const std::basic_string_view& in, bool strict = true) { TTo out{}; return convert(out, in, strict); } template, class TFromAlloc = std::allocator> inline TTo convert(const std::basic_string& in, bool strict = true) { TTo out{}; return convert(out, std::basic_string_view(in), strict); } template>> inline TTo convert(const TFromElem* in, size_t length = (std::numeric_limits::max)(), bool strict = true) { if (length == (std::numeric_limits::max)()) length = std::char_traits::length(in); TTo out{}; return convert(out, std::basic_string_view(in, length), strict); } }