// // 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 namespace beast { namespace detail { template class buffer_cat_helper { std::tuple bs_; public: using value_type = ValueType; 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&&) = default; buffer_cat_helper& operator=(buffer_cat_helper const&) = default; explicit buffer_cat_helper(Bs const&... bs) : bs_(bs...) { } const_iterator begin() const; const_iterator end() const; }; template std::size_t constexpr max_sizeof() { return sizeof(U); } template std::size_t constexpr max_sizeof() { return max_sizeof() > max_sizeof() ? max_sizeof() : max_sizeof(); } template class buffer_cat_helper< ValueType, Bs...>::const_iterator { std::size_t n_; std::tuple const* bs_; 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 = ValueType; 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& bs, bool at_end); void construct(C) { auto constexpr I = sizeof...(Bs); n_ = I; } template void construct(C) { if(std::get(*bs_).begin() != std::get(*bs_).end()) { n_ = I; new(buf_.data()) iter_t{ std::get(*bs_).begin()}; return; } construct(C{}); } void destroy(C) { return; } template void destroy(C) { if(n_ == I) { using Iter = iter_t; iter().~Iter(); return; } destroy(C{}); } void move(C, const_iterator&&) { } template void move(C, const_iterator&& other) { if(n_ == I) { new(buf_.data()) iter_t{ std::move(other.iter())}; return; } move(C{}, std::move(other)); } void copy(C, const_iterator const&) { } template void copy(C, const_iterator const& other) { if(n_ == I) { new(buf_.data()) iter_t{ other.iter()}; return; } copy(C{}, other); } bool equal(C, const_iterator const&) const { return true; } template bool equal(C, const_iterator const& other) const { if(n_ == I) return iter() == other.iter(); return equal(C{}, other); } [[noreturn]] reference dereference(C) const { throw std::logic_error("invalid iterator"); } template reference dereference(C) const { if(n_ == I) return *iter(); return dereference(C{}); } [[noreturn]] void increment(C) { throw std::logic_error("invalid iterator"); } template void increment(C) { if(n_ == I) { if(++iter() != std::get(*bs_).end()) return; using Iter = iter_t; iter().~Iter(); return construct(C{}); } increment(C{}); } void decrement(C) { auto constexpr I = sizeof...(Bs); if(n_ == I) { --n_; new(buf_.data()) iter_t{ std::get(*bs_).end()}; } decrement(C{}); } void decrement(C<0>) { auto constexpr I = 0; if(iter() != std::get(*bs_).begin()) { --iter(); return; } throw std::logic_error("invalid iterator"); } template void decrement(C) { if(n_ == I) { if(iter() != std::get(*bs_).begin()) { --iter(); return; } --n_; using Iter = iter_t; iter().~Iter(); new(buf_.data()) iter_t{ std::get(*bs_).end()}; } decrement(C{}); } }; //------------------------------------------------------------------------------ template buffer_cat_helper:: const_iterator::~const_iterator() { destroy(C<0>{}); } template buffer_cat_helper:: const_iterator::const_iterator() : n_(sizeof...(Bs)) , bs_(nullptr) { } template buffer_cat_helper:: const_iterator::const_iterator( std::tuple const& bs, bool at_end) : bs_(&bs) { if(at_end) n_ = sizeof...(Bs); else construct(C<0>{}); } template buffer_cat_helper:: const_iterator::const_iterator(const_iterator&& other) : n_(other.n_) , bs_(other.bs_) { move(C<0>{}, std::move(other)); } template buffer_cat_helper:: const_iterator::const_iterator(const_iterator const& other) : n_(other.n_) , bs_(other.bs_) { copy(C<0>{}, other); } template auto buffer_cat_helper:: const_iterator::operator=(const_iterator&& other) -> const_iterator& { if(&other == this) return *this; destroy(C<0>{}); n_ = other.n_; bs_ = other.bs_; move(C<0>{}, std::move(other)); 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_; bs_ = other.bs_; copy(C<0>{}, other); return *this; } template bool buffer_cat_helper:: const_iterator::operator==(const_iterator const& other) const { if(bs_ != other.bs_) return false; if(n_ != other.n_) return false; return equal(C<0>{}, other); } 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 auto buffer_cat_helper::begin() const -> const_iterator { return const_iterator(bs_, false); } template auto buffer_cat_helper::end() const -> const_iterator { return const_iterator(bs_, true); } } // detail } // beast #endif