2017-02-25 449 views
1

如何使用std::codecvt_utf8_utf16将uft8转换为utf16并将其转换为而不使用使用任何字符串类(例如std::stringstd::wstring),但仅使用普通数组和字符串?我如何知道我需要存储转换的缓冲区的大小?如何使用std :: codecvt_utf8_utf16将utf8转换为utf8或不使用任何字符串类?

例如,以满足该接口:

std::unique_ptr<char16_t[]> ToUTF16(const char* utf8String); 
std::unique_ptr<char[]> ToUTF8(const char16_t* utf16String); 
+0

尺寸信息因指针而丢失,所以你不能。 –

+2

为什么你不想使用字符串类?这样做可以毫不费力地使用'std :: wstring_convert'来促进转换,并且可以将文字和数组作为输入传递给它。使用'std :: string'和'std :: u16string'比使用'std :: unique_ptr'数组更容易。至少,如果您必须返回一个'std :: unique_ptr'数组,您可以使用'std :: wstring_convert'进行转换,然后将结果字符串复制到输出数组中。数组大小将是字符串大小。 –

+0

@RemyLebeau由于强大的内存管理需求(如有状态分配器),我使用自定义容器(字符串,向量等不是stl)。 –

回答

3

您可以通过使用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_t的和char的进行交换。

+2

_wcstrlen不工作,因为char16_t不是wchar_t_ ...使用'std :: char_traits :: length(str)' – zett42

+0

@ zett42:非常好。谢谢。 –

+0

我只建议在while循环中添加'std :: codecvt_base :: result'来检查'error',并删除未使用的'old'变量:)。 –