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 <boost/log/detail/config.hpp>
17 #include <vector>
18 #include <algorithm>
19 #include <boost/log/detail/parameter_tools.hpp>
20 #include <boost/log/sinks/auto_newline_mode.hpp>
21 #include <boost/log/sinks/text_ostream_backend.hpp>
22 #include <boost/log/detail/header.hpp>
23 
24 namespace boost {
25 
26 BOOST_LOG_OPEN_NAMESPACE
27 
28 namespace sinks {
29 
30 //! Sink implementation
31 template< typename CharT >
32 struct basic_text_ostream_backend< CharT >::implementation
33 {
34     //! Type of the container that holds all aggregated streams
35     typedef std::vector< shared_ptr< stream_type > > ostream_sequence;
36 
37     //! Output stream list
38     ostream_sequence m_Streams;
39     //! Indicates whether to append a trailing newline after every log record
40     auto_newline_mode m_AutoNewlineMode;
41     //! Auto-flush flag
42     bool m_fAutoFlush;
43 
implementationboost::sinks::basic_text_ostream_backend::implementation44     implementation(auto_newline_mode auto_newline, bool auto_flush) :
45         m_AutoNewlineMode(auto_newline),
46         m_fAutoFlush(auto_flush)
47     {
48     }
49 };
50 
51 
52 //! Constructor
53 template< typename CharT >
basic_text_ostream_backend()54 BOOST_LOG_API basic_text_ostream_backend< CharT >::basic_text_ostream_backend()
55 {
56     construct(log::aux::empty_arg_list());
57 }
58 
59 //! Constructor implementation
60 template< typename CharT >
construct(auto_newline_mode auto_newline,bool auto_flush)61 BOOST_LOG_API void basic_text_ostream_backend< CharT >::construct(auto_newline_mode auto_newline, bool auto_flush)
62 {
63     m_pImpl = new implementation(auto_newline, auto_flush);
64 }
65 
66 //! Destructor (just to make it link from the shared library)
67 template< typename CharT >
~basic_text_ostream_backend()68 BOOST_LOG_API basic_text_ostream_backend< CharT >::~basic_text_ostream_backend()
69 {
70     delete m_pImpl;
71 }
72 
73 //! Selects whether a trailing newline should be automatically inserted after every log record.
74 template< typename CharT >
set_auto_newline_mode(auto_newline_mode mode)75 BOOST_LOG_API void basic_text_ostream_backend< CharT >::set_auto_newline_mode(auto_newline_mode mode)
76 {
77     m_pImpl->m_AutoNewlineMode = mode;
78 }
79 
80 //! The method adds a new stream to the sink
81 template< typename CharT >
add_stream(shared_ptr<stream_type> const & strm)82 BOOST_LOG_API void basic_text_ostream_backend< CharT >::add_stream(shared_ptr< stream_type > const& strm)
83 {
84     typename implementation::ostream_sequence::iterator it =
85         std::find(m_pImpl->m_Streams.begin(), m_pImpl->m_Streams.end(), strm);
86     if (it == m_pImpl->m_Streams.end())
87     {
88         m_pImpl->m_Streams.push_back(strm);
89     }
90 }
91 
92 //! The method removes a stream from the sink
93 template< typename CharT >
remove_stream(shared_ptr<stream_type> const & strm)94 BOOST_LOG_API void basic_text_ostream_backend< CharT >::remove_stream(shared_ptr< stream_type > const& strm)
95 {
96     typename implementation::ostream_sequence::iterator it =
97         std::find(m_pImpl->m_Streams.begin(), m_pImpl->m_Streams.end(), strm);
98     if (it != m_pImpl->m_Streams.end())
99         m_pImpl->m_Streams.erase(it);
100 }
101 
102 //! Sets the flag to automatically flush buffers after each logged line
103 template< typename CharT >
auto_flush(bool f)104 BOOST_LOG_API void basic_text_ostream_backend< CharT >::auto_flush(bool f)
105 {
106     m_pImpl->m_fAutoFlush = f;
107 }
108 
109 //! The method writes the message to the sink
110 template< typename CharT >
consume(record_view const &,string_type const & message)111 BOOST_LOG_API void basic_text_ostream_backend< CharT >::consume(record_view const&, string_type const& message)
112 {
113     typename string_type::const_pointer const p = message.data();
114     typename string_type::size_type const s = message.size();
115     typename implementation::ostream_sequence::const_iterator
116         it = m_pImpl->m_Streams.begin(), end = m_pImpl->m_Streams.end();
117     bool need_trailing_newline = false;
118     if (m_pImpl->m_AutoNewlineMode != disabled_auto_newline)
119         need_trailing_newline = (m_pImpl->m_AutoNewlineMode == always_insert || s == 0u || p[s - 1u] != static_cast< char_type >('\n'));
120 
121     for (; it != end; ++it)
122     {
123         stream_type* const strm = it->get();
124         if (BOOST_LIKELY(strm->good()))
125         {
126             strm->write(p, static_cast< std::streamsize >(s));
127             if (need_trailing_newline)
128                 strm->put(static_cast< char_type >('\n'));
129 
130             if (m_pImpl->m_fAutoFlush)
131                 strm->flush();
132         }
133     }
134 }
135 
136 //! The method flushes the associated streams
137 template< typename CharT >
flush()138 BOOST_LOG_API void basic_text_ostream_backend< CharT >::flush()
139 {
140     typename implementation::ostream_sequence::const_iterator
141         it = m_pImpl->m_Streams.begin(), end = m_pImpl->m_Streams.end();
142     for (; it != end; ++it)
143     {
144         stream_type* const strm = it->get();
145         if (BOOST_LIKELY(strm->good()))
146             strm->flush();
147     }
148 }
149 
150 //! Explicitly instantiate sink backend implementation
151 #ifdef BOOST_LOG_USE_CHAR
152 template class basic_text_ostream_backend< char >;
153 #endif
154 #ifdef BOOST_LOG_USE_WCHAR_T
155 template class basic_text_ostream_backend< wchar_t >;
156 #endif
157 
158 } // namespace sinks
159 
160 BOOST_LOG_CLOSE_NAMESPACE // namespace log
161 
162 } // namespace boost
163 
164 #include <boost/log/detail/footer.hpp>
165