C++ - UTF8 encode/decode in Windows

decode from utf8 string into unicdoe wstring
std::wstring from_utf8(const std::string& str_in_utf8)
{
    // prepare buffer
    //   buffer_size 是已含 \0 之長度,因為我們在 input size 傳了 -1。
    auto buffer_size = MultiByteToWideChar(CP_UTF8, 0, str_in_utf8.data(), -1, NULL, 0);
    if(buffer_size == 0)
        throw std::invalid_argument("from_utf8(): String cannot be decoded from utf8 code page.");
    std::unique_ptr<wchar_t[]> buffer(new wchar_t[buffer_size + 1]());

    // do decode
    auto written_count = 
        MultiByteToWideChar(
            CP_UTF8,  // 表明編碼使用 UTF8
            0,  // 轉換用的 flags, msdn 說 CP_UTF8 無 flag 可用,必須設 0。
            str_in_utf8.data(),  // 輸入字串的位址。
            -1, // std::string::data() 是 \0 結尾,所以可以傳 -1 進去自動判斷長度。
            buffer.get(), // 輸出結果的字串位址。
            buffer_size // 因為我們在輸入字串長度給 -1,所以會回傳含 \0 的長度。
        );
    if(written_count == 0)
        throw std::invalid_argument("from_utf8(): String cannot be decoded from utf8 code page.");
    return buffer.get();
}
encode from unicode wstring into utf8 string
std::string to_utf8(const std::wstring& str_in_unicode)
{
    // prepare buffer
    //   buffer_size 是已含 \0 之長度,因為我們在 input size 傳了 -1。
    auto buffer_size = WideCharToMultiByte(CP_UTF8, 0, str_in_unicode.data(), -1, NULL, 0, 0, 0);
    if(buffer_size == 0)
        throw std::invalid_argument("to_utf8(): String cannot be encoded to utf8 code page.");
    
    // 
    std::unique_ptr<char[]> buffer(new char[buffer_size]());

    // do encode
    auto written_count = 
        WideCharToMultiByte(
            CP_UTF8, // 表明編碼使用 UTF8
            0, // 轉換用的 flags, msdn 說 CP_UTF8 無 flag 可用,必須設 0。
            str_in_unicode.data(), // 輸入字串的位址。
            -1, // std::wstring::data() 是 \0 結尾,所以可以傳 -1 進去自動判斷長度。
            buffer.get(), // 輸出結果的字串位址。
            buffer_size, // 因為我們在輸入字串長度給 -1,所以會回傳含 \0 的長度。
            0, // 若有無法解析時,使用此預設字元, 此處不用,設 0。
            0  // BOOL*, 表示有遇到無法解析的情況。
        );
    if(written_count == 0)
        throw std::invalid_argument("to_utf8(): String cannot be encoded to utf8 code page.");
    return buffer.get();
}

no throw 版
std::wstring from_utf8(std::nothrow_t, const std::string& str_in_utf8)
{
    try
    {
        return from_utf8(str_in_utf8);
    }
    catch(std::invalid_argument)
    {
        return L"";
    }
}
std::string to_utf8(std::nothrow_t, const std::wstring& str_in_unicode)
{
    try
    {
        return to_utf8(str_in_unicode);
    }
    catch(std::invalid_argument)
    {
        return "";
    }
}
dependency header
#include <new> // nothrow_t
#include <string> // string/wstring
#include <memory> // unique_ptr
#include <Windows.h> // MultiByteToWideChar/WideCharToMultiByte
comments powered by Disqus