mirror of
https://github.com/libretro/Mesen.git
synced 2025-02-12 04:10:29 +00:00
369 lines
10 KiB
C++
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
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|