#include "wchar_util.h" #include "list_pointer.h" #include #include bool stringToChar(std::string input, char*& output) { auto sz = input.size(); auto s = (char*)malloc(sz + 1); if (!s) { return false; } memcpy(s, input.c_str(), sz); s[sz] = 0; output = s; return true; } void freeChar(char* input) { if (input) free(input); } #if _WIN32 unsigned long wchar_util::getMultiByteToWideCharOptions(const unsigned long ori_options, unsigned int cp) { if (cp == CP_ACP) cp = GetACP(); if (cp == CP_OEMCP) cp = GetOEMCP(); switch (cp) { case 50220: case 50221: case 50222: case 50225: case 50227: case 50229: case CP_UTF7: case 42: return 0; default: break; } if (cp >= 57002 && cp <= 57011) return 0; if (cp == CP_UTF8 || cp == 54936) { return MB_ERR_INVALID_CHARS & ori_options; } return ori_options; } unsigned long wchar_util::getWideCharToMultiByteOptions(const unsigned long ori_options, unsigned int cp) { if (cp == CP_ACP) cp = GetACP(); if (cp == CP_OEMCP) cp = GetOEMCP(); switch (cp) { case 50220: case 50221: case 50222: case 50225: case 50227: case 50229: case CP_UTF7: case 42: return 0; default: break; } if (cp >= 57002 && cp <= 57011) return 0; if (cp == CP_UTF8 || cp == 54936) { return WC_ERR_INVALID_CHARS & ori_options; } return ori_options; } bool wchar_util::str_to_wstr(std::wstring& out, std::string inp, unsigned int cp, unsigned long options) { if (inp.empty()) { out = std::wstring(); return true; } DWORD opt = getMultiByteToWideCharOptions(options, cp); int wlen = MultiByteToWideChar(cp, opt, inp.c_str(), inp.length(), nullptr, 0); if (!wlen) { return false; } wchar_t* wstr = (wchar_t*) malloc(wlen * sizeof(wchar_t)); if (wstr == nullptr) { return false; } if (!MultiByteToWideChar(cp, opt, inp.c_str(), inp.length(), wstr, wlen)) { free(wstr); return false; } out = std::wstring(wstr, wlen); free(wstr); return true; } bool wchar_util::wstr_to_str(std::string& out, std::wstring inp, unsigned int cp, unsigned long options) { if (inp.empty()) { out = std::string(); return true; } DWORD opt = getWideCharToMultiByteOptions(options, cp); int len = WideCharToMultiByte(cp, opt, inp.c_str(), inp.length(), nullptr, 0, nullptr, nullptr); if (!len) { return false; } char* str = (char*) malloc(len); if (str == nullptr) { return false; } if (!WideCharToMultiByte(cp, opt, inp.c_str(), inp.length(), str, len, nullptr, nullptr)) { free(str); return false; } out = std::string(str, len); free(str); return true; } /** * @brief Convert wstring version argv to UTF-8 encoding argv * @param ArgvW Source * @param argc The count of parameters * @param argv dest (Need free memory by calling freeArgv) * @return true if OK */ bool ArgvWToArgv(const LPWSTR* ArgvW, int argc, char**& argv) { if (!ArgvW) return false; std::list li; for (int i = 0; i < argc; i++) { if (!ArgvW[i]) return false; std::wstring s = ArgvW[i]; std::string r; if (!wchar_util::wstr_to_str(r, s, CP_UTF8)) return false; li.push_back(r); } char** t; if (!listToPointer(li, t, &stringToChar, &freeChar)) { return false; } argv = t; return true; } bool wchar_util::getArgv(char**& argv, int& argc) { auto cm = GetCommandLineW(); int argcw = 0; auto argvw = CommandLineToArgvW(cm, &argcw); if (!argvw) return false; char** t; if (!ArgvWToArgv(argvw, argcw, t)) { LocalFree(argvw); return false; } LocalFree(argvw); argc = argcw; argv = t; return true; } void wchar_util::freeArgv(char** argv, int argc) { freePointerList(argv, argc, nullptr); } bool wchar_util::getArgv(std::vector& argv) { auto cmd = GetCommandLineW(); int argcw = 0; auto argvw = CommandLineToArgvW(cmd, &argcw); if (!argvw) return false; bool ret = true; for (int i = 0; i < argcw; i++) { std::wstring s = argvw[i]; std::string r; if (!wchar_util::wstr_to_str(r, s, CP_UTF8)) { ret = false; break; } argv.push_back(r); } LocalFree(argvw); return ret; } #endif