// // Copyright (c) 2016-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) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_IMPL_BUFFERS_PREFIX_IPP #define BOOST_BEAST_IMPL_BUFFERS_PREFIX_IPP #include #include #include #include #include #include namespace boost { namespace beast { namespace detail { inline boost::asio::const_buffer buffers_prefix(std::size_t size, boost::asio::const_buffer buffer) { return {buffer.data(), (std::min)(size, buffer.size())}; } inline boost::asio::mutable_buffer buffers_prefix(std::size_t size, boost::asio::mutable_buffer buffer) { return {buffer.data(), (std::min)(size, buffer.size())}; } } // detail template class buffers_prefix_view::const_iterator { friend class buffers_prefix_view; buffers_prefix_view const* b_ = nullptr; std::size_t remain_; iter_type it_; public: using value_type = typename std::conditional< std::is_convertible::value_type, boost::asio::mutable_buffer>::value, boost::asio::mutable_buffer, boost::asio::const_buffer>::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() = default; const_iterator(const_iterator&& other) = default; const_iterator(const_iterator const& other) = default; const_iterator& operator=(const_iterator&& 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 { return detail::buffers_prefix(remain_, *it_); } pointer operator->() const = delete; const_iterator& operator++() { remain_ -= boost::asio::buffer_size(*it_++); return *this; } const_iterator operator++(int) { auto temp = *this; remain_ -= boost::asio::buffer_size(*it_++); return temp; } const_iterator& operator--() { remain_ += boost::asio::buffer_size(*--it_); return *this; } const_iterator operator--(int) { auto temp = *this; remain_ += boost::asio::buffer_size(*--it_); return temp; } private: const_iterator(buffers_prefix_view const& b, std::true_type) : b_(&b) , remain_(0) , it_(b_->end_) { } const_iterator(buffers_prefix_view const& b, std::false_type) : b_(&b) , remain_(b_->size_) , it_(boost::asio::buffer_sequence_begin(b_->bs_)) { } }; template void buffers_prefix_view:: setup(std::size_t size) { size_ = 0; end_ = boost::asio::buffer_sequence_begin(bs_); auto const last = bs_.end(); while(end_ != last) { auto const len = boost::asio::buffer_size(*end_++); if(len >= size) { size_ += size; break; } size -= len; size_ += len; } } template buffers_prefix_view:: buffers_prefix_view(buffers_prefix_view&& other) : buffers_prefix_view(std::move(other), std::distance( boost::asio::buffer_sequence_begin(other.bs_), other.end_)) { } template buffers_prefix_view:: buffers_prefix_view(buffers_prefix_view const& other) : buffers_prefix_view(other, std::distance( boost::asio::buffer_sequence_begin(other.bs_), other.end_)) { } template auto buffers_prefix_view:: operator=(buffers_prefix_view&& other) -> buffers_prefix_view& { auto const dist = std::distance( boost::asio::buffer_sequence_begin(other.bs_), other.end_); bs_ = std::move(other.bs_); size_ = other.size_; end_ = std::next( boost::asio::buffer_sequence_begin(bs_), dist); return *this; } template auto buffers_prefix_view:: operator=(buffers_prefix_view const& other) -> buffers_prefix_view& { auto const dist = std::distance( boost::asio::buffer_sequence_begin(other.bs_), other.end_); bs_ = other.bs_; size_ = other.size_; end_ = std::next( boost::asio::buffer_sequence_begin(bs_), dist); return *this; } template buffers_prefix_view:: buffers_prefix_view(std::size_t size, BufferSequence 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 inline auto buffers_prefix_view::begin() const -> const_iterator { return const_iterator{*this, std::false_type{}}; } template inline auto buffers_prefix_view::end() const -> const_iterator { return const_iterator{*this, std::true_type{}}; } } // beast } // boost #endif