Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:27

0001 /*
0002  *             Copyright Andrey Semashev 2020.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          https://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   utility/manipulators/tuple.hpp
0009  * \author Andrey Semashev
0010  * \date   11.05.2020
0011  *
0012  * The header contains implementation of a stream manipulator for inserting a tuple or any heterogeneous sequence of elements, optionally separated with a delimiter.
0013  */
0014 
0015 #ifndef BOOST_LOG_UTILITY_MANIPULATORS_TUPLE_HPP_INCLUDED_
0016 #define BOOST_LOG_UTILITY_MANIPULATORS_TUPLE_HPP_INCLUDED_
0017 
0018 #include <cstddef>
0019 #include <boost/core/enable_if.hpp>
0020 #include <boost/type_traits/is_scalar.hpp>
0021 #include <boost/type_traits/conditional.hpp>
0022 #include <boost/type_traits/integral_constant.hpp>
0023 #include <boost/fusion/include/fold.hpp>
0024 #include <boost/fusion/include/for_each.hpp>
0025 #include <boost/log/detail/config.hpp>
0026 #include <boost/log/detail/is_ostream.hpp>
0027 #include <boost/log/detail/header.hpp>
0028 
0029 #ifdef BOOST_HAS_PRAGMA_ONCE
0030 #pragma once
0031 #endif
0032 
0033 namespace boost {
0034 
0035 BOOST_LOG_OPEN_NAMESPACE
0036 
0037 /*!
0038  * Stream manipulator for inserting a heterogeneous sequence of elements, optionally separated with a delimiter.
0039  */
0040 template< typename TupleT, typename DelimiterT >
0041 class tuple_manipulator
0042 {
0043 private:
0044     typedef typename conditional<
0045         is_scalar< DelimiterT >::value,
0046         DelimiterT,
0047         DelimiterT const&
0048     >::type stored_delimiter_type;
0049 
0050     template< typename StreamT >
0051     struct output_visitor
0052     {
0053         typedef boost::true_type result_type;
0054 
0055         output_visitor(StreamT& stream, stored_delimiter_type delimiter) BOOST_NOEXCEPT :
0056             m_stream(stream),
0057             m_delimiter(delimiter)
0058         {
0059         }
0060 
0061         template< typename T >
0062         result_type operator() (boost::true_type, T const& elem) const
0063         {
0064             m_stream << m_delimiter;
0065             return operator()(boost::false_type(), elem);
0066         }
0067 
0068         template< typename T >
0069         result_type operator() (boost::false_type, T const& elem) const
0070         {
0071             m_stream << elem;
0072             return result_type();
0073         }
0074 
0075     private:
0076         StreamT& m_stream;
0077         stored_delimiter_type m_delimiter;
0078     };
0079 
0080 private:
0081     TupleT const& m_tuple;
0082     stored_delimiter_type m_delimiter;
0083 
0084 public:
0085     //! Initializing constructor
0086     tuple_manipulator(TupleT const& tuple, stored_delimiter_type delimiter) BOOST_NOEXCEPT :
0087         m_tuple(tuple),
0088         m_delimiter(delimiter)
0089     {
0090     }
0091 
0092     //! The method outputs elements of the sequence separated with delimiter
0093     template< typename StreamT >
0094     void output(StreamT& stream) const
0095     {
0096         boost::fusion::fold(m_tuple, boost::false_type(), output_visitor< StreamT >(stream, m_delimiter));
0097     }
0098 };
0099 
0100 /*!
0101  * Stream manipulator for inserting a heterogeneous sequence of elements. Specialization for when there is no delimiter.
0102  */
0103 template< typename TupleT >
0104 class tuple_manipulator< TupleT, void >
0105 {
0106 private:
0107     template< typename StreamT >
0108     struct output_visitor
0109     {
0110         typedef void result_type;
0111 
0112         explicit output_visitor(StreamT& stream) BOOST_NOEXCEPT :
0113             m_stream(stream)
0114         {
0115         }
0116 
0117         template< typename T >
0118         result_type operator() (T const& elem) const
0119         {
0120             m_stream << elem;
0121         }
0122 
0123     private:
0124         StreamT& m_stream;
0125     };
0126 
0127 private:
0128     TupleT const& m_tuple;
0129 
0130 public:
0131     //! Initializing constructor
0132     explicit tuple_manipulator(TupleT const& tuple) BOOST_NOEXCEPT :
0133         m_tuple(tuple)
0134     {
0135     }
0136 
0137     //! The method outputs elements of the sequence
0138     template< typename StreamT >
0139     void output(StreamT& stream) const
0140     {
0141         boost::fusion::for_each(m_tuple, output_visitor< StreamT >(stream));
0142     }
0143 };
0144 
0145 /*!
0146  * Stream output operator for \c tuple_manipulator. Outputs every element of the sequence, separated with a delimiter, if one was specified on manipulator construction.
0147  */
0148 template< typename StreamT, typename TupleT, typename DelimiterT >
0149 inline typename boost::enable_if_c< log::aux::is_ostream< StreamT >::value, StreamT& >::type operator<< (StreamT& strm, tuple_manipulator< TupleT, DelimiterT > const& manip)
0150 {
0151     if (BOOST_LIKELY(strm.good()))
0152         manip.output(strm);
0153 
0154     return strm;
0155 }
0156 
0157 /*!
0158  * Tuple manipulator generator function.
0159  *
0160  * \param tuple Heterogeneous sequence of elements to output. The sequence must be supported by Boost.Fusion, and its elements must support stream output.
0161  * \param delimiter Delimiter to separate elements in the output. Optional. If not specified, elements are output without separation.
0162  * \returns Manipulator to be inserted into the stream.
0163  *
0164  * \note Both \a tuple and \a delimiter objects must outlive the created manipulator object.
0165  */
0166 template< typename TupleT, typename DelimiterT >
0167 inline typename boost::enable_if_c<
0168     is_scalar< DelimiterT >::value,
0169     tuple_manipulator< TupleT, DelimiterT >
0170 >::type tuple_manip(TupleT const& tuple, DelimiterT delimiter) BOOST_NOEXCEPT
0171 {
0172     return tuple_manipulator< TupleT, DelimiterT >(tuple, delimiter);
0173 }
0174 
0175 /*!
0176  * Tuple manipulator generator function.
0177  *
0178  * \param tuple Heterogeneous sequence of elements to output. The sequence must be supported by Boost.Fusion, and its elements must support stream output.
0179  * \param delimiter Delimiter to separate elements in the output. Optional. If not specified, elements are output without separation.
0180  * \returns Manipulator to be inserted into the stream.
0181  *
0182  * \note Both \a tuple and \a delimiter objects must outlive the created manipulator object.
0183  */
0184 template< typename TupleT, typename DelimiterT >
0185 inline typename boost::disable_if_c<
0186     is_scalar< DelimiterT >::value,
0187     tuple_manipulator< TupleT, DelimiterT >
0188 >::type tuple_manip(TupleT const& tuple, DelimiterT const& delimiter) BOOST_NOEXCEPT
0189 {
0190     return tuple_manipulator< TupleT, DelimiterT >(tuple, delimiter);
0191 }
0192 
0193 /*!
0194  * Tuple manipulator generator function.
0195  *
0196  * \param tuple Heterogeneous sequence of elements to output. The sequence must be supported by Boost.Fusion, and its elements must support stream output.
0197  * \param delimiter Delimiter to separate elements in the output. Optional. If not specified, elements are output without separation.
0198  * \returns Manipulator to be inserted into the stream.
0199  *
0200  * \note Both \a tuple and \a delimiter objects must outlive the created manipulator object.
0201  */
0202 template< typename TupleT, typename DelimiterElementT, std::size_t N >
0203 inline tuple_manipulator< TupleT, DelimiterElementT* > tuple_manip(TupleT const& tuple, DelimiterElementT (&delimiter)[N]) BOOST_NOEXCEPT
0204 {
0205     return tuple_manipulator< TupleT, DelimiterElementT* >(tuple, delimiter);
0206 }
0207 
0208 /*!
0209  * Tuple manipulator generator function.
0210  *
0211  * \param tuple Heterogeneous sequence of elements to output. The sequence must be supported by Boost.Fusion, and its elements must support stream output.
0212  * \returns Manipulator to be inserted into the stream.
0213  *
0214  * \note \a tuple object must outlive the created manipulator object.
0215  */
0216 template< typename TupleT >
0217 inline tuple_manipulator< TupleT, void > tuple_manip(TupleT const& tuple) BOOST_NOEXCEPT
0218 {
0219     return tuple_manipulator< TupleT, void >(tuple);
0220 }
0221 
0222 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0223 
0224 } // namespace boost
0225 
0226 #include <boost/log/detail/footer.hpp>
0227 
0228 #endif // BOOST_LOG_UTILITY_MANIPULATORS_TUPLE_HPP_INCLUDED_