| 165 | |
| 166 | template <typename From, typename To, typename FromTrait = ConvertTrait<From>, typename ToTrait = ConvertTrait<To>> |
| 167 | bool utfConvert( |
| 168 | const std::basic_string<From> &from, std::basic_string<To> &to, |
| 169 | ConversionResult (*cvtfunc)(const typename FromTrait::ArgType **, const typename FromTrait::ArgType *, |
| 170 | typename ToTrait::ArgType **, typename ToTrait::ArgType *, |
| 171 | ConversionFlags)) { |
| 172 | static_assert(sizeof(From) == sizeof(typename FromTrait::ArgType), "Error size mismatched"); |
| 173 | static_assert(sizeof(To) == sizeof(typename ToTrait::ArgType), "Error size mismatched"); |
| 174 | |
| 175 | if (from.empty()) { |
| 176 | to.clear(); |
| 177 | return true; |
| 178 | } |
| 179 | |
| 180 | // See: http://unicode.org/faq/utf_bom.html#gen6 |
| 181 | constexpr int mostBytesPerCharacter = 4; |
| 182 | |
| 183 | const size_t maxNumberOfChars = from.length(); // all UTFs at most one element represents one character. |
| 184 | const size_t numberOfOut = maxNumberOfChars * mostBytesPerCharacter / sizeof(To); |
| 185 | |
| 186 | std::basic_string<To> working(numberOfOut, 0); |
| 187 | |
| 188 | auto inbeg = reinterpret_cast<const typename FromTrait::ArgType *>(&from[0]); |
| 189 | auto inend = inbeg + from.length(); |
| 190 | |
| 191 | auto outbeg = reinterpret_cast<typename ToTrait::ArgType *>(&working[0]); |
| 192 | auto outend = outbeg + working.length(); |
| 193 | auto r = cvtfunc(&inbeg, inend, &outbeg, outend, strictConversion); |
| 194 | if (r != conversionOK) { |
| 195 | return false; |
| 196 | } |
| 197 | |
| 198 | working.resize(reinterpret_cast<To *>(outbeg) - &working[0]); |
| 199 | to = std::move(working); |
| 200 | |
| 201 | return true; |
| 202 | }; |
| 203 | |
| 204 | CC_DLL void UTF8LooseFix(const ccstd::string &in, ccstd::string &out) { //NOLINT |
| 205 | const auto *p = reinterpret_cast<const UTF8 *>(in.c_str()); |
no test coverage detected