Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // buffers_iterator.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 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 
0088 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0089 
0090   template <typename ByteType>
0091   struct buffers_iterator_types<mutable_buffers_1, ByteType>
0092   {
0093     typedef mutable_buffer buffer_type;
0094     typedef ByteType byte_type;
0095     typedef const mutable_buffer* const_iterator;
0096   };
0097 
0098   template <typename ByteType>
0099   struct buffers_iterator_types<const_buffers_1, ByteType>
0100   {
0101     typedef const_buffer buffer_type;
0102     typedef add_const_t<ByteType> byte_type;
0103     typedef const const_buffer* const_iterator;
0104   };
0105 
0106 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0107 }
0108 
0109 /// A random access iterator over the bytes in a buffer sequence.
0110 template <typename BufferSequence, typename ByteType = char>
0111 class buffers_iterator
0112 {
0113 private:
0114   typedef typename detail::buffers_iterator_types<
0115       BufferSequence, ByteType>::buffer_type buffer_type;
0116 
0117   typedef typename detail::buffers_iterator_types<BufferSequence,
0118           ByteType>::const_iterator buffer_sequence_iterator_type;
0119 
0120 public:
0121   /// The type used for the distance between two iterators.
0122   typedef std::ptrdiff_t difference_type;
0123 
0124   /// The type of the value pointed to by the iterator.
0125   typedef ByteType value_type;
0126 
0127 #if defined(GENERATING_DOCUMENTATION)
0128   /// The type of the result of applying operator->() to the iterator.
0129   /**
0130    * If the buffer sequence stores buffer objects that are convertible to
0131    * mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
0132    * pointer to a const ByteType.
0133    */
0134   typedef const_or_non_const_ByteType* pointer;
0135 #else // defined(GENERATING_DOCUMENTATION)
0136   typedef typename detail::buffers_iterator_types<
0137       BufferSequence, ByteType>::byte_type* pointer;
0138 #endif // defined(GENERATING_DOCUMENTATION)
0139 
0140 #if defined(GENERATING_DOCUMENTATION)
0141   /// The type of the result of applying operator*() to the iterator.
0142   /**
0143    * If the buffer sequence stores buffer objects that are convertible to
0144    * mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
0145    * reference to a const ByteType.
0146    */
0147   typedef const_or_non_const_ByteType& reference;
0148 #else // defined(GENERATING_DOCUMENTATION)
0149   typedef typename detail::buffers_iterator_types<
0150       BufferSequence, ByteType>::byte_type& reference;
0151 #endif // defined(GENERATING_DOCUMENTATION)
0152 
0153   /// The iterator category.
0154   typedef std::random_access_iterator_tag iterator_category;
0155 
0156   /// Default constructor. Creates an iterator in an undefined state.
0157   buffers_iterator()
0158     : current_buffer_(),
0159       current_buffer_position_(0),
0160       begin_(),
0161       current_(),
0162       end_(),
0163       position_(0)
0164   {
0165   }
0166 
0167   /// Construct an iterator representing the beginning of the buffers' data.
0168   static buffers_iterator begin(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       new_iter.current_buffer_ = *new_iter.current_;
0180       if (new_iter.current_buffer_.size() > 0)
0181         break;
0182       ++new_iter.current_;
0183     }
0184     return new_iter;
0185   }
0186 
0187   /// Construct an iterator representing the end of the buffers' data.
0188   static buffers_iterator end(const BufferSequence& buffers)
0189 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0190     __attribute__ ((__noinline__))
0191 #endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0192   {
0193     buffers_iterator new_iter;
0194     new_iter.begin_ = boost::asio::buffer_sequence_begin(buffers);
0195     new_iter.current_ = boost::asio::buffer_sequence_begin(buffers);
0196     new_iter.end_ = boost::asio::buffer_sequence_end(buffers);
0197     while (new_iter.current_ != new_iter.end_)
0198     {
0199       buffer_type buffer = *new_iter.current_;
0200       new_iter.position_ += buffer.size();
0201       ++new_iter.current_;
0202     }
0203     return new_iter;
0204   }
0205 
0206   /// Dereference an iterator.
0207   reference operator*() const
0208   {
0209     return dereference();
0210   }
0211 
0212   /// Dereference an iterator.
0213   pointer operator->() const
0214   {
0215     return &dereference();
0216   }
0217 
0218   /// Access an individual element.
0219   reference operator[](std::ptrdiff_t difference) const
0220   {
0221     buffers_iterator tmp(*this);
0222     tmp.advance(difference);
0223     return *tmp;
0224   }
0225 
0226   /// Increment operator (prefix).
0227   buffers_iterator& operator++()
0228   {
0229     increment();
0230     return *this;
0231   }
0232 
0233   /// Increment operator (postfix).
0234   buffers_iterator operator++(int)
0235   {
0236     buffers_iterator tmp(*this);
0237     ++*this;
0238     return tmp;
0239   }
0240 
0241   /// Decrement operator (prefix).
0242   buffers_iterator& operator--()
0243   {
0244     decrement();
0245     return *this;
0246   }
0247 
0248   /// Decrement operator (postfix).
0249   buffers_iterator operator--(int)
0250   {
0251     buffers_iterator tmp(*this);
0252     --*this;
0253     return tmp;
0254   }
0255 
0256   /// Addition operator.
0257   buffers_iterator& operator+=(std::ptrdiff_t difference)
0258   {
0259     advance(difference);
0260     return *this;
0261   }
0262 
0263   /// Subtraction operator.
0264   buffers_iterator& operator-=(std::ptrdiff_t difference)
0265   {
0266     advance(-difference);
0267     return *this;
0268   }
0269 
0270   /// Addition operator.
0271   friend buffers_iterator operator+(const buffers_iterator& iter,
0272       std::ptrdiff_t difference)
0273   {
0274     buffers_iterator tmp(iter);
0275     tmp.advance(difference);
0276     return tmp;
0277   }
0278 
0279   /// Addition operator.
0280   friend buffers_iterator operator+(std::ptrdiff_t difference,
0281       const buffers_iterator& iter)
0282   {
0283     buffers_iterator tmp(iter);
0284     tmp.advance(difference);
0285     return tmp;
0286   }
0287 
0288   /// Subtraction operator.
0289   friend buffers_iterator operator-(const buffers_iterator& iter,
0290       std::ptrdiff_t difference)
0291   {
0292     buffers_iterator tmp(iter);
0293     tmp.advance(-difference);
0294     return tmp;
0295   }
0296 
0297   /// Subtraction operator.
0298   friend std::ptrdiff_t operator-(const buffers_iterator& a,
0299       const buffers_iterator& b)
0300   {
0301     return b.distance_to(a);
0302   }
0303 
0304   /// Test two iterators for equality.
0305   friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
0306   {
0307     return a.equal(b);
0308   }
0309 
0310   /// Test two iterators for inequality.
0311   friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
0312   {
0313     return !a.equal(b);
0314   }
0315 
0316   /// Compare two iterators.
0317   friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
0318   {
0319     return a.distance_to(b) > 0;
0320   }
0321 
0322   /// Compare two iterators.
0323   friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
0324   {
0325     return !(b < a);
0326   }
0327 
0328   /// Compare two iterators.
0329   friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
0330   {
0331     return b < a;
0332   }
0333 
0334   /// Compare two iterators.
0335   friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
0336   {
0337     return !(a < b);
0338   }
0339 
0340 private:
0341   // Dereference the iterator.
0342   reference dereference() const
0343   {
0344     return static_cast<pointer>(
0345         current_buffer_.data())[current_buffer_position_];
0346   }
0347 
0348   // Compare two iterators for equality.
0349   bool equal(const buffers_iterator& other) const
0350   {
0351     return position_ == other.position_;
0352   }
0353 
0354   // Increment the iterator.
0355   void increment()
0356   {
0357     BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
0358     ++position_;
0359 
0360     // Check if the increment can be satisfied by the current buffer.
0361     ++current_buffer_position_;
0362     if (current_buffer_position_ != current_buffer_.size())
0363       return;
0364 
0365     // Find the next non-empty buffer.
0366     ++current_;
0367     current_buffer_position_ = 0;
0368     while (current_ != end_)
0369     {
0370       current_buffer_ = *current_;
0371       if (current_buffer_.size() > 0)
0372         return;
0373       ++current_;
0374     }
0375   }
0376 
0377   // Decrement the iterator.
0378   void decrement()
0379   {
0380     BOOST_ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
0381     --position_;
0382 
0383     // Check if the decrement can be satisfied by the current buffer.
0384     if (current_buffer_position_ != 0)
0385     {
0386       --current_buffer_position_;
0387       return;
0388     }
0389 
0390     // Find the previous non-empty buffer.
0391     buffer_sequence_iterator_type iter = current_;
0392     while (iter != begin_)
0393     {
0394       --iter;
0395       buffer_type buffer = *iter;
0396       std::size_t buffer_size = buffer.size();
0397       if (buffer_size > 0)
0398       {
0399         current_ = iter;
0400         current_buffer_ = buffer;
0401         current_buffer_position_ = buffer_size - 1;
0402         return;
0403       }
0404     }
0405   }
0406 
0407   // Advance the iterator by the specified distance.
0408   void advance(std::ptrdiff_t n)
0409   {
0410     if (n > 0)
0411     {
0412       BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
0413       for (;;)
0414       {
0415         std::ptrdiff_t current_buffer_balance
0416           = current_buffer_.size() - current_buffer_position_;
0417 
0418         // Check if the advance can be satisfied by the current buffer.
0419         if (current_buffer_balance > n)
0420         {
0421           position_ += n;
0422           current_buffer_position_ += n;
0423           return;
0424         }
0425 
0426         // Update position.
0427         n -= current_buffer_balance;
0428         position_ += current_buffer_balance;
0429 
0430         // Move to next buffer. If it is empty then it will be skipped on the
0431         // next iteration of this loop.
0432         if (++current_ == end_)
0433         {
0434           BOOST_ASIO_ASSERT(n == 0 && "iterator out of bounds");
0435           current_buffer_ = buffer_type();
0436           current_buffer_position_ = 0;
0437           return;
0438         }
0439         current_buffer_ = *current_;
0440         current_buffer_position_ = 0;
0441       }
0442     }
0443     else if (n < 0)
0444     {
0445       std::size_t abs_n = -n;
0446       BOOST_ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
0447       for (;;)
0448       {
0449         // Check if the advance can be satisfied by the current buffer.
0450         if (current_buffer_position_ >= abs_n)
0451         {
0452           position_ -= abs_n;
0453           current_buffer_position_ -= abs_n;
0454           return;
0455         }
0456 
0457         // Update position.
0458         abs_n -= current_buffer_position_;
0459         position_ -= current_buffer_position_;
0460 
0461         // Check if we've reached the beginning of the buffers.
0462         if (current_ == begin_)
0463         {
0464           BOOST_ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
0465           current_buffer_position_ = 0;
0466           return;
0467         }
0468 
0469         // Find the previous non-empty buffer.
0470         buffer_sequence_iterator_type iter = current_;
0471         while (iter != begin_)
0472         {
0473           --iter;
0474           buffer_type buffer = *iter;
0475           std::size_t buffer_size = buffer.size();
0476           if (buffer_size > 0)
0477           {
0478             current_ = iter;
0479             current_buffer_ = buffer;
0480             current_buffer_position_ = buffer_size;
0481             break;
0482           }
0483         }
0484       }
0485     }
0486   }
0487 
0488   // Determine the distance between two iterators.
0489   std::ptrdiff_t distance_to(const buffers_iterator& other) const
0490   {
0491     return other.position_ - position_;
0492   }
0493 
0494   buffer_type current_buffer_;
0495   std::size_t current_buffer_position_;
0496   buffer_sequence_iterator_type begin_;
0497   buffer_sequence_iterator_type current_;
0498   buffer_sequence_iterator_type end_;
0499   std::size_t position_;
0500 };
0501 
0502 /// Construct an iterator representing the beginning of the buffers' data.
0503 template <typename BufferSequence>
0504 inline buffers_iterator<BufferSequence> buffers_begin(
0505     const BufferSequence& buffers)
0506 {
0507   return buffers_iterator<BufferSequence>::begin(buffers);
0508 }
0509 
0510 /// Construct an iterator representing the end of the buffers' data.
0511 template <typename BufferSequence>
0512 inline buffers_iterator<BufferSequence> buffers_end(
0513     const BufferSequence& buffers)
0514 {
0515   return buffers_iterator<BufferSequence>::end(buffers);
0516 }
0517 
0518 } // namespace asio
0519 } // namespace boost
0520 
0521 #include <boost/asio/detail/pop_options.hpp>
0522 
0523 #endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP