File indexing completed on 2025-01-18 09:29:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP
0011 #define BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP
0012
0013 #include <boost/beast/core/buffer_traits.hpp>
0014 #include <boost/config/workaround.hpp>
0015 #include <algorithm>
0016 #include <cstdint>
0017 #include <iterator>
0018 #include <stdexcept>
0019 #include <type_traits>
0020 #include <utility>
0021
0022 namespace boost {
0023 namespace beast {
0024
0025 template<class Buffers>
0026 class buffers_prefix_view<Buffers>::const_iterator
0027 {
0028 friend class buffers_prefix_view<Buffers>;
0029
0030 buffers_prefix_view const* b_ = nullptr;
0031 std::size_t remain_ = 0;
0032 iter_type it_{};
0033
0034 public:
0035 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0036 using value_type = typename std::conditional<
0037 boost::is_convertible<typename
0038 std::iterator_traits<iter_type>::value_type,
0039 net::mutable_buffer>::value,
0040 net::mutable_buffer,
0041 net::const_buffer>::type;
0042 #else
0043 using value_type = buffers_type<Buffers>;
0044 #endif
0045
0046 BOOST_STATIC_ASSERT(std::is_same<
0047 typename const_iterator::value_type,
0048 typename buffers_prefix_view::value_type>::value);
0049
0050 using pointer = value_type const*;
0051 using reference = value_type;
0052 using difference_type = std::ptrdiff_t;
0053 using iterator_category =
0054 std::bidirectional_iterator_tag;
0055
0056 const_iterator() = default;
0057 const_iterator(
0058 const_iterator const& other) = default;
0059 const_iterator& operator=(
0060 const_iterator const& other) = default;
0061
0062 bool
0063 operator==(const_iterator const& other) const
0064 {
0065 return b_ == other.b_ && it_ == other.it_;
0066 }
0067
0068 bool
0069 operator!=(const_iterator const& other) const
0070 {
0071 return !(*this == other);
0072 }
0073
0074 reference
0075 operator*() const
0076 {
0077 value_type v(*it_);
0078 if(remain_ < v.size())
0079 return {v.data(), remain_};
0080 return v;
0081 }
0082
0083 pointer
0084 operator->() const = delete;
0085
0086 const_iterator&
0087 operator++()
0088 {
0089 value_type const v = *it_++;
0090 remain_ -= v.size();
0091 return *this;
0092 }
0093
0094 const_iterator
0095 operator++(int)
0096 {
0097 auto temp = *this;
0098 value_type const v = *it_++;
0099 remain_ -= v.size();
0100 return temp;
0101 }
0102
0103 const_iterator&
0104 operator--()
0105 {
0106 value_type const v = *--it_;
0107 remain_ += v.size();
0108 return *this;
0109 }
0110
0111 const_iterator
0112 operator--(int)
0113 {
0114 auto temp = *this;
0115 value_type const v = *--it_;
0116 remain_ += v.size();
0117 return temp;
0118 }
0119
0120 private:
0121 const_iterator(
0122 buffers_prefix_view const& b,
0123 std::true_type)
0124 : b_(&b)
0125 , remain_(b.remain_)
0126 , it_(b_->end_)
0127 {
0128 }
0129
0130 const_iterator(
0131 buffers_prefix_view const& b,
0132 std::false_type)
0133 : b_(&b)
0134 , remain_(b_->size_)
0135 , it_(net::buffer_sequence_begin(b_->bs_))
0136 {
0137 }
0138 };
0139
0140
0141
0142 template<class Buffers>
0143 void
0144 buffers_prefix_view<Buffers>::
0145 setup(std::size_t size)
0146 {
0147 size_ = 0;
0148 remain_ = 0;
0149 end_ = net::buffer_sequence_begin(bs_);
0150 auto const last = bs_.end();
0151 while(end_ != last)
0152 {
0153 auto const len = buffer_bytes(*end_++);
0154 if(len >= size)
0155 {
0156 size_ += size;
0157
0158
0159 BOOST_STATIC_ASSERT(std::is_unsigned<
0160 decltype(remain_)>::value);
0161 remain_ = size - len;
0162 break;
0163 }
0164 size -= len;
0165 size_ += len;
0166 }
0167 }
0168
0169 template<class Buffers>
0170 buffers_prefix_view<Buffers>::
0171 buffers_prefix_view(
0172 buffers_prefix_view const& other,
0173 std::size_t dist)
0174 : bs_(other.bs_)
0175 , size_(other.size_)
0176 , remain_(other.remain_)
0177 , end_(std::next(bs_.begin(), dist))
0178 {
0179 }
0180
0181 template<class Buffers>
0182 buffers_prefix_view<Buffers>::
0183 buffers_prefix_view(buffers_prefix_view const& other)
0184 : buffers_prefix_view(other,
0185 std::distance<iter_type>(
0186 net::buffer_sequence_begin(other.bs_),
0187 other.end_))
0188 {
0189 }
0190
0191 template<class Buffers>
0192 auto
0193 buffers_prefix_view<Buffers>::
0194 operator=(buffers_prefix_view const& other) ->
0195 buffers_prefix_view&
0196 {
0197 auto const dist = std::distance<iter_type>(
0198 net::buffer_sequence_begin(other.bs_),
0199 other.end_);
0200 bs_ = other.bs_;
0201 size_ = other.size_;
0202 remain_ = other.remain_;
0203 end_ = std::next(
0204 net::buffer_sequence_begin(bs_),
0205 dist);
0206 return *this;
0207 }
0208
0209 template<class Buffers>
0210 buffers_prefix_view<Buffers>::
0211 buffers_prefix_view(
0212 std::size_t size,
0213 Buffers const& bs)
0214 : bs_(bs)
0215 {
0216 setup(size);
0217 }
0218
0219 template<class Buffers>
0220 template<class... Args>
0221 buffers_prefix_view<Buffers>::
0222 buffers_prefix_view(
0223 std::size_t size,
0224 boost::in_place_init_t,
0225 Args&&... args)
0226 : bs_(std::forward<Args>(args)...)
0227 {
0228 setup(size);
0229 }
0230
0231 template<class Buffers>
0232 auto
0233 buffers_prefix_view<Buffers>::
0234 begin() const ->
0235 const_iterator
0236 {
0237 return const_iterator{
0238 *this, std::false_type{}};
0239 }
0240
0241 template<class Buffers>
0242 auto
0243 buffers_prefix_view<Buffers>::
0244 end() const ->
0245 const_iterator
0246 {
0247 return const_iterator{
0248 *this, std::true_type{}};
0249 }
0250
0251
0252
0253 template<>
0254 class buffers_prefix_view<net::const_buffer>
0255 : public net::const_buffer
0256 {
0257 public:
0258 using net::const_buffer::const_buffer;
0259 buffers_prefix_view(buffers_prefix_view const&) = default;
0260 buffers_prefix_view& operator=(buffers_prefix_view const&) = default;
0261
0262 buffers_prefix_view(
0263 std::size_t size,
0264 net::const_buffer buffer)
0265 : net::const_buffer(
0266 buffer.data(),
0267 std::min<std::size_t>(size, buffer.size())
0268 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0269 , buffer.get_debug_check()
0270 #endif
0271 )
0272 {
0273 }
0274
0275 template<class... Args>
0276 buffers_prefix_view(
0277 std::size_t size,
0278 boost::in_place_init_t,
0279 Args&&... args)
0280 : buffers_prefix_view(size,
0281 net::const_buffer(
0282 std::forward<Args>(args)...))
0283 {
0284 }
0285 };
0286
0287
0288
0289 template<>
0290 class buffers_prefix_view<net::mutable_buffer>
0291 : public net::mutable_buffer
0292 {
0293 public:
0294 using net::mutable_buffer::mutable_buffer;
0295 buffers_prefix_view(buffers_prefix_view const&) = default;
0296 buffers_prefix_view& operator=(buffers_prefix_view const&) = default;
0297
0298 buffers_prefix_view(
0299 std::size_t size,
0300 net::mutable_buffer buffer)
0301 : net::mutable_buffer(
0302 buffer.data(),
0303 std::min<std::size_t>(size, buffer.size())
0304 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0305 , buffer.get_debug_check()
0306 #endif
0307 )
0308 {
0309 }
0310
0311 template<class... Args>
0312 buffers_prefix_view(
0313 std::size_t size,
0314 boost::in_place_init_t,
0315 Args&&... args)
0316 : buffers_prefix_view(size,
0317 net::mutable_buffer(
0318 std::forward<Args>(args)...))
0319 {
0320 }
0321 };
0322
0323 }
0324 }
0325
0326 #endif