]> git.proxmox.com Git - ceph.git/blame - ceph/src/Beast/include/beast/core/impl/flat_streambuf.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / include / beast / core / impl / flat_streambuf.ipp
CommitLineData
7c673cae
FG
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
14namespace beast {
15
16/* Memory is laid out thusly:
17
18 p_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
19*/
20
21namespace detail {
22
23inline
24std::size_t
25next_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
38template<class Allocator>
39void
40basic_flat_streambuf<Allocator>::
41move_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
56template<class Allocator>
57template<class OtherAlloc>
58void
59basic_flat_streambuf<Allocator>::
60copy_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
83template<class Allocator>
84basic_flat_streambuf<Allocator>::
85~basic_flat_streambuf()
86{
87 if(p_)
88 alloc_traits::deallocate(
89 this->member(), p_, dist(p_, end_));
90}
91
92template<class Allocator>
93basic_flat_streambuf<Allocator>::
94basic_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
101template<class Allocator>
102basic_flat_streambuf<Allocator>::
103basic_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
116template<class Allocator>
117basic_flat_streambuf<Allocator>::
118basic_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
127template<class Allocator>
128basic_flat_streambuf<Allocator>::
129basic_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
138template<class Allocator>
139template<class OtherAlloc>
140basic_flat_streambuf<Allocator>::
141basic_flat_streambuf(
142 basic_flat_streambuf<OtherAlloc> const& other)
143{
144 copy_from(other);
145}
146
147template<class Allocator>
148template<class OtherAlloc>
149basic_flat_streambuf<Allocator>::
150basic_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
159template<class Allocator>
160basic_flat_streambuf<Allocator>::
161basic_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
172template<class Allocator>
173basic_flat_streambuf<Allocator>::
174basic_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
188template<class Allocator>
189auto
190basic_flat_streambuf<Allocator>::
191prepare(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
228template<class Allocator>
229void
230basic_flat_streambuf<Allocator>::
231consume(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
242template<class Allocator>
243void
244basic_flat_streambuf<Allocator>::
245reserve(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
269template<class Allocator>
270void
271basic_flat_streambuf<Allocator>::
272shrink_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
297template<class Allocator>
298std::size_t
299read_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