1 // Copyright (c) 2016 Klemens D. Morgenstern 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 7 #ifndef BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_ 8 #define BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_ 9 10 #include <boost/process/detail/config.hpp> 11 12 #include <boost/process/detail/handler_base.hpp> 13 #include <boost/process/detail/traits/cmd_or_exe.hpp> 14 #include <boost/process/detail/traits/wchar_t.hpp> 15 16 #if defined( BOOST_WINDOWS_API ) 17 #include <boost/process/detail/windows/basic_cmd.hpp> 18 #include <boost/process/detail/windows/cmd.hpp> 19 #elif defined( BOOST_POSIX_API ) 20 #include <boost/process/detail/posix/basic_cmd.hpp> 21 #include <boost/process/detail/posix/cmd.hpp> 22 #endif 23 24 #include <boost/process/shell.hpp> 25 26 #include <iterator> 27 28 29 namespace boost { namespace process { namespace detail { 30 31 template<typename Char> 32 struct exe_setter_ 33 { 34 typedef Char value_type; 35 typedef std::basic_string<Char> string_type; 36 37 string_type exe_; exe_setter_boost::process::detail::exe_setter_38 exe_setter_(string_type && str) : exe_(std::move(str)) {} exe_setter_boost::process::detail::exe_setter_39 exe_setter_(const string_type & str) : exe_(str) {} 40 }; 41 42 template<> struct is_wchar_t<exe_setter_<wchar_t>> : std::true_type {}; 43 44 45 template<> 46 struct char_converter<char, exe_setter_<wchar_t>> 47 { convboost::process::detail::char_converter48 static exe_setter_<char> conv(const exe_setter_<wchar_t> & in) 49 { 50 return {::boost::process::detail::convert(in.exe_)}; 51 } 52 }; 53 54 template<> 55 struct char_converter<wchar_t, exe_setter_<char>> 56 { convboost::process::detail::char_converter57 static exe_setter_<wchar_t> conv(const exe_setter_<char> & in) 58 { 59 return {::boost::process::detail::convert(in.exe_)}; 60 } 61 }; 62 63 64 65 template <typename Char, bool Append > 66 struct arg_setter_ 67 { 68 using value_type = Char; 69 using string_type = std::basic_string<value_type>; 70 std::vector<string_type> _args; 71 72 typedef typename std::vector<string_type>::iterator iterator; 73 typedef typename std::vector<string_type>::const_iterator const_iterator; 74 75 template<typename Iterator> arg_setter_boost::process::detail::arg_setter_76 arg_setter_(Iterator && begin, Iterator && end) : _args(begin, end) {} 77 78 template<typename Range> arg_setter_boost::process::detail::arg_setter_79 arg_setter_(Range && str) : 80 _args(std::begin(str), 81 std::end(str)) {} 82 beginboost::process::detail::arg_setter_83 iterator begin() {return _args.begin();} endboost::process::detail::arg_setter_84 iterator end() {return _args.end();} beginboost::process::detail::arg_setter_85 const_iterator begin() const {return _args.begin();} endboost::process::detail::arg_setter_86 const_iterator end() const {return _args.end();} arg_setter_boost::process::detail::arg_setter_87 arg_setter_(string_type & str) : _args{{str}} {} arg_setter_boost::process::detail::arg_setter_88 arg_setter_(string_type && s) : _args({std::move(s)}) {} arg_setter_boost::process::detail::arg_setter_89 arg_setter_(const string_type & s) : _args({s}) {} arg_setter_boost::process::detail::arg_setter_90 arg_setter_(const value_type* s) : _args({std::move(s)}) {} 91 92 template<std::size_t Size> arg_setter_boost::process::detail::arg_setter_93 arg_setter_(const value_type (&s) [Size]) : _args({s}) {} 94 }; 95 96 template<> struct is_wchar_t<arg_setter_<wchar_t, true >> : std::true_type {}; 97 template<> struct is_wchar_t<arg_setter_<wchar_t, false>> : std::true_type {}; 98 99 template<> 100 struct char_converter<char, arg_setter_<wchar_t, true>> 101 { convboost::process::detail::char_converter102 static arg_setter_<char, true> conv(const arg_setter_<wchar_t, true> & in) 103 { 104 std::vector<std::string> vec(in._args.size()); 105 std::transform(in._args.begin(), in._args.end(), vec.begin(), 106 [](const std::wstring & ws) 107 { 108 return ::boost::process::detail::convert(ws); 109 }); 110 return {vec}; 111 } 112 }; 113 114 template<> 115 struct char_converter<wchar_t, arg_setter_<char, true>> 116 { convboost::process::detail::char_converter117 static arg_setter_<wchar_t, true> conv(const arg_setter_<char, true> & in) 118 { 119 std::vector<std::wstring> vec(in._args.size()); 120 std::transform(in._args.begin(), in._args.end(), vec.begin(), 121 [](const std::string & ws) 122 { 123 return ::boost::process::detail::convert(ws); 124 }); 125 126 return {vec}; 127 } 128 }; 129 130 template<> 131 struct char_converter<char, arg_setter_<wchar_t, false>> 132 { convboost::process::detail::char_converter133 static arg_setter_<char, false> conv(const arg_setter_<wchar_t, false> & in) 134 { 135 std::vector<std::string> vec(in._args.size()); 136 std::transform(in._args.begin(), in._args.end(), vec.begin(), 137 [](const std::wstring & ws) 138 { 139 return ::boost::process::detail::convert(ws); 140 }); 141 return {vec}; } 142 }; 143 144 template<> 145 struct char_converter<wchar_t, arg_setter_<char, false>> 146 { convboost::process::detail::char_converter147 static arg_setter_<wchar_t, false> conv(const arg_setter_<char, false> & in) 148 { 149 std::vector<std::wstring> vec(in._args.size()); 150 std::transform(in._args.begin(), in._args.end(), vec.begin(), 151 [](const std::string & ws) 152 { 153 return ::boost::process::detail::convert(ws); 154 }); 155 return {vec}; 156 } 157 }; 158 159 using api::exe_cmd_init; 160 161 template<typename Char> 162 struct exe_builder 163 { 164 //set by path, because that will not be interpreted as a cmd 165 bool not_cmd = false; 166 bool shell = false; 167 using string_type = std::basic_string<Char>; 168 string_type exe; 169 std::vector<string_type> args; 170 operator ()boost::process::detail::exe_builder171 void operator()(const boost::filesystem::path & data) 172 { 173 not_cmd = true; 174 if (exe.empty()) 175 exe = data.native(); 176 else 177 args.push_back(data.native()); 178 } 179 operator ()boost::process::detail::exe_builder180 void operator()(const string_type & data) 181 { 182 if (exe.empty()) 183 exe = data; 184 else 185 args.push_back(data); 186 } operator ()boost::process::detail::exe_builder187 void operator()(const Char* data) 188 { 189 if (exe.empty()) 190 exe = data; 191 else 192 args.push_back(data); 193 } operator ()boost::process::detail::exe_builder194 void operator()(shell_) {shell = true;} operator ()boost::process::detail::exe_builder195 void operator()(std::vector<string_type> && data) 196 { 197 if (data.empty()) 198 return; 199 200 auto itr = std::make_move_iterator(data.begin()); 201 auto end = std::make_move_iterator(data.end()); 202 203 if (exe.empty()) 204 { 205 exe = *itr; 206 itr++; 207 } 208 args.insert(args.end(), itr, end); 209 } 210 operator ()boost::process::detail::exe_builder211 void operator()(const std::vector<string_type> & data) 212 { 213 if (data.empty()) 214 return; 215 216 auto itr = data.begin(); 217 auto end = data.end(); 218 219 if (exe.empty()) 220 { 221 exe = *itr; 222 itr++; 223 } 224 args.insert(args.end(), itr, end); 225 } operator ()boost::process::detail::exe_builder226 void operator()(exe_setter_<Char> && data) 227 { 228 not_cmd = true; 229 exe = std::move(data.exe_); 230 } operator ()boost::process::detail::exe_builder231 void operator()(const exe_setter_<Char> & data) 232 { 233 not_cmd = true; 234 exe = data.exe_; 235 } operator ()boost::process::detail::exe_builder236 void operator()(arg_setter_<Char, false> && data) 237 { 238 args.assign( 239 std::make_move_iterator(data._args.begin()), 240 std::make_move_iterator(data._args.end())); 241 } operator ()boost::process::detail::exe_builder242 void operator()(arg_setter_<Char, true> && data) 243 { 244 args.insert(args.end(), 245 std::make_move_iterator(data._args.begin()), 246 std::make_move_iterator(data._args.end())); 247 } operator ()boost::process::detail::exe_builder248 void operator()(const arg_setter_<Char, false> & data) 249 { 250 args.assign(data._args.begin(), data._args.end()); 251 } operator ()boost::process::detail::exe_builder252 void operator()(const arg_setter_<Char, true> & data) 253 { 254 args.insert(args.end(), data._args.begin(), data._args.end()); 255 } 256 get_initializerboost::process::detail::exe_builder257 api::exe_cmd_init<Char> get_initializer() 258 { 259 if (not_cmd || !args.empty()) 260 { 261 if (shell) 262 return api::exe_cmd_init<Char>::exe_args_shell(std::move(exe), std::move(args)); 263 else 264 return api::exe_cmd_init<Char>::exe_args(std::move(exe), std::move(args)); 265 } 266 else 267 if (shell) 268 return api::exe_cmd_init<Char>::cmd_shell(std::move(exe)); 269 else 270 return api::exe_cmd_init<Char>::cmd(std::move(exe)); 271 272 } 273 typedef api::exe_cmd_init<Char> result_type; 274 }; 275 276 template<> 277 struct initializer_builder<cmd_or_exe_tag<char>> 278 { 279 typedef exe_builder<char> type; 280 }; 281 282 template<> 283 struct initializer_builder<cmd_or_exe_tag<wchar_t>> 284 { 285 typedef exe_builder<wchar_t> type; 286 }; 287 288 }}} 289 290 291 292 #endif /* BOOST_PROCESS_DETAIL_EXE_BUILDER_HPP_ */ 293