File indexing completed on 2025-01-18 09:50:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef BOOST_PROCESS_EXECUTE_HPP
0018 #define BOOST_PROCESS_EXECUTE_HPP
0019
0020 #include <boost/process/detail/config.hpp>
0021 #include <boost/process/detail/traits.hpp>
0022
0023 #if defined(BOOST_POSIX_API)
0024 #include <boost/process/detail/posix/executor.hpp>
0025 #elif defined(BOOST_WINDOWS_API)
0026 #include <boost/process/detail/windows/executor.hpp>
0027 #endif
0028
0029 #include <boost/process/detail/basic_cmd.hpp>
0030 #include <boost/process/detail/handler.hpp>
0031
0032 #include <boost/fusion/view.hpp>
0033 #include <boost/fusion/container.hpp>
0034 #include <boost/fusion/sequence.hpp>
0035 #include <boost/fusion/tuple.hpp>
0036 #include <boost/fusion/algorithm/transformation/filter_if.hpp>
0037 #include <boost/fusion/adapted/std_tuple.hpp>
0038 #include <boost/fusion/container/vector/convert.hpp>
0039
0040 #include <type_traits>
0041 #include <utility>
0042
0043 namespace boost { namespace process {
0044
0045 class child;
0046
0047 namespace detail {
0048
0049
0050 template<typename ...Args>
0051 struct has_wchar;
0052
0053 template<typename First, typename ...Args>
0054 struct has_wchar<First, Args...>
0055 {
0056 typedef has_wchar<Args...> next;
0057 typedef typename std::remove_cv<
0058 typename std::remove_reference<First>::type>::type res_type;
0059
0060 constexpr static bool my_value = is_wchar_t<res_type>::value;
0061 constexpr static bool value = my_value || next::value;
0062
0063 typedef std::integral_constant<bool, value> type;
0064 };
0065
0066 template<typename First>
0067 struct has_wchar<First>
0068 {
0069 typedef typename std::remove_cv<
0070 typename std::remove_reference<First>::type>::type res_type;
0071
0072 constexpr static bool value = is_wchar_t<res_type>::value;
0073
0074 typedef std::integral_constant<bool, value> type;
0075 };
0076
0077
0078 #if defined(BOOST_WINDOWS_API)
0079
0080 #if defined(BOOST_NO_ANSI_APIS)
0081 template<bool has_wchar>
0082 struct required_char_type
0083 {
0084 typedef wchar_t type;
0085 };
0086 #else
0087 template<bool has_wchar> struct required_char_type;
0088 template<> struct required_char_type<true>
0089 {
0090 typedef wchar_t type;
0091 };
0092 template<> struct required_char_type<false>
0093 {
0094 typedef char type;
0095 };
0096 #endif
0097
0098 #elif defined(BOOST_POSIX_API)
0099 template<bool has_wchar>
0100 struct required_char_type
0101 {
0102 typedef char type;
0103 };
0104 #endif
0105
0106 template<typename ... Args>
0107 using required_char_type_t = typename required_char_type<
0108 has_wchar<Args...>::value>::type;
0109
0110
0111 template<typename Iterator, typename End, typename ...Args>
0112 struct make_builders_from_view
0113 {
0114 typedef boost::fusion::set<Args...> set;
0115 typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type;
0116 typedef typename std::remove_reference<ref_type>::type res_type;
0117 typedef typename initializer_tag<res_type>::type tag;
0118 typedef typename initializer_builder<tag>::type builder_type;
0119 typedef typename boost::fusion::result_of::has_key<set, builder_type> has_key;
0120
0121 typedef typename boost::fusion::result_of::next<Iterator>::type next_itr;
0122 typedef typename make_builders_from_view<next_itr, End>::type next;
0123
0124 typedef typename
0125 std::conditional<has_key::value,
0126 typename make_builders_from_view<next_itr, End, Args...>::type,
0127 typename make_builders_from_view<next_itr, End, Args..., builder_type>::type
0128 >::type type;
0129
0130 };
0131
0132 template<typename Iterator, typename ...Args>
0133 struct make_builders_from_view<Iterator, Iterator, Args...>
0134 {
0135 typedef boost::fusion::set<Args...> type;
0136 };
0137
0138 template<typename Builders>
0139 struct builder_ref
0140 {
0141 Builders &builders;
0142 builder_ref(Builders & builders) : builders(builders) {};
0143
0144 template<typename T>
0145 void operator()(T && value) const
0146 {
0147 typedef typename initializer_tag<typename std::remove_reference<T>::type>::type tag;
0148 typedef typename initializer_builder<tag>::type builder_type;
0149 boost::fusion::at_key<builder_type>(builders)(std::forward<T>(value));
0150 }
0151 };
0152
0153 template<typename T>
0154 struct get_initializers_result
0155 {
0156 typedef typename T::result_type type;
0157 };
0158
0159 template<>
0160 struct get_initializers_result<boost::fusion::void_>
0161 {
0162 typedef boost::fusion::void_ type;
0163 };
0164
0165 template<typename ...Args>
0166 struct helper_vector
0167 {
0168
0169 };
0170
0171 template<typename T, typename ...Stack>
0172 struct invoke_get_initializer_collect_keys;
0173
0174 template<typename ...Stack>
0175 struct invoke_get_initializer_collect_keys<boost::fusion::vector<>, Stack...>
0176 {
0177 typedef helper_vector<Stack...> type;
0178 };
0179
0180
0181 template<typename First, typename ...Args, typename ...Stack>
0182 struct invoke_get_initializer_collect_keys<boost::fusion::vector<First, Args...>, Stack...>
0183 {
0184 typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>, Stack..., First>::type next;
0185 typedef helper_vector<Stack...> stack_t;
0186
0187 typedef typename std::conditional<std::is_same<boost::fusion::void_, First>::value,
0188 stack_t, next>::type type;
0189
0190
0191 };
0192
0193
0194 template<typename Keys>
0195 struct invoke_get_initializer;
0196
0197 template<typename ...Args>
0198 struct invoke_get_initializer<helper_vector<Args...>>
0199
0200 {
0201 typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> result_type;
0202
0203 template<typename Sequence>
0204 static result_type call(Sequence & seq)
0205 {
0206 return result_type(boost::fusion::at_key<Args>(seq).get_initializer()...);;
0207 }
0208 };
0209
0210
0211
0212
0213
0214 template<typename ...Args>
0215 inline boost::fusion::tuple<typename get_initializers_result<Args>::type...>
0216 get_initializers(boost::fusion::set<Args...> & builders)
0217 {
0218
0219 typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>>::type keys;
0220 return invoke_get_initializer<keys>::call(builders);
0221 }
0222
0223
0224 template<typename Char, typename ... Args>
0225 inline child basic_execute_impl(Args && ... args)
0226 {
0227
0228 boost::fusion::tuple<typename std::remove_reference<Args>::type&...> tup(args...);
0229
0230 auto inits = boost::fusion::filter_if<
0231 boost::process::detail::is_initializer<
0232 typename std::remove_reference<
0233 boost::mpl::_
0234 >::type
0235 >
0236 >(tup);
0237
0238 auto others = boost::fusion::filter_if<
0239 boost::mpl::not_<
0240 boost::process::detail::is_initializer<
0241 typename std::remove_reference<
0242 boost::mpl::_
0243 >::type
0244 >
0245 >
0246 >(tup);
0247
0248
0249
0250
0251 typedef typename boost::fusion::result_of::as_vector<decltype(others)>::type others_t;
0252
0253 typedef typename ::boost::process::detail::make_builders_from_view<
0254 typename boost::fusion::result_of::begin<others_t>::type,
0255 typename boost::fusion::result_of::end <others_t>::type>::type builder_t;
0256
0257 builder_t builders;
0258 ::boost::process::detail::builder_ref<builder_t> builder_ref(builders);
0259
0260 boost::fusion::for_each(others, builder_ref);
0261 auto other_inits = ::boost::process::detail::get_initializers(builders);
0262
0263
0264 boost::fusion::joint_view<decltype(other_inits), decltype(inits)> complete_inits(other_inits, inits);
0265
0266 auto exec = boost::process::detail::api::make_executor<Char>(complete_inits);
0267 return exec();
0268 }
0269
0270 template<typename ...Args>
0271 inline child execute_impl(Args&& ... args)
0272 {
0273 typedef required_char_type_t<Args...> req_char_type;
0274
0275 return basic_execute_impl<req_char_type>(
0276 boost::process::detail::char_converter_t<req_char_type, Args>::conv(
0277 std::forward<Args>(args))...
0278 );
0279 }
0280
0281 }}}
0282
0283
0284 #endif