Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   record_ostream.hpp
0009  * \author Andrey Semashev
0010  * \date   09.03.2009
0011  *
0012  * This header contains a wrapper class around a logging record that allows to compose the
0013  * record message with a streaming expression.
0014  */
0015 
0016 #ifndef BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
0017 #define BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
0018 
0019 #include <string>
0020 #include <iosfwd>
0021 #include <ostream>
0022 #include <boost/assert.hpp>
0023 #include <boost/move/core.hpp>
0024 #include <boost/move/utility_core.hpp>
0025 #include <boost/type_traits/is_enum.hpp>
0026 #include <boost/type_traits/is_scalar.hpp>
0027 #include <boost/type_traits/remove_cv.hpp>
0028 #include <boost/core/addressof.hpp>
0029 #include <boost/core/enable_if.hpp>
0030 #include <boost/core/explicit_operator_bool.hpp>
0031 #include <boost/core/uncaught_exceptions.hpp>
0032 #include <boost/log/detail/config.hpp>
0033 #include <boost/log/detail/native_typeof.hpp>
0034 #include <boost/log/core/record.hpp>
0035 #include <boost/log/utility/unique_identifier_name.hpp>
0036 #include <boost/log/utility/formatting_ostream.hpp>
0037 #include <boost/log/detail/header.hpp>
0038 
0039 #ifdef BOOST_HAS_PRAGMA_ONCE
0040 #pragma once
0041 #endif
0042 
0043 namespace boost {
0044 
0045 BOOST_LOG_OPEN_NAMESPACE
0046 
0047 template< typename CharT >
0048 class basic_record_ostream;
0049 
0050 namespace aux {
0051 
0052 template< typename StreamT, typename T, bool ByValueV, typename R >
0053 struct enable_record_ostream_generic_operator {};
0054 
0055 template< typename CharT, typename T, typename R >
0056 struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, false, R > :
0057     public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
0058 {
0059 };
0060 
0061 template< typename CharT, typename T, typename R >
0062 struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, true, R > :
0063     public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
0064 {
0065 };
0066 
0067 template< typename CharT, typename T, typename R >
0068 struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T*, true, R > :
0069     public disable_if_streamable_char_type< typename boost::remove_cv< T >::type, R >
0070 {
0071 };
0072 
0073 } // namespace aux
0074 
0075 /*!
0076  * \brief Logging record adapter with a streaming capability
0077  *
0078  * This class allows to compose the logging record message by streaming operations. It
0079  * aggregates the log record and provides the standard output stream interface.
0080  */
0081 template< typename CharT >
0082 class basic_record_ostream :
0083     public basic_formatting_ostream< CharT >
0084 {
0085     //! Self type
0086     typedef basic_record_ostream< CharT > this_type;
0087     //! Base stream class
0088     typedef basic_formatting_ostream< CharT > base_type;
0089 
0090 public:
0091     //! Character type
0092     typedef CharT char_type;
0093     //! String type to be used as a message text holder
0094     typedef std::basic_string< char_type > string_type;
0095     //! Stream type
0096     typedef std::basic_ostream< char_type > stream_type;
0097     //! Character traits
0098     typedef typename base_type::traits_type traits_type;
0099 
0100 private:
0101     //! Log record
0102     record* m_record;
0103 
0104 public:
0105     /*!
0106      * Default constructor. Creates an empty record that is equivalent to the invalid record handle.
0107      * The stream capability is not available after construction.
0108      *
0109      * \post <tt>!*this == true</tt>
0110      */
0111     basic_record_ostream() BOOST_NOEXCEPT : m_record(NULL) {}
0112 
0113     /*!
0114      * Constructor from a record object. Attaches to the provided record.
0115      *
0116      * \pre <tt>!!rec == true</tt>
0117      * \post <tt>&this->get_record() == &rec</tt>
0118      * \param rec The record handle being attached to
0119      */
0120     explicit basic_record_ostream(record& rec)
0121     {
0122         BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
0123         m_record = &rec;
0124         init_stream();
0125     }
0126 
0127     /*!
0128      * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
0129      */
0130     ~basic_record_ostream() BOOST_NOEXCEPT
0131     {
0132         detach_from_record();
0133     }
0134 
0135     /*!
0136      * Conversion to an unspecified boolean type
0137      *
0138      * \return \c true, if stream is valid and ready for formatting, \c false, if the stream is not valid. The latter also applies to
0139      *         the case when the stream is not attached to a log record.
0140      */
0141     BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
0142 
0143     /*!
0144      * Inverted conversion to an unspecified boolean type
0145      *
0146      * \return \c false, if stream is valid and ready for formatting, \c true, if the stream is not valid. The latter also applies to
0147      *         the case when the stream is not attached to a log record.
0148      */
0149     bool operator! () const BOOST_NOEXCEPT
0150     {
0151         return (!m_record || base_type::fail());
0152     }
0153 
0154     /*!
0155      * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
0156      *
0157      * \return The aggregated record object
0158      */
0159     record& get_record()
0160     {
0161         BOOST_ASSERT(m_record != NULL);
0162         this->flush();
0163         return *m_record;
0164     }
0165 
0166     /*!
0167      * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
0168      *
0169      * \return The aggregated record object
0170      */
0171     record const& get_record() const
0172     {
0173         BOOST_ASSERT(m_record != NULL);
0174         const_cast< this_type* >(this)->flush();
0175         return *m_record;
0176     }
0177 
0178     /*!
0179      * If the stream is attached to a log record, flushes internal buffers to complete all pending formatting operations.
0180      * Then reattaches the stream to another log record.
0181      *
0182      * \param rec New log record to attach to
0183      */
0184     void attach_record(record& rec)
0185     {
0186         BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
0187         detach_from_record();
0188         m_record = &rec;
0189         init_stream();
0190     }
0191 
0192     //! The function resets the stream into a detached (default initialized) state
0193     BOOST_LOG_API void detach_from_record() BOOST_NOEXCEPT;
0194 
0195     basic_record_ostream& operator<< (typename base_type::ios_base_manip manip)
0196     {
0197         static_cast< base_type& >(*this) << manip;
0198         return *this;
0199     }
0200     basic_record_ostream& operator<< (typename base_type::basic_ios_manip manip)
0201     {
0202         static_cast< base_type& >(*this) << manip;
0203         return *this;
0204     }
0205     basic_record_ostream& operator<< (typename base_type::stream_manip manip)
0206     {
0207         static_cast< base_type& >(*this) << manip;
0208         return *this;
0209     }
0210 
0211     basic_record_ostream& operator<< (char c)
0212     {
0213         static_cast< base_type& >(*this) << c;
0214         return *this;
0215     }
0216     basic_record_ostream& operator<< (const char* p)
0217     {
0218         static_cast< base_type& >(*this) << p;
0219         return *this;
0220     }
0221 
0222     // When no native character type is supported, the following overloads are disabled as they have ambiguous meaning.
0223     // Use basic_string_view or basic_string to explicitly indicate that the data is a string.
0224 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
0225     basic_record_ostream& operator<< (wchar_t c)
0226     {
0227         static_cast< base_type& >(*this) << c;
0228         return *this;
0229     }
0230     basic_record_ostream& operator<< (const wchar_t* p)
0231     {
0232         static_cast< base_type& >(*this) << p;
0233         return *this;
0234     }
0235 #endif
0236 #if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
0237 #if !defined(BOOST_NO_CXX11_CHAR16_T)
0238     basic_record_ostream& operator<< (char16_t c)
0239     {
0240         static_cast< base_type& >(*this) << c;
0241         return *this;
0242     }
0243     basic_record_ostream& operator<< (const char16_t* p)
0244     {
0245         static_cast< base_type& >(*this) << p;
0246         return *this;
0247     }
0248 #endif
0249 #if !defined(BOOST_NO_CXX11_CHAR32_T)
0250     basic_record_ostream& operator<< (char32_t c)
0251     {
0252         static_cast< base_type& >(*this) << c;
0253         return *this;
0254     }
0255     basic_record_ostream& operator<< (const char32_t* p)
0256     {
0257         static_cast< base_type& >(*this) << p;
0258         return *this;
0259     }
0260 #endif
0261 #endif
0262 
0263     basic_record_ostream& operator<< (bool value)
0264     {
0265         static_cast< base_type& >(*this) << value;
0266         return *this;
0267     }
0268     basic_record_ostream& operator<< (signed char value)
0269     {
0270         static_cast< base_type& >(*this) << value;
0271         return *this;
0272     }
0273     basic_record_ostream& operator<< (unsigned char value)
0274     {
0275         static_cast< base_type& >(*this) << value;
0276         return *this;
0277     }
0278     basic_record_ostream& operator<< (short value)
0279     {
0280         static_cast< base_type& >(*this) << value;
0281         return *this;
0282     }
0283     basic_record_ostream& operator<< (unsigned short value)
0284     {
0285         static_cast< base_type& >(*this) << value;
0286         return *this;
0287     }
0288     basic_record_ostream& operator<< (int value)
0289     {
0290         static_cast< base_type& >(*this) << value;
0291         return *this;
0292     }
0293     basic_record_ostream& operator<< (unsigned int value)
0294     {
0295         static_cast< base_type& >(*this) << value;
0296         return *this;
0297     }
0298     basic_record_ostream& operator<< (long value)
0299     {
0300         static_cast< base_type& >(*this) << value;
0301         return *this;
0302     }
0303     basic_record_ostream& operator<< (unsigned long value)
0304     {
0305         static_cast< base_type& >(*this) << value;
0306         return *this;
0307     }
0308 #if !defined(BOOST_NO_LONG_LONG)
0309     basic_record_ostream& operator<< (long long value)
0310     {
0311         static_cast< base_type& >(*this) << value;
0312         return *this;
0313     }
0314     basic_record_ostream& operator<< (unsigned long long value)
0315     {
0316         static_cast< base_type& >(*this) << value;
0317         return *this;
0318     }
0319 #endif
0320 
0321     basic_record_ostream& operator<< (float value)
0322     {
0323         static_cast< base_type& >(*this) << value;
0324         return *this;
0325     }
0326     basic_record_ostream& operator<< (double value)
0327     {
0328         static_cast< base_type& >(*this) << value;
0329         return *this;
0330     }
0331     basic_record_ostream& operator<< (long double value)
0332     {
0333         static_cast< base_type& >(*this) << value;
0334         return *this;
0335     }
0336 
0337     basic_record_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
0338     {
0339         static_cast< base_type& >(*this) << buf;
0340         return *this;
0341     }
0342 
0343 private:
0344     //! The function initializes the stream and the stream buffer
0345     BOOST_LOG_API void init_stream();
0346 
0347     //  Copy and assignment are closed
0348     BOOST_DELETED_FUNCTION(basic_record_ostream(basic_record_ostream const&))
0349     BOOST_DELETED_FUNCTION(basic_record_ostream& operator= (basic_record_ostream const&))
0350 };
0351 
0352 
0353 #ifdef BOOST_LOG_USE_CHAR
0354 typedef basic_record_ostream< char > record_ostream;        //!< Convenience typedef for narrow-character logging
0355 #endif
0356 #ifdef BOOST_LOG_USE_WCHAR_T
0357 typedef basic_record_ostream< wchar_t > wrecord_ostream;    //!< Convenience typedef for wide-character logging
0358 #endif
0359 
0360 // Implementation note: these operators below should be the least attractive for the compiler
0361 // so that user's overloads are chosen, when present. We use function template partial ordering for this purpose.
0362 // We also don't use perfect forwarding for the right hand argument because in ths case the generic overload
0363 // would be more preferred than the typical one written by users:
0364 //
0365 // record_ostream& operator<< (record_ostream& strm, my_type const& arg);
0366 //
0367 // This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required
0368 // if there is a perfect forwarding overload.
0369 template< typename StreamT, typename T >
0370 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, true, StreamT& >::type
0371 operator<< (StreamT& strm, T value)
0372 {
0373     typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
0374     static_cast< formatting_ostream_type& >(strm) << value;
0375     return strm;
0376 }
0377 
0378 template< typename StreamT, typename T >
0379 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
0380 operator<< (StreamT& strm, T const& value)
0381 {
0382     typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
0383     static_cast< formatting_ostream_type& >(strm) << value;
0384     return strm;
0385 }
0386 
0387 template< typename StreamT, typename T >
0388 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
0389 operator<< (StreamT& strm, T& value)
0390 {
0391     typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
0392     static_cast< formatting_ostream_type& >(strm) << value;
0393     return strm;
0394 }
0395 
0396 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0397 
0398 template< typename StreamT, typename T >
0399 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, true, StreamT& >::type
0400 operator<< (StreamT&& strm, T value)
0401 {
0402     typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
0403     static_cast< formatting_ostream_type& >(strm) << value;
0404     return strm;
0405 }
0406 
0407 template< typename StreamT, typename T >
0408 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
0409 operator<< (StreamT&& strm, T const& value)
0410 {
0411     typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
0412     static_cast< formatting_ostream_type& >(strm) << value;
0413     return strm;
0414 }
0415 
0416 template< typename StreamT, typename T >
0417 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
0418 operator<< (StreamT&& strm, T& value)
0419 {
0420     typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
0421     static_cast< formatting_ostream_type& >(strm) << value;
0422     return strm;
0423 }
0424 
0425 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0426 
0427 namespace aux {
0428 
0429 //! Internal class that provides formatting streams for record pumps
0430 template< typename CharT >
0431 struct stream_provider
0432 {
0433     //! Character type
0434     typedef CharT char_type;
0435 
0436     //! Formatting stream compound
0437     struct stream_compound
0438     {
0439         stream_compound* next;
0440 
0441         //! Log record stream adapter
0442         basic_record_ostream< char_type > stream;
0443 
0444         //! Initializing constructor
0445         explicit stream_compound(record& rec) : next(NULL), stream(rec) {}
0446     };
0447 
0448     //! The method returns an allocated stream compound
0449     BOOST_LOG_API static stream_compound* allocate_compound(record& rec);
0450     //! The method releases a compound
0451     BOOST_LOG_API static void release_compound(stream_compound* compound) BOOST_NOEXCEPT;
0452 
0453     //  Non-constructible, non-copyable, non-assignable
0454     BOOST_DELETED_FUNCTION(stream_provider())
0455     BOOST_DELETED_FUNCTION(stream_provider(stream_provider const&))
0456     BOOST_DELETED_FUNCTION(stream_provider& operator= (stream_provider const&))
0457 };
0458 
0459 
0460 /*!
0461  * \brief Logging record pump implementation
0462  *
0463  * The pump is used to format the logging record message text and then
0464  * push it to the logging core. It is constructed on each attempt to write
0465  * a log record and destroyed afterwards.
0466  *
0467  * The pump class template is instantiated on the logger type.
0468  */
0469 template< typename LoggerT >
0470 class record_pump
0471 {
0472     BOOST_MOVABLE_BUT_NOT_COPYABLE(record_pump)
0473 
0474 private:
0475     //! Logger type
0476     typedef LoggerT logger_type;
0477     //! Character type
0478     typedef typename logger_type::char_type char_type;
0479     //! Stream compound provider
0480     typedef stream_provider< char_type > stream_provider_type;
0481     //! Stream compound type
0482     typedef typename stream_provider_type::stream_compound stream_compound;
0483 
0484     //! Stream compound release guard
0485     class auto_release;
0486     friend class auto_release;
0487     class auto_release
0488     {
0489         stream_compound* m_pCompound;
0490 
0491     public:
0492         explicit auto_release(stream_compound* p) BOOST_NOEXCEPT : m_pCompound(p) {}
0493         ~auto_release() BOOST_NOEXCEPT { stream_provider_type::release_compound(m_pCompound); }
0494     };
0495 
0496 protected:
0497     //! A reference to the logger
0498     logger_type* m_pLogger;
0499     //! Stream compound
0500     stream_compound* m_pStreamCompound;
0501     //! Exception state
0502     const unsigned int m_ExceptionCount;
0503 
0504 public:
0505     //! Constructor
0506     explicit record_pump(logger_type& lg, record& rec) :
0507         m_pLogger(boost::addressof(lg)),
0508         m_pStreamCompound(stream_provider_type::allocate_compound(rec)),
0509         m_ExceptionCount(boost::core::uncaught_exceptions())
0510     {
0511     }
0512     //! Move constructor
0513     record_pump(BOOST_RV_REF(record_pump) that) BOOST_NOEXCEPT :
0514         m_pLogger(that.m_pLogger),
0515         m_pStreamCompound(that.m_pStreamCompound),
0516         m_ExceptionCount(that.m_ExceptionCount)
0517     {
0518         that.m_pLogger = 0;
0519         that.m_pStreamCompound = 0;
0520     }
0521     //! Destructor. Pushes the composed message to log.
0522     ~record_pump() BOOST_NOEXCEPT_IF(false)
0523     {
0524         if (m_pLogger)
0525         {
0526             auto_release cleanup(m_pStreamCompound); // destructor doesn't throw
0527             // Only push the record if no exception has been thrown in the streaming expression (if possible)
0528             if (m_ExceptionCount >= boost::core::uncaught_exceptions())
0529                 m_pLogger->push_record(boost::move(m_pStreamCompound->stream.get_record()));
0530         }
0531     }
0532 
0533     //! Returns the stream to be used for message text formatting
0534     basic_record_ostream< char_type >& stream() const BOOST_NOEXCEPT
0535     {
0536         BOOST_ASSERT(m_pStreamCompound != 0);
0537         return m_pStreamCompound->stream;
0538     }
0539 };
0540 
0541 template< typename LoggerT >
0542 BOOST_FORCEINLINE record_pump< LoggerT > make_record_pump(LoggerT& lg, record& rec)
0543 {
0544     return record_pump< LoggerT >(lg, rec);
0545 }
0546 
0547 } // namespace aux
0548 
0549 #ifndef BOOST_LOG_DOXYGEN_PASS
0550 
0551 #define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\
0552     for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\
0553         ::boost::log::aux::make_record_pump((logger), rec_var).stream()
0554 
0555 #define BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, rec_var, params_seq)\
0556     for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\
0557         ::boost::log::aux::make_record_pump((logger), rec_var).stream()
0558 
0559 #endif // BOOST_LOG_DOXYGEN_PASS
0560 
0561 //! The macro writes a record to the log
0562 #define BOOST_LOG_STREAM(logger)\
0563     BOOST_LOG_STREAM_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_))
0564 
0565 //! The macro writes a record to the log and allows to pass additional named arguments to the logger
0566 #define BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)\
0567     BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_), params_seq)
0568 
0569 #ifndef BOOST_LOG_NO_SHORTHAND_NAMES
0570 
0571 //! An equivalent to BOOST_LOG_STREAM(logger)
0572 #define BOOST_LOG(logger) BOOST_LOG_STREAM(logger)
0573 
0574 //! An equivalent to BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
0575 #define BOOST_LOG_WITH_PARAMS(logger, params_seq) BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
0576 
0577 #endif // BOOST_LOG_NO_SHORTHAND_NAMES
0578 
0579 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0580 
0581 } // namespace boost
0582 
0583 #include <boost/log/detail/footer.hpp>
0584 
0585 #endif // BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_