// // Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BEAST_DETAIL_BUFFER_CAT_HPP #define BEAST_DETAIL_BUFFER_CAT_HPP #include #include #include #include #include #include #include #include #include namespace beast { namespace detail { template struct common_buffers_type { using type = typename std::conditional< std::is_convertible, typename repeat_tuple::type>::value, boost::asio::mutable_buffer, boost::asio::const_buffer>::type; }; template class buffer_cat_helper { std::tuple bn_; public: using value_type = typename common_buffers_type::type; class const_iterator; buffer_cat_helper(buffer_cat_helper&&) = default; buffer_cat_helper(buffer_cat_helper const&) = default; buffer_cat_helper& operator=(buffer_cat_helper&&) = delete; buffer_cat_helper& operator=(buffer_cat_helper const&) = delete; explicit buffer_cat_helper(Bn const&... bn) : bn_(bn...) { } const_iterator begin() const; const_iterator end() const; }; template class buffer_cat_helper::const_iterator { std::size_t n_; std::tuple const* bn_; std::array()> buf_; friend class buffer_cat_helper; template using C = std::integral_constant; template using iter_t = typename std::tuple_element< I, std::tuple>::type::const_iterator; template iter_t& iter() { return *reinterpret_cast< iter_t*>(buf_.data()); } template iter_t const& iter() const { return *reinterpret_cast< iter_t const*>(buf_.data()); } public: using value_type = typename common_buffers_type::type; using pointer = value_type const*; using reference = value_type; using difference_type = std::ptrdiff_t; using iterator_category = std::bidirectional_iterator_tag; ~const_iterator(); const_iterator(); const_iterator(const_iterator&& other); const_iterator(const_iterator const& other); const_iterator& operator=(const_iterator&& other); const_iterator& operator=(const_iterator const& other); bool operator==(const_iterator const& other) const; bool operator!=(const_iterator const& other) const { return !(*this == other); } reference operator*() const; pointer operator->() const = delete; const_iterator& operator++(); const_iterator operator++(int) { auto temp = *this; ++(*this); return temp; } const_iterator& operator--(); const_iterator operator--(int) { auto temp = *this; --(*this); return temp; } private: const_iterator( std::tuple const& bn, bool at_end); void construct(C const&) { auto constexpr I = sizeof...(Bn); n_ = I; } template void construct(C const&) { if(std::get(*bn_).begin() != std::get(*bn_).end()) { n_ = I; new(buf_.data()) iter_t{ std::get(*bn_).begin()}; return; } construct(C{}); } void destroy(C const&) { return; } template void destroy(C const&) { if(n_ == I) { using Iter = iter_t; iter().~Iter(); return; } destroy(C{}); } void move(const_iterator&&, C const&) { } template void move(const_iterator&& other, C const&) { if(n_ == I) { new(buf_.data()) iter_t{ std::move(other.iter())}; return; } move(std::move(other), C{}); } void copy(const_iterator const&, C const&) { } template void copy(const_iterator const& other, C const&) { if(n_ == I) { new(buf_.data()) iter_t{ other.iter()}; return; } copy(other, C{}); } bool equal(const_iterator const&, C const&) const { return true; } template bool equal(const_iterator const& other, C const&) const { if(n_ == I) return iter() == other.iter(); return equal(other, C{}); } [[noreturn]] reference dereference(C const&) const { throw std::logic_error("invalid iterator"); } template reference dereference(C const&) const { if(n_ == I) return *iter(); return dereference(C{}); } [[noreturn]] void increment(C const&) { throw std::logic_error("invalid iterator"); } template void increment(C const&) { if(n_ == I) { if(++iter() != std::get(*bn_).end()) return; using Iter = iter_t; iter().~Iter(); return construct(C{}); } increment(C{}); } void decrement(C const&) { auto constexpr I = sizeof...(Bn); if(n_ == I) { --n_; new(buf_.data()) iter_t{ std::get(*bn_).end()}; } decrement(C{}); } void decrement(C<0> const&) { auto constexpr I = 0; if(iter() != std::get(*bn_).begin()) { --iter(); return; } throw std::logic_error("invalid iterator"); } template void decrement(C const&) { if(n_ == I) { if(iter() != std::get(*bn_).begin()) { --iter(); return; } --n_; using Iter = iter_t; iter().~Iter(); new(buf_.data()) iter_t{ std::get(*bn_).end()}; } decrement(C{}); } }; //------------------------------------------------------------------------------ template buffer_cat_helper:: const_iterator::~const_iterator() { destroy(C<0>{}); } template buffer_cat_helper:: const_iterator::const_iterator() : n_(sizeof...(Bn)) , bn_(nullptr) { } template buffer_cat_helper:: const_iterator::const_iterator( std::tuple const& bn, bool at_end) : bn_(&bn) { if(at_end) n_ = sizeof...(Bn); else construct(C<0>{}); } template buffer_cat_helper:: const_iterator::const_iterator(const_iterator&& other) : n_(other.n_) , bn_(other.bn_) { move(std::move(other), C<0>{}); } template buffer_cat_helper:: const_iterator::const_iterator(const_iterator const& other) : n_(other.n_) , bn_(other.bn_) { copy(other, C<0>{}); } template auto buffer_cat_helper:: const_iterator::operator=(const_iterator&& other) -> const_iterator& { if(&other == this) return *this; destroy(C<0>{}); n_ = other.n_; bn_ = other.bn_; move(std::move(other), C<0>{}); return *this; } template auto buffer_cat_helper:: const_iterator::operator=(const_iterator const& other) -> const_iterator& { if(&other == this) return *this; destroy(C<0>{}); n_ = other.n_; bn_ = other.bn_; copy(other, C<0>{}); return *this; } template bool buffer_cat_helper:: const_iterator::operator==(const_iterator const& other) const { if(bn_ != other.bn_) return false; if(n_ != other.n_) return false; return equal(other, C<0>{}); } template auto buffer_cat_helper:: const_iterator::operator*() const -> reference { return dereference(C<0>{}); } template auto buffer_cat_helper:: const_iterator::operator++() -> const_iterator& { increment(C<0>{}); return *this; } template auto buffer_cat_helper:: const_iterator::operator--() -> const_iterator& { decrement(C{}); return *this; } template inline auto buffer_cat_helper::begin() const -> const_iterator { return const_iterator{bn_, false}; } template inline auto buffer_cat_helper::end() const -> const_iterator { return const_iterator{bn_, true}; } } // detail } // beast #endif