如何在没有任何字符串 class 的情况下使用 std::codecvt_utf8_utf16 与 utf8 相互转换?
How can I use std::codecvt_utf8_utf16 to convert to and from utf8 without any string class?
如何使用 std::codecvt_utf8_utf16
从 uft8 转换为 utf16 并返回 而无需 使用任何字符串 class 例如 std::string
或 std::wstring
但只有普通数组和文字字符串?我怎么知道我需要存储转换的缓冲区的正确大小?
例如满足这个接口:
std::unique_ptr<char16_t[]> ToUTF16(const char* utf8String);
std::unique_ptr<char[]> ToUTF8(const char16_t* utf16String);
您可以使用 codecvt_utf8_utf16
members directly 来完成此操作。您的第一步是使用 strlen
查找输入的长度(假设它以 NUL 终止)。 codecvt
成员工作超出范围,因此您需要知道您的输入有多大。
但是,一个问题出现了:输出缓冲区的长度。虽然 codecvt
确实有一个 length
成员,但它只会计算使用 in
的转换长度。即从 UTF-8 到 UTF-16 的转换。没有进行其他转换的长度方法。
因此,处理此问题的唯一方法是将一些数据转换为已知大小的缓冲区。如果转换没有完全完成,那么再转换一些数据。完成所有这些后,现在您知道将有多少个字符,将所有片段放入缓冲区。
虽然你的问题说你不想使用字符串,但我打算使用 vector<T>
因为如果我不这样做,我会 重写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
和 char
被交换之外,其他代码以相同的方式工作。
如何使用 std::codecvt_utf8_utf16
从 uft8 转换为 utf16 并返回 而无需 使用任何字符串 class 例如 std::string
或 std::wstring
但只有普通数组和文字字符串?我怎么知道我需要存储转换的缓冲区的正确大小?
例如满足这个接口:
std::unique_ptr<char16_t[]> ToUTF16(const char* utf8String);
std::unique_ptr<char[]> ToUTF8(const char16_t* utf16String);
您可以使用 codecvt_utf8_utf16
members directly 来完成此操作。您的第一步是使用 strlen
查找输入的长度(假设它以 NUL 终止)。 codecvt
成员工作超出范围,因此您需要知道您的输入有多大。
但是,一个问题出现了:输出缓冲区的长度。虽然 codecvt
确实有一个 length
成员,但它只会计算使用 in
的转换长度。即从 UTF-8 到 UTF-16 的转换。没有进行其他转换的长度方法。
因此,处理此问题的唯一方法是将一些数据转换为已知大小的缓冲区。如果转换没有完全完成,那么再转换一些数据。完成所有这些后,现在您知道将有多少个字符,将所有片段放入缓冲区。
虽然你的问题说你不想使用字符串,但我打算使用 vector<T>
因为如果我不这样做,我会 重写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
和 char
被交换之外,其他代码以相同的方式工作。