// // Copyright (c) 2016-2019 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) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP #define BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP #include #include #include #include #include #include #include #include namespace boost { namespace beast { template class buffers_prefix_view::const_iterator { friend class buffers_prefix_view; buffers_prefix_view const* b_ = nullptr; std::size_t remain_ = 0; iter_type it_{}; public: #if BOOST_WORKAROUND(BOOST_MSVC, < 1910) using value_type = typename std::conditional< boost::is_convertible::value_type, net::mutable_buffer>::value, net::mutable_buffer, net::const_buffer>::type; #else using value_type = buffers_type; #endif BOOST_STATIC_ASSERT(std::is_same< typename const_iterator::value_type, typename buffers_prefix_view::value_type>::value); using pointer = value_type const*; using reference = value_type; using difference_type = std::ptrdiff_t; using iterator_category = std::bidirectional_iterator_tag; const_iterator() = default; const_iterator( const_iterator const& other) = default; const_iterator& operator=( const_iterator const& other) = default; bool operator==(const_iterator const& other) const { return b_ == other.b_ && it_ == other.it_; } bool operator!=(const_iterator const& other) const { return !(*this == other); } reference operator*() const { value_type v(*it_); if(remain_ < v.size()) return {v.data(), remain_}; return v; } pointer operator->() const = delete; const_iterator& operator++() { value_type const v = *it_++; remain_ -= v.size(); return *this; } const_iterator operator++(int) { auto temp = *this; value_type const v = *it_++; remain_ -= v.size(); return temp; } const_iterator& operator--() { value_type const v = *--it_; remain_ += v.size(); return *this; } const_iterator operator--(int) { auto temp = *this; value_type const v = *--it_; remain_ += v.size(); return temp; } private: const_iterator( buffers_prefix_view const& b, std::true_type) : b_(&b) , remain_(b.remain_) , it_(b_->end_) { } const_iterator( buffers_prefix_view const& b, std::false_type) : b_(&b) , remain_(b_->size_) , it_(net::buffer_sequence_begin(b_->bs_)) { } }; //------------------------------------------------------------------------------ template void buffers_prefix_view:: setup(std::size_t size) { size_ = 0; remain_ = 0; end_ = net::buffer_sequence_begin(bs_); auto const last = bs_.end(); while(end_ != last) { auto const len = buffer_bytes(*end_++); if(len >= size) { size_ += size; // by design, this subtraction can wrap BOOST_STATIC_ASSERT(std::is_unsigned< decltype(remain_)>::value); remain_ = size - len; break; } size -= len; size_ += len; } } template buffers_prefix_view:: buffers_prefix_view( buffers_prefix_view const& other, std::size_t dist) : bs_(other.bs_) , size_(other.size_) , remain_(other.remain_) , end_(std::next(bs_.begin(), dist)) { } template buffers_prefix_view:: buffers_prefix_view(buffers_prefix_view const& other) : buffers_prefix_view(other, std::distance( net::buffer_sequence_begin(other.bs_), other.end_)) { } template auto buffers_prefix_view:: operator=(buffers_prefix_view const& other) -> buffers_prefix_view& { auto const dist = std::distance( net::buffer_sequence_begin(other.bs_), other.end_); bs_ = other.bs_; size_ = other.size_; remain_ = other.remain_; end_ = std::next( net::buffer_sequence_begin(bs_), dist); return *this; } template buffers_prefix_view:: buffers_prefix_view( std::size_t size, Buffers const& bs) : bs_(bs) { setup(size); } template template buffers_prefix_view:: buffers_prefix_view( std::size_t size, boost::in_place_init_t, Args&&... args) : bs_(std::forward(args)...) { setup(size); } template auto buffers_prefix_view:: begin() const -> const_iterator { return const_iterator{ *this, std::false_type{}}; } template auto buffers_prefix_view:: end() const -> const_iterator { return const_iterator{ *this, std::true_type{}}; } //------------------------------------------------------------------------------ template<> class buffers_prefix_view : public net::const_buffer { public: using net::const_buffer::const_buffer; buffers_prefix_view(buffers_prefix_view const&) = default; buffers_prefix_view& operator=(buffers_prefix_view const&) = default; buffers_prefix_view( std::size_t size, net::const_buffer buffer) : net::const_buffer( buffer.data(), std::min(size, buffer.size()) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) , buffer.get_debug_check() #endif ) { } template buffers_prefix_view( std::size_t size, boost::in_place_init_t, Args&&... args) : buffers_prefix_view(size, net::const_buffer( std::forward(args)...)) { } }; //------------------------------------------------------------------------------ template<> class buffers_prefix_view : public net::mutable_buffer { public: using net::mutable_buffer::mutable_buffer; buffers_prefix_view(buffers_prefix_view const&) = default; buffers_prefix_view& operator=(buffers_prefix_view const&) = default; buffers_prefix_view( std::size_t size, net::mutable_buffer buffer) : net::mutable_buffer( buffer.data(), std::min(size, buffer.size()) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) , buffer.get_debug_check() #endif ) { } template buffers_prefix_view( std::size_t size, boost::in_place_init_t, Args&&... args) : buffers_prefix_view(size, net::mutable_buffer( std::forward(args)...)) { } }; } // beast } // boost #endif