Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:25

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 
0048     // construct from two iterators plus optionally subrange definition
0049     subrange(
0050         iter_type first,        // iterator to first buffer in storage
0051         iter_type last,         // iterator to last buffer in storage
0052         std::size_t pos = 0,    // the offset in bytes from the beginning of the storage
0053         std::size_t n =         // the total length of the subrange
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     // allow conversion from mutable to const
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     // points to the first buffer in the sequence
0110     iter_type first_;
0111 
0112     // Points to one past the end of the underlying buffer sequence
0113     iter_type last_;
0114 
0115     // The initial offset into the first buffer
0116     std::size_t first_offset_;
0117 
0118     // how many bytes in the penultimate buffer are used (if any)
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 // subrange
0449 
0450 template<class MutableBufferSequence>
0451 template<bool isMutable>
0452 buffers_adaptor<MutableBufferSequence>::
0453 subrange<isMutable>::
0454 subrange(
0455     iter_type first,  // iterator to first buffer in storage
0456     iter_type last,   // iterator to last buffer in storage
0457     std::size_t pos,        // the offset in bytes from the beginning of the storage
0458     std::size_t n)         // the total length of the subrange
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         // both first and last element
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 // buffers_adaptor::subrange::iterator
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 } // beast
0705 } // boost
0706 
0707 #endif