]> git.proxmox.com Git - ceph.git/blame - ceph/src/Beast/include/beast/core/detail/buffer_cat.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / include / beast / core / detail / buffer_cat.hpp
CommitLineData
7c673cae
FG
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_BUFFER_CAT_HPP
9#define BEAST_DETAIL_BUFFER_CAT_HPP
10
11#include <beast/core/buffer_concepts.hpp>
12#include <beast/core/detail/type_traits.hpp>
13#include <boost/asio/buffer.hpp>
14#include <cstdint>
15#include <iterator>
16#include <new>
17#include <stdexcept>
18#include <tuple>
19#include <utility>
20
21namespace beast {
22namespace detail {
23
24template<class... Bn>
25struct common_buffers_type
26{
27 using type = typename std::conditional<
28 std::is_convertible<std::tuple<Bn...>,
29 typename repeat_tuple<sizeof...(Bn),
30 boost::asio::mutable_buffer>::type>::value,
31 boost::asio::mutable_buffer,
32 boost::asio::const_buffer>::type;
33};
34
35template<class... Bn>
36class buffer_cat_helper
37{
38 std::tuple<Bn...> bn_;
39
40public:
41 using value_type = typename
42 common_buffers_type<Bn...>::type;
43
44 class const_iterator;
45
46 buffer_cat_helper(buffer_cat_helper&&) = default;
47 buffer_cat_helper(buffer_cat_helper const&) = default;
48 buffer_cat_helper& operator=(buffer_cat_helper&&) = delete;
49 buffer_cat_helper& operator=(buffer_cat_helper const&) = delete;
50
51 explicit
52 buffer_cat_helper(Bn const&... bn)
53 : bn_(bn...)
54 {
55 }
56
57 const_iterator
58 begin() const;
59
60 const_iterator
61 end() const;
62};
63
64template<class... Bn>
65class buffer_cat_helper<Bn...>::const_iterator
66{
67 std::size_t n_;
68 std::tuple<Bn...> const* bn_;
69 std::array<std::uint8_t,
70 max_sizeof<typename Bn::const_iterator...>()> buf_;
71
72 friend class buffer_cat_helper<Bn...>;
73
74 template<std::size_t I>
75 using C = std::integral_constant<std::size_t, I>;
76
77 template<std::size_t I>
78 using iter_t = typename std::tuple_element<
79 I, std::tuple<Bn...>>::type::const_iterator;
80
81 template<std::size_t I>
82 iter_t<I>&
83 iter()
84 {
85 // type-pun
86 return *reinterpret_cast<
87 iter_t<I>*>(static_cast<void*>(
88 buf_.data()));
89 }
90
91 template<std::size_t I>
92 iter_t<I> const&
93 iter() const
94 {
95 // type-pun
96 return *reinterpret_cast<
97 iter_t<I> const*>(static_cast<
98 void const*>(buf_.data()));
99 }
100
101public:
102 using value_type = typename
103 common_buffers_type<Bn...>::type;
104 using pointer = value_type const*;
105 using reference = value_type;
106 using difference_type = std::ptrdiff_t;
107 using iterator_category =
108 std::bidirectional_iterator_tag;
109
110 ~const_iterator();
111 const_iterator();
112 const_iterator(const_iterator&& other);
113 const_iterator(const_iterator const& other);
114 const_iterator& operator=(const_iterator&& other);
115 const_iterator& operator=(const_iterator const& other);
116
117 bool
118 operator==(const_iterator const& other) const;
119
120 bool
121 operator!=(const_iterator const& other) const
122 {
123 return !(*this == other);
124 }
125
126 reference
127 operator*() const;
128
129 pointer
130 operator->() const = delete;
131
132 const_iterator&
133 operator++();
134
135 const_iterator
136 operator++(int)
137 {
138 auto temp = *this;
139 ++(*this);
140 return temp;
141 }
142
143 const_iterator&
144 operator--();
145
146 const_iterator
147 operator--(int)
148 {
149 auto temp = *this;
150 --(*this);
151 return temp;
152 }
153
154private:
155 const_iterator(
156 std::tuple<Bn...> const& bn, bool at_end);
157
158 void
159 construct(C<sizeof...(Bn)> const&)
160 {
161 auto constexpr I = sizeof...(Bn);
162 n_ = I;
163 }
164
165 template<std::size_t I>
166 void
167 construct(C<I> const&)
168 {
169 if(std::get<I>(*bn_).begin() !=
170 std::get<I>(*bn_).end())
171 {
172 n_ = I;
173 new(buf_.data()) iter_t<I>{
174 std::get<I>(*bn_).begin()};
175 return;
176 }
177 construct(C<I+1>{});
178 }
179
180 void
181 destroy(C<sizeof...(Bn)> const&)
182 {
183 return;
184 }
185
186 template<std::size_t I>
187 void
188 destroy(C<I> const&)
189 {
190 if(n_ == I)
191 {
192 using Iter = iter_t<I>;
193 iter<I>().~Iter();
194 return;
195 }
196 destroy(C<I+1>{});
197 }
198
199 void
200 move(const_iterator&&,
201 C<sizeof...(Bn)> const&)
202 {
203 }
204
205 template<std::size_t I>
206 void
207 move(const_iterator&& other,
208 C<I> const&)
209 {
210 if(n_ == I)
211 {
212 new(buf_.data()) iter_t<I>{
213 std::move(other.iter<I>())};
214 return;
215 }
216 move(std::move(other), C<I+1>{});
217 }
218
219 void
220 copy(const_iterator const&,
221 C<sizeof...(Bn)> const&)
222 {
223 }
224
225 template<std::size_t I>
226 void
227 copy(const_iterator const& other,
228 C<I> const&)
229 {
230 if(n_ == I)
231 {
232 new(buf_.data()) iter_t<I>{
233 other.iter<I>()};
234 return;
235 }
236 copy(other, C<I+1>{});
237 }
238
239 bool
240 equal(const_iterator const&,
241 C<sizeof...(Bn)> const&) const
242 {
243 return true;
244 }
245
246 template<std::size_t I>
247 bool
248 equal(const_iterator const& other,
249 C<I> const&) const
250 {
251 if(n_ == I)
252 return iter<I>() == other.iter<I>();
253 return equal(other, C<I+1>{});
254 }
255
256 [[noreturn]]
257 reference
258 dereference(C<sizeof...(Bn)> const&) const
259 {
260 throw detail::make_exception<std::logic_error>(
261 "invalid iterator", __FILE__, __LINE__);
262 }
263
264 template<std::size_t I>
265 reference
266 dereference(C<I> const&) const
267 {
268 if(n_ == I)
269 return *iter<I>();
270 return dereference(C<I+1>{});
271 }
272
273 [[noreturn]]
274 void
275 increment(C<sizeof...(Bn)> const&)
276 {
277 throw detail::make_exception<std::logic_error>(
278 "invalid iterator", __FILE__, __LINE__);
279 }
280
281 template<std::size_t I>
282 void
283 increment(C<I> const&)
284 {
285 if(n_ == I)
286 {
287 if(++iter<I>() !=
288 std::get<I>(*bn_).end())
289 return;
290 using Iter = iter_t<I>;
291 iter<I>().~Iter();
292 return construct(C<I+1>{});
293 }
294 increment(C<I+1>{});
295 }
296
297 void
298 decrement(C<sizeof...(Bn)> const&)
299 {
300 auto constexpr I = sizeof...(Bn);
301 if(n_ == I)
302 {
303 --n_;
304 new(buf_.data()) iter_t<I-1>{
305 std::get<I-1>(*bn_).end()};
306 }
307 decrement(C<I-1>{});
308 }
309
310 void
311 decrement(C<0> const&)
312 {
313 auto constexpr I = 0;
314 if(iter<I>() != std::get<I>(*bn_).begin())
315 {
316 --iter<I>();
317 return;
318 }
319 throw detail::make_exception<std::logic_error>(
320 "invalid iterator", __FILE__, __LINE__);
321 }
322
323 template<std::size_t I>
324 void
325 decrement(C<I> const&)
326 {
327 if(n_ == I)
328 {
329 if(iter<I>() != std::get<I>(*bn_).begin())
330 {
331 --iter<I>();
332 return;
333 }
334 --n_;
335 using Iter = iter_t<I>;
336 iter<I>().~Iter();
337 new(buf_.data()) iter_t<I-1>{
338 std::get<I-1>(*bn_).end()};
339 }
340 decrement(C<I-1>{});
341 }
342};
343
344//------------------------------------------------------------------------------
345
346template<class... Bn>
347buffer_cat_helper<Bn...>::
348const_iterator::~const_iterator()
349{
350 destroy(C<0>{});
351}
352
353template<class... Bn>
354buffer_cat_helper<Bn...>::
355const_iterator::const_iterator()
356 : n_(sizeof...(Bn))
357 , bn_(nullptr)
358{
359}
360
361template<class... Bn>
362buffer_cat_helper<Bn...>::
363const_iterator::const_iterator(
364 std::tuple<Bn...> const& bn, bool at_end)
365 : bn_(&bn)
366{
367 if(at_end)
368 n_ = sizeof...(Bn);
369 else
370 construct(C<0>{});
371}
372
373template<class... Bn>
374buffer_cat_helper<Bn...>::
375const_iterator::const_iterator(const_iterator&& other)
376 : n_(other.n_)
377 , bn_(other.bn_)
378{
379 move(std::move(other), C<0>{});
380}
381
382template<class... Bn>
383buffer_cat_helper<Bn...>::
384const_iterator::const_iterator(const_iterator const& other)
385 : n_(other.n_)
386 , bn_(other.bn_)
387{
388 copy(other, C<0>{});
389}
390
391template<class... Bn>
392auto
393buffer_cat_helper<Bn...>::
394const_iterator::operator=(const_iterator&& other) ->
395 const_iterator&
396{
397 if(&other == this)
398 return *this;
399 destroy(C<0>{});
400 n_ = other.n_;
401 bn_ = other.bn_;
402 move(std::move(other), C<0>{});
403 return *this;
404}
405
406template<class... Bn>
407auto
408buffer_cat_helper<Bn...>::
409const_iterator::operator=(const_iterator const& other) ->
410const_iterator&
411{
412 if(&other == this)
413 return *this;
414 destroy(C<0>{});
415 n_ = other.n_;
416 bn_ = other.bn_;
417 copy(other, C<0>{});
418 return *this;
419}
420
421template<class... Bn>
422bool
423buffer_cat_helper<Bn...>::
424const_iterator::operator==(const_iterator const& other) const
425{
426 if(bn_ != other.bn_)
427 return false;
428 if(n_ != other.n_)
429 return false;
430 return equal(other, C<0>{});
431}
432
433template<class... Bn>
434auto
435buffer_cat_helper<Bn...>::
436const_iterator::operator*() const ->
437 reference
438{
439 return dereference(C<0>{});
440}
441
442template<class... Bn>
443auto
444buffer_cat_helper<Bn...>::
445const_iterator::operator++() ->
446 const_iterator&
447{
448 increment(C<0>{});
449 return *this;
450}
451
452template<class... Bn>
453auto
454buffer_cat_helper<Bn...>::
455const_iterator::operator--() ->
456 const_iterator&
457{
458 decrement(C<sizeof...(Bn)>{});
459 return *this;
460}
461
462template<class... Bn>
463inline
464auto
465buffer_cat_helper<Bn...>::begin() const ->
466 const_iterator
467{
468 return const_iterator{bn_, false};
469}
470
471template<class... Bn>
472inline
473auto
474buffer_cat_helper<Bn...>::end() const ->
475 const_iterator
476{
477 return const_iterator{bn_, true};
478}
479
480} // detail
481} // beast
482
483#endif