2017-02-25 40 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'變量:)。 –