execute_impl.hpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // Copyright (c) 2006, 2007 Julio M. Merino Vidal
  2. // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
  3. // Copyright (c) 2009 Boris Schaeling
  4. // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
  5. // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
  6. // Copyright (c) 2016 Klemens D. Morgenstern
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. /**
  11. * \file boost/process/execute.hpp
  12. *
  13. * Defines a function to execute a program.
  14. */
  15. #ifndef BOOST_PROCESS_EXECUTE_HPP
  16. #define BOOST_PROCESS_EXECUTE_HPP
  17. #include <boost/process/detail/config.hpp>
  18. #include <boost/process/detail/traits.hpp>
  19. #if defined(BOOST_POSIX_API)
  20. #include <boost/process/detail/posix/executor.hpp>
  21. #elif defined(BOOST_WINDOWS_API)
  22. #include <boost/process/detail/windows/executor.hpp>
  23. #endif
  24. #include <boost/process/detail/basic_cmd.hpp>
  25. #include <boost/process/detail/handler.hpp>
  26. #include <boost/fusion/view.hpp>
  27. #include <boost/fusion/container.hpp>
  28. #include <boost/fusion/sequence.hpp>
  29. #include <boost/fusion/tuple.hpp>
  30. #include <boost/fusion/algorithm/transformation/filter_if.hpp>
  31. #include <boost/fusion/adapted/std_tuple.hpp>
  32. #include <boost/fusion/container/vector/convert.hpp>
  33. #include <type_traits>
  34. #include <utility>
  35. namespace boost { namespace process {
  36. class child;
  37. namespace detail {
  38. template<typename ...Args>
  39. struct has_wchar;
  40. template<typename First, typename ...Args>
  41. struct has_wchar<First, Args...>
  42. {
  43. typedef has_wchar<Args...> next;
  44. typedef typename std::remove_cv<
  45. typename std::remove_reference<First>::type>::type res_type;
  46. constexpr static bool my_value = is_wchar_t<res_type>::value;
  47. constexpr static bool value = my_value || next::value;
  48. typedef std::integral_constant<bool, value> type;
  49. };
  50. template<typename First>
  51. struct has_wchar<First>
  52. {
  53. typedef typename std::remove_cv<
  54. typename std::remove_reference<First>::type>::type res_type;
  55. constexpr static bool value = is_wchar_t<res_type>::value;
  56. typedef std::integral_constant<bool, value> type;
  57. };
  58. #if defined(BOOST_WINDOWS_API)
  59. //everything needs to be wchar_t
  60. #if defined(BOOST_NO_ANSI_APIS)
  61. template<bool has_wchar>
  62. struct required_char_type
  63. {
  64. typedef wchar_t type;
  65. };
  66. #else
  67. template<bool has_wchar> struct required_char_type;
  68. template<> struct required_char_type<true>
  69. {
  70. typedef wchar_t type;
  71. };
  72. template<> struct required_char_type<false>
  73. {
  74. typedef char type;
  75. };
  76. #endif
  77. #elif defined(BOOST_POSIX_API)
  78. template<bool has_wchar>
  79. struct required_char_type
  80. {
  81. typedef char type;
  82. };
  83. #endif
  84. template<typename ... Args>
  85. using required_char_type_t = typename required_char_type<
  86. has_wchar<Args...>::value>::type;
  87. template<typename Iterator, typename End, typename ...Args>
  88. struct make_builders_from_view
  89. {
  90. typedef boost::fusion::set<Args...> set;
  91. typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type;
  92. typedef typename std::remove_reference<ref_type>::type res_type;
  93. typedef typename initializer_tag<res_type>::type tag;
  94. typedef typename initializer_builder<tag>::type builder_type;
  95. typedef typename boost::fusion::result_of::has_key<set, builder_type> has_key;
  96. typedef typename boost::fusion::result_of::next<Iterator>::type next_itr;
  97. typedef typename make_builders_from_view<next_itr, End>::type next;
  98. typedef typename
  99. std::conditional<has_key::value,
  100. typename make_builders_from_view<next_itr, End, Args...>::type,
  101. typename make_builders_from_view<next_itr, End, Args..., builder_type>::type
  102. >::type type;
  103. };
  104. template<typename Iterator, typename ...Args>
  105. struct make_builders_from_view<Iterator, Iterator, Args...>
  106. {
  107. typedef boost::fusion::set<Args...> type;
  108. };
  109. template<typename Builders>
  110. struct builder_ref
  111. {
  112. Builders &builders;
  113. builder_ref(Builders & builders) : builders(builders) {};
  114. template<typename T>
  115. void operator()(T && value) const
  116. {
  117. typedef typename initializer_tag<typename std::remove_reference<T>::type>::type tag;
  118. typedef typename initializer_builder<tag>::type builder_type;
  119. boost::fusion::at_key<builder_type>(builders)(std::forward<T>(value));
  120. }
  121. };
  122. template<typename T>
  123. struct get_initializers_result
  124. {
  125. typedef typename T::result_type type;
  126. };
  127. template<>
  128. struct get_initializers_result<boost::fusion::void_>
  129. {
  130. typedef boost::fusion::void_ type;
  131. };
  132. template<typename ...Args>
  133. struct helper_vector
  134. {
  135. };
  136. template<typename T, typename ...Stack>
  137. struct invoke_get_initializer_collect_keys;
  138. template<typename ...Stack>
  139. struct invoke_get_initializer_collect_keys<boost::fusion::vector<>, Stack...>
  140. {
  141. typedef helper_vector<Stack...> type;
  142. };
  143. template<typename First, typename ...Args, typename ...Stack>
  144. struct invoke_get_initializer_collect_keys<boost::fusion::vector<First, Args...>, Stack...>
  145. {
  146. typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>, Stack..., First>::type next;
  147. typedef helper_vector<Stack...> stack_t;
  148. typedef typename std::conditional<std::is_same<boost::fusion::void_, First>::value,
  149. stack_t, next>::type type;
  150. };
  151. template<typename Keys>
  152. struct invoke_get_initializer;
  153. template<typename ...Args>
  154. struct invoke_get_initializer<helper_vector<Args...>>
  155. {
  156. typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> result_type;
  157. template<typename Sequence>
  158. static result_type call(Sequence & seq)
  159. {
  160. return result_type(boost::fusion::at_key<Args>(seq).get_initializer()...);;
  161. }
  162. };
  163. template<typename ...Args>
  164. inline boost::fusion::tuple<typename get_initializers_result<Args>::type...>
  165. get_initializers(boost::fusion::set<Args...> & builders)
  166. {
  167. //typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> return_type;
  168. typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>>::type keys;
  169. return invoke_get_initializer<keys>::call(builders);
  170. }
  171. template<typename Char, typename ... Args>
  172. inline child basic_execute_impl(Args && ... args)
  173. {
  174. //create a tuple from the argument list
  175. boost::fusion::tuple<typename std::remove_reference<Args>::type&...> tup(args...);
  176. auto inits = boost::fusion::filter_if<
  177. boost::process::detail::is_initializer<
  178. typename std::remove_reference<
  179. boost::mpl::_
  180. >::type
  181. >
  182. >(tup);
  183. auto others = boost::fusion::filter_if<
  184. boost::mpl::not_<
  185. boost::process::detail::is_initializer<
  186. typename std::remove_reference<
  187. boost::mpl::_
  188. >::type
  189. >
  190. >
  191. >(tup);
  192. // typename detail::make_builders_from_view<decltype(others)>::type builders;
  193. //typedef typename boost::fusion::result_of::as_vector<decltype(inits)>::type inits_t;
  194. typedef typename boost::fusion::result_of::as_vector<decltype(others)>::type others_t;
  195. // typedef decltype(others) others_t;
  196. typedef typename ::boost::process::detail::make_builders_from_view<
  197. typename boost::fusion::result_of::begin<others_t>::type,
  198. typename boost::fusion::result_of::end <others_t>::type>::type builder_t;
  199. builder_t builders;
  200. ::boost::process::detail::builder_ref<builder_t> builder_ref(builders);
  201. boost::fusion::for_each(others, builder_ref);
  202. auto other_inits = ::boost::process::detail::get_initializers(builders);
  203. boost::fusion::joint_view<decltype(other_inits), decltype(inits)> complete_inits(other_inits, inits);
  204. auto exec = boost::process::detail::api::make_executor<Char>(complete_inits);
  205. return exec();
  206. }
  207. template<typename ...Args>
  208. inline child execute_impl(Args&& ... args)
  209. {
  210. typedef required_char_type_t<Args...> req_char_type;
  211. return basic_execute_impl<req_char_type>(
  212. boost::process::detail::char_converter_t<req_char_type, Args>::conv(
  213. std::forward<Args>(args))...
  214. );
  215. }
  216. }}}
  217. #endif