]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/detail/ostream.hpp
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / boost / boost / beast / core / detail / ostream.hpp
1 //
2 // Copyright (c) 2016-2019 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/buffers_range.hpp>
15 #include <boost/throw_exception.hpp>
16 #include <boost/asio/buffer.hpp>
17 #include <memory>
18 #include <ostream>
19 #include <streambuf>
20 #include <type_traits>
21 #include <utility>
22
23 namespace boost {
24 namespace beast {
25 namespace detail {
26
27 struct basic_streambuf_movable_helper :
28 std::basic_streambuf<char, std::char_traits<char>>
29 {
30 basic_streambuf_movable_helper(
31 basic_streambuf_movable_helper&&) = default;
32 };
33
34 using basic_streambuf_movable =
35 std::is_move_constructible<basic_streambuf_movable_helper>;
36
37 template<class DynamicBuffer,
38 class CharT, class Traits, bool isMovable>
39 class ostream_buffer;
40
41 //------------------------------------------------------------------------------
42
43 template<class DynamicBuffer, class CharT, class Traits>
44 class ostream_buffer
45 <DynamicBuffer, CharT, Traits, true> final
46 : public std::basic_streambuf<CharT, Traits>
47 {
48 using int_type = typename
49 std::basic_streambuf<CharT, Traits>::int_type;
50
51 using traits_type = typename
52 std::basic_streambuf<CharT, Traits>::traits_type;
53
54 DynamicBuffer& b_;
55
56 public:
57 ostream_buffer(ostream_buffer&&) = default;
58 ostream_buffer(ostream_buffer const&) = delete;
59
60 ~ostream_buffer() noexcept
61 {
62 sync();
63 }
64
65 explicit
66 ostream_buffer(DynamicBuffer& b)
67 : b_(b)
68 {
69 b_.prepare(0);
70 }
71
72 int_type
73 overflow(int_type ch) override
74 {
75 BOOST_ASSERT(! Traits::eq_int_type(
76 ch, Traits::eof()));
77 sync();
78
79 static std::size_t constexpr max_size = 65536;
80 auto const max_prepare = std::min<std::size_t>(
81 std::max<std::size_t>(
82 512, b_.capacity() - b_.size()),
83 std::min<std::size_t>(
84 max_size, b_.max_size() - b_.size()));
85 if(max_prepare == 0)
86 return Traits::eof();
87 auto const bs = b_.prepare(max_prepare);
88 auto const b = buffers_front(bs);
89 auto const p = static_cast<CharT*>(b.data());
90 this->setp(p, p + b.size() / sizeof(CharT));
91
92 BOOST_ASSERT(b_.capacity() > b_.size());
93 return this->sputc(
94 Traits::to_char_type(ch));
95 }
96
97 int
98 sync() override
99 {
100 b_.commit(
101 (this->pptr() - this->pbase()) *
102 sizeof(CharT));
103 this->setp(nullptr, nullptr);
104 return 0;
105 }
106 };
107
108 //------------------------------------------------------------------------------
109
110 // This nonsense is all to work around a glitch in libstdc++
111 // where std::basic_streambuf copy constructor is private:
112 // https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799
113
114 template<class DynamicBuffer, class CharT, class Traits>
115 class ostream_buffer
116 <DynamicBuffer, CharT, Traits, false>
117 : public std::basic_streambuf<CharT, Traits>
118 {
119 using int_type = typename
120 std::basic_streambuf<CharT, Traits>::int_type;
121
122 using traits_type = typename
123 std::basic_streambuf<CharT, Traits>::traits_type;
124
125 DynamicBuffer& b_;
126
127 public:
128 ostream_buffer(ostream_buffer&&) = delete;
129 ostream_buffer(ostream_buffer const&) = delete;
130
131 ~ostream_buffer() noexcept
132 {
133 sync();
134 }
135
136 explicit
137 ostream_buffer(DynamicBuffer& b)
138 : b_(b)
139 {
140 }
141
142 int_type
143 overflow(int_type ch) override
144 {
145 BOOST_ASSERT(! Traits::eq_int_type(
146 ch, Traits::eof()));
147 sync();
148
149 static std::size_t constexpr max_size = 65536;
150 auto const max_prepare = std::min<std::size_t>(
151 std::max<std::size_t>(
152 512, b_.capacity() - b_.size()),
153 std::min<std::size_t>(
154 max_size, b_.max_size() - b_.size()));
155 if(max_prepare == 0)
156 return Traits::eof();
157 auto const bs = b_.prepare(max_prepare);
158 auto const b = buffers_front(bs);
159 auto const p = static_cast<CharT*>(b.data());
160 this->setp(p, p + b.size() / sizeof(CharT));
161
162 BOOST_ASSERT(b_.capacity() > b_.size());
163 return this->sputc(
164 Traits::to_char_type(ch));
165 }
166
167 int
168 sync() override
169 {
170 b_.commit(
171 (this->pptr() - this->pbase()) *
172 sizeof(CharT));
173 this->setp(nullptr, nullptr);
174 return 0;
175 }
176 };
177
178 //------------------------------------------------------------------------------
179
180 template<class DynamicBuffer,
181 class CharT, class Traits, bool isMovable>
182 class ostream_helper;
183
184 template<class DynamicBuffer, class CharT, class Traits>
185 class ostream_helper<
186 DynamicBuffer, CharT, Traits, true>
187 : public std::basic_ostream<CharT, Traits>
188 {
189 ostream_buffer<
190 DynamicBuffer, CharT, Traits, true> osb_;
191
192 public:
193 explicit
194 ostream_helper(DynamicBuffer& b);
195
196 ostream_helper(ostream_helper&& other);
197 };
198
199 template<class DynamicBuffer, class CharT, class Traits>
200 ostream_helper<DynamicBuffer, CharT, Traits, true>::
201 ostream_helper(DynamicBuffer& b)
202 : std::basic_ostream<CharT, Traits>(&this->osb_)
203 , osb_(b)
204 {
205 }
206
207 template<class DynamicBuffer, class CharT, class Traits>
208 ostream_helper<DynamicBuffer, CharT, Traits, true>::
209 ostream_helper(ostream_helper&& other)
210 : std::basic_ostream<CharT, Traits>(&osb_)
211 , osb_(std::move(other.osb_))
212 {
213 }
214
215 // This work-around is for libstdc++ versions that
216 // don't have a movable std::basic_streambuf
217
218 template<class T>
219 class ostream_helper_base
220 {
221 protected:
222 std::unique_ptr<T> member;
223
224 ostream_helper_base(
225 ostream_helper_base&&) = default;
226
227 explicit
228 ostream_helper_base(T* t)
229 : member(t)
230 {
231 }
232 };
233
234 template<class DynamicBuffer, class CharT, class Traits>
235 class ostream_helper<
236 DynamicBuffer, CharT, Traits, false>
237 : private ostream_helper_base<ostream_buffer<
238 DynamicBuffer, CharT, Traits, false>>
239 , public std::basic_ostream<CharT, Traits>
240 {
241 public:
242 explicit
243 ostream_helper(DynamicBuffer& b)
244 : ostream_helper_base<ostream_buffer<
245 DynamicBuffer, CharT, Traits, false>>(
246 new ostream_buffer<DynamicBuffer,
247 CharT, Traits, false>(b))
248 , std::basic_ostream<CharT, Traits>(
249 this->member.get())
250 {
251 }
252
253 ostream_helper(ostream_helper&& other)
254 : ostream_helper_base<ostream_buffer<
255 DynamicBuffer, CharT, Traits, false>>(
256 std::move(other))
257 , std::basic_ostream<CharT, Traits>(
258 this->member.get())
259 {
260 }
261 };
262
263 } // detail
264 } // beast
265 } // boost
266
267 #endif