File indexing completed on 2025-01-18 09:29:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
0011 #define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
0012
0013 #include <boost/beast/core/buffer_traits.hpp>
0014 #include <boost/beast/core/buffers_adaptor.hpp>
0015 #include <boost/asio/buffer.hpp>
0016 #include <boost/config/workaround.hpp>
0017 #include <boost/throw_exception.hpp>
0018 #include <algorithm>
0019 #include <cstring>
0020 #include <iterator>
0021 #include <stdexcept>
0022 #include <type_traits>
0023 #include <utility>
0024
0025 namespace boost {
0026 namespace beast {
0027
0028
0029
0030 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0031 # pragma warning (push)
0032 # pragma warning (disable: 4521)
0033 # pragma warning (disable: 4522)
0034 #endif
0035
0036 template<class MutableBufferSequence>
0037 template<bool isMutable>
0038 class buffers_adaptor<MutableBufferSequence>::subrange
0039 {
0040 public:
0041 using value_type = typename std::conditional<
0042 isMutable,
0043 net::mutable_buffer,
0044 net::const_buffer>::type;
0045
0046 struct iterator;
0047
0048
0049 subrange(
0050 iter_type first,
0051 iter_type last,
0052 std::size_t pos = 0,
0053 std::size_t n =
0054 (std::numeric_limits<std::size_t>::max)());
0055
0056 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0057 subrange(
0058 subrange const& other)
0059 : first_(other.first_)
0060 , last_(other.last_)
0061 , first_offset_(other.first_offset_)
0062 , last_size_(other.last_size_)
0063 {
0064 }
0065
0066 subrange& operator=(
0067 subrange const& other)
0068 {
0069 first_ = other.first_;
0070 last_ = other.last_;
0071 first_offset_ = other.first_offset_;
0072 last_size_ = other.last_size_;
0073 return *this;
0074 }
0075 #else
0076 subrange(
0077 subrange const&) = default;
0078 subrange& operator=(
0079 subrange const&) = default;
0080 #endif
0081
0082
0083 template<bool isMutable_ = isMutable, typename
0084 std::enable_if<!isMutable_>::type * = nullptr>
0085 subrange(subrange<true> const &other)
0086 : first_(other.first_)
0087 , last_(other.last_)
0088 , first_offset_(other.first_offset_)
0089 , last_size_(other.last_size_)
0090 {
0091 }
0092
0093 iterator
0094 begin() const;
0095
0096 iterator
0097 end() const;
0098
0099 private:
0100
0101 friend subrange<!isMutable>;
0102
0103 void
0104 adjust(
0105 std::size_t pos,
0106 std::size_t n);
0107
0108 private:
0109
0110 iter_type first_;
0111
0112
0113 iter_type last_;
0114
0115
0116 std::size_t first_offset_;
0117
0118
0119 std::size_t last_size_;
0120 };
0121
0122 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0123 # pragma warning (pop)
0124 #endif
0125
0126
0127
0128 template<class MutableBufferSequence>
0129 template<bool isMutable>
0130 struct buffers_adaptor<MutableBufferSequence>::
0131 subrange<isMutable>::
0132 iterator
0133 {
0134 using iterator_category = std::bidirectional_iterator_tag;
0135 using value_type = typename
0136 buffers_adaptor<MutableBufferSequence>::
0137 template subrange<isMutable>::
0138 value_type;
0139 using reference = value_type&;
0140 using pointer = value_type*;
0141 using difference_type = std::ptrdiff_t;
0142
0143 iterator(
0144 subrange<isMutable> const *parent,
0145 iter_type it);
0146
0147 iterator();
0148
0149 value_type
0150 operator*() const;
0151
0152 pointer
0153 operator->() const = delete;
0154
0155 iterator &
0156 operator++();
0157
0158 iterator
0159 operator++(int);
0160
0161 iterator &
0162 operator--();
0163
0164 iterator
0165 operator--(int);
0166
0167 bool
0168 operator==(iterator const &b) const;
0169
0170 bool
0171 operator!=(iterator const &b) const;
0172
0173 private:
0174
0175 subrange<isMutable> const *parent_;
0176 iter_type it_;
0177 };
0178
0179
0180
0181 template<class MutableBufferSequence>
0182 auto
0183 buffers_adaptor<MutableBufferSequence>::
0184 end_impl() const ->
0185 iter_type
0186 {
0187 return out_ == end_ ? end_ : std::next(out_);
0188 }
0189
0190 template<class MutableBufferSequence>
0191 buffers_adaptor<MutableBufferSequence>::
0192 buffers_adaptor(
0193 buffers_adaptor const& other,
0194 std::size_t nbegin,
0195 std::size_t nout,
0196 std::size_t nend)
0197 : bs_(other.bs_)
0198 , begin_(std::next(net::buffer_sequence_begin(bs_), nbegin))
0199 , out_(std::next(net::buffer_sequence_begin(bs_), nout))
0200 , end_(std::next(net::buffer_sequence_begin(bs_), nend))
0201 , max_size_(other.max_size_)
0202 , in_pos_(other.in_pos_)
0203 , in_size_(other.in_size_)
0204 , out_pos_(other.out_pos_)
0205 , out_end_(other.out_end_)
0206 {
0207 }
0208
0209 template<class MutableBufferSequence>
0210 buffers_adaptor<MutableBufferSequence>::
0211 buffers_adaptor(MutableBufferSequence const& bs)
0212 : bs_(bs)
0213 , begin_(net::buffer_sequence_begin(bs_))
0214 , out_ (net::buffer_sequence_begin(bs_))
0215 , end_ (net::buffer_sequence_begin(bs_))
0216 , max_size_(
0217 [&bs]
0218 {
0219 return buffer_bytes(bs);
0220 }())
0221 {
0222 }
0223
0224 template<class MutableBufferSequence>
0225 template<class... Args>
0226 buffers_adaptor<MutableBufferSequence>::
0227 buffers_adaptor(
0228 boost::in_place_init_t, Args&&... args)
0229 : bs_{std::forward<Args>(args)...}
0230 , begin_(net::buffer_sequence_begin(bs_))
0231 , out_ (net::buffer_sequence_begin(bs_))
0232 , end_ (net::buffer_sequence_begin(bs_))
0233 , max_size_(
0234 [&]
0235 {
0236 return buffer_bytes(bs_);
0237 }())
0238 {
0239 }
0240
0241 template<class MutableBufferSequence>
0242 buffers_adaptor<MutableBufferSequence>::
0243 buffers_adaptor(buffers_adaptor const& other)
0244 : buffers_adaptor(
0245 other,
0246 std::distance<iter_type>(
0247 net::buffer_sequence_begin(other.bs_),
0248 other.begin_),
0249 std::distance<iter_type>(
0250 net::buffer_sequence_begin(other.bs_),
0251 other.out_),
0252 std::distance<iter_type>(
0253 net::buffer_sequence_begin(other.bs_),
0254 other.end_))
0255 {
0256 }
0257
0258 template<class MutableBufferSequence>
0259 auto
0260 buffers_adaptor<MutableBufferSequence>::
0261 operator=(buffers_adaptor const& other) ->
0262 buffers_adaptor&
0263 {
0264 if(this == &other)
0265 return *this;
0266 auto const nbegin = std::distance<iter_type>(
0267 net::buffer_sequence_begin(other.bs_),
0268 other.begin_);
0269 auto const nout = std::distance<iter_type>(
0270 net::buffer_sequence_begin(other.bs_),
0271 other.out_);
0272 auto const nend = std::distance<iter_type>(
0273 net::buffer_sequence_begin(other.bs_),
0274 other.end_);
0275 bs_ = other.bs_;
0276 begin_ = std::next(
0277 net::buffer_sequence_begin(bs_), nbegin);
0278 out_ = std::next(
0279 net::buffer_sequence_begin(bs_), nout);
0280 end_ = std::next(
0281 net::buffer_sequence_begin(bs_), nend);
0282 max_size_ = other.max_size_;
0283 in_pos_ = other.in_pos_;
0284 in_size_ = other.in_size_;
0285 out_pos_ = other.out_pos_;
0286 out_end_ = other.out_end_;
0287 return *this;
0288 }
0289
0290
0291
0292 template<class MutableBufferSequence>
0293 auto
0294 buffers_adaptor<MutableBufferSequence>::
0295 data() const noexcept ->
0296 const_buffers_type
0297 {
0298 return const_buffers_type(
0299 begin_, end_,
0300 in_pos_, in_size_);
0301 }
0302
0303 template<class MutableBufferSequence>
0304 auto
0305 buffers_adaptor<MutableBufferSequence>::
0306 data() noexcept ->
0307 mutable_buffers_type
0308 {
0309 return mutable_buffers_type(
0310 begin_, end_,
0311 in_pos_, in_size_);
0312 }
0313
0314 template<class MutableBufferSequence>
0315 auto
0316 buffers_adaptor<MutableBufferSequence>::
0317 prepare(std::size_t n) ->
0318 mutable_buffers_type
0319 {
0320 auto prepared = n;
0321 end_ = out_;
0322 if(end_ != net::buffer_sequence_end(bs_))
0323 {
0324 auto size = buffer_bytes(*end_) - out_pos_;
0325 if(n > size)
0326 {
0327 n -= size;
0328 while(++end_ !=
0329 net::buffer_sequence_end(bs_))
0330 {
0331 size = buffer_bytes(*end_);
0332 if(n < size)
0333 {
0334 out_end_ = n;
0335 n = 0;
0336 ++end_;
0337 break;
0338 }
0339 n -= size;
0340 out_end_ = size;
0341 }
0342 }
0343 else
0344 {
0345 ++end_;
0346 out_end_ = out_pos_ + n;
0347 n = 0;
0348 }
0349 }
0350 if(n > 0)
0351 BOOST_THROW_EXCEPTION(std::length_error{
0352 "buffers_adaptor too long"});
0353 return mutable_buffers_type(out_, end_, out_pos_, prepared);
0354 }
0355
0356 template<class MutableBufferSequence>
0357 void
0358 buffers_adaptor<MutableBufferSequence>::
0359 commit(std::size_t n) noexcept
0360 {
0361 if(out_ == end_)
0362 return;
0363 auto const last = std::prev(end_);
0364 while(out_ != last)
0365 {
0366 auto const avail =
0367 buffer_bytes(*out_) - out_pos_;
0368 if(n < avail)
0369 {
0370 out_pos_ += n;
0371 in_size_ += n;
0372 return;
0373 }
0374 ++out_;
0375 n -= avail;
0376 out_pos_ = 0;
0377 in_size_ += avail;
0378 }
0379
0380 n = std::min<std::size_t>(
0381 n, out_end_ - out_pos_);
0382 out_pos_ += n;
0383 in_size_ += n;
0384 if(out_pos_ == buffer_bytes(*out_))
0385 {
0386 ++out_;
0387 out_pos_ = 0;
0388 out_end_ = 0;
0389 }
0390 }
0391
0392 template<class MutableBufferSequence>
0393 void
0394 buffers_adaptor<MutableBufferSequence>::
0395 consume(std::size_t n) noexcept
0396 {
0397 while(begin_ != out_)
0398 {
0399 auto const avail =
0400 buffer_bytes(*begin_) - in_pos_;
0401 if(n < avail)
0402 {
0403 in_size_ -= n;
0404 in_pos_ += n;
0405 return;
0406 }
0407 n -= avail;
0408 in_size_ -= avail;
0409 in_pos_ = 0;
0410 ++begin_;
0411 }
0412 auto const avail = out_pos_ - in_pos_;
0413 if(n < avail)
0414 {
0415 in_size_ -= n;
0416 in_pos_ += n;
0417 }
0418 else
0419 {
0420 in_size_ -= avail;
0421 in_pos_ = out_pos_;
0422 }
0423 }
0424
0425 template<class MutableBufferSequence>
0426 auto
0427 buffers_adaptor<MutableBufferSequence>::
0428 make_subrange(std::size_t pos, std::size_t n) ->
0429 subrange<true>
0430 {
0431 return subrange<true>(
0432 begin_, net::buffer_sequence_end(bs_),
0433 in_pos_ + pos, n);
0434 }
0435
0436 template<class MutableBufferSequence>
0437 auto
0438 buffers_adaptor<MutableBufferSequence>::
0439 make_subrange(std::size_t pos, std::size_t n) const ->
0440 subrange<false>
0441 {
0442 return subrange<false>(
0443 begin_, net::buffer_sequence_end(bs_),
0444 in_pos_ + pos, n);
0445 }
0446
0447
0448
0449
0450 template<class MutableBufferSequence>
0451 template<bool isMutable>
0452 buffers_adaptor<MutableBufferSequence>::
0453 subrange<isMutable>::
0454 subrange(
0455 iter_type first,
0456 iter_type last,
0457 std::size_t pos,
0458 std::size_t n)
0459 : first_(first)
0460 , last_(last)
0461 , first_offset_(0)
0462 , last_size_((std::numeric_limits<std::size_t>::max)())
0463 {
0464 adjust(pos, n);
0465 }
0466
0467 template<class MutableBufferSequence>
0468 template<bool isMutable>
0469 void
0470 buffers_adaptor<MutableBufferSequence>::
0471 subrange<isMutable>::
0472 adjust(
0473 std::size_t pos,
0474 std::size_t n)
0475 {
0476 if (n == 0)
0477 last_ = first_;
0478
0479 if (first_ == last_)
0480 {
0481 first_offset_ = 0;
0482 last_size_ = 0;
0483 return;
0484 }
0485
0486 auto is_last = [this](iter_type iter) {
0487 return std::next(iter) == last_;
0488 };
0489
0490
0491 pos += first_offset_;
0492 while (pos)
0493 {
0494 auto adjust = (std::min)(pos, first_->size());
0495 if (adjust >= first_->size())
0496 {
0497 ++first_;
0498 first_offset_ = 0;
0499 pos -= adjust;
0500 }
0501 else
0502 {
0503 first_offset_ = adjust;
0504 pos = 0;
0505 break;
0506 }
0507 }
0508
0509 auto current = first_;
0510 auto max_elem = current->size() - first_offset_;
0511 if (is_last(current))
0512 {
0513
0514 last_size_ = (std::min)(max_elem, n);
0515 last_ = std::next(current);
0516 return;
0517 }
0518 else if (max_elem >= n)
0519 {
0520 last_ = std::next(current);
0521 last_size_ = n;
0522 }
0523 else
0524 {
0525 n -= max_elem;
0526 ++current;
0527 }
0528
0529 for (;;)
0530 {
0531 max_elem = current->size();
0532 if (is_last(current))
0533 {
0534 last_size_ = (std::min)(n, last_size_);
0535 return;
0536 }
0537 else if (max_elem < n)
0538 {
0539 n -= max_elem;
0540 ++current;
0541 }
0542 else
0543 {
0544 last_size_ = n;
0545 last_ = std::next(current);
0546 return;
0547 }
0548 }
0549 }
0550
0551
0552 template<class MutableBufferSequence>
0553 template<bool isMutable>
0554 auto
0555 buffers_adaptor<MutableBufferSequence>::
0556 subrange<isMutable>::
0557 begin() const ->
0558 iterator
0559 {
0560 return iterator(this, first_);
0561 }
0562
0563 template<class MutableBufferSequence>
0564 template<bool isMutable>
0565 auto
0566 buffers_adaptor<MutableBufferSequence>::
0567 subrange<isMutable>::
0568 end() const ->
0569 iterator
0570 {
0571 return iterator(this, last_);
0572 }
0573
0574
0575
0576
0577 template<class MutableBufferSequence>
0578 template<bool isMutable>
0579 buffers_adaptor<MutableBufferSequence>::
0580 subrange<isMutable>::
0581 iterator::
0582 iterator()
0583 : parent_(nullptr)
0584 , it_()
0585 {
0586 }
0587
0588 template<class MutableBufferSequence>
0589 template<bool isMutable>
0590 buffers_adaptor<MutableBufferSequence>::
0591 subrange<isMutable>::
0592 iterator::
0593 iterator(subrange<isMutable> const *parent,
0594 iter_type it)
0595 : parent_(parent)
0596 , it_(it)
0597 {
0598 }
0599
0600 template<class MutableBufferSequence>
0601 template<bool isMutable>
0602 auto
0603 buffers_adaptor<MutableBufferSequence>::
0604 subrange<isMutable>::
0605 iterator::
0606 operator*() const ->
0607 value_type
0608 {
0609 value_type result = *it_;
0610
0611 if (it_ == parent_->first_)
0612 result += parent_->first_offset_;
0613
0614 if (std::next(it_) == parent_->last_)
0615 {
0616 result = value_type(
0617 result.data(),
0618 (std::min)(
0619 parent_->last_size_,
0620 result.size()));
0621 }
0622
0623 return result;
0624 }
0625
0626 template<class MutableBufferSequence>
0627 template<bool isMutable>
0628 auto
0629 buffers_adaptor<MutableBufferSequence>::
0630 subrange<isMutable>::
0631 iterator::
0632 operator++() ->
0633 iterator &
0634 {
0635 ++it_;
0636 return *this;
0637 }
0638
0639 template<class MutableBufferSequence>
0640 template<bool isMutable>
0641 auto
0642 buffers_adaptor<MutableBufferSequence>::
0643 subrange<isMutable>::
0644 iterator::
0645 operator++(int) ->
0646 iterator
0647 {
0648 auto result = *this;
0649 ++it_;
0650 return result;
0651 }
0652
0653 template<class MutableBufferSequence>
0654 template<bool isMutable>
0655 auto
0656 buffers_adaptor<MutableBufferSequence>::
0657 subrange<isMutable>::
0658 iterator::
0659 operator--() ->
0660 iterator &
0661 {
0662 --it_;
0663 return *this;
0664 }
0665
0666 template<class MutableBufferSequence>
0667 template<bool isMutable>
0668 auto
0669 buffers_adaptor<MutableBufferSequence>::
0670 subrange<isMutable>::
0671 iterator::
0672 operator--(int) ->
0673 iterator
0674 {
0675 auto result = *this;
0676 --it_;
0677 return result;
0678 }
0679
0680 template<class MutableBufferSequence>
0681 template<bool isMutable>
0682 auto
0683 buffers_adaptor<MutableBufferSequence>::
0684 subrange<isMutable>::
0685 iterator::
0686 operator==(iterator const &b) const ->
0687 bool
0688 {
0689 return it_ == b.it_;
0690 }
0691
0692 template<class MutableBufferSequence>
0693 template<bool isMutable>
0694 auto
0695 buffers_adaptor<MutableBufferSequence>::
0696 subrange<isMutable>::
0697 iterator::
0698 operator!=(iterator const &b) const ->
0699 bool
0700 {
0701 return !(*this == b);
0702 }
0703
0704 }
0705 }
0706
0707 #endif