]> git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/include/beast/core/detail/buffer_cat.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / Beast / include / beast / core / detail / buffer_cat.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_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
21 namespace beast {
22 namespace detail {
23
24 template<class... Bn>
25 struct 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
35 template<class... Bn>
36 class buffer_cat_helper
37 {
38 std::tuple<Bn...> bn_;
39
40 public:
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
64 template<class... Bn>
65 class 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
101 public:
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
154 private:
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
346 template<class... Bn>
347 buffer_cat_helper<Bn...>::
348 const_iterator::~const_iterator()
349 {
350 destroy(C<0>{});
351 }
352
353 template<class... Bn>
354 buffer_cat_helper<Bn...>::
355 const_iterator::const_iterator()
356 : n_(sizeof...(Bn))
357 , bn_(nullptr)
358 {
359 }
360
361 template<class... Bn>
362 buffer_cat_helper<Bn...>::
363 const_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
373 template<class... Bn>
374 buffer_cat_helper<Bn...>::
375 const_iterator::const_iterator(const_iterator&& other)
376 : n_(other.n_)
377 , bn_(other.bn_)
378 {
379 move(std::move(other), C<0>{});
380 }
381
382 template<class... Bn>
383 buffer_cat_helper<Bn...>::
384 const_iterator::const_iterator(const_iterator const& other)
385 : n_(other.n_)
386 , bn_(other.bn_)
387 {
388 copy(other, C<0>{});
389 }
390
391 template<class... Bn>
392 auto
393 buffer_cat_helper<Bn...>::
394 const_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
406 template<class... Bn>
407 auto
408 buffer_cat_helper<Bn...>::
409 const_iterator::operator=(const_iterator const& other) ->
410 const_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
421 template<class... Bn>
422 bool
423 buffer_cat_helper<Bn...>::
424 const_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
433 template<class... Bn>
434 auto
435 buffer_cat_helper<Bn...>::
436 const_iterator::operator*() const ->
437 reference
438 {
439 return dereference(C<0>{});
440 }
441
442 template<class... Bn>
443 auto
444 buffer_cat_helper<Bn...>::
445 const_iterator::operator++() ->
446 const_iterator&
447 {
448 increment(C<0>{});
449 return *this;
450 }
451
452 template<class... Bn>
453 auto
454 buffer_cat_helper<Bn...>::
455 const_iterator::operator--() ->
456 const_iterator&
457 {
458 decrement(C<sizeof...(Bn)>{});
459 return *this;
460 }
461
462 template<class... Bn>
463 inline
464 auto
465 buffer_cat_helper<Bn...>::begin() const ->
466 const_iterator
467 {
468 return const_iterator{bn_, false};
469 }
470
471 template<class... Bn>
472 inline
473 auto
474 buffer_cat_helper<Bn...>::end() const ->
475 const_iterator
476 {
477 return const_iterator{bn_, true};
478 }
479
480 } // detail
481 } // beast
482
483 #endif