Skip to content

Instantly share code, notes, and snippets.

@jin-x
Last active August 10, 2020 15:30
Show Gist options
  • Save jin-x/cdd641d98887524b091fb1f82a68717d to your computer and use it in GitHub Desktop.
Save jin-x/cdd641d98887524b091fb1f82a68717d to your computer and use it in GitHub Desktop.
ArgvToCommandLine
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
std::string ArgvToCommandLine(int argc, const char** argv)
{
std::string result;
for (int i = 0; i < argc; ++i) {
std::string temp = argv[i];
bool add_qu = (temp.find_first_of(" \t") != std::string::npos), found;
// Add slash (\) before double quotes (") and duplicate slashes before it (and at the end of string if whitespace chars are present)
auto pos = temp.find('"');
while ((found = (pos != std::string::npos)) || add_qu) {
int cnt = found;
if (!found) { pos = temp.size(); }
while (pos > 0 && temp[pos-1] == '\\') { ++cnt, --pos; }
temp.insert(pos, cnt, '\\');
if (!found) { break; }
pos = temp.find('"', pos + cnt * 2);
}
// Add quotes around string if whitespace chars are present
if (add_qu) { temp = '"' + temp + '"'; }
// Add space delimiter
if (i > 0) { result.push_back(' '); }
result.append(temp);
}
return result;
}
std::string ArgvToCommandLine(std::vector<const char*> str_vec)
{
return ArgvToCommandLine(str_vec.size(), str_vec.data());
}
std::wstring ArgvToCommandLineW(int argc, const wchar_t** argv)
{
std::wstring result;
for (int i = 0; i < argc; ++i) {
std::wstring temp = argv[i];
bool add_qu = (temp.find_first_of(L" \t") != std::wstring::npos), found;
// Add slash (\) before double quotes (") and duplicate slashes before it (and at the end of string if whitespace chars are present)
size_t pos = temp.find(L'"');
while ((found = (pos != std::wstring::npos)) || add_qu) {
int cnt = found;
if (!found) { pos = temp.size(); }
while (pos > 0 && temp[pos-1] == L'\\') { ++cnt, --pos; }
temp.insert(pos, cnt, L'\\');
if (!found) { break; }
pos = temp.find(L'"', pos + cnt * 2);
}
// Add quotes around string if whitespace chars are present
if (add_qu) { temp = L'"' + temp + L'"'; }
// Add space delimiter
if (i > 0) { result.push_back(L' '); }
result.append(temp);
}
return result;
}
std::wstring ArgvToCommandLineW(std::vector<const wchar_t*> str_vec)
{
return ArgvToCommandLineW(str_vec.size(), str_vec.data());
}
int main(int argc, const char** argv)
{
//*
const char* argv1[] = {
"test.exe",
"C:\\Program Files\\",
"normal\\",
"a\ttab",
"quote\"mark",
"\\\\\\\"",
" \" ",
"\"quote\\\"\"\ttab \\space\\\\\""
};
const int argc1 = sizeof(argv1)/sizeof(*argv1);
argv = argv1;
argc = argc1;
//*/
std::cout << std::endl << ">> Source arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << '[' << argv[i] << ']' << std::endl;
}
std::cout << std::endl << ">> ArgvToCommandLine:" << std::endl;
std::string cmdline = ArgvToCommandLine(argc, argv);
std::cout << '[' << cmdline << ']' << std::endl;
std::cout << std::endl << ">> CommandLineToArgvW:" << std::endl;
int argcW;
std::wstring cmdlineW(cmdline.cbegin(), cmdline.cend());
wchar_t** argvW = CommandLineToArgvW(cmdlineW.c_str(), &argcW);
bool correct = (argc == argcW);
for (int i = 0; i < argcW; ++i) {
std::wcout << L'[' << argvW[i] << L']' << std::endl;
if (correct) {
std::wstring argW = argvW[i];
std::string arg(argW.cbegin(), argW.cend());
correct = correct && (argv[i] == arg);
}
}
LocalFree(argvW);
std::cout << std::endl << ">> Correct: " << std::boolalpha << correct << std::endl;
return 0;
}
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
std::string ArgvToCommandLine(int argc, const char** argv)
{
std::string result;
for (int i = 0; i < argc; ++i) {
std::string temp = argv[i];
// Add slash (\) before double quotes (") and duplicate slashes before it
auto pos = temp.find('"');
while (pos != std::string::npos) {
int cnt = 1;
while (pos > 0 && temp[pos-1] == '\\') { ++cnt, --pos; }
temp.insert(pos, cnt, '\\');
pos = temp.find('"', pos + cnt * 2);
}
// Add quotes around string if whitespace chars are present (with slash duplicating at the end of string)
if (temp.find_first_of(" \t") != std::string::npos) {
pos = temp.size();
int cnt = 0;
while (pos > 0 && temp[pos-1] == '\\') { ++cnt, --pos; }
if (cnt > 0) { temp.append(cnt, '\\'); }
temp = '"' + temp + '"';
}
// Add space delimiter
if (i > 0) { result.push_back(' '); }
result.append(temp);
}
return result;
}
std::string ArgvToCommandLine(std::vector<const char*> str_vec)
{
return ArgvToCommandLine(str_vec.size(), str_vec.data());
}
std::wstring ArgvToCommandLineW(int argc, const wchar_t** argv)
{
std::wstring result;
for (int i = 0; i < argc; ++i) {
std::wstring temp = argv[i];
// Add slash (\) before double quotes (") and duplicate slashes before it
auto pos = temp.find(L'"');
while (pos != std::wstring::npos) {
int cnt = 1;
while (pos > 0 && temp[pos-1] == L'\\') { ++cnt, --pos; }
temp.insert(pos, cnt, L'\\');
pos = temp.find(L'"', pos + cnt * 2);
}
// Add quotes around string if whitespace chars are present (with slash duplicating at the end of string)
if (temp.find_first_of(L" \t") != std::wstring::npos) {
pos = temp.size();
int cnt = 0;
while (pos > 0 && temp[pos-1] == L'\\') { ++cnt, --pos; }
if (cnt > 0) { temp.append(cnt, L'\\'); }
temp = L'"' + temp + L'"';
}
// Add space delimiter
if (i > 0) { result.push_back(L' '); }
result.append(temp);
}
return result;
}
std::wstring ArgvToCommandLineW(std::vector<const wchar_t*> str_vec)
{
return ArgvToCommandLineW(str_vec.size(), str_vec.data());
}
int main(int argc, const char** argv)
{
//*
const char* argv1[] = {
"test.exe",
"C:\\Program Files\\",
"normal\\",
"a\ttab",
"quote\"mark",
"\\\\\\\"",
" \" ",
"\"quote\\\"\"\ttab \\space\\\\\""
};
const int argc1 = sizeof(argv1)/sizeof(*argv1);
argv = argv1;
argc = argc1;
//*/
std::cout << std::endl << ">> Source arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << '[' << argv[i] << ']' << std::endl;
}
std::cout << std::endl << ">> ArgvToCommandLine:" << std::endl;
std::string cmdline = ArgvToCommandLine(argc, argv);
std::cout << '[' << cmdline << ']' << std::endl;
std::cout << std::endl << ">> CommandLineToArgvW:" << std::endl;
int argcW;
std::wstring cmdlineW(cmdline.cbegin(), cmdline.cend());
wchar_t** argvW = CommandLineToArgvW(cmdlineW.c_str(), &argcW);
bool correct = (argc == argcW);
for (int i = 0; i < argcW; ++i) {
std::wcout << L'[' << argvW[i] << L']' << std::endl;
if (correct) {
std::wstring argW = argvW[i];
std::string arg(argW.cbegin(), argW.cend());
correct = correct && (argv[i] == arg);
}
}
LocalFree(argvW);
std::cout << std::endl << ">> Correct: " << std::boolalpha << correct << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment