Windows ANSI string

mohadang·2023년 1월 7일
0

System

목록 보기
1/12
post-thumbnail

윈도우의 System API들은 ANSI 문자열이나 유니코드 문자열을 받도록 되어 있다.
하지만 아스키코드와 유니코드를 처리하기 위해 시스템에서 char, wchar_t, string, wstring등을 혼용하면서 사용하는것은 불편하다고 생각된다.(ex: 문자열을 json으로 저장할때 아스키와 유니코드 처리등...)

그래서 가급적이면 시스템에서는 하나의 문자열을 사용하는 것이 좋을 것 같다.
한글이나 일본어 같은 유니코드 문자들을 ansi로 변경한 후 WindowsApiA 같이 끝이 A로 끝나는 API들만 호출 하도록 처리 하는 것이다.

이 방법은 유니코드가 시스템에 들어오는 지점에서 ANSI로 문자열을 변경하는 처리만 잘 해주면 시스템 안에서 문자열들은 string 하나의 타입만으로도 가능 하다.

#include <windows.h>
inline DWORD convert_unicode_to_ansi_string(
  __out std::string& ansi,
  __in const wchar_t* unicode,
  __in const size_t unicode_size) {
  DWORD error = 0;     do {
    if ((nullptr == unicode) || (0 == unicode_size)) {
      error = ERROR_INVALID_PARAMETER;
      break;
    }
    ansi.clear();
    /*
     * getting required cch.
     */
    int required_cch = ::WideCharToMultiByte(
      CP_ACP, 0, unicode, static_cast<int>(unicode_size), nullptr, 0, nullptr, nullptr);
    if (0 == required_cch) {
      error = ::GetLastError();
      break;
    }
    /*
     * allocate.
     */
    ansi.resize(required_cch);
    /*
     * convert.
     */
    if (0 == ::WideCharToMultiByte(
      CP_ACP, 0, unicode, static_cast<int>(unicode_size), const_cast<char*>(ansi.c_str()),
      static_cast<int>(ansi.size()), nullptr, nullptr)) {
      error = ::GetLastError();
      break;
    }
  } while (false);
  return error;
}

inline std::string convert_utf16_to_ansi(const wchar_t* str) {
  std::wstring intput_str(str);
  std::string output_str;
  convert_unicode_to_ansi_string(output_str, intput_str.c_str(), intput_str.size());
  return output_str;
}

std::string ansi_to_utf8(const std::string& str) {
  const char* pszIn = str.c_str();
  std::string resultString;
  int nLenOfUni = 0, nLenOfUTF = 0;
  wchar_t* us = NULL;
  char* pszOut = NULL;
  if ((nLenOfUni = MultiByteToWideChar(CP_ACP, 0, pszIn, strlen(pszIn), NULL, 0)) <= 0) {
    return str;
  }

  us = new wchar_t[nLenOfUni + 1];
  memset(us, 0x00, sizeof(wchar_t) * (nLenOfUni + 1));

  // ansi -> unicode
  nLenOfUni = MultiByteToWideChar(CP_ACP, 0, pszIn, strlen(pszIn), us, nLenOfUni);

  if ((nLenOfUTF = WideCharToMultiByte(CP_UTF8, 0, us, nLenOfUni, NULL, 0, NULL, NULL)) <= 0) {
    delete[] us;
    return str;
  }

  pszOut = new char[nLenOfUTF + 1];
  memset(pszOut, 0x00, sizeof(char) * (nLenOfUTF + 1));

  // unicode -> utf8
  nLenOfUTF = WideCharToMultiByte(CP_UTF8, 0, us, nLenOfUni, pszOut, nLenOfUTF, NULL, NULL);
  pszOut[nLenOfUTF] = 0;
  resultString = pszOut;
  delete[] us;
  delete[] pszOut;
  return resultString;
}

//example
__declspec(dllexport) void __stdcall Example(
  const char16_t* file_path) {
  auto ansi_file_path = convert_utf16_to_ansi((const wchar_t*)file_path);
  
  PathFindFileNameA(ansi_file_path.c_str())
  DWORD h = 0;
  DWORD resource_size = ::GetFileVersionInfoSizeA(const_cast<char*>(ansi_file_path.c_str()), &h);
}
profile
mohadang

0개의 댓글