본문 바로가기

devlog/Windows API

MultiByte Unicode UTF-8 String Conversion

FMOD 사운드 로드 API중 System::createSound() 한글경로에서 로드안됨. 

 프로그램에서 이걸 사용하는데 만일 로드하려는 사운드에 한글 경로가 포함되면

 createSound() 리턴값이 FMOD_ERR_FILE_NOTFOUND로 바뀌고 로드에 실패한다. 

 외부 라이브러리는 외국에서 만든것들이 많아서인지 utf-8 인코딩만 지원해서 한글경로는 변환이 필수.

 위와같은 맥락으로 libVLC도 한글경로 지원 안되긴 마찬가지..

 

 사용한 변환코드는 아래와같다.






int utf8ToNormalMultiByteStr(const char* utfstr, char* str)

{

int size = MultiByteToWideChar( CP_UTF8, 0, utfstr, -1, 0, 0);

vector<wchar_t> wbuffer(size);

size = MultiByteToWideChar( CP_UTF8, 0, utfstr, -1, &wbuffer[0], size);


int cnt = WideCharToMultiByte(CP_ACP, 0, &wbuffer[0], -1, str, size*2, NULL, NULL);


return cnt;

}


BOOL ConvertUnicodeToMultibyte(LPCWSTR unicodeStr, LPSTR multiByteStr, DWORD size)

{

DWORD minSize;

minSize = WideCharToMultiByte(CP_OEMCP, NULL, unicodeStr, -1, NULL, 0, NULL, FALSE);

if (size < minSize)

{

return FALSE;

}


WideCharToMultiByte(CP_OEMCP, NULL, unicodeStr, -1, multiByteStr, size, NULL, FALSE);

return TRUE;

}


BOOL ConvertMultibyteToUnicode(LPCSTR multiByteStr, LPWSTR unicodeStr, DWORD size)

{

DWORD minSize;

minSize = MultiByteToWideChar(CP_ACP, 0, multiByteStr, -1, NULL, 0);


if (size < minSize)

{

return FALSE;

}


MultiByteToWideChar(CP_ACP, 0, multiByteStr, -1, unicodeStr, minSize);

return TRUE;

}


size_t UnicodeToUTF8(wchar_t uc, char * UTF8)

{

size_t tRequiredSize = 0;


if (uc <= 0x7f)

{

if (NULL != UTF8)

{

UTF8[0] = (char)uc;

UTF8[1] = (char) '\0';

}

tRequiredSize = 1;

}

else if (uc <= 0x7ff)

{

if (NULL != UTF8)

{

UTF8[0] = (char)(0xc0 + uc / (0x01 << 6));

UTF8[1] = (char)(0x80 + uc % (0x01 << 6));

UTF8[2] = (char) '\0';

}

tRequiredSize = 2;

}

else if (uc <= 0xffff)

{

if (NULL != UTF8)

{

UTF8[0] = (char)(0xe0 + uc / (0x01 << 12));

UTF8[1] = (char)(0x80 + uc / (0x01 << 6) % (0x01 << 6));

UTF8[2] = (char)(0x80 + uc % (0x01 << 6));

UTF8[3] = (char) '\0';

}

tRequiredSize = 3;

}


return tRequiredSize;

}


size_t UTF8ToUnicode(char * UTF8, wchar_t & uc)

{

size_t tRequiredSize = 0;


uc = 0x0000;


// ASCII byte 

if (0 == (UTF8[0] & 0x80))

{

uc = UTF8[0];

tRequiredSize = 1;

}

else // Start byte for 2byte

if (0xC0 == (UTF8[0] & 0xE0) &&

0x80 == (UTF8[1] & 0xC0))

{

uc += (UTF8[0] & 0x1F) << 6;

uc += (UTF8[1] & 0x3F) << 0;

tRequiredSize = 2;

}

else // Start byte for 3byte

if (0xE0 == (UTF8[0] & 0xE0) &&

0x80 == (UTF8[1] & 0xC0) &&

0x80 == (UTF8[2] & 0xC0))

{

uc += (UTF8[0] & 0x1F) << 12;

uc += (UTF8[1] & 0x3F) << 6;

uc += (UTF8[2] & 0x3F) << 0;

tRequiredSize = 3;

}

else

{

// Invalid case

assert(false);

}


return tRequiredSize;

}


size_t UnicodeStrToUTF8Str(wchar_t * szUni, char * szUTF8)

{

size_t tRequiredSize = 0;


int i = 0;

for (i = 0; szUni[i]; i++)

{

size_t tSize = 0;

if (NULL != szUTF8)

tSize = UnicodeToUTF8(szUni[i], szUTF8 + tRequiredSize);

else

tSize = UnicodeToUTF8(szUni[i], NULL);

tRequiredSize += tSize;

}

return tRequiredSize;

}


size_t UTF8StrToUnicodeStr(char * szUTF8, size_t tUTF8Len, wchar_t * szUni)

{

size_t tReadPos = 0;


size_t i = 0;

for (i = 0; tReadPos<tUTF8Len; i++)

{

wchar_t tTempUnicodeChar = 0;

size_t tSize = UTF8ToUnicode(szUTF8 + tReadPos, tTempUnicodeChar);

if (NULL != szUni)

szUni[i] = tTempUnicodeChar;

tReadPos += tSize;

}

return i;

}



Conversion From MultiByte to Unicode character set

UTF8 과 UTF16 간의 변환 공식

FMOD System::createSound