diff options
Diffstat (limited to 'boost/process/error.hpp')
-rw-r--r-- | boost/process/error.hpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/boost/process/error.hpp b/boost/process/error.hpp new file mode 100644 index 0000000000..f70cce6c83 --- /dev/null +++ b/boost/process/error.hpp @@ -0,0 +1,211 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// 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_ERROR_HPP +#define BOOST_PROCESS_DETAIL_ERROR_HPP + +#include <boost/process/detail/config.hpp> +#include <boost/process/detail/traits.hpp> + + +#if defined(BOOST_POSIX_API) +#include <boost/process/detail/posix/handler.hpp> +#elif defined(BOOST_WINDOWS_API) +#include <boost/process/detail/windows/handler.hpp> +#endif + +#include <system_error> + +#include <type_traits> +#include <boost/fusion/algorithm/query/find_if.hpp> +#include <boost/fusion/sequence/intrinsic/begin.hpp> +#include <boost/fusion/sequence/intrinsic/end.hpp> +#include <boost/fusion/container/vector/convert.hpp> +#include <boost/fusion/iterator/deref.hpp> +#include <boost/fusion/sequence/comparison/equal_to.hpp> +#include <boost/fusion/container/set/convert.hpp> +#include <boost/type_index.hpp> + +/** \file boost/process/error.hpp + * + * Header which provides the error properties. It allows to explicitly set the error handling, the properties are: + * +\xmlonly +<programlisting> +namespace boost { + namespace process { + <emphasis>unspecified</emphasis> <globalname alt="boost::process::ignore_error">ignore_error</globalname>; + <emphasis>unspecified</emphasis> <globalname alt="boost::process::throw_on_error">throw_on_error</globalname>; + <emphasis>unspecified</emphasis> <globalname alt="boost::process::error">error</globalname>; + <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_ref">error_ref</globalname>; + <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_code">error_code</globalname>; + } +} +</programlisting> +\endxmlonly + * For error there are two aliases: error_ref and error_code + */ + +namespace boost { namespace process { + +namespace detail { + +struct throw_on_error_ : ::boost::process::detail::api::handler_base_ext +{ + constexpr throw_on_error_() {}; + + template <class Executor> + void on_error(Executor&, const std::error_code & ec) const + { + throw process_error(ec, "process creation failed"); + } + + const throw_on_error_ &operator()() const {return *this;} +}; + +struct ignore_error_ : ::boost::process::detail::api::handler_base_ext +{ + constexpr ignore_error_() {}; +}; + +struct set_on_error : ::boost::process::detail::api::handler_base_ext +{ + set_on_error(const set_on_error&) = default; + explicit set_on_error(std::error_code &ec) : ec_(ec) {} + + template <class Executor> + void on_error(Executor&, const std::error_code & ec) const + { + ec_ = ec; + } + +private: + std::error_code &ec_; +}; + +struct error_ +{ + constexpr error_() {} + set_on_error operator()(std::error_code &ec) const {return set_on_error(ec);} + set_on_error operator= (std::error_code &ec) const {return set_on_error(ec);} + +}; + + +template<typename T> +struct is_error_handler : std::false_type {}; + +template<> struct is_error_handler<set_on_error> : std::true_type {}; +template<> struct is_error_handler<throw_on_error_> : std::true_type {}; +template<> struct is_error_handler<ignore_error_> : std::true_type {}; + + + +template<typename Iterator, typename End> +struct has_error_handler_impl +{ + typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type; + typedef typename std::remove_reference<ref_type>::type res_type_; + typedef typename std::remove_cv<res_type_>::type res_type; + typedef typename is_error_handler<res_type>::type cond; + + typedef typename boost::fusion::result_of::next<Iterator>::type next_itr; + typedef typename has_error_handler_impl<next_itr, End>::type next; + + typedef typename boost::mpl::or_<cond, next>::type type; +}; + +template<typename Iterator> +struct has_error_handler_impl<Iterator, Iterator> +{ + typedef boost::mpl::false_ type; +}; + + +template<typename Sequence> +struct has_error_handler +{ + typedef typename boost::fusion::result_of::as_vector<Sequence>::type vector_type; + + typedef typename has_error_handler_impl< + typename boost::fusion::result_of::begin<vector_type>::type, + typename boost::fusion::result_of::end< vector_type>::type + >::type type; +}; + +template<typename Sequence> +struct has_ignore_error +{ + typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type; + typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_>::type type1; + typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_&>::type type2; + typedef typename boost::fusion::result_of::has_key<set_type, const ignore_error_&>::type type3; + typedef typename boost::mpl::or_<type1,type2, type3>::type type; +}; + +struct error_builder +{ + std::error_code *err; + typedef set_on_error result_type; + set_on_error get_initializer() {return set_on_error(*err);}; + void operator()(std::error_code & ec) {err = &ec;}; +}; + +template<> +struct initializer_tag<std::error_code> +{ + typedef error_tag type; +}; + + +template<> +struct initializer_builder<error_tag> +{ + typedef error_builder type; +}; + +} +/**The ignore_error property will disable any error handling. This can be useful +on linux, where error handling will require a pipe.*/ +constexpr boost::process::detail::ignore_error_ ignore_error; +/**The throw_on_error property will enable the exception when launching a process. +It is unnecessary by default, but may be used, when an additional error_code is provided.*/ +constexpr boost::process::detail::throw_on_error_ throw_on_error; +/** +The error property will set the executor to handle any errors by setting an +[std::error_code](http://en.cppreference.com/w/cpp/error/error_code). + +\code{.cpp} +std::error_code ec; +system("gcc", error(ec)); +\endcode + +The following syntax is valid: + +\code{.cpp} +error(ec); +error=ec; +\endcode + +The overload version is achieved by just passing an object of + [std::error_code](http://en.cppreference.com/w/cpp/error/error_code) to the function. + + + */ +constexpr boost::process::detail::error_ error; +///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly . +constexpr boost::process::detail::error_ error_ref; +///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly . +constexpr boost::process::detail::error_ error_code; + + +}} + +#endif |