整理
This commit is contained in:
182
include/boost/process/v1/detail/posix/basic_cmd.hpp
Normal file
182
include/boost/process/v1/detail/posix/basic_cmd.hpp
Normal file
@@ -0,0 +1,182 @@
|
||||
// Copyright (c) 2016 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
#ifndef BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
|
||||
#define BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
|
||||
|
||||
#include <boost/process/v1/detail/config.hpp>
|
||||
#include <boost/process/v1/detail/posix/handler.hpp>
|
||||
#include <boost/process/v1/detail/posix/cmd.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/process/v1/shell.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace process
|
||||
{
|
||||
BOOST_PROCESS_V1_INLINE namespace v1
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace posix
|
||||
{
|
||||
|
||||
inline std::string build_cmd_shell(const std::string & exe, std::vector<std::string> && data)
|
||||
{
|
||||
std::string st = exe;
|
||||
for (auto & arg : data)
|
||||
{
|
||||
boost::replace_all(arg, "\"", "\\\"");
|
||||
|
||||
auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
|
||||
if (it != arg.end())//ok, contains spaces.
|
||||
{
|
||||
//the first one is put directly onto the output,
|
||||
//because then I don't have to copy the whole string
|
||||
arg.insert(arg.begin(), '"' );
|
||||
arg += '"'; //that is the post one.
|
||||
}
|
||||
|
||||
if (!st.empty())//first one does not need a preceding space
|
||||
st += ' ';
|
||||
|
||||
st += arg;
|
||||
}
|
||||
return st ;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> build_args(const std::string & data)
|
||||
{
|
||||
std::vector<std::string> st;
|
||||
|
||||
typedef std::string::const_iterator itr_t;
|
||||
|
||||
//normal quotes outside can be stripped, inside ones marked as \" will be replaced.
|
||||
auto make_entry = [](const itr_t & begin, const itr_t & end)
|
||||
{
|
||||
std::string data;
|
||||
if ((*begin == '"') && (*(end-1) == '"'))
|
||||
data.assign(begin+1, end-1);
|
||||
else
|
||||
data.assign(begin, end);
|
||||
|
||||
boost::replace_all(data, "\\\"", "\"");
|
||||
return data;
|
||||
|
||||
};
|
||||
|
||||
bool in_quote = false;
|
||||
|
||||
auto part_beg = data.cbegin();
|
||||
auto itr = data.cbegin();
|
||||
|
||||
for (; itr != data.cend(); itr++)
|
||||
{
|
||||
if (*itr == '"')
|
||||
in_quote ^= true;
|
||||
|
||||
if (!in_quote && (*itr == ' '))
|
||||
{
|
||||
//alright, got a space
|
||||
|
||||
if ((itr != data.cbegin()) && (*(itr -1) != ' ' ))
|
||||
st.push_back(make_entry(part_beg, itr));
|
||||
|
||||
part_beg = itr+1;
|
||||
}
|
||||
}
|
||||
if (part_beg != itr)
|
||||
st.emplace_back(make_entry(part_beg, itr));
|
||||
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
template<typename Char>
|
||||
struct exe_cmd_init;
|
||||
|
||||
template<>
|
||||
struct exe_cmd_init<char> : boost::process::v1::detail::api::handler_base_ext
|
||||
{
|
||||
exe_cmd_init(const exe_cmd_init & ) = delete;
|
||||
exe_cmd_init(exe_cmd_init && ) = default;
|
||||
exe_cmd_init(std::string && exe, std::vector<std::string> && args)
|
||||
: exe(std::move(exe)), args(std::move(args)) {};
|
||||
template <class Executor>
|
||||
void on_setup(Executor& exec)
|
||||
{
|
||||
if (exe.empty()) //cmd style
|
||||
{
|
||||
if (args.empty())
|
||||
exec.exe = "";
|
||||
else
|
||||
exec.exe = args.front().c_str();
|
||||
exec.cmd_style = true;
|
||||
}
|
||||
else
|
||||
exec.exe = &exe.front();
|
||||
|
||||
cmd_impl = make_cmd();
|
||||
exec.cmd_line = cmd_impl.data();
|
||||
}
|
||||
static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
|
||||
static exe_cmd_init cmd (std::string && cmd)
|
||||
{
|
||||
auto args = build_args(cmd);
|
||||
return exe_cmd_init({}, std::move(args));
|
||||
}
|
||||
|
||||
static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
|
||||
{
|
||||
auto cmd = build_cmd_shell(std::move(exe), std::move(args));
|
||||
|
||||
std::vector<std::string> args_ = {"-c", std::move(cmd)};
|
||||
std::string sh = shell().string();
|
||||
|
||||
return exe_cmd_init(std::move(sh), std::move(args_));
|
||||
}
|
||||
static exe_cmd_init cmd_shell(std::string&& cmd)
|
||||
{
|
||||
std::vector<std::string> args = {"-c", cmd};
|
||||
std::string sh = shell().string();
|
||||
|
||||
return exe_cmd_init(
|
||||
std::move(sh),
|
||||
{std::move(args)});
|
||||
}
|
||||
private:
|
||||
inline std::vector<char*> make_cmd();
|
||||
std::string exe;
|
||||
std::vector<std::string> args;
|
||||
std::vector<char*> cmd_impl;
|
||||
};
|
||||
|
||||
std::vector<char*> exe_cmd_init<char>::make_cmd()
|
||||
{
|
||||
// any string must be writable.
|
||||
static char empty_string[1] = "";
|
||||
std::vector<char*> vec;
|
||||
if (!exe.empty())
|
||||
vec.push_back(exe.empty() ? empty_string : &exe.front());
|
||||
|
||||
if (!args.empty()) {
|
||||
for (auto & v : args)
|
||||
vec.push_back(v.empty() ? empty_string : &v.front());
|
||||
}
|
||||
|
||||
vec.push_back(nullptr);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
}}}}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user