Mesen/Utilities/utf8conv_inl.h
2014-06-29 16:51:58 -04:00

369 lines
10 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// FILE: utf8conv_inl.h
//
// by Giovanni Dicanio <gdicanio@mvps.org>
//
// Private header file containing implementations of inline functions.
// The public header file for this module is "utf8conv.h";
// users should *not* #include this private header file directly.
//
//////////////////////////////////////////////////////////////////////////
#pragma once
#include <string.h> // strlen()
#include <Windows.h> // Win32 Platform SDK main header
namespace utf8util {
//------------------------------------------------------------------------
// Implementation of utf8_conversion_error class methods
//------------------------------------------------------------------------
inline utf8_conversion_error::utf8_conversion_error(
const char * message,
conversion_type conversion,
error_code_type error_code
) :
std::runtime_error(message),
m_conversion(conversion),
m_error_code(error_code)
{
}
inline utf8_conversion_error::utf8_conversion_error(
const std::string & message,
conversion_type conversion,
error_code_type error_code
) :
std::runtime_error(message),
m_conversion(conversion),
m_error_code(error_code)
{
}
inline utf8_conversion_error::conversion_type utf8_conversion_error::conversion() const
{
return m_conversion;
}
inline utf8_conversion_error::error_code_type utf8_conversion_error::error_code() const
{
return m_error_code;
}
//------------------------------------------------------------------------
// Implementation of module functions
//------------------------------------------------------------------------
inline std::wstring UTF16FromUTF8(const std::string & utf8)
{
//
// Special case of empty input string
//
if (utf8.empty())
return std::wstring();
// Fail if an invalid input character is encountered
const DWORD conversionFlags = MB_ERR_INVALID_CHARS;
//
// Get length (in wchar_t's) of resulting UTF-16 string
//
const int utf16Length = ::MultiByteToWideChar(
CP_UTF8, // convert from UTF-8
conversionFlags, // flags
utf8.data(), // source UTF-8 string
utf8.length(), // length (in chars) of source UTF-8 string
NULL, // unused - no conversion done in this step
0 // request size of destination buffer, in wchar_t's
);
if (utf16Length == 0)
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
(error == ERROR_NO_UNICODE_TRANSLATION) ?
"Invalid UTF-8 sequence found in input string." :
"Can't get length of UTF-16 string (MultiByteToWideChar failed).",
utf8_conversion_error::conversion_utf16_from_utf8,
error);
}
//
// Allocate destination buffer for UTF-16 string
//
std::wstring utf16;
utf16.resize(utf16Length);
//
// Do the conversion from UTF-8 to UTF-16
//
if ( ! ::MultiByteToWideChar(
CP_UTF8, // convert from UTF-8
0, // validation was done in previous call,
// so speed up things with default flags
utf8.data(), // source UTF-8 string
utf8.length(), // length (in chars) of source UTF-8 string
&utf16[0], // destination buffer
utf16.length() // size of destination buffer, in wchar_t's
) )
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
"Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar failed).",
utf8_conversion_error::conversion_utf16_from_utf8,
error);
}
//
// Return resulting UTF-16 string
//
return utf16;
}
inline std::wstring UTF16FromUTF8(const char * utf8)
{
//
// Special case of empty input string
//
if (utf8 == NULL || *utf8 == '\0')
return std::wstring();
// Prefetch the length of the input UTF-8 string
const int utf8Length = static_cast<int>(strlen(utf8));
// Fail if an invalid input character is encountered
const DWORD conversionFlags = MB_ERR_INVALID_CHARS;
//
// Get length (in wchar_t's) of resulting UTF-16 string
//
const int utf16Length = ::MultiByteToWideChar(
CP_UTF8, // convert from UTF-8
conversionFlags, // flags
utf8, // source UTF-8 string
utf8Length, // length (in chars) of source UTF-8 string
NULL, // unused - no conversion done in this step
0 // request size of destination buffer, in wchar_t's
);
if (utf16Length == 0)
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
(error == ERROR_NO_UNICODE_TRANSLATION) ?
"Invalid UTF-8 sequence found in input string." :
"Can't get length of UTF-16 string (MultiByteToWideChar failed).",
utf8_conversion_error::conversion_utf16_from_utf8,
error);
}
//
// Allocate destination buffer for UTF-16 string
//
std::wstring utf16;
utf16.resize(utf16Length);
//
// Do the conversion from UTF-8 to UTF-16
//
if ( ! ::MultiByteToWideChar(
CP_UTF8, // convert from UTF-8
0, // validation was done in previous call,
// so speed up things with default flags
utf8, // source UTF-8 string
utf8Length, // length (in chars) of source UTF-8 string
&utf16[0], // destination buffer
utf16.length() // size of destination buffer, in wchar_t's
) )
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
"Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar failed).",
utf8_conversion_error::conversion_utf16_from_utf8,
error);
}
//
// Return resulting UTF-16 string
//
return utf16;
}
inline std::string UTF8FromUTF16(const std::wstring & utf16)
{
//
// Special case of empty input string
//
if (utf16.empty())
return std::string();
//
// Get length (in chars) of resulting UTF-8 string
//
const int utf8Length = ::WideCharToMultiByte(
CP_UTF8, // convert to UTF-8
0, // default flags
utf16.data(), // source UTF-16 string
utf16.length(), // source string length, in wchar_t's,
NULL, // unused - no conversion required in this step
0, // request buffer size
NULL, NULL // unused
);
if (utf8Length == 0)
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
"Can't get length of UTF-8 string (WideCharToMultiByte failed).",
utf8_conversion_error::conversion_utf8_from_utf16,
error);
}
//
// Allocate destination buffer for UTF-8 string
//
std::string utf8;
utf8.resize(utf8Length);
//
// Do the conversion from UTF-16 to UTF-8
//
if ( ! ::WideCharToMultiByte(
CP_UTF8, // convert to UTF-8
0, // default flags
utf16.data(), // source UTF-16 string
utf16.length(), // source string length, in wchar_t's,
&utf8[0], // destination buffer
utf8.length(), // destination buffer size, in chars
NULL, NULL // unused
) )
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
"Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte failed).",
utf8_conversion_error::conversion_utf8_from_utf16,
error);
}
//
// Return resulting UTF-8 string
//
return utf8;
}
inline std::string UTF8FromUTF16(const wchar_t * utf16)
{
//
// Special case of empty input string
//
if (utf16 == NULL || *utf16 == L'\0')
return std::string();
// Prefetch the length of the input UTF-16 string
const int utf16Length = static_cast<int>(wcslen(utf16));
//
// Get length (in chars) of resulting UTF-8 string
//
const int utf8Length = ::WideCharToMultiByte(
CP_UTF8, // convert to UTF-8
0, // default flags
utf16, // source UTF-16 string
utf16Length, // source string length, in wchar_t's,
NULL, // unused - no conversion required in this step
0, // request buffer size
NULL, NULL // unused
);
if (utf8Length == 0)
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
"Can't get length of UTF-8 string (WideCharToMultiByte failed).",
utf8_conversion_error::conversion_utf8_from_utf16,
error);
}
//
// Allocate destination buffer for UTF-8 string
//
std::string utf8;
utf8.resize(utf8Length);
//
// Do the conversion from UTF-16 to UTF-8
//
if ( ! ::WideCharToMultiByte(
CP_UTF8, // convert to UTF-8
0, // default flags
utf16, // source UTF-16 string
utf16Length, // source string length, in wchar_t's,
&utf8[0], // destination buffer
utf8.length(), // destination buffer size, in chars
NULL, NULL // unused
) )
{
// Error
DWORD error = ::GetLastError();
throw utf8_conversion_error(
"Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte failed).",
utf8_conversion_error::conversion_utf8_from_utf16,
error);
}
//
// Return resulting UTF-8 string
//
return utf8;
}
} // namespace utf8util
//////////////////////////////////////////////////////////////////////////