File indexing completed on 2025-01-30 09:34:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)
0013 #define BOOST_CIRCULAR_BUFFER_DETAILS_HPP
0014
0015 #if defined(_MSC_VER)
0016 #pragma once
0017 #endif
0018
0019 #include <boost/throw_exception.hpp>
0020 #include <boost/core/allocator_access.hpp>
0021 #include <boost/core/pointer_traits.hpp>
0022 #include <boost/move/move.hpp>
0023 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
0024 #include <boost/core/no_exceptions_support.hpp>
0025 #include <iterator>
0026
0027
0028
0029
0030 #if defined(_MSC_VER)
0031 # pragma warning(push)
0032 # pragma warning(disable:4913)
0033 #endif
0034
0035 namespace boost {
0036
0037 namespace cb_details {
0038
0039 template <class Alloc> struct nonconst_traits;
0040
0041 template<class ForwardIterator, class Diff, class T, class Alloc>
0042 void uninitialized_fill_n_with_alloc(
0043 ForwardIterator first, Diff n, const T& item, Alloc& alloc);
0044
0045 template<class InputIterator, class ForwardIterator, class Alloc>
0046 ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a);
0047
0048 template<class InputIterator, class ForwardIterator, class Alloc>
0049 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a);
0050
0051
0052
0053
0054
0055 template <class Alloc>
0056 struct const_traits {
0057
0058 typedef typename Alloc::value_type value_type;
0059 typedef typename boost::allocator_const_pointer<Alloc>::type pointer;
0060 typedef const value_type& reference;
0061 typedef typename boost::allocator_size_type<Alloc>::type size_type;
0062 typedef typename boost::allocator_difference_type<Alloc>::type difference_type;
0063
0064
0065 typedef nonconst_traits<Alloc> nonconst_self;
0066 };
0067
0068
0069
0070
0071
0072 template <class Alloc>
0073 struct nonconst_traits {
0074
0075 typedef typename Alloc::value_type value_type;
0076 typedef typename boost::allocator_pointer<Alloc>::type pointer;
0077 typedef value_type& reference;
0078 typedef typename boost::allocator_size_type<Alloc>::type size_type;
0079 typedef typename boost::allocator_difference_type<Alloc>::type difference_type;
0080
0081
0082 typedef nonconst_traits<Alloc> nonconst_self;
0083 };
0084
0085
0086
0087
0088
0089 template <class Iterator>
0090 struct iterator_wrapper {
0091 mutable Iterator m_it;
0092 explicit iterator_wrapper(Iterator it) : m_it(it) {}
0093 Iterator operator () () const { return m_it++; }
0094 private:
0095 iterator_wrapper<Iterator>& operator = (const iterator_wrapper<Iterator>&);
0096 };
0097
0098
0099
0100
0101
0102 template <class Pointer, class Value>
0103 struct item_wrapper {
0104 Value m_item;
0105 explicit item_wrapper(Value item) : m_item(item) {}
0106 Pointer operator () () const { return &m_item; }
0107 private:
0108 item_wrapper<Pointer, Value>& operator = (const item_wrapper<Pointer, Value>&);
0109 };
0110
0111
0112
0113
0114
0115 template <class Value, class Alloc>
0116 struct assign_n {
0117 typedef typename boost::allocator_size_type<Alloc>::type size_type;
0118 size_type m_n;
0119 Value m_item;
0120 Alloc& m_alloc;
0121 assign_n(size_type n, Value item, Alloc& alloc) : m_n(n), m_item(item), m_alloc(alloc) {}
0122 template <class Pointer>
0123 void operator () (Pointer p) const {
0124 uninitialized_fill_n_with_alloc(p, m_n, m_item, m_alloc);
0125 }
0126 private:
0127 assign_n<Value, Alloc>& operator = (const assign_n<Value, Alloc>&);
0128 };
0129
0130
0131
0132
0133
0134 template <class Iterator, class Alloc>
0135 struct assign_range {
0136 Iterator m_first;
0137 Iterator m_last;
0138 Alloc& m_alloc;
0139
0140 assign_range(const Iterator& first, const Iterator& last, Alloc& alloc)
0141 : m_first(first), m_last(last), m_alloc(alloc) {}
0142
0143 template <class Pointer>
0144 void operator () (Pointer p) const {
0145 boost::cb_details::uninitialized_copy(m_first, m_last, p, m_alloc);
0146 }
0147 };
0148
0149 template <class Iterator, class Alloc>
0150 inline assign_range<Iterator, Alloc> make_assign_range(const Iterator& first, const Iterator& last, Alloc& a) {
0151 return assign_range<Iterator, Alloc>(first, last, a);
0152 }
0153
0154
0155
0156
0157
0158 template <class Size>
0159 class capacity_control {
0160
0161
0162 Size m_capacity;
0163
0164
0165 Size m_min_capacity;
0166
0167 public:
0168
0169
0170 capacity_control(Size buffer_capacity, Size min_buffer_capacity = 0)
0171 : m_capacity(buffer_capacity), m_min_capacity(min_buffer_capacity)
0172 {
0173 BOOST_CB_ASSERT(buffer_capacity >= min_buffer_capacity);
0174 }
0175
0176
0177
0178
0179
0180
0181 Size capacity() const { return m_capacity; }
0182
0183
0184 Size min_capacity() const { return m_min_capacity; }
0185
0186
0187 operator Size() const { return m_capacity; }
0188 };
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 template <class Buff, class Traits>
0199 struct iterator
0200 #if BOOST_CB_ENABLE_DEBUG
0201 : public debug_iterator_base
0202 #endif
0203 {
0204
0205
0206
0207 typedef iterator<Buff, typename Traits::nonconst_self> nonconst_self;
0208
0209
0210 typedef std::random_access_iterator_tag iterator_category;
0211
0212
0213 typedef typename Traits::value_type value_type;
0214
0215
0216 typedef typename Traits::pointer pointer;
0217
0218
0219 typedef typename Traits::reference reference;
0220
0221
0222 typedef typename Traits::size_type size_type;
0223
0224
0225 typedef typename Traits::difference_type difference_type;
0226
0227
0228
0229
0230 const Buff* m_buff;
0231
0232
0233 pointer m_it;
0234
0235
0236
0237
0238
0239
0240 iterator() : m_buff(0), m_it(0) {}
0241
0242 #if BOOST_CB_ENABLE_DEBUG
0243
0244
0245 iterator(const nonconst_self& it) : debug_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {}
0246
0247
0248
0249
0250
0251 iterator(const Buff* cb, const pointer p) : debug_iterator_base(cb), m_buff(cb), m_it(p) {}
0252
0253 #else
0254
0255 iterator(const nonconst_self& it) : m_buff(it.m_buff), m_it(it.m_it) {}
0256
0257 iterator(const Buff* cb, const pointer p) : m_buff(cb), m_it(p) {}
0258
0259 #endif
0260
0261
0262 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
0263 iterator& operator=(const iterator&) = default;
0264 #else
0265 iterator& operator=(const iterator& it) {
0266 if (this == &it)
0267 return *this;
0268 #if BOOST_CB_ENABLE_DEBUG
0269 debug_iterator_base::operator =(it);
0270 #endif
0271 m_buff = it.m_buff;
0272 m_it = it.m_it;
0273 return *this;
0274 }
0275 #endif
0276
0277
0278
0279
0280 reference operator * () const {
0281 BOOST_CB_ASSERT(is_valid(m_buff));
0282 BOOST_CB_ASSERT(m_it != 0);
0283 return *m_it;
0284 }
0285
0286
0287 pointer operator -> () const { return &(operator*()); }
0288
0289
0290 template <class Traits0>
0291 difference_type operator - (const iterator<Buff, Traits0>& it) const {
0292 BOOST_CB_ASSERT(is_valid(m_buff));
0293 BOOST_CB_ASSERT(it.is_valid(m_buff));
0294 return linearize_pointer(*this) - linearize_pointer(it);
0295 }
0296
0297
0298 iterator& operator ++ () {
0299 BOOST_CB_ASSERT(is_valid(m_buff));
0300 BOOST_CB_ASSERT(m_it != 0);
0301 m_buff->increment(m_it);
0302 if (m_it == m_buff->m_last)
0303 m_it = 0;
0304 return *this;
0305 }
0306
0307
0308 iterator operator ++ (int) {
0309 iterator<Buff, Traits> tmp = *this;
0310 ++*this;
0311 return tmp;
0312 }
0313
0314
0315 iterator& operator -- () {
0316 BOOST_CB_ASSERT(is_valid(m_buff));
0317 BOOST_CB_ASSERT(m_it != m_buff->m_first);
0318 if (m_it == 0)
0319 m_it = m_buff->m_last;
0320 m_buff->decrement(m_it);
0321 return *this;
0322 }
0323
0324
0325 iterator operator -- (int) {
0326 iterator<Buff, Traits> tmp = *this;
0327 --*this;
0328 return tmp;
0329 }
0330
0331
0332 iterator& operator += (difference_type n) {
0333 BOOST_CB_ASSERT(is_valid(m_buff));
0334 if (n > 0) {
0335 BOOST_CB_ASSERT(m_buff->end() - *this >= n);
0336 m_it = m_buff->add(m_it, n);
0337 if (m_it == m_buff->m_last)
0338 m_it = 0;
0339 } else if (n < 0) {
0340 *this -= -n;
0341 }
0342 return *this;
0343 }
0344
0345
0346 iterator operator + (difference_type n) const { return iterator<Buff, Traits>(*this) += n; }
0347
0348
0349 iterator& operator -= (difference_type n) {
0350 BOOST_CB_ASSERT(is_valid(m_buff));
0351 if (n > 0) {
0352 BOOST_CB_ASSERT(*this - m_buff->begin() >= n);
0353 m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n);
0354 } else if (n < 0) {
0355 *this += -n;
0356 }
0357 return *this;
0358 }
0359
0360
0361 iterator operator - (difference_type n) const { return iterator<Buff, Traits>(*this) -= n; }
0362
0363
0364 reference operator [] (difference_type n) const { return *(*this + n); }
0365
0366
0367
0368
0369 template <class Traits0>
0370 bool operator == (const iterator<Buff, Traits0>& it) const {
0371 BOOST_CB_ASSERT(is_valid(m_buff));
0372 BOOST_CB_ASSERT(it.is_valid(m_buff));
0373 return m_it == it.m_it;
0374 }
0375
0376
0377 template <class Traits0>
0378 bool operator != (const iterator<Buff, Traits0>& it) const {
0379 BOOST_CB_ASSERT(is_valid(m_buff));
0380 BOOST_CB_ASSERT(it.is_valid(m_buff));
0381 return m_it != it.m_it;
0382 }
0383
0384
0385 template <class Traits0>
0386 bool operator < (const iterator<Buff, Traits0>& it) const {
0387 BOOST_CB_ASSERT(is_valid(m_buff));
0388 BOOST_CB_ASSERT(it.is_valid(m_buff));
0389 return linearize_pointer(*this) < linearize_pointer(it);
0390 }
0391
0392
0393 template <class Traits0>
0394 bool operator > (const iterator<Buff, Traits0>& it) const { return it < *this; }
0395
0396
0397 template <class Traits0>
0398 bool operator <= (const iterator<Buff, Traits0>& it) const { return !(it < *this); }
0399
0400
0401 template <class Traits0>
0402 bool operator >= (const iterator<Buff, Traits0>& it) const { return !(*this < it); }
0403
0404
0405
0406
0407 template <class Traits0>
0408 typename Traits0::pointer linearize_pointer(const iterator<Buff, Traits0>& it) const {
0409 return it.m_it == 0 ? m_buff->m_buff + m_buff->size() :
0410 (it.m_it < m_buff->m_first ? it.m_it + (m_buff->m_end - m_buff->m_first)
0411 : m_buff->m_buff + (it.m_it - m_buff->m_first));
0412 }
0413 };
0414
0415
0416 template <class Buff, class Traits>
0417 inline iterator<Buff, Traits>
0418 operator + (typename Traits::difference_type n, const iterator<Buff, Traits>& it) {
0419 return it + n;
0420 }
0421
0422
0423
0424
0425
0426 template<class InputIterator, class ForwardIterator, class Alloc>
0427 inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) {
0428 ForwardIterator next = dest;
0429 BOOST_TRY {
0430 for (; first != last; ++first, ++dest)
0431 boost::allocator_construct(a, boost::to_address(dest), *first);
0432 } BOOST_CATCH(...) {
0433 for (; next != dest; ++next)
0434 boost::allocator_destroy(a, boost::to_address(next));
0435 BOOST_RETHROW
0436 }
0437 BOOST_CATCH_END
0438 return dest;
0439 }
0440
0441 template<class InputIterator, class ForwardIterator, class Alloc>
0442 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
0443 true_type) {
0444 for (; first != last; ++first, ++dest)
0445 boost::allocator_construct(a, boost::to_address(dest), boost::move(*first));
0446 return dest;
0447 }
0448
0449 template<class InputIterator, class ForwardIterator, class Alloc>
0450 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
0451 false_type) {
0452 return uninitialized_copy(first, last, dest, a);
0453 }
0454
0455
0456
0457
0458
0459 template<class InputIterator, class ForwardIterator, class Alloc>
0460 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) {
0461 typedef typename boost::is_nothrow_move_constructible<typename Alloc::value_type>::type tag_t;
0462 return uninitialized_move_if_noexcept_impl(first, last, dest, a, tag_t());
0463 }
0464
0465
0466
0467
0468
0469 template<class ForwardIterator, class Diff, class T, class Alloc>
0470 inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) {
0471 ForwardIterator next = first;
0472 BOOST_TRY {
0473 for (; n > 0; ++first, --n)
0474 boost::allocator_construct(alloc, boost::to_address(first), item);
0475 } BOOST_CATCH(...) {
0476 for (; next != first; ++next)
0477 boost::allocator_destroy(alloc, boost::to_address(next));
0478 BOOST_RETHROW
0479 }
0480 BOOST_CATCH_END
0481 }
0482
0483 }
0484
0485 }
0486
0487 #if defined(_MSC_VER)
0488 # pragma warning(pop)
0489 #endif
0490
0491 #endif