]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/detail/ostream.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / core / detail / ostream.hpp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
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)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
11 #define BOOST_BEAST_DETAIL_OSTREAM_HPP
12
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>
17 #include <memory>
18 #include <iosfwd>
19 #include <streambuf>
20 #include <type_traits>
21 #include <utility>
22
23 namespace boost {
24 namespace beast {
25 namespace detail {
26
27 template<class Buffers>
28 class buffers_helper
29 {
30 Buffers b_;
31
32 public:
33 explicit
34 buffers_helper(Buffers const& b)
35 : b_(b)
36 {
37 }
38
39 template<class B>
40 friend
41 std::ostream&
42 operator<<(std::ostream& os,
43 buffers_helper<B> const& v);
44 };
45
46 template<class Buffers>
47 std::ostream&
48 operator<<(std::ostream& os,
49 buffers_helper<Buffers> const& v)
50 {
51 for(auto b : buffers_range(v.b_))
52 os.write(
53 reinterpret_cast<char const*>(b.data()),
54 b.size());
55 return os;
56 }
57
58 //------------------------------------------------------------------------------
59
60 struct basic_streambuf_movable_helper :
61 std::basic_streambuf<char, std::char_traits<char>>
62 {
63 basic_streambuf_movable_helper(
64 basic_streambuf_movable_helper&&) = default;
65 };
66
67 using basic_streambuf_movable =
68 std::is_move_constructible<basic_streambuf_movable_helper>;
69
70 //------------------------------------------------------------------------------
71
72 template<class DynamicBuffer,
73 class CharT, class Traits, bool isMovable>
74 class ostream_buffer;
75
76 template<class DynamicBuffer, class CharT, class Traits>
77 class ostream_buffer
78 <DynamicBuffer, CharT, Traits, true>
79 : public std::basic_streambuf<CharT, Traits>
80 {
81 using int_type = typename
82 std::basic_streambuf<CharT, Traits>::int_type;
83
84 using traits_type = typename
85 std::basic_streambuf<CharT, Traits>::traits_type;
86
87 static std::size_t constexpr max_size = 512;
88
89 DynamicBuffer& buf_;
90
91 public:
92 ostream_buffer(ostream_buffer&&) = default;
93 ostream_buffer(ostream_buffer const&) = delete;
94
95 ~ostream_buffer() noexcept
96 {
97 sync();
98 }
99
100 explicit
101 ostream_buffer(DynamicBuffer& buf)
102 : buf_(buf)
103 {
104 prepare();
105 }
106
107 int_type
108 overflow(int_type ch) override
109 {
110 if(! Traits::eq_int_type(ch, Traits::eof()))
111 {
112 Traits::assign(*this->pptr(),
113 static_cast<CharT>(ch));
114 flush(1);
115 prepare();
116 return ch;
117 }
118 flush();
119 return traits_type::eof();
120 }
121
122 int
123 sync() override
124 {
125 flush();
126 prepare();
127 return 0;
128 }
129
130 private:
131 void
132 prepare()
133 {
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());
138 this->setp(p,
139 p + b.size() / sizeof(CharT) - 1);
140 }
141
142 void
143 flush(int extra = 0)
144 {
145 buf_.commit(
146 (this->pptr() - this->pbase() + extra) *
147 sizeof(CharT));
148 }
149 };
150
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
154
155 template<class DynamicBuffer, class CharT, class Traits>
156 class ostream_buffer
157 <DynamicBuffer, CharT, Traits, false>
158 : public std::basic_streambuf<CharT, Traits>
159 {
160 using int_type = typename
161 std::basic_streambuf<CharT, Traits>::int_type;
162
163 using traits_type = typename
164 std::basic_streambuf<CharT, Traits>::traits_type;
165
166 static std::size_t constexpr max_size = 512;
167
168 DynamicBuffer& buf_;
169
170 public:
171 ostream_buffer(ostream_buffer&&) = delete;
172 ostream_buffer(ostream_buffer const&) = delete;
173
174 ~ostream_buffer() noexcept
175 {
176 sync();
177 }
178
179 explicit
180 ostream_buffer(DynamicBuffer& buf)
181 : buf_(buf)
182 {
183 prepare();
184 }
185
186 int_type
187 overflow(int_type ch) override
188 {
189 if(! Traits::eq_int_type(ch, Traits::eof()))
190 {
191 Traits::assign(*this->pptr(),
192 static_cast<CharT>(ch));
193 flush(1);
194 prepare();
195 return ch;
196 }
197 flush();
198 return traits_type::eof();
199 }
200
201 int
202 sync() override
203 {
204 flush();
205 prepare();
206 return 0;
207 }
208
209 private:
210 void
211 prepare()
212 {
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());
217 this->setp(p,
218 p + b.size() / sizeof(CharT) - 1);
219 }
220
221 void
222 flush(int extra = 0)
223 {
224 buf_.commit(
225 (this->pptr() - this->pbase() + extra) *
226 sizeof(CharT));
227 }
228 };
229
230 //------------------------------------------------------------------------------
231
232 template<class DynamicBuffer,
233 class CharT, class Traits, bool isMovable>
234 class ostream_helper;
235
236 template<class DynamicBuffer, class CharT, class Traits>
237 class ostream_helper<
238 DynamicBuffer, CharT, Traits, true>
239 : public std::basic_ostream<CharT, Traits>
240 {
241 ostream_buffer<
242 DynamicBuffer, CharT, Traits, true> osb_;
243
244 public:
245 explicit
246 ostream_helper(DynamicBuffer& buf);
247
248 ostream_helper(ostream_helper&& other);
249 };
250
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>(
255 &this->osb_)
256 , osb_(buf)
257 {
258 }
259
260 template<class DynamicBuffer, class CharT, class Traits>
261 ostream_helper<DynamicBuffer, CharT, Traits, true>::
262 ostream_helper(
263 ostream_helper&& other)
264 : std::basic_ostream<CharT, Traits>(&osb_)
265 , osb_(std::move(other.osb_))
266 {
267 }
268
269 // This work-around is for libstdc++ versions that
270 // don't have a movable std::basic_streambuf
271
272 template<class T>
273 class ostream_helper_base
274 {
275 protected:
276 std::unique_ptr<T> member;
277
278 ostream_helper_base(
279 ostream_helper_base&&) = default;
280
281 explicit
282 ostream_helper_base(T* t)
283 : member(t)
284 {
285 }
286 };
287
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>
294 {
295 public:
296 explicit
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())
303 {
304 }
305
306 ostream_helper(ostream_helper&& other)
307 : ostream_helper_base<ostream_buffer<
308 DynamicBuffer, CharT, Traits, false>>(
309 std::move(other))
310 , std::basic_ostream<CharT, Traits>(this->member.get())
311 {
312 }
313 };
314
315 } // detail
316 } // beast
317 } // boost
318
319 #endif