Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:28:54

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