1 /*
2  *          Copyright Andrey Semashev 2007 - 2015.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   text_ostream_backend.cpp
9  * \author Andrey Semashev
10  * \date   19.04.2007
11  *
12  * \brief  This header is the Boost.Log library implementation, see the library documentation
13  *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14  */
15 
16 #include <vector>
17 #include <algorithm>
18 #include <boost/log/sinks/text_ostream_backend.hpp>
19 #include <boost/log/detail/header.hpp>
20 
21 namespace boost {
22 
23 BOOST_LOG_OPEN_NAMESPACE
24 
25 namespace sinks {
26 
27 //! Sink implementation
28 template< typename CharT >
29 struct basic_text_ostream_backend< CharT >::implementation
30 {
31     //! Type of the container that holds all aggregated streams
32     typedef std::vector< shared_ptr< stream_type > > ostream_sequence;
33 
34     //! Output stream list
35     ostream_sequence m_Streams;
36     //! Auto-flush flag
37     bool m_fAutoFlush;
38 
implementationboost::sinks::basic_text_ostream_backend::implementation39     implementation() : m_fAutoFlush(false)
40     {
41     }
42 };
43 
44 
45 //! Constructor
46 template< typename CharT >
basic_text_ostream_backend()47 BOOST_LOG_API basic_text_ostream_backend< CharT >::basic_text_ostream_backend() : m_pImpl(new implementation())
48 {
49 }
50 
51 //! Destructor (just to make it link from the shared library)
52 template< typename CharT >
~basic_text_ostream_backend()53 BOOST_LOG_API basic_text_ostream_backend< CharT >::~basic_text_ostream_backend()
54 {
55     delete m_pImpl;
56 }
57 
58 //! The method adds a new stream to the sink
59 template< typename CharT >
add_stream(shared_ptr<stream_type> const & strm)60 BOOST_LOG_API void basic_text_ostream_backend< CharT >::add_stream(shared_ptr< stream_type > const& strm)
61 {
62     typename implementation::ostream_sequence::iterator it =
63         std::find(m_pImpl->m_Streams.begin(), m_pImpl->m_Streams.end(), strm);
64     if (it == m_pImpl->m_Streams.end())
65     {
66         m_pImpl->m_Streams.push_back(strm);
67     }
68 }
69 
70 //! The method removes a stream from the sink
71 template< typename CharT >
remove_stream(shared_ptr<stream_type> const & strm)72 BOOST_LOG_API void basic_text_ostream_backend< CharT >::remove_stream(shared_ptr< stream_type > const& strm)
73 {
74     typename implementation::ostream_sequence::iterator it =
75         std::find(m_pImpl->m_Streams.begin(), m_pImpl->m_Streams.end(), strm);
76     if (it != m_pImpl->m_Streams.end())
77         m_pImpl->m_Streams.erase(it);
78 }
79 
80 //! Sets the flag to automatically flush buffers after each logged line
81 template< typename CharT >
auto_flush(bool f)82 BOOST_LOG_API void basic_text_ostream_backend< CharT >::auto_flush(bool f)
83 {
84     m_pImpl->m_fAutoFlush = f;
85 }
86 
87 //! The method writes the message to the sink
88 template< typename CharT >
consume(record_view const &,string_type const & message)89 BOOST_LOG_API void basic_text_ostream_backend< CharT >::consume(record_view const&, string_type const& message)
90 {
91     typename string_type::const_pointer const p = message.data();
92     typename string_type::size_type const s = message.size();
93     typename implementation::ostream_sequence::const_iterator
94         it = m_pImpl->m_Streams.begin(), end = m_pImpl->m_Streams.end();
95     for (; it != end; ++it)
96     {
97         stream_type* const strm = it->get();
98         if (strm->good())
99         {
100             strm->write(p, static_cast< std::streamsize >(s));
101             strm->put(static_cast< char_type >('\n'));
102 
103             if (m_pImpl->m_fAutoFlush)
104                 strm->flush();
105         }
106     }
107 }
108 
109 //! The method flushes the associated streams
110 template< typename CharT >
flush()111 BOOST_LOG_API void basic_text_ostream_backend< CharT >::flush()
112 {
113     typename implementation::ostream_sequence::const_iterator
114         it = m_pImpl->m_Streams.begin(), end = m_pImpl->m_Streams.end();
115     for (; it != end; ++it)
116     {
117         stream_type* const strm = it->get();
118         if (strm->good())
119             strm->flush();
120     }
121 }
122 
123 //! Explicitly instantiate sink backend implementation
124 #ifdef BOOST_LOG_USE_CHAR
125 template class basic_text_ostream_backend< char >;
126 #endif
127 #ifdef BOOST_LOG_USE_WCHAR_T
128 template class basic_text_ostream_backend< wchar_t >;
129 #endif
130 
131 } // namespace sinks
132 
133 BOOST_LOG_CLOSE_NAMESPACE // namespace log
134 
135 } // namespace boost
136 
137 #include <boost/log/detail/footer.hpp>
138