// // Copyright (c) 2013-2017 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_IMPL_BUFFER_CAT_IPP #define BEAST_IMPL_BUFFER_CAT_IPP #include #include #include #include #include #include #include #include #include #include namespace beast { template class buffer_cat_view::const_iterator { #if 0 static_assert( detail::is_all_const_buffer_sequence::value, "BufferSequence requirements not met"); #endif std::size_t n_; std::tuple const* bn_; std::array()> buf_; friend class buffer_cat_view; template using C = std::integral_constant; template using iter_t = typename std::tuple_element< I, std::tuple>::type::const_iterator; template iter_t& iter() { // type-pun return *reinterpret_cast< iter_t*>(static_cast(buf_.data())); } template iter_t const& iter() const { // type-pun return *reinterpret_cast< iter_t const*>(static_cast< void const*>(buf_.data())); } public: using value_type = typename detail::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); const_iterator& operator--(); const_iterator operator--(int); 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(boost::asio::buffer_size( std::get(*bn_)) != 0) { n_ = I; new(&buf_[0]) iter_t{ std::get(*bn_).begin()}; return; } construct(C{}); } void rconstruct(C<0> const&) { auto constexpr I = 0; if(boost::asio::buffer_size( std::get(*bn_)) != 0) { n_ = I; new(&buf_[0]) iter_t{ std::get(*bn_).end()}; return; } BOOST_THROW_EXCEPTION(std::logic_error{ "invalid iterator"}); } template void rconstruct(C const&) { if(boost::asio::buffer_size( std::get(*bn_)) != 0) { n_ = I; new(&buf_[0]) iter_t{ std::get(*bn_).end()}; return; } rconstruct(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_[0]) 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_[0]) 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 { BOOST_THROW_EXCEPTION(std::logic_error{ "invalid iterator"}); } template reference dereference(C const&) const { if(n_ == I) return *iter(); return dereference(C{}); } [[noreturn]] void increment(C const&) { BOOST_THROW_EXCEPTION(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) rconstruct(C{}); decrement(C{}); } template void decrement(C const&) { if(n_ == I) { if(iter() != std::get(*bn_).begin()) { --iter(); return; } --n_; using Iter = iter_t; iter().~Iter(); rconstruct(C{}); } decrement(C{}); } void decrement(C<0> const&) { auto constexpr I = 0; if(iter() != std::get(*bn_).begin()) { --iter(); return; } BOOST_THROW_EXCEPTION(std::logic_error{ "invalid iterator"}); } }; //------------------------------------------------------------------------------ template buffer_cat_view:: const_iterator::~const_iterator() { destroy(C<0>{}); } template buffer_cat_view:: const_iterator::const_iterator() : n_(sizeof...(Bn)) , bn_(nullptr) { } template buffer_cat_view:: 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_view:: const_iterator::const_iterator(const_iterator&& other) : n_(other.n_) , bn_(other.bn_) { move(std::move(other), C<0>{}); } template buffer_cat_view:: const_iterator::const_iterator(const_iterator const& other) : n_(other.n_) , bn_(other.bn_) { copy(other, C<0>{}); } template auto buffer_cat_view:: const_iterator::operator=(const_iterator&& other) -> const_iterator& { if(&other == this) return *this; destroy(C<0>{}); n_ = other.n_; bn_ = other.bn_; // VFALCO What about exceptions? move(std::move(other), C<0>{}); return *this; } template auto buffer_cat_view:: const_iterator::operator=(const_iterator const& other) -> const_iterator& { if(&other == this) return *this; destroy(C<0>{}); n_ = other.n_; bn_ = other.bn_; // VFALCO What about exceptions? copy(other, C<0>{}); return *this; } template bool buffer_cat_view:: 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_view:: const_iterator::operator*() const -> reference { return dereference(C<0>{}); } template auto buffer_cat_view:: const_iterator::operator++() -> const_iterator& { increment(C<0>{}); return *this; } template auto buffer_cat_view:: const_iterator::operator++(int) -> const_iterator { auto temp = *this; ++(*this); return temp; } template auto buffer_cat_view:: const_iterator::operator--() -> const_iterator& { decrement(C{}); return *this; } template auto buffer_cat_view:: const_iterator::operator--(int) -> const_iterator { auto temp = *this; --(*this); return temp; } //------------------------------------------------------------------------------ template buffer_cat_view:: buffer_cat_view(Bn const&... bn) : bn_(bn...) { } template inline auto buffer_cat_view::begin() const -> const_iterator { return const_iterator{bn_, false}; } template inline auto buffer_cat_view::end() const -> const_iterator { return const_iterator{bn_, true}; } } // beast #endif