如何在没有任何字符串 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::stringstd::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 变成 outchar16_tchar 被交换之外,其他代码以相同的方式工作。