2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
8 #ifndef BEAST_DETAIL_BUFFER_CAT_HPP
9 #define BEAST_DETAIL_BUFFER_CAT_HPP
11 #include <beast/core/buffer_concepts.hpp>
12 #include <beast/core/detail/type_traits.hpp>
13 #include <boost/asio/buffer.hpp>
25 struct common_buffers_type
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;
36 class buffer_cat_helper
38 std::tuple<Bn...> bn_;
41 using value_type = typename
42 common_buffers_type<Bn...>::type;
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;
52 buffer_cat_helper(Bn const&... bn)
65 class buffer_cat_helper<Bn...>::const_iterator
68 std::tuple<Bn...> const* bn_;
69 std::array<std::uint8_t,
70 max_sizeof<typename Bn::const_iterator...>()> buf_;
72 friend class buffer_cat_helper<Bn...>;
74 template<std::size_t I>
75 using C = std::integral_constant<std::size_t, I>;
77 template<std::size_t I>
78 using iter_t = typename std::tuple_element<
79 I, std::tuple<Bn...>>::type::const_iterator;
81 template<std::size_t I>
86 return *reinterpret_cast<
87 iter_t<I>*>(static_cast<void*>(
91 template<std::size_t I>
96 return *reinterpret_cast<
97 iter_t<I> const*>(static_cast<
98 void const*>(buf_.data()));
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;
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);
118 operator==(const_iterator const& other) const;
121 operator!=(const_iterator const& other) const
123 return !(*this == other);
130 operator->() const = delete;
156 std::tuple<Bn...> const& bn, bool at_end);
159 construct(C<sizeof...(Bn)> const&)
161 auto constexpr I = sizeof...(Bn);
165 template<std::size_t I>
167 construct(C<I> const&)
169 if(std::get<I>(*bn_).begin() !=
170 std::get<I>(*bn_).end())
173 new(buf_.data()) iter_t<I>{
174 std::get<I>(*bn_).begin()};
181 destroy(C<sizeof...(Bn)> const&)
186 template<std::size_t I>
192 using Iter = iter_t<I>;
200 move(const_iterator&&,
201 C<sizeof...(Bn)> const&)
205 template<std::size_t I>
207 move(const_iterator&& other,
212 new(buf_.data()) iter_t<I>{
213 std::move(other.iter<I>())};
216 move(std::move(other), C<I+1>{});
220 copy(const_iterator const&,
221 C<sizeof...(Bn)> const&)
225 template<std::size_t I>
227 copy(const_iterator const& other,
232 new(buf_.data()) iter_t<I>{
236 copy(other, C<I+1>{});
240 equal(const_iterator const&,
241 C<sizeof...(Bn)> const&) const
246 template<std::size_t I>
248 equal(const_iterator const& other,
252 return iter<I>() == other.iter<I>();
253 return equal(other, C<I+1>{});
258 dereference(C<sizeof...(Bn)> const&) const
260 throw detail::make_exception<std::logic_error>(
261 "invalid iterator", __FILE__, __LINE__);
264 template<std::size_t I>
266 dereference(C<I> const&) const
270 return dereference(C<I+1>{});
275 increment(C<sizeof...(Bn)> const&)
277 throw detail::make_exception<std::logic_error>(
278 "invalid iterator", __FILE__, __LINE__);
281 template<std::size_t I>
283 increment(C<I> const&)
288 std::get<I>(*bn_).end())
290 using Iter = iter_t<I>;
292 return construct(C<I+1>{});
298 decrement(C<sizeof...(Bn)> const&)
300 auto constexpr I = sizeof...(Bn);
304 new(buf_.data()) iter_t<I-1>{
305 std::get<I-1>(*bn_).end()};
311 decrement(C<0> const&)
313 auto constexpr I = 0;
314 if(iter<I>() != std::get<I>(*bn_).begin())
319 throw detail::make_exception<std::logic_error>(
320 "invalid iterator", __FILE__, __LINE__);
323 template<std::size_t I>
325 decrement(C<I> const&)
329 if(iter<I>() != std::get<I>(*bn_).begin())
335 using Iter = iter_t<I>;
337 new(buf_.data()) iter_t<I-1>{
338 std::get<I-1>(*bn_).end()};
344 //------------------------------------------------------------------------------
346 template<class... Bn>
347 buffer_cat_helper<Bn...>::
348 const_iterator::~const_iterator()
353 template<class... Bn>
354 buffer_cat_helper<Bn...>::
355 const_iterator::const_iterator()
361 template<class... Bn>
362 buffer_cat_helper<Bn...>::
363 const_iterator::const_iterator(
364 std::tuple<Bn...> const& bn, bool at_end)
373 template<class... Bn>
374 buffer_cat_helper<Bn...>::
375 const_iterator::const_iterator(const_iterator&& other)
379 move(std::move(other), C<0>{});
382 template<class... Bn>
383 buffer_cat_helper<Bn...>::
384 const_iterator::const_iterator(const_iterator const& other)
391 template<class... Bn>
393 buffer_cat_helper<Bn...>::
394 const_iterator::operator=(const_iterator&& other) ->
402 move(std::move(other), C<0>{});
406 template<class... Bn>
408 buffer_cat_helper<Bn...>::
409 const_iterator::operator=(const_iterator const& other) ->
421 template<class... Bn>
423 buffer_cat_helper<Bn...>::
424 const_iterator::operator==(const_iterator const& other) const
430 return equal(other, C<0>{});
433 template<class... Bn>
435 buffer_cat_helper<Bn...>::
436 const_iterator::operator*() const ->
439 return dereference(C<0>{});
442 template<class... Bn>
444 buffer_cat_helper<Bn...>::
445 const_iterator::operator++() ->
452 template<class... Bn>
454 buffer_cat_helper<Bn...>::
455 const_iterator::operator--() ->
458 decrement(C<sizeof...(Bn)>{});
462 template<class... Bn>
465 buffer_cat_helper<Bn...>::begin() const ->
468 return const_iterator{bn_, false};
471 template<class... Bn>
474 buffer_cat_helper<Bn...>::end() const ->
477 return const_iterator{bn_, true};