#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); } char32_t lower(char32_t in); char32_t upper(char32_t in); template> TTo& convert(TTo& out, const std::basic_string_view& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) { 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 = decode(c, &in[decIdx], in.size() - decIdx, strict))); decIdx += decLen) { if (pfnCharMap) c = pfnCharMap(c); const auto encIdx = out.size(); const auto encLen = encode(nullptr, c, strict); out.resize(encIdx + encLen); encode(&out[encIdx], c, strict); } return out; } template, class TFromAlloc = std::allocator> TTo& convert(TTo& out, const std::basic_string& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) { return convert(out, std::basic_string_view(in), pfnCharMap, strict); } template>> TTo& convert(TTo& out, const TFromElem* in, size_t length = (std::numeric_limits::max)(), char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) { if (length == (std::numeric_limits::max)()) length = std::char_traits::length(in); return convert(out, std::basic_string_view(in, length), pfnCharMap, strict); } template> TTo convert(const std::basic_string_view& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) { TTo out{}; return convert(out, in, pfnCharMap, strict); } template, class TFromAlloc = std::allocator> TTo convert(const std::basic_string& in, char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) { TTo out{}; return convert(out, std::basic_string_view(in), pfnCharMap, strict); } template>> TTo convert(const TFromElem* in, size_t length = (std::numeric_limits::max)(), char32_t(*pfnCharMap)(char32_t) = nullptr, bool strict = false) { if (length == (std::numeric_limits::max)()) length = std::char_traits::length(in); TTo out{}; return convert(out, std::basic_string_view(in, length), pfnCharMap, strict); } inline const std::u8string& convert(const std::u8string& in) { return in; } inline const std::u16string& convert(const std::u16string& in) { return in; } inline const std::u32string& convert(const std::u32string& in) { return in; } inline const std::string& convert(const std::string& in) { return in; } inline const std::wstring& convert(const std::wstring& in) { return in; } }