]> git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/include/beast/core/impl/flat_streambuf.ipp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / Beast / include / beast / core / impl / flat_streambuf.ipp
1 //
2 // Copyright (c) 2013-2016 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
8 #ifndef BEAST_IMPL_FLAT_STREAMBUF_HPP
9 #define BEAST_IMPL_FLAT_STREAMBUF_HPP
10
11 #include <boost/assert.hpp>
12 #include <stdexcept>
13
14 namespace beast {
15
16 /* Memory is laid out thusly:
17
18 p_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
19 */
20
21 namespace detail {
22
23 inline
24 std::size_t
25 next_pow2(std::size_t x)
26 {
27 std::size_t n = 0;
28 while(x > 0)
29 {
30 ++n;
31 x >>= 1;
32 }
33 return std::size_t{1} << n;
34 }
35
36 } // detail
37
38 template<class Allocator>
39 void
40 basic_flat_streambuf<Allocator>::
41 move_from(basic_flat_streambuf& other)
42 {
43 p_ = other.p_;
44 in_ = other.in_;
45 out_ = other.out_;
46 last_ = out_;
47 end_ = other.end_;
48 max_ = other.max_;
49 other.p_ = nullptr;
50 other.in_ = nullptr;
51 other.out_ = nullptr;
52 other.last_ = nullptr;
53 other.end_ = nullptr;
54 }
55
56 template<class Allocator>
57 template<class OtherAlloc>
58 void
59 basic_flat_streambuf<Allocator>::
60 copy_from(basic_flat_streambuf<
61 OtherAlloc> const& other)
62 {
63 max_ = other.max_;
64 auto const n = other.size();
65 if(n > 0)
66 {
67 p_ = alloc_traits::allocate(
68 this->member(), n);
69 in_ = p_;
70 out_ = p_ + n;
71 last_ = out_;
72 end_ = out_;
73 std::memcpy(in_, other.in_, n);
74 return;
75 }
76 p_ = nullptr;
77 in_ = nullptr;
78 out_ = nullptr;
79 last_ = nullptr;
80 end_ = nullptr;
81 }
82
83 template<class Allocator>
84 basic_flat_streambuf<Allocator>::
85 ~basic_flat_streambuf()
86 {
87 if(p_)
88 alloc_traits::deallocate(
89 this->member(), p_, dist(p_, end_));
90 }
91
92 template<class Allocator>
93 basic_flat_streambuf<Allocator>::
94 basic_flat_streambuf(basic_flat_streambuf&& other)
95 : detail::empty_base_optimization<
96 allocator_type>(std::move(other.member()))
97 {
98 move_from(other);
99 }
100
101 template<class Allocator>
102 basic_flat_streambuf<Allocator>::
103 basic_flat_streambuf(basic_flat_streambuf&& other,
104 Allocator const& alloc)
105 : detail::empty_base_optimization<
106 allocator_type>(alloc)
107 {
108 if(this->member() != other.member())
109 {
110 copy_from(other);
111 return;
112 }
113 move_from(other);
114 }
115
116 template<class Allocator>
117 basic_flat_streambuf<Allocator>::
118 basic_flat_streambuf(
119 basic_flat_streambuf const& other)
120 : detail::empty_base_optimization<allocator_type>(
121 alloc_traits::select_on_container_copy_construction(
122 other.member()))
123 {
124 copy_from(other);
125 }
126
127 template<class Allocator>
128 basic_flat_streambuf<Allocator>::
129 basic_flat_streambuf(
130 basic_flat_streambuf const& other,
131 Allocator const& alloc)
132 : detail::empty_base_optimization<
133 allocator_type>(alloc)
134 {
135 copy_from(other);
136 }
137
138 template<class Allocator>
139 template<class OtherAlloc>
140 basic_flat_streambuf<Allocator>::
141 basic_flat_streambuf(
142 basic_flat_streambuf<OtherAlloc> const& other)
143 {
144 copy_from(other);
145 }
146
147 template<class Allocator>
148 template<class OtherAlloc>
149 basic_flat_streambuf<Allocator>::
150 basic_flat_streambuf(
151 basic_flat_streambuf<OtherAlloc> const& other,
152 Allocator const& alloc)
153 : detail::empty_base_optimization<
154 allocator_type>(alloc)
155 {
156 copy_from(other);
157 }
158
159 template<class Allocator>
160 basic_flat_streambuf<Allocator>::
161 basic_flat_streambuf(std::size_t limit)
162 : p_(nullptr)
163 , in_(nullptr)
164 , out_(nullptr)
165 , last_(nullptr)
166 , end_(nullptr)
167 , max_(limit)
168 {
169 BOOST_ASSERT(limit >= 1);
170 }
171
172 template<class Allocator>
173 basic_flat_streambuf<Allocator>::
174 basic_flat_streambuf(Allocator const& alloc,
175 std::size_t limit)
176 : detail::empty_base_optimization<
177 allocator_type>(alloc)
178 , p_(nullptr)
179 , in_(nullptr)
180 , out_(nullptr)
181 , last_(nullptr)
182 , end_(nullptr)
183 , max_(limit)
184 {
185 BOOST_ASSERT(limit >= 1);
186 }
187
188 template<class Allocator>
189 auto
190 basic_flat_streambuf<Allocator>::
191 prepare(std::size_t n) ->
192 mutable_buffers_type
193 {
194 if(n <= dist(out_, end_))
195 {
196 last_ = out_ + n;
197 return{out_, n};
198 }
199 auto const len = size();
200 if(n <= dist(p_, end_) - len)
201 {
202 if(len > 0)
203 std::memmove(p_, in_, len);
204 in_ = p_;
205 out_ = in_ + len;
206 last_ = out_ + n;
207 return {out_, n};
208 }
209 if(n > max_ - len)
210 throw std::length_error{
211 "flat_streambuf overflow"};
212 auto const new_size = (std::min)(max_,
213 std::max<std::size_t>(
214 detail::next_pow2(len + n), min_size));
215 auto const p = alloc_traits::allocate(
216 this->member(), new_size);
217 std::memcpy(p, in_, len);
218 alloc_traits::deallocate(
219 this->member(), p_, dist(p_, end_));
220 p_ = p;
221 in_ = p_;
222 out_ = in_ + len;
223 last_ = out_ + n;
224 end_ = p_ + new_size;
225 return {out_, n};
226 }
227
228 template<class Allocator>
229 void
230 basic_flat_streambuf<Allocator>::
231 consume(std::size_t n)
232 {
233 if(n >= dist(in_, out_))
234 {
235 in_ = p_;
236 out_ = p_;
237 return;
238 }
239 in_ += n;
240 }
241
242 template<class Allocator>
243 void
244 basic_flat_streambuf<Allocator>::
245 reserve(std::size_t n)
246 {
247 if(n <= dist(p_, end_))
248 return;
249 if(n > max_)
250 throw std::length_error{
251 "flat_streambuf overflow"};
252 auto const new_size = (std::min)(max_,
253 std::max<std::size_t>(
254 detail::next_pow2(n), min_size));
255 auto const p = alloc_traits::allocate(
256 this->member(), new_size);
257 auto const len = size();
258 if(len > 0)
259 std::memcpy(p, in_, len);
260 alloc_traits::deallocate(
261 this->member(), p_, dist(p_, end_));
262 p_ = p;
263 in_ = p_;
264 out_ = p_ + len;
265 last_ = out_;
266 end_ = p_ + new_size;
267 }
268
269 template<class Allocator>
270 void
271 basic_flat_streambuf<Allocator>::
272 shrink_to_fit()
273 {
274 auto const len = size();
275 if(len == dist(p_, end_))
276 return;
277 char* p;
278 if(len > 0)
279 {
280 p = alloc_traits::allocate(
281 this->member(), len);
282 std::memcpy(p, in_, len);
283 }
284 else
285 {
286 p = nullptr;
287 }
288 alloc_traits::deallocate(
289 this->member(), p_, dist(p_, end_));
290 p_ = p;
291 in_ = p_;
292 out_ = p_ + len;
293 last_ = out_;
294 end_ = out_;
295 }
296
297 template<class Allocator>
298 std::size_t
299 read_size_helper(basic_flat_streambuf<
300 Allocator> const& fb, std::size_t max_size)
301 {
302 BOOST_ASSERT(max_size >= 1);
303 auto const len = fb.size();
304 auto const avail = fb.capacity() - len;
305 if (avail > 0)
306 return (std::min)(avail, max_size);
307 auto size = (std::min)(
308 fb.capacity() * 2, fb.max_size()) - len;
309 if(size == 0)
310 size = 1;
311 return (std::min)(size, max_size);
312 }
313
314 } // beast
315
316 #endif