| 276 | |
| 277 | template <typename From, typename To, typename FromTrait = ConvertTrait<From>, typename ToTrait = ConvertTrait<To>> |
| 278 | bool utfConvert(const std::basic_string_view<From>& from, |
| 279 | std::basic_string<To>& to, |
| 280 | ConversionResult (*cvtfunc)(const typename FromTrait::ArgType**, |
| 281 | const typename FromTrait::ArgType*, |
| 282 | typename ToTrait::ArgType**, |
| 283 | typename ToTrait::ArgType*, |
| 284 | ConversionFlags)) |
| 285 | { |
| 286 | static_assert(sizeof(From) == sizeof(typename FromTrait::ArgType), "Error size mismatched"); |
| 287 | static_assert(sizeof(To) == sizeof(typename ToTrait::ArgType), "Error size mismatched"); |
| 288 | |
| 289 | if (from.empty()) |
| 290 | { |
| 291 | to.clear(); |
| 292 | return true; |
| 293 | } |
| 294 | |
| 295 | // See: http://unicode.org/faq/utf_bom.html#gen6 |
| 296 | static const int most_bytes_per_character = 4; |
| 297 | |
| 298 | const size_t maxNumberOfChars = from.length(); // all UTFs at most one element represents one character. |
| 299 | const size_t numberOfOut = maxNumberOfChars * most_bytes_per_character / sizeof(To); |
| 300 | |
| 301 | std::basic_string<To> working(numberOfOut, 0); |
| 302 | |
| 303 | auto inbeg = reinterpret_cast<const typename FromTrait::ArgType*>(&from[0]); |
| 304 | auto inend = inbeg + from.length(); |
| 305 | |
| 306 | auto outbeg = reinterpret_cast<typename ToTrait::ArgType*>(&working[0]); |
| 307 | auto outend = outbeg + working.length(); |
| 308 | auto r = cvtfunc(&inbeg, inend, &outbeg, outend, strictConversion); |
| 309 | if (r != conversionOK) |
| 310 | return false; |
| 311 | |
| 312 | working.resize(reinterpret_cast<To*>(outbeg) - &working[0]); |
| 313 | to = std::move(working); |
| 314 | |
| 315 | return true; |
| 316 | }; |
| 317 | |
| 318 | bool UTF8ToUTF16(std::string_view utf8, std::u16string& outUtf16) |
| 319 | { |
no test coverage detected