| 124 | |
| 125 | template<typename T> |
| 126 | static std::u32string convertUtf16ToUtf32(const T& utf16_str) { |
| 127 | std::u32string result; |
| 128 | result.reserve(utf16_str.size()); |
| 129 | |
| 130 | for (size_t i = 0; i < utf16_str.size(); ++i) { |
| 131 | char16_t ch = utf16_str[i]; |
| 132 | |
| 133 | if (ch >= 0xD800 && ch <= 0xDBFF) { // 4 byte character |
| 134 | if (i + 1 >= utf16_str.size()) // Error - unfinished character |
| 135 | return result; |
| 136 | |
| 137 | char16_t low_surrogate = utf16_str[++i]; |
| 138 | |
| 139 | if (low_surrogate < 0xDC00 || low_surrogate > 0xDFFF) // Error - bad low surrogate |
| 140 | return result; |
| 141 | |
| 142 | char32_t character = 0x10000 + ((ch - 0xD800) << 10) + (low_surrogate - 0xDC00); |
| 143 | result.push_back(character); |
| 144 | } |
| 145 | else if (ch >= 0xDC00 && ch <= 0xDFFF) // Error - missing high surrogate |
| 146 | return result; |
| 147 | else // 2 byte character |
| 148 | result.push_back(static_cast<char32_t>(ch)); |
| 149 | } |
| 150 | |
| 151 | return result; |
| 152 | } |
| 153 | |
| 154 | static std::u32string convertToUtf32(const std::string& utf8_str) { |
| 155 | return convertUtf8ToUtf32<std::u32string>(utf8_str); |