如何使用std::codecvt_utf8_utf16
从uft8转换为utf16并使用任何字符串类(例如std::string
或std::wstring
返回而不使用但仅使用普通数组和文字字符串?如何知道存储转换所需的缓冲区大小?
例如,要满足此界面:
std::unique_ptr<char16_t[]> ToUTF16(const char* utf8String);
std::unique_ptr<char[]> ToUTF8(const char16_t* utf16String);
答案 0 :(得分:4)
您可以使用codecvt_utf8_utf16
members directly执行此操作。您的第一步是使用strlen
找到输入的长度(假设它已终止NUL)。 codecvt
成员在范围之外工作,因此您需要知道您的输入有多大。
然而,出现了一个问题:输出缓冲区的长度。虽然codecvt
确实有length
成员,但它只会使用in
来计算转化的长度。也就是说,从UTF-8到UTF-16的转换。没有长度方法可以进行其他转换。
因此,处理此问题的唯一方法是将一些数据转换为已知大小的缓冲区。如果转换未完全完成,则转换更多数据。完成所有操作后,将所有部分放入缓冲区,因为您知道将有多少字符存在。
虽然你的问题说你不想使用字符串,但我会使用vector<T>
,因为如果我没有,我只是重写{{1} } 的。并且没有理由这样做。
vector
其他代码的工作方式相同,只是std::unique_ptr<char16_t[]> ToUTF16(const char* utf8String)
{
auto end_ptr = utf8String + std::char_traits<char>::length(utf8String);
std::codecvt_utf8_utf16<char16_t> converter;
std::codecvt_utf8_utf16<char16_t>::state_type state;
std::array<char16_t, buffer_size> buffer;
std::vector<char16_t> storage;
auto curr_in_ptr = utf8String;
auto out_loc = buffer.begin();
do
{
std::codecvt_base::result rslt = converter.in(state,
curr_in_ptr, end_ptr, curr_in_ptr,
buffer.begin(), buffer.end(), out_loc);
storage.insert(storage.end(), buffer.begin(), out_loc);
}
while(curr_in_ptr != end_ptr);
//+1 for NUL terminator.
std::unique_ptr<char16_t[]> ret(new char16_t[storage.size() + 1]);
std::copy(storage.begin(), storage.end(), ret.get());
ret.get()[storage.size()] = char16_t();
return ret;
}
变为in
,out
和char16_t
被交换。