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