To split command-line arguments with double quotes.
#include "split_cmdline_args.hpp"
#include <assert.h>
using namespace std;
void case_empty()
{
assert(split_cmdline_args(string()) == deque<string>());
assert(split_cmdline_args("") == deque<string>());
assert(split_cmdline_args(wstring()) == deque<wstring>());
assert(split_cmdline_args(L"") == deque<wstring>());
}
void case_basic()
{
assert(split_cmdline_args(" foo bar \n\t baz ") == deque<string>({ "foo", "bar", "baz" }));
assert(split_cmdline_args("fo\"oo\"o \"ba\"r ba\"z\" \"qu x\" \"q u\"\"u x\"") == deque<string>({ "fo\"oo\"o", "\"ba\"r", "ba\"z\"", "\"qu x\"", "\"q u\"\"u x\"" }));
assert(split_cmdline_args(L"とある 科学の \"超\"電磁砲") == deque<wstring>({ L"とある", L"科学の", L"\"超\"電磁砲" }));
// Have to save in 'UTF-8 with BOM' to compile by MSVC. :( -- ref. https://msdn.microsoft.com/en-us/library/xwy0e8f2
// However, the Unicode Standard neither requires nor recommends the use of the BOM for UTF-8.
}
void case_misc()
{
for (auto i : split_cmdline_args("foo bar"));
}
int main()
{
case_empty();
case_basic();
case_misc();
return 0;
}
#pragma once
#include <string>
#include <deque>
#include <locale> // Use isspace template instead of isspace/iswspace in <cctype>.
template<typename T>
std::deque<std::basic_string<T>> split_cmdline_args(const std::basic_string<T> &cmd)
{
using namespace std;
typedef basic_string<T> string_type;
auto in = cmd.begin();
deque<string_type> out;
auto has_next = [&]() -> bool
{
return in != cmd.end();
};
locale loc;
while (has_next())
{
while (has_next() && isspace(*in, loc)) in++;
string_type token;
while (has_next() && !isspace(*in, loc))
{
if (*in == '"')
{
token.push_back(*in++);
while (has_next())
{
token.push_back(*in++);
if (token.back() == '"') break;
}
}
else
{
token.push_back(*in++);
}
}
if (token.size() > 0) out.push_back(token);
}
return out;
}
template<typename T>
inline std::deque<std::basic_string<T>> split_cmdline_args(const T *cmd)
{
return split_cmdline_args(std::basic_string<T>(cmd));
}
cmake_minimum_required(VERSION 3.1)
project(split_cmdline_args)
add_executable(${PROJECT_NAME} split_cmdline_args.hpp split_cmdline_args_test.cpp)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)
@ECHO OFF
CD /D %~dp0
PATH ^
%ProgramFiles%\CMake\bin;^
%ProgramFiles(x86)%\CMake\bin;^
C:\MinGW\bin
IF NOT EXIST build MKDIR build
CD build
cmake %* ..
PAUSE