Chris@16
|
1 /*
|
Chris@101
|
2 * Copyright Andrey Semashev 2007 - 2015.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7 /*!
|
Chris@16
|
8 * \file attachable_sstream_buf.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 29.07.2007
|
Chris@16
|
11 *
|
Chris@16
|
12 * \brief This header is the Boost.Log library implementation, see the library documentation
|
Chris@16
|
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
|
Chris@16
|
14 */
|
Chris@16
|
15
|
Chris@16
|
16 #ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
|
Chris@16
|
17 #define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
|
Chris@16
|
18
|
Chris@16
|
19 #include <memory>
|
Chris@16
|
20 #include <string>
|
Chris@16
|
21 #include <streambuf>
|
Chris@16
|
22 #include <boost/assert.hpp>
|
Chris@16
|
23 #include <boost/utility/addressof.hpp>
|
Chris@16
|
24 #include <boost/log/detail/config.hpp>
|
Chris@16
|
25 #include <boost/log/detail/header.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
28 #pragma once
|
Chris@16
|
29 #endif
|
Chris@16
|
30
|
Chris@16
|
31 namespace boost {
|
Chris@16
|
32
|
Chris@16
|
33 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
34
|
Chris@16
|
35 namespace aux {
|
Chris@16
|
36
|
Chris@16
|
37 //! A streambuf that puts the formatted data to an external string
|
Chris@16
|
38 template<
|
Chris@16
|
39 typename CharT,
|
Chris@16
|
40 typename TraitsT = std::char_traits< CharT >,
|
Chris@16
|
41 typename AllocatorT = std::allocator< CharT >
|
Chris@16
|
42 >
|
Chris@16
|
43 class basic_ostringstreambuf :
|
Chris@16
|
44 public std::basic_streambuf< CharT, TraitsT >
|
Chris@16
|
45 {
|
Chris@16
|
46 //! Self type
|
Chris@16
|
47 typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type;
|
Chris@16
|
48 //! Base type
|
Chris@16
|
49 typedef std::basic_streambuf< CharT, TraitsT > base_type;
|
Chris@16
|
50
|
Chris@16
|
51 //! Buffer size
|
Chris@16
|
52 enum { buffer_size = 16 };
|
Chris@16
|
53
|
Chris@16
|
54 public:
|
Chris@16
|
55 //! Character type
|
Chris@16
|
56 typedef typename base_type::char_type char_type;
|
Chris@16
|
57 //! Traits type
|
Chris@16
|
58 typedef typename base_type::traits_type traits_type;
|
Chris@16
|
59 //! String type
|
Chris@16
|
60 typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
|
Chris@16
|
61 //! Int type
|
Chris@16
|
62 typedef typename base_type::int_type int_type;
|
Chris@16
|
63
|
Chris@16
|
64 private:
|
Chris@16
|
65 //! A reference to the string that will be filled
|
Chris@16
|
66 string_type* m_Storage;
|
Chris@16
|
67 //! A buffer used to temporarily store output
|
Chris@16
|
68 char_type m_Buffer[buffer_size];
|
Chris@16
|
69
|
Chris@16
|
70 public:
|
Chris@16
|
71 //! Constructor
|
Chris@16
|
72 explicit basic_ostringstreambuf() : m_Storage(0)
|
Chris@16
|
73 {
|
Chris@16
|
74 base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
|
Chris@16
|
75 }
|
Chris@16
|
76 //! Constructor
|
Chris@16
|
77 explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage))
|
Chris@16
|
78 {
|
Chris@16
|
79 base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 //! Clears the buffer to the initial state
|
Chris@16
|
83 void clear()
|
Chris@16
|
84 {
|
Chris@101
|
85 char_type* pBase = this->pbase();
|
Chris@101
|
86 char_type* pPtr = this->pptr();
|
Chris@16
|
87 if (pBase != pPtr)
|
Chris@16
|
88 this->pbump(static_cast< int >(pBase - pPtr));
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 //! Detaches the buffer from the string
|
Chris@16
|
92 void detach()
|
Chris@16
|
93 {
|
Chris@16
|
94 if (m_Storage)
|
Chris@16
|
95 {
|
Chris@16
|
96 this_type::sync();
|
Chris@16
|
97 m_Storage = 0;
|
Chris@16
|
98 }
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 //! Attaches the buffer to another string
|
Chris@16
|
102 void attach(string_type& storage)
|
Chris@16
|
103 {
|
Chris@16
|
104 detach();
|
Chris@16
|
105 m_Storage = boost::addressof(storage);
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 //! Returns a pointer to the attached string
|
Chris@16
|
109 string_type* storage() const { return m_Storage; }
|
Chris@16
|
110
|
Chris@16
|
111 protected:
|
Chris@16
|
112 //! Puts all buffered data to the string
|
Chris@16
|
113 int sync()
|
Chris@16
|
114 {
|
Chris@16
|
115 BOOST_ASSERT(m_Storage != 0);
|
Chris@101
|
116 char_type* pBase = this->pbase();
|
Chris@101
|
117 char_type* pPtr = this->pptr();
|
Chris@16
|
118 if (pBase != pPtr)
|
Chris@16
|
119 {
|
Chris@16
|
120 m_Storage->append(pBase, pPtr);
|
Chris@16
|
121 this->pbump(static_cast< int >(pBase - pPtr));
|
Chris@16
|
122 }
|
Chris@16
|
123 return 0;
|
Chris@16
|
124 }
|
Chris@16
|
125 //! Puts an unbuffered character to the string
|
Chris@16
|
126 int_type overflow(int_type c)
|
Chris@16
|
127 {
|
Chris@16
|
128 BOOST_ASSERT(m_Storage != 0);
|
Chris@16
|
129 basic_ostringstreambuf::sync();
|
Chris@16
|
130 if (!traits_type::eq_int_type(c, traits_type::eof()))
|
Chris@16
|
131 {
|
Chris@16
|
132 m_Storage->push_back(traits_type::to_char_type(c));
|
Chris@16
|
133 return c;
|
Chris@16
|
134 }
|
Chris@16
|
135 else
|
Chris@16
|
136 return traits_type::not_eof(c);
|
Chris@16
|
137 }
|
Chris@16
|
138 //! Puts a character sequence to the string
|
Chris@16
|
139 std::streamsize xsputn(const char_type* s, std::streamsize n)
|
Chris@16
|
140 {
|
Chris@16
|
141 BOOST_ASSERT(m_Storage != 0);
|
Chris@16
|
142 basic_ostringstreambuf::sync();
|
Chris@16
|
143 typedef typename string_type::size_type string_size_type;
|
Chris@101
|
144 const string_size_type max_storage_left =
|
Chris@16
|
145 m_Storage->max_size() - m_Storage->size();
|
Chris@16
|
146 if (static_cast< string_size_type >(n) < max_storage_left)
|
Chris@16
|
147 {
|
Chris@16
|
148 m_Storage->append(s, static_cast< string_size_type >(n));
|
Chris@16
|
149 return n;
|
Chris@16
|
150 }
|
Chris@16
|
151 else
|
Chris@16
|
152 {
|
Chris@16
|
153 m_Storage->append(s, max_storage_left);
|
Chris@16
|
154 return static_cast< std::streamsize >(max_storage_left);
|
Chris@16
|
155 }
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 //! Copy constructor (closed)
|
Chris@16
|
159 BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
|
Chris@16
|
160 //! Assignment (closed)
|
Chris@16
|
161 BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that))
|
Chris@16
|
162 };
|
Chris@16
|
163
|
Chris@16
|
164 } // namespace aux
|
Chris@16
|
165
|
Chris@16
|
166 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
167
|
Chris@16
|
168 } // namespace boost
|
Chris@16
|
169
|
Chris@16
|
170 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
171
|
Chris@16
|
172 #endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
|