2 // Copyright (c) 2016-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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_IMPL_BUFFERS_CAT_IPP
11 #define BOOST_BEAST_IMPL_BUFFERS_CAT_IPP
13 #include <boost/beast/core/detail/type_traits.hpp>
14 #include <boost/asio/buffer.hpp>
15 #include <boost/throw_exception.hpp>
28 class buffers_cat_view<Bn...>::const_iterator
31 std::tuple<Bn...> const* bn_;
32 std::array<char, detail::max_sizeof<
33 typename detail::buffer_sequence_iterator<Bn>::type...>()> buf_;
35 friend class buffers_cat_view<Bn...>;
37 template<std::size_t I>
38 using C = std::integral_constant<std::size_t, I>;
40 template<std::size_t I>
41 using iter_t = typename detail::buffer_sequence_iterator<
42 typename std::tuple_element<I, std::tuple<Bn...>>::type>::type;
44 template<std::size_t I>
49 return *reinterpret_cast<
50 iter_t<I>*>(static_cast<void*>(buf_.data()));
53 template<std::size_t I>
58 return *reinterpret_cast<
59 iter_t<I> const*>(static_cast<
60 void const*>(buf_.data()));
64 using value_type = typename
65 detail::common_buffers_type<Bn...>::type;
66 using pointer = value_type const*;
67 using reference = value_type;
68 using difference_type = std::ptrdiff_t;
69 using iterator_category =
70 std::bidirectional_iterator_tag;
74 const_iterator(const_iterator&& other);
75 const_iterator(const_iterator const& other);
76 const_iterator& operator=(const_iterator&& other);
77 const_iterator& operator=(const_iterator const& other);
80 operator==(const_iterator const& other) const;
83 operator!=(const_iterator const& other) const
85 return ! (*this == other);
92 operator->() const = delete;
108 std::tuple<Bn...> const& bn, bool at_end);
111 construct(C<sizeof...(Bn)> const&)
113 auto constexpr I = sizeof...(Bn);
117 template<std::size_t I>
119 construct(C<I> const&)
121 if(boost::asio::buffer_size(
122 std::get<I>(*bn_)) != 0)
125 new(&buf_[0]) iter_t<I>{
126 boost::asio::buffer_sequence_begin(
134 rconstruct(C<0> const&)
136 auto constexpr I = 0;
137 if(boost::asio::buffer_size(
138 std::get<I>(*bn_)) != 0)
141 new(&buf_[0]) iter_t<I>{
142 boost::asio::buffer_sequence_end(
146 BOOST_THROW_EXCEPTION(std::logic_error{
147 "invalid iterator"});
150 template<std::size_t I>
152 rconstruct(C<I> const&)
154 if(boost::asio::buffer_size(
155 std::get<I>(*bn_)) != 0)
158 new(&buf_[0]) iter_t<I>{
159 boost::asio::buffer_sequence_end(
163 rconstruct(C<I-1>{});
167 destroy(C<sizeof...(Bn)> const&)
172 template<std::size_t I>
178 using Iter = iter_t<I>;
186 move(const_iterator&&,
187 C<sizeof...(Bn)> const&)
191 template<std::size_t I>
193 move(const_iterator&& other,
198 new(&buf_[0]) iter_t<I>{
199 std::move(other.iter<I>())};
202 move(std::move(other), C<I+1>{});
206 copy(const_iterator const&,
207 C<sizeof...(Bn)> const&)
211 template<std::size_t I>
213 copy(const_iterator const& other,
218 new(&buf_[0]) iter_t<I>{
222 copy(other, C<I+1>{});
226 equal(const_iterator const&,
227 C<sizeof...(Bn)> const&) const
232 template<std::size_t I>
234 equal(const_iterator const& other,
238 return iter<I>() == other.iter<I>();
239 return equal(other, C<I+1>{});
244 dereference(C<sizeof...(Bn)> const&) const
246 BOOST_THROW_EXCEPTION(std::logic_error{
247 "invalid iterator"});
250 template<std::size_t I>
252 dereference(C<I> const&) const
256 return dereference(C<I+1>{});
261 increment(C<sizeof...(Bn)> const&)
263 BOOST_THROW_EXCEPTION(std::logic_error{
264 "invalid iterator"});
267 template<std::size_t I>
269 increment(C<I> const&)
274 boost::asio::buffer_sequence_end(
277 using Iter = iter_t<I>;
279 return construct(C<I+1>{});
285 decrement(C<sizeof...(Bn)> const&)
287 auto constexpr I = sizeof...(Bn);
289 rconstruct(C<I-1>{});
293 template<std::size_t I>
295 decrement(C<I> const&)
300 boost::asio::buffer_sequence_begin(
307 using Iter = iter_t<I>;
309 rconstruct(C<I-1>{});
315 decrement(C<0> const&)
317 auto constexpr I = 0;
319 boost::asio::buffer_sequence_begin(
325 BOOST_THROW_EXCEPTION(std::logic_error{
326 "invalid iterator"});
330 //------------------------------------------------------------------------------
332 template<class... Bn>
333 buffers_cat_view<Bn...>::
334 const_iterator::~const_iterator()
339 template<class... Bn>
340 buffers_cat_view<Bn...>::
341 const_iterator::const_iterator()
347 template<class... Bn>
348 buffers_cat_view<Bn...>::
349 const_iterator::const_iterator(
350 std::tuple<Bn...> const& bn, bool at_end)
359 template<class... Bn>
360 buffers_cat_view<Bn...>::
361 const_iterator::const_iterator(const_iterator&& other)
365 move(std::move(other), C<0>{});
368 template<class... Bn>
369 buffers_cat_view<Bn...>::
370 const_iterator::const_iterator(const_iterator const& other)
377 template<class... Bn>
379 buffers_cat_view<Bn...>::
380 const_iterator::operator=(const_iterator&& other) ->
388 // VFALCO What about exceptions?
389 move(std::move(other), C<0>{});
393 template<class... Bn>
395 buffers_cat_view<Bn...>::
396 const_iterator::operator=(const_iterator const& other) ->
404 // VFALCO What about exceptions?
409 template<class... Bn>
411 buffers_cat_view<Bn...>::
412 const_iterator::operator==(const_iterator const& other) const
418 return equal(other, C<0>{});
421 template<class... Bn>
423 buffers_cat_view<Bn...>::
424 const_iterator::operator*() const ->
427 return dereference(C<0>{});
430 template<class... Bn>
432 buffers_cat_view<Bn...>::
433 const_iterator::operator++() ->
440 template<class... Bn>
442 buffers_cat_view<Bn...>::
443 const_iterator::operator++(int) ->
451 template<class... Bn>
453 buffers_cat_view<Bn...>::
454 const_iterator::operator--() ->
457 decrement(C<sizeof...(Bn)>{});
461 template<class... Bn>
463 buffers_cat_view<Bn...>::
464 const_iterator::operator--(int) ->
472 //------------------------------------------------------------------------------
474 template<class... Bn>
475 buffers_cat_view<Bn...>::
476 buffers_cat_view(Bn const&... bn)
482 template<class... Bn>
485 buffers_cat_view<Bn...>::begin() const ->
488 return const_iterator{bn_, false};
491 template<class... Bn>
494 buffers_cat_view<Bn...>::end() const ->
497 return const_iterator{bn_, true};