MultiByte・WideChar 相互変換のコード

MultiByte → WideChar 変換の場合は const char* を変換して結果を std::wstring にセット、逆は const wchar_t* を変換して結果を std::string にセット、というインターフェースを持つ関数として、 C の locale・C++ の localeで、また参考までに Win32・C++BuilderVCL も含めた 4通りの方法で実装してみました。(引数の NULL チェックは省略しています)

C locale の場合

// どこかで最初に 1 度だけ ::setlocale(LC_ALL, ""); を実行しておく
void convertMultiByteToWideChar(const char* pStrMultiByte, std::wstring& rStrWideChar)
{
  size_t numWCharsNeeded =  ::mbstowcs(NULL, pStrMultiByte, 0);
  wchar_t* pStrWChar = new wchar_t[numWCharsNeeded + 1];
  size_t numWCharsConverted =::mbstowcs(pStrWChar, pStrMultiByte, numWCharsNeeded);
  pStrWChar[numWCharsConverted] = L'\0';

  rStrWideChar = pStrWChar;
  delete pStrWChar;
}

void convertWideCharToMultiByte(const wchar_t* pStrWideChar, std::string& rStrMultiByte)
{
  size_t numCharsNeeded = ::wcstombs(NULL, pStrWideChar, 0);
  char* pStrMultiByte = new char[numCharsNeeded + 1];
  size_t numCharsConverted = ::wcstombs(pStrMultiByte, pStrWideChar, numCharsNeeded);
  pStrMultiByte[numCharsConverted] = '\0';

  rStrMultiByte = pStrMultiByte;
  delete pStrMultiByte;
}

C++ locale の場合

オブジェクト指向でソースが短くわかりやすくなるどころか、一番長くなっているのがなんとも orz な話ですね…。

void convertMultiByteToWideChar(const char* pStrMultiByte, std::wstring& rStrWideChar)
{
  std::string strMultiByte(pStrMultiByte);
  std::locale localeCurrent("");

  std::mbstate_t stateWChar = 0;
  const std::codecvt& rConvertMultiByteToWChar =
    std::use_facet >(localeCurrent);
  const char* pNextMultiByteChar = NULL;
  int sizeStrWChar = strMultiByte.size() * 2;
  wchar_t* pStrWChar = new wchar_t[sizeStrWChar + 1];
  wchar_t* pNextWChar = NULL;
  int result = rConvertMultiByteToWChar.in(stateWChar, strMultiByte.data(),
          strMultiByte.data() + strMultiByte.size(), pNextMultiByteChar,
          pStrWChar, pStrWChar + sizeStrWChar, pNextWChar);
  *pNextWChar = L'\0';

  rStrWideChar = pStrWChar;
  delete pStrWChar;
}

void convertWideCharToMultiByte(const wchar_t* pStrWideChar, std::string& rStrMultiByte)
{
  std::wstring strWideChar(pStrWideChar);
  std::locale localeCurrent("");

  std::mbstate_t stateMultiByte = 0;
  const std::codecvt& rConvertWCharToMultiByte =
    std::use_facet >(localeCurrent);
  const wchar_t* pNextWChar = NULL;
  int sizeStrMultiByte = strWideChar.size() * 3;
  char* pStrMultiByte = new char[sizeStrMultiByte + 1];
  char* pNextMultiByteChar = NULL;
  int result = rConvertWCharToMultiByte.out(stateMultiByte, strWideChar.data(),
          strWideChar.data() + strWideChar.size(), pNextWChar,
          pStrMultiByte, pStrMultiByte + sizeStrMultiByte, pNextMultiByteChar);
  *pNextMultiByteChar = '\0';

  rStrMultiByte = pStrMultiByte;
  delete pStrMultiByte;
}

Win32 API の場合

void convertMultiByteToWideChar(const char* pStrMultiByte, std::wstring& rStrWideChar)
{
  std::string strMultiByte(pStrMultiByte);
  int sizeStrWideChar = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strMultiByte.c_str(), strMultiByte.length(), NULL, 0);
  wchar_t* pStrWideChar = new wchar_t[sizeStrWideChar + 1];
  ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strMultiByte.c_str(), strMultiByte.length(), pStrWideChar, sizeStrWideChar);
  pStrWideChar[sizeStrWideChar] = '\0';
  rStrWideChar = pStrWideChar;
  delete pStrWideChar;
}

void convertWideCharToMultiByte(const wchar_t* pStrWideChar, std::string& rStrMultiByte)
{
  std::wstring strWideChar(pStrWideChar);
  int sizeStrMultiByte = ::WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), strWideChar.length(), NULL, 0, NULL, NULL);
  char* pStrMultiByte = new char[sizeStrMultiByte + 1];
  ::WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), strWideChar.length(), pStrMultiByte, sizeStrMultiByte, NULL, NULL);
  pStrMultiByte[sizeStrMultiByte] = '\0';

  rStrMultiByte = pStrMultiByte;
  delete pStrMultiByte;
}

VCL の場合

まあこれは半分シャレのつもりです(^^;)。VCLに特化してしまえば実に幸せですねぇ(笑)。

void convertWideCharToMultiByte(const wchar_t* pStrWideChar, std::string& rStrMultiByte)
{
  rStrMultiByte = AnsiString(pStrWideChar).c_str();
}

void convertMultiByteToWideChar(const char* pStrMultiByte, std::wstring& rStrWideChar)
{
  rStrWideChar = WideString(pStrMultiByte).c_bstr();
}