Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:29:12

0001 //
0002 // buffers_iterator.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_BUFFERS_ITERATOR_HPP
0012 #define BOOST_ASIO_BUFFERS_ITERATOR_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cstddef>
0020 #include <iterator>
0021 #include <boost/asio/buffer.hpp>
0022 #include <boost/asio/detail/assert.hpp>
0023 #include <boost/asio/detail/type_traits.hpp>
0024 
0025 #include <boost/asio/detail/push_options.hpp>
0026 
0027 namespace boost {
0028 namespace asio {
0029 
0030 namespace detail
0031 {
0032   template <bool IsMutable>
0033   struct buffers_iterator_types_helper;
0034 
0035   template <>
0036   struct buffers_iterator_types_helper<false>
0037   {
0038     typedef const_buffer buffer_type;
0039     template <typename ByteType>
0040     struct byte_type
0041     {
0042       typedef add_const_t<ByteType> type;
0043     };
0044   };
0045 
0046   template <>
0047   struct buffers_iterator_types_helper<true>
0048   {
0049     typedef mutable_buffer buffer_type;
0050     template <typename ByteType>
0051     struct byte_type
0052     {
0053       typedef ByteType type;
0054     };
0055   };
0056 
0057   template <typename BufferSequence, typename ByteType>
0058   struct buffers_iterator_types
0059   {
0060     enum
0061     {
0062       is_mutable = is_convertible<
0063           typename BufferSequence::value_type,
0064           mutable_buffer>::value
0065     };
0066     typedef buffers_iterator_types_helper<is_mutable> helper;
0067     typedef typename helper::buffer_type buffer_type;
0068     typedef typename helper::template byte_type<ByteType>::type byte_type;
0069     typedef typename BufferSequence::const_iterator const_iterator;
0070   };
0071 
0072   template <typename ByteType>
0073   struct buffers_iterator_types<mutable_buffer, ByteType>
0074   {
0075     typedef mutable_buffer buffer_type;
0076     typedef ByteType byte_type;
0077     typedef const mutable_buffer* const_iterator;
0078   };
0079 
0080   template <typename ByteType>
0081   struct buffers_iterator_types<const_buffer, ByteType>
0082   {
0083     typedef const_buffer buffer_type;
0084     typedef add_const_t<ByteType> byte_type;
0085     typedef const const_buffer* const_iterator;
0086   };
0087 } // namespace detail
0088 
0089 /// A random access iterator over the bytes in a buffer sequence.
0090 template <typename BufferSequence, typename ByteType = char>
0091 class buffers_iterator
0092 {
0093 private:
0094   typedef typename detail::buffers_iterator_types<
0095       BufferSequence, ByteType>::buffer_type buffer_type;
0096 
0097   typedef typename detail::buffers_iterator_types<BufferSequence,
0098           ByteType>::const_iterator buffer_sequence_iterator_type;
0099 
0100 public:
0101   /// The type used for the distance between two iterators.
0102   typedef std::ptrdiff_t difference_type;
0103 
0104   /// The type of the value pointed to by the iterator.
0105   typedef ByteType value_type;
0106 
0107 #if defined(GENERATING_DOCUMENTATION)
0108   /// The type of the result of applying operator->() to the iterator.
0109   /**
0110    * If the buffer sequence stores buffer objects that are convertible to
0111    * mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
0112    * pointer to a const ByteType.
0113    */
0114   typedef const_or_non_const_ByteType* pointer;
0115 #else // defined(GENERATING_DOCUMENTATION)
0116   typedef typename detail::buffers_iterator_types<
0117       BufferSequence, ByteType>::byte_type* pointer;
0118 #endif // defined(GENERATING_DOCUMENTATION)
0119 
0120 #if defined(GENERATING_DOCUMENTATION)
0121   /// The type of the result of applying operator*() to the iterator.
0122   /**
0123    * If the buffer sequence stores buffer objects that are convertible to
0124    * mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
0125    * reference to a const ByteType.
0126    */
0127   typedef const_or_non_const_ByteType& reference;
0128 #else // defined(GENERATING_DOCUMENTATION)
0129   typedef typename detail::buffers_iterator_types<
0130       BufferSequence, ByteType>::byte_type& reference;
0131 #endif // defined(GENERATING_DOCUMENTATION)
0132 
0133   /// The iterator category.
0134   typedef std::random_access_iterator_tag iterator_category;
0135 
0136   /// Default constructor. Creates an iterator in an undefined state.
0137   buffers_iterator()
0138     : current_buffer_(),
0139       current_buffer_position_(0),
0140       begin_(),
0141       current_(),
0142       end_(),
0143       position_(0)
0144   {
0145   }
0146 
0147   /// Construct an iterator representing the beginning of the buffers' data.
0148   static buffers_iterator begin(const BufferSequence& buffers)
0149 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0150     __attribute__ ((__noinline__))
0151 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0152   {
0153     buffers_iterator new_iter;
0154     new_iter.begin_ = boost::asio::buffer_sequence_begin(buffers);
0155     new_iter.current_ = boost::asio::buffer_sequence_begin(buffers);
0156     new_iter.end_ = boost::asio::buffer_sequence_end(buffers);
0157     while (new_iter.current_ != new_iter.end_)
0158     {
0159       new_iter.current_buffer_ = *new_iter.current_;
0160       if (new_iter.current_buffer_.size() > 0)
0161         break;
0162       ++new_iter.current_;
0163     }
0164     return new_iter;
0165   }
0166 
0167   /// Construct an iterator representing the end of the buffers' data.
0168   static buffers_iterator end(const BufferSequence& buffers)
0169 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0170     __attribute__ ((__noinline__))
0171 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0172   {
0173     buffers_iterator new_iter;
0174     new_iter.begin_ = boost::asio::buffer_sequence_begin(buffers);
0175     new_iter.current_ = boost::asio::buffer_sequence_begin(buffers);
0176     new_iter.end_ = boost::asio::buffer_sequence_end(buffers);
0177     while (new_iter.current_ != new_iter.end_)
0178     {
0179       buffer_type buffer = *new_iter.current_;
0180       new_iter.position_ += buffer.size();
0181       ++new_iter.current_;
0182     }
0183     return new_iter;
0184   }
0185 
0186   /// Dereference an iterator.
0187   reference operator*() const
0188   {
0189     return dereference();
0190   }
0191 
0192   /// Dereference an iterator.
0193   pointer operator->() const
0194   {
0195     return &dereference();
0196   }
0197 
0198   /// Access an individual element.
0199   reference operator[](std::ptrdiff_t difference) const
0200   {
0201     buffers_iterator tmp(*this);
0202     tmp.advance(difference);
0203     return *tmp;
0204   }
0205 
0206   /// Increment operator (prefix).
0207   buffers_iterator& operator++()
0208   {
0209     increment();
0210     return *this;
0211   }
0212 
0213   /// Increment operator (postfix).
0214   buffers_iterator operator++(int)
0215   {
0216     buffers_iterator tmp(*this);
0217     ++*this;
0218     return tmp;
0219   }
0220 
0221   /// Decrement operator (prefix).
0222   buffers_iterator& operator--()
0223   {
0224     decrement();
0225     return *this;
0226   }
0227 
0228   /// Decrement operator (postfix).
0229   buffers_iterator operator--(int)
0230   {
0231     buffers_iterator tmp(*this);
0232     --*this;
0233     return tmp;
0234   }
0235 
0236   /// Addition operator.
0237   buffers_iterator& operator+=(std::ptrdiff_t difference)
0238   {
0239     advance(difference);
0240     return *this;
0241   }
0242 
0243   /// Subtraction operator.
0244   buffers_iterator& operator-=(std::ptrdiff_t difference)
0245   {
0246     advance(-difference);
0247     return *this;
0248   }
0249 
0250   /// Addition operator.
0251   friend buffers_iterator operator+(const buffers_iterator& iter,
0252       std::ptrdiff_t difference)
0253   {
0254     buffers_iterator tmp(iter);
0255     tmp.advance(difference);
0256     return tmp;
0257   }
0258 
0259   /// Addition operator.
0260   friend buffers_iterator operator+(std::ptrdiff_t difference,
0261       const buffers_iterator& iter)
0262   {
0263     buffers_iterator tmp(iter);
0264     tmp.advance(difference);
0265     return tmp;
0266   }
0267 
0268   /// Subtraction operator.
0269   friend buffers_iterator operator-(const buffers_iterator& iter,
0270       std::ptrdiff_t difference)
0271   {
0272     buffers_iterator tmp(iter);
0273     tmp.advance(-difference);
0274     return tmp;
0275   }
0276 
0277   /// Subtraction operator.
0278   friend std::ptrdiff_t operator-(const buffers_iterator& a,
0279       const buffers_iterator& b)
0280   {
0281     return b.distance_to(a);
0282   }
0283 
0284   /// Test two iterators for equality.
0285   friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
0286   {
0287     return a.equal(b);
0288   }
0289 
0290   /// Test two iterators for inequality.
0291   friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
0292   {
0293     return !a.equal(b);
0294   }
0295 
0296   /// Compare two iterators.
0297   friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
0298   {
0299     return a.distance_to(b) > 0;
0300   }
0301 
0302   /// Compare two iterators.
0303   friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
0304   {
0305     return !(b < a);
0306   }
0307 
0308   /// Compare two iterators.
0309   friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
0310   {
0311     return b < a;
0312   }
0313 
0314   /// Compare two iterators.
0315   friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
0316   {
0317     return !(a < b);
0318   }
0319 
0320 private:
0321   // Dereference the iterator.
0322   reference dereference() const
0323   {
0324     return static_cast<pointer>(
0325         current_buffer_.data())[current_buffer_position_];
0326   }
0327 
0328   // Compare two iterators for equality.
0329   bool equal(const buffers_iterator& other) const
0330   {
0331     return position_ == other.position_;
0332   }
0333 
0334   // Increment the iterator.
0335   void increment()
0336   {
0337     BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
0338     ++position_;
0339 
0340     // Check if the increment can be satisfied by the current buffer.
0341     ++current_buffer_position_;
0342     if (current_buffer_position_ != current_buffer_.size())
0343       return;
0344 
0345     // Find the next non-empty buffer.
0346     ++current_;
0347     current_buffer_position_ = 0;
0348     while (current_ != end_)
0349     {
0350       current_buffer_ = *current_;
0351       if (current_buffer_.size() > 0)
0352         return;
0353       ++current_;
0354     }
0355   }
0356 
0357   // Decrement the iterator.
0358   void decrement()
0359   {
0360     BOOST_ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
0361     --position_;
0362 
0363     // Check if the decrement can be satisfied by the current buffer.
0364     if (current_buffer_position_ != 0)
0365     {
0366       --current_buffer_position_;
0367       return;
0368     }
0369 
0370     // Find the previous non-empty buffer.
0371     buffer_sequence_iterator_type iter = current_;
0372     while (iter != begin_)
0373     {
0374       --iter;
0375       buffer_type buffer = *iter;
0376       std::size_t buffer_size = buffer.size();
0377       if (buffer_size > 0)
0378       {
0379         current_ = iter;
0380         current_buffer_ = buffer;
0381         current_buffer_position_ = buffer_size - 1;
0382         return;
0383       }
0384     }
0385   }
0386 
0387   // Advance the iterator by the specified distance.
0388   void advance(std::ptrdiff_t n)
0389   {
0390     if (n > 0)
0391     {
0392       BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
0393       for (;;)
0394       {
0395         std::ptrdiff_t current_buffer_balance
0396           = current_buffer_.size() - current_buffer_position_;
0397 
0398         // Check if the advance can be satisfied by the current buffer.
0399         if (current_buffer_balance > n)
0400         {
0401           position_ += n;
0402           current_buffer_position_ += n;
0403           return;
0404         }
0405 
0406         // Update position.
0407         n -= current_buffer_balance;
0408         position_ += current_buffer_balance;
0409 
0410         // Move to next buffer. If it is empty then it will be skipped on the
0411         // next iteration of this loop.
0412         if (++current_ == end_)
0413         {
0414           BOOST_ASIO_ASSERT(n == 0 && "iterator out of bounds");
0415           current_buffer_ = buffer_type();
0416           current_buffer_position_ = 0;
0417           return;
0418         }
0419         current_buffer_ = *current_;
0420         current_buffer_position_ = 0;
0421       }
0422     }
0423     else if (n < 0)
0424     {
0425       std::size_t abs_n = -n;
0426       BOOST_ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
0427       for (;;)
0428       {
0429         // Check if the advance can be satisfied by the current buffer.
0430         if (current_buffer_position_ >= abs_n)
0431         {
0432           position_ -= abs_n;
0433           current_buffer_position_ -= abs_n;
0434           return;
0435         }
0436 
0437         // Update position.
0438         abs_n -= current_buffer_position_;
0439         position_ -= current_buffer_position_;
0440 
0441         // Check if we've reached the beginning of the buffers.
0442         if (current_ == begin_)
0443         {
0444           BOOST_ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
0445           current_buffer_position_ = 0;
0446           return;
0447         }
0448 
0449         // Find the previous non-empty buffer.
0450         buffer_sequence_iterator_type iter = current_;
0451         while (iter != begin_)
0452         {
0453           --iter;
0454           buffer_type buffer = *iter;
0455           std::size_t buffer_size = buffer.size();
0456           if (buffer_size > 0)
0457           {
0458             current_ = iter;
0459             current_buffer_ = buffer;
0460             current_buffer_position_ = buffer_size;
0461             break;
0462           }
0463         }
0464       }
0465     }
0466   }
0467 
0468   // Determine the distance between two iterators.
0469   std::ptrdiff_t distance_to(const buffers_iterator& other) const
0470   {
0471     return other.position_ - position_;
0472   }
0473 
0474   buffer_type current_buffer_;
0475   std::size_t current_buffer_position_;
0476   buffer_sequence_iterator_type begin_;
0477   buffer_sequence_iterator_type current_;
0478   buffer_sequence_iterator_type end_;
0479   std::size_t position_;
0480 };
0481 
0482 /// Construct an iterator representing the beginning of the buffers' data.
0483 template <typename BufferSequence>
0484 inline buffers_iterator<BufferSequence> buffers_begin(
0485     const BufferSequence& buffers)
0486 {
0487   return buffers_iterator<BufferSequence>::begin(buffers);
0488 }
0489 
0490 /// Construct an iterator representing the end of the buffers' data.
0491 template <typename BufferSequence>
0492 inline buffers_iterator<BufferSequence> buffers_end(
0493     const BufferSequence& buffers)
0494 {
0495   return buffers_iterator<BufferSequence>::end(buffers);
0496 }
0497 
0498 } // namespace asio
0499 } // namespace boost
0500 
0501 #include <boost/asio/detail/pop_options.hpp>
0502 
0503 #endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP