]> git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/include/beast/core/detail/prepare_buffers.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / Beast / include / beast / core / detail / prepare_buffers.hpp
1 //
2 // Copyright (c) 2013-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
8 #ifndef BEAST_DETAIL_PREPARED_BUFFERS_HPP
9 #define BEAST_DETAIL_PREPARED_BUFFERS_HPP
10
11 #include <beast/core/prepare_buffer.hpp>
12 #include <boost/asio/buffer.hpp>
13 #include <algorithm>
14 #include <cstdint>
15 #include <iterator>
16 #include <stdexcept>
17 #include <type_traits>
18 #include <utility>
19
20 namespace beast {
21 namespace detail {
22
23 /** A buffer sequence adapter that shortens the sequence size.
24
25 The class adapts a buffer sequence to efficiently represent
26 a shorter subset of the original list of buffers starting
27 with the first byte of the original sequence.
28
29 @tparam BufferSequence The buffer sequence to adapt.
30 */
31 template<class BufferSequence>
32 class prepared_buffers
33 {
34 using iter_type =
35 typename BufferSequence::const_iterator;
36
37 BufferSequence bs_;
38 iter_type back_;
39 iter_type end_;
40 std::size_t size_;
41
42 template<class Deduced>
43 prepared_buffers(Deduced&& other,
44 std::size_t nback, std::size_t nend)
45 : bs_(std::forward<Deduced>(other).bs_)
46 , back_(std::next(bs_.begin(), nback))
47 , end_(std::next(bs_.begin(), nend))
48 , size_(other.size_)
49 {
50 }
51
52 void
53 setup(std::size_t n);
54
55 public:
56 /// The type for each element in the list of buffers.
57 using value_type = typename std::conditional<
58 std::is_convertible<typename
59 std::iterator_traits<iter_type>::value_type,
60 boost::asio::mutable_buffer>::value,
61 boost::asio::mutable_buffer,
62 boost::asio::const_buffer>::type;
63
64 #if BEAST_DOXYGEN
65 /// A bidirectional iterator type that may be used to read elements.
66 using const_iterator = implementation_defined;
67
68 #else
69 class const_iterator;
70
71 #endif
72
73 /// Move constructor.
74 prepared_buffers(prepared_buffers&&);
75
76 /// Copy constructor.
77 prepared_buffers(prepared_buffers const&);
78
79 /// Move assignment.
80 prepared_buffers& operator=(prepared_buffers&&);
81
82 /// Copy assignment.
83 prepared_buffers& operator=(prepared_buffers const&);
84
85 /** Construct a shortened buffer sequence.
86
87 @param n The maximum number of bytes in the wrapped
88 sequence. If this is larger than the size of passed,
89 buffers, the resulting sequence will represent the
90 entire input sequence.
91
92 @param buffers The buffer sequence to adapt. A copy of
93 the sequence will be made, but ownership of the underlying
94 memory is not transferred.
95 */
96 prepared_buffers(std::size_t n, BufferSequence const& buffers);
97
98 /// Get a bidirectional iterator to the first element.
99 const_iterator
100 begin() const;
101
102 /// Get a bidirectional iterator to one past the last element.
103 const_iterator
104 end() const;
105 };
106
107 template<class BufferSequence>
108 class prepared_buffers<BufferSequence>::const_iterator
109 {
110 friend class prepared_buffers<BufferSequence>;
111
112 using iter_type =
113 typename BufferSequence::const_iterator;
114
115 prepared_buffers const* b_ = nullptr;
116 typename BufferSequence::const_iterator it_;
117
118 public:
119 using value_type = typename std::conditional<
120 std::is_convertible<typename
121 std::iterator_traits<iter_type>::value_type,
122 boost::asio::mutable_buffer>::value,
123 boost::asio::mutable_buffer,
124 boost::asio::const_buffer>::type;
125 using pointer = value_type const*;
126 using reference = value_type;
127 using difference_type = std::ptrdiff_t;
128 using iterator_category =
129 std::bidirectional_iterator_tag;
130
131 const_iterator() = default;
132 const_iterator(const_iterator&& other);
133 const_iterator(const_iterator const& other);
134 const_iterator& operator=(const_iterator&& other);
135 const_iterator& operator=(const_iterator const& other);
136
137 bool
138 operator==(const_iterator const& other) const
139 {
140 return b_ == other.b_ && it_ == other.it_;
141 }
142
143 bool
144 operator!=(const_iterator const& other) const
145 {
146 return !(*this == other);
147 }
148
149 reference
150 operator*() const
151 {
152 if(it_ == b_->back_)
153 return prepare_buffer(b_->size_, *it_);
154 return *it_;
155 }
156
157 pointer
158 operator->() const = delete;
159
160 const_iterator&
161 operator++()
162 {
163 ++it_;
164 return *this;
165 }
166
167 const_iterator
168 operator++(int)
169 {
170 auto temp = *this;
171 ++(*this);
172 return temp;
173 }
174
175 const_iterator&
176 operator--()
177 {
178 --it_;
179 return *this;
180 }
181
182 const_iterator
183 operator--(int)
184 {
185 auto temp = *this;
186 --(*this);
187 return temp;
188 }
189
190 private:
191 const_iterator(prepared_buffers const& b,
192 bool at_end)
193 : b_(&b)
194 , it_(at_end ? b.end_ : b.bs_.begin())
195 {
196 }
197 };
198
199 template<class BufferSequence>
200 void
201 prepared_buffers<BufferSequence>::
202 setup(std::size_t n)
203 {
204 for(end_ = bs_.begin(); end_ != bs_.end(); ++end_)
205 {
206 auto const len =
207 boost::asio::buffer_size(*end_);
208 if(n <= len)
209 {
210 size_ = n;
211 back_ = end_++;
212 return;
213 }
214 n -= len;
215 }
216 size_ = 0;
217 back_ = end_;
218 }
219
220 template<class BufferSequence>
221 prepared_buffers<BufferSequence>::const_iterator::
222 const_iterator(const_iterator&& other)
223 : b_(other.b_)
224 , it_(std::move(other.it_))
225 {
226 }
227
228 template<class BufferSequence>
229 prepared_buffers<BufferSequence>::const_iterator::
230 const_iterator(const_iterator const& other)
231 : b_(other.b_)
232 , it_(other.it_)
233 {
234 }
235
236 template<class BufferSequence>
237 auto
238 prepared_buffers<BufferSequence>::const_iterator::
239 operator=(const_iterator&& other) ->
240 const_iterator&
241 {
242 b_ = other.b_;
243 it_ = std::move(other.it_);
244 return *this;
245 }
246
247 template<class BufferSequence>
248 auto
249 prepared_buffers<BufferSequence>::const_iterator::
250 operator=(const_iterator const& other) ->
251 const_iterator&
252 {
253 if(&other == this)
254 return *this;
255 b_ = other.b_;
256 it_ = other.it_;
257 return *this;
258 }
259
260 template<class BufferSequence>
261 prepared_buffers<BufferSequence>::
262 prepared_buffers(prepared_buffers&& other)
263 : prepared_buffers(std::move(other),
264 std::distance<iter_type>(other.bs_.begin(), other.back_),
265 std::distance<iter_type>(other.bs_.begin(), other.end_))
266 {
267 }
268
269 template<class BufferSequence>
270 prepared_buffers<BufferSequence>::
271 prepared_buffers(prepared_buffers const& other)
272 : prepared_buffers(other,
273 std::distance<iter_type>(other.bs_.begin(), other.back_),
274 std::distance<iter_type>(other.bs_.begin(), other.end_))
275 {
276 }
277
278 template<class BufferSequence>
279 auto
280 prepared_buffers<BufferSequence>::
281 operator=(prepared_buffers&& other) ->
282 prepared_buffers&
283 {
284 auto const nback = std::distance<iter_type>(
285 other.bs_.begin(), other.back_);
286 auto const nend = std::distance<iter_type>(
287 other.bs_.begin(), other.end_);
288 bs_ = std::move(other.bs_);
289 back_ = std::next(bs_.begin(), nback);
290 end_ = std::next(bs_.begin(), nend);
291 size_ = other.size_;
292 return *this;
293 }
294
295 template<class BufferSequence>
296 auto
297 prepared_buffers<BufferSequence>::
298 operator=(prepared_buffers const& other) ->
299 prepared_buffers&
300 {
301 auto const nback = std::distance<iter_type>(
302 other.bs_.begin(), other.back_);
303 auto const nend = std::distance<iter_type>(
304 other.bs_.begin(), other.end_);
305 bs_ = other.bs_;
306 back_ = std::next(bs_.begin(), nback);
307 end_ = std::next(bs_.begin(), nend);
308 size_ = other.size_;
309 return *this;
310 }
311
312 template<class BufferSequence>
313 prepared_buffers<BufferSequence>::
314 prepared_buffers(std::size_t n, BufferSequence const& bs)
315 : bs_(bs)
316 {
317 setup(n);
318 }
319
320 template<class BufferSequence>
321 inline
322 auto
323 prepared_buffers<BufferSequence>::begin() const ->
324 const_iterator
325 {
326 return const_iterator{*this, false};
327 }
328
329 template<class BufferSequence>
330 inline
331 auto
332 prepared_buffers<BufferSequence>::end() const ->
333 const_iterator
334 {
335 return const_iterator{*this, true};
336 }
337
338 } // detail
339 } // beast
340
341 #endif