File indexing completed on 2025-09-16 08:29:12
0001
0002
0003
0004
0005
0006
0007
0008
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
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
0089
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
0102 typedef std::ptrdiff_t difference_type;
0103
0104
0105 typedef ByteType value_type;
0106
0107 #if defined(GENERATING_DOCUMENTATION)
0108
0109
0110
0111
0112
0113
0114 typedef const_or_non_const_ByteType* pointer;
0115 #else
0116 typedef typename detail::buffers_iterator_types<
0117 BufferSequence, ByteType>::byte_type* pointer;
0118 #endif
0119
0120 #if defined(GENERATING_DOCUMENTATION)
0121
0122
0123
0124
0125
0126
0127 typedef const_or_non_const_ByteType& reference;
0128 #else
0129 typedef typename detail::buffers_iterator_types<
0130 BufferSequence, ByteType>::byte_type& reference;
0131 #endif
0132
0133
0134 typedef std::random_access_iterator_tag iterator_category;
0135
0136
0137 buffers_iterator()
0138 : current_buffer_(),
0139 current_buffer_position_(0),
0140 begin_(),
0141 current_(),
0142 end_(),
0143 position_(0)
0144 {
0145 }
0146
0147
0148 static buffers_iterator begin(const BufferSequence& buffers)
0149 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0150 __attribute__ ((__noinline__))
0151 #endif
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
0168 static buffers_iterator end(const BufferSequence& buffers)
0169 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0170 __attribute__ ((__noinline__))
0171 #endif
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
0187 reference operator*() const
0188 {
0189 return dereference();
0190 }
0191
0192
0193 pointer operator->() const
0194 {
0195 return &dereference();
0196 }
0197
0198
0199 reference operator[](std::ptrdiff_t difference) const
0200 {
0201 buffers_iterator tmp(*this);
0202 tmp.advance(difference);
0203 return *tmp;
0204 }
0205
0206
0207 buffers_iterator& operator++()
0208 {
0209 increment();
0210 return *this;
0211 }
0212
0213
0214 buffers_iterator operator++(int)
0215 {
0216 buffers_iterator tmp(*this);
0217 ++*this;
0218 return tmp;
0219 }
0220
0221
0222 buffers_iterator& operator--()
0223 {
0224 decrement();
0225 return *this;
0226 }
0227
0228
0229 buffers_iterator operator--(int)
0230 {
0231 buffers_iterator tmp(*this);
0232 --*this;
0233 return tmp;
0234 }
0235
0236
0237 buffers_iterator& operator+=(std::ptrdiff_t difference)
0238 {
0239 advance(difference);
0240 return *this;
0241 }
0242
0243
0244 buffers_iterator& operator-=(std::ptrdiff_t difference)
0245 {
0246 advance(-difference);
0247 return *this;
0248 }
0249
0250
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
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
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
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
0285 friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
0286 {
0287 return a.equal(b);
0288 }
0289
0290
0291 friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
0292 {
0293 return !a.equal(b);
0294 }
0295
0296
0297 friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
0298 {
0299 return a.distance_to(b) > 0;
0300 }
0301
0302
0303 friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
0304 {
0305 return !(b < a);
0306 }
0307
0308
0309 friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
0310 {
0311 return b < a;
0312 }
0313
0314
0315 friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
0316 {
0317 return !(a < b);
0318 }
0319
0320 private:
0321
0322 reference dereference() const
0323 {
0324 return static_cast<pointer>(
0325 current_buffer_.data())[current_buffer_position_];
0326 }
0327
0328
0329 bool equal(const buffers_iterator& other) const
0330 {
0331 return position_ == other.position_;
0332 }
0333
0334
0335 void increment()
0336 {
0337 BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
0338 ++position_;
0339
0340
0341 ++current_buffer_position_;
0342 if (current_buffer_position_ != current_buffer_.size())
0343 return;
0344
0345
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
0358 void decrement()
0359 {
0360 BOOST_ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
0361 --position_;
0362
0363
0364 if (current_buffer_position_ != 0)
0365 {
0366 --current_buffer_position_;
0367 return;
0368 }
0369
0370
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
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
0399 if (current_buffer_balance > n)
0400 {
0401 position_ += n;
0402 current_buffer_position_ += n;
0403 return;
0404 }
0405
0406
0407 n -= current_buffer_balance;
0408 position_ += current_buffer_balance;
0409
0410
0411
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
0430 if (current_buffer_position_ >= abs_n)
0431 {
0432 position_ -= abs_n;
0433 current_buffer_position_ -= abs_n;
0434 return;
0435 }
0436
0437
0438 abs_n -= current_buffer_position_;
0439 position_ -= current_buffer_position_;
0440
0441
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
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
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
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
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 }
0499 }
0500
0501 #include <boost/asio/detail/pop_options.hpp>
0502
0503 #endif