2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
11 #define BOOST_BEAST_DETAIL_OSTREAM_HPP
13 #include <boost/beast/core/buffers_prefix.hpp>
14 #include <boost/beast/core/read_size.hpp>
15 #include <boost/beast/core/detail/type_traits.hpp>
16 #include <boost/asio/buffer.hpp>
20 #include <type_traits>
27 template<class Buffers>
34 buffers_helper(Buffers const& b)
42 operator<<(std::ostream& os,
43 buffers_helper<B> const& v);
46 template<class Buffers>
48 operator<<(std::ostream& os,
49 buffers_helper<Buffers> const& v)
51 for(auto b : buffers_range(v.b_))
53 reinterpret_cast<char const*>(b.data()),
58 //------------------------------------------------------------------------------
60 struct basic_streambuf_movable_helper :
61 std::basic_streambuf<char, std::char_traits<char>>
63 basic_streambuf_movable_helper(
64 basic_streambuf_movable_helper&&) = default;
67 using basic_streambuf_movable =
68 std::is_move_constructible<basic_streambuf_movable_helper>;
70 //------------------------------------------------------------------------------
72 template<class DynamicBuffer,
73 class CharT, class Traits, bool isMovable>
76 template<class DynamicBuffer, class CharT, class Traits>
78 <DynamicBuffer, CharT, Traits, true>
79 : public std::basic_streambuf<CharT, Traits>
81 using int_type = typename
82 std::basic_streambuf<CharT, Traits>::int_type;
84 using traits_type = typename
85 std::basic_streambuf<CharT, Traits>::traits_type;
87 static std::size_t constexpr max_size = 512;
92 ostream_buffer(ostream_buffer&&) = default;
93 ostream_buffer(ostream_buffer const&) = delete;
95 ~ostream_buffer() noexcept
101 ostream_buffer(DynamicBuffer& buf)
108 overflow(int_type ch) override
110 if(! Traits::eq_int_type(ch, Traits::eof()))
112 Traits::assign(*this->pptr(),
113 static_cast<CharT>(ch));
119 return traits_type::eof();
134 auto bs = buf_.prepare(
135 read_size_or_throw(buf_, max_size));
136 auto const b = buffers_front(bs);
137 auto const p = reinterpret_cast<CharT*>(b.data());
139 p + b.size() / sizeof(CharT) - 1);
146 (this->pptr() - this->pbase() + extra) *
151 // This nonsense is all to work around a glitch in libstdc++
152 // where std::basic_streambuf copy constructor is private:
153 // https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799
155 template<class DynamicBuffer, class CharT, class Traits>
157 <DynamicBuffer, CharT, Traits, false>
158 : public std::basic_streambuf<CharT, Traits>
160 using int_type = typename
161 std::basic_streambuf<CharT, Traits>::int_type;
163 using traits_type = typename
164 std::basic_streambuf<CharT, Traits>::traits_type;
166 static std::size_t constexpr max_size = 512;
171 ostream_buffer(ostream_buffer&&) = delete;
172 ostream_buffer(ostream_buffer const&) = delete;
174 ~ostream_buffer() noexcept
180 ostream_buffer(DynamicBuffer& buf)
187 overflow(int_type ch) override
189 if(! Traits::eq_int_type(ch, Traits::eof()))
191 Traits::assign(*this->pptr(),
192 static_cast<CharT>(ch));
198 return traits_type::eof();
213 auto bs = buf_.prepare(
214 read_size_or_throw(buf_, max_size));
215 auto const b = buffers_front(bs);
216 auto const p = reinterpret_cast<CharT*>(b.data());
218 p + b.size() / sizeof(CharT) - 1);
225 (this->pptr() - this->pbase() + extra) *
230 //------------------------------------------------------------------------------
232 template<class DynamicBuffer,
233 class CharT, class Traits, bool isMovable>
234 class ostream_helper;
236 template<class DynamicBuffer, class CharT, class Traits>
237 class ostream_helper<
238 DynamicBuffer, CharT, Traits, true>
239 : public std::basic_ostream<CharT, Traits>
242 DynamicBuffer, CharT, Traits, true> osb_;
246 ostream_helper(DynamicBuffer& buf);
248 ostream_helper(ostream_helper&& other);
251 template<class DynamicBuffer, class CharT, class Traits>
252 ostream_helper<DynamicBuffer, CharT, Traits, true>::
253 ostream_helper(DynamicBuffer& buf)
254 : std::basic_ostream<CharT, Traits>(
260 template<class DynamicBuffer, class CharT, class Traits>
261 ostream_helper<DynamicBuffer, CharT, Traits, true>::
263 ostream_helper&& other)
264 : std::basic_ostream<CharT, Traits>(&osb_)
265 , osb_(std::move(other.osb_))
269 // This work-around is for libstdc++ versions that
270 // don't have a movable std::basic_streambuf
273 class ostream_helper_base
276 std::unique_ptr<T> member;
279 ostream_helper_base&&) = default;
282 ostream_helper_base(T* t)
288 template<class DynamicBuffer, class CharT, class Traits>
289 class ostream_helper<
290 DynamicBuffer, CharT, Traits, false>
291 : private ostream_helper_base<ostream_buffer<
292 DynamicBuffer, CharT, Traits, false>>
293 , public std::basic_ostream<CharT, Traits>
297 ostream_helper(DynamicBuffer& buf)
298 : ostream_helper_base<ostream_buffer<
299 DynamicBuffer, CharT, Traits, false>>(
300 new ostream_buffer<DynamicBuffer,
301 CharT, Traits, false>(buf))
302 , std::basic_ostream<CharT, Traits>(this->member.get())
306 ostream_helper(ostream_helper&& other)
307 : ostream_helper_base<ostream_buffer<
308 DynamicBuffer, CharT, Traits, false>>(
310 , std::basic_ostream<CharT, Traits>(this->member.get())