File indexing completed on 2025-01-18 09:29:08
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 #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
0107 }
0108
0109
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
0122 typedef std::ptrdiff_t difference_type;
0123
0124
0125 typedef ByteType value_type;
0126
0127 #if defined(GENERATING_DOCUMENTATION)
0128
0129
0130
0131
0132
0133
0134 typedef const_or_non_const_ByteType* pointer;
0135 #else
0136 typedef typename detail::buffers_iterator_types<
0137 BufferSequence, ByteType>::byte_type* pointer;
0138 #endif
0139
0140 #if defined(GENERATING_DOCUMENTATION)
0141
0142
0143
0144
0145
0146
0147 typedef const_or_non_const_ByteType& reference;
0148 #else
0149 typedef typename detail::buffers_iterator_types<
0150 BufferSequence, ByteType>::byte_type& reference;
0151 #endif
0152
0153
0154 typedef std::random_access_iterator_tag iterator_category;
0155
0156
0157 buffers_iterator()
0158 : current_buffer_(),
0159 current_buffer_position_(0),
0160 begin_(),
0161 current_(),
0162 end_(),
0163 position_(0)
0164 {
0165 }
0166
0167
0168 static buffers_iterator begin(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 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
0188 static buffers_iterator end(const BufferSequence& buffers)
0189 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
0190 __attribute__ ((__noinline__))
0191 #endif
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
0207 reference operator*() const
0208 {
0209 return dereference();
0210 }
0211
0212
0213 pointer operator->() const
0214 {
0215 return &dereference();
0216 }
0217
0218
0219 reference operator[](std::ptrdiff_t difference) const
0220 {
0221 buffers_iterator tmp(*this);
0222 tmp.advance(difference);
0223 return *tmp;
0224 }
0225
0226
0227 buffers_iterator& operator++()
0228 {
0229 increment();
0230 return *this;
0231 }
0232
0233
0234 buffers_iterator operator++(int)
0235 {
0236 buffers_iterator tmp(*this);
0237 ++*this;
0238 return tmp;
0239 }
0240
0241
0242 buffers_iterator& operator--()
0243 {
0244 decrement();
0245 return *this;
0246 }
0247
0248
0249 buffers_iterator operator--(int)
0250 {
0251 buffers_iterator tmp(*this);
0252 --*this;
0253 return tmp;
0254 }
0255
0256
0257 buffers_iterator& operator+=(std::ptrdiff_t difference)
0258 {
0259 advance(difference);
0260 return *this;
0261 }
0262
0263
0264 buffers_iterator& operator-=(std::ptrdiff_t difference)
0265 {
0266 advance(-difference);
0267 return *this;
0268 }
0269
0270
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
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
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
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
0305 friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
0306 {
0307 return a.equal(b);
0308 }
0309
0310
0311 friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
0312 {
0313 return !a.equal(b);
0314 }
0315
0316
0317 friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
0318 {
0319 return a.distance_to(b) > 0;
0320 }
0321
0322
0323 friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
0324 {
0325 return !(b < a);
0326 }
0327
0328
0329 friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
0330 {
0331 return b < a;
0332 }
0333
0334
0335 friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
0336 {
0337 return !(a < b);
0338 }
0339
0340 private:
0341
0342 reference dereference() const
0343 {
0344 return static_cast<pointer>(
0345 current_buffer_.data())[current_buffer_position_];
0346 }
0347
0348
0349 bool equal(const buffers_iterator& other) const
0350 {
0351 return position_ == other.position_;
0352 }
0353
0354
0355 void increment()
0356 {
0357 BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
0358 ++position_;
0359
0360
0361 ++current_buffer_position_;
0362 if (current_buffer_position_ != current_buffer_.size())
0363 return;
0364
0365
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
0378 void decrement()
0379 {
0380 BOOST_ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
0381 --position_;
0382
0383
0384 if (current_buffer_position_ != 0)
0385 {
0386 --current_buffer_position_;
0387 return;
0388 }
0389
0390
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
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
0419 if (current_buffer_balance > n)
0420 {
0421 position_ += n;
0422 current_buffer_position_ += n;
0423 return;
0424 }
0425
0426
0427 n -= current_buffer_balance;
0428 position_ += current_buffer_balance;
0429
0430
0431
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
0450 if (current_buffer_position_ >= abs_n)
0451 {
0452 position_ -= abs_n;
0453 current_buffer_position_ -= abs_n;
0454 return;
0455 }
0456
0457
0458 abs_n -= current_buffer_position_;
0459 position_ -= current_buffer_position_;
0460
0461
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
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
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
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
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 }
0519 }
0520
0521 #include <boost/asio/detail/pop_options.hpp>
0522
0523 #endif