c++utf-8charcstringunicode-string

Conversion of UTF-8 char * to CString


How do I convert a string in UTF-8 char* to CString?


Solution

  • #include <windows.h>
    #include <atlstr.h>
    
    bool Utf8ToCString( CString& cstr, const char* utf8Str )
    {
        size_t utf8StrLen = strlen(utf8Str);
    
        if( utf8StrLen == 0 )
        {
            cstr.Empty();
            return true;
        }
    
    #ifdef UNICODE
        // CString is UNICODE string so we just decode UTF-8 to wide string
        int cstrLen = MultiByteToWideChar(
                                CP_UTF8, 0,
                                utf8Str, utf8StrLen,  NULL, 0
                                );
    
        if( cstrLen > 0 )
        try
        {
            LPWSTR cstrBuf = cstr.GetBuffer(cstrLen+1);
    
            cstrLen = MultiByteToWideChar(
                                CP_UTF8, 0,
                                utf8Str, utf8StrLen,  cstrBuf, cstrLen+1
                                );
    
            if( cstrLen > 0 )
            {
                cstr.ReleaseBuffer(cstrLen);
                return true;
            }
    
            cstr.ReleaseBuffer(0);
        }
        catch(...) {} // CMemoryException from cstr.GetBuffer()
    #else
        // CString is system ANSI string so (1) we decode UTF-8 to wide string...
        int wstrLen = MultiByteToWideChar(
                                CP_UTF8,  0,
                                utf8Str, utf8StrLen,  NULL, 0
                                );
        WCHAR* wstrBuf;
    
        if(  wstrLen > 0  &&
            ( wstrBuf = (WCHAR*)malloc( (wstrLen+1)*sizeof(WCHAR) ) ) != NULL )
        {
            int wstrLen = MultiByteToWideChar(
                                CP_UTF8,  0,
                                utf8Str, utf8StrLen,  wstrBuf, wstrLen+1
                                );
            int cstrLen;
    
            //... and (2) we encode wide string to system ANSI encoding
            if(  wstrLen > 0  &&
                  ( cstrLen = WideCharToMultiByte(
                                        CP_ACP, 0,  wstrBuf, wstrLen, NULL, 0
                                        ) ) > 0  )
            try
            {
                LPSTR cstrBuf = cstr.GetBuffer(cstrLen+1);
    
                cstrLen = WideCharToMultiByte(
                                CP_ACP,  0,
                                wstrBuf, wstrLen,   cstrBuf, cstrLen+1
                                );
    
                if( cstrLen > 0 )
                {
                    free(wstrBuf);
                    cstr.ReleaseBuffer(cstrLen);
                    return true;
                }
    
                cstr.ReleaseBuffer(0);
            }
            catch(...) {} // CMemoryException from cstr.GetBuffer()
    
            free(wstrBuf);
        }
    #endif
    
        return false;
    }
    

    Though this function is valid for both UNICODE and non-UNICODE configurations IMHO using UNICODE configuration in Win32 programs is much more productive (in general and in this function).