]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
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_; | |
38 | exe_setter_(string_type && str) : exe_(std::move(str)) {} | |
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 | { | |
48 | 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 | { | |
57 | 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> | |
76 | arg_setter_(Iterator && begin, Iterator && end) : _args(begin, end) {} | |
77 | ||
78 | template<typename Range> | |
79 | arg_setter_(Range && str) : | |
80 | _args(std::begin(str), | |
81 | std::end(str)) {} | |
82 | ||
83 | iterator begin() {return _args.begin();} | |
84 | iterator end() {return _args.end();} | |
85 | const_iterator begin() const {return _args.begin();} | |
86 | const_iterator end() const {return _args.end();} | |
87 | arg_setter_(string_type & str) : _args{{str}} {} | |
88 | arg_setter_(string_type && s) : _args({std::move(s)}) {} | |
89 | arg_setter_(const string_type & s) : _args({s}) {} | |
90 | arg_setter_(const value_type* s) : _args({std::move(s)}) {} | |
91 | ||
92 | template<std::size_t Size> | |
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 | { | |
102 | 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 | { | |
117 | 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 | { | |
133 | 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 | { | |
147 | 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 | ||
171 | 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 | ||
180 | void operator()(const string_type & data) | |
181 | { | |
182 | if (exe.empty()) | |
183 | exe = data; | |
184 | else | |
185 | args.push_back(data); | |
186 | } | |
187 | void operator()(const Char* data) | |
188 | { | |
189 | if (exe.empty()) | |
190 | exe = data; | |
191 | else | |
192 | args.push_back(data); | |
193 | } | |
194 | void operator()(shell_) {shell = true;} | |
195 | 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 | ||
211 | 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 | } | |
226 | void operator()(exe_setter_<Char> && data) | |
227 | { | |
228 | not_cmd = true; | |
229 | exe = std::move(data.exe_); | |
230 | } | |
231 | void operator()(const exe_setter_<Char> & data) | |
232 | { | |
233 | not_cmd = true; | |
234 | exe = data.exe_; | |
235 | } | |
236 | 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 | } | |
242 | 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 | } | |
248 | void operator()(const arg_setter_<Char, false> & data) | |
249 | { | |
250 | args.assign(data._args.begin(), data._args.end()); | |
251 | } | |
252 | void operator()(const arg_setter_<Char, true> & data) | |
253 | { | |
254 | args.insert(args.end(), data._args.begin(), data._args.end()); | |
255 | } | |
256 | ||
257 | 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_ */ |