1/*
2 *
3 * Copyright (c) 1997
4 * Moscow Center for SPARC Technology
5 *
6 * Copyright (c) 1999
7 * Boris Fomitchev
8 *
9 * This material is provided "as is", with absolutely no warranty expressed
10 * or implied. Any use is at your own risk.
11 *
12 * Permission to use or copy this software for any purpose is hereby granted
13 * without fee, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
17 *
18 */
19
20#ifndef _STLP_DBG_ITERATOR_H
21#define _STLP_DBG_ITERATOR_H
22
23#ifndef _STLP_INTERNAL_PAIR_H
24#  include <stl/_pair.h>
25#endif
26
27#ifndef _STLP_INTERNAL_ALLOC_H
28#  include <stl/_alloc.h>
29#endif
30
31_STLP_BEGIN_NAMESPACE
32_STLP_MOVE_TO_PRIV_NAMESPACE
33
34//============================================================
35
36template <class _Iterator>
37void _Decrement(_Iterator& __it, const bidirectional_iterator_tag &)
38{ --__it; }
39
40template <class _Iterator>
41void _Decrement(_Iterator& __it, const random_access_iterator_tag &)
42{ --__it; }
43
44template <class _Iterator>
45void _Decrement(_Iterator& __it, const forward_iterator_tag &)
46{ _STLP_ASSERT(0) }
47
48template <class _Iterator>
49void _Advance(_Iterator&, ptrdiff_t, const forward_iterator_tag &)
50{ _STLP_ASSERT(0) }
51
52template <class _Iterator>
53void _Advance(_Iterator& __it, ptrdiff_t, const bidirectional_iterator_tag &)
54{ _STLP_ASSERT(0) }
55
56template <class _Iterator>
57void _Advance(_Iterator& __it, ptrdiff_t __n, const random_access_iterator_tag &)
58{ __it += __n; }
59
60template <class _Iterator>
61ptrdiff_t _DBG_distance(const _Iterator& __x, const _Iterator& __y, const random_access_iterator_tag &)
62{ return __x - __y; }
63
64template <class _Iterator>
65ptrdiff_t _DBG_distance(const _Iterator&, const _Iterator&, const forward_iterator_tag &) {
66  _STLP_ASSERT(0)
67  return 0;
68}
69
70template <class _Iterator>
71ptrdiff_t _DBG_distance(const _Iterator&, const _Iterator&, const bidirectional_iterator_tag &) {
72  _STLP_ASSERT(0)
73  return 0;
74}
75
76template <class _Iterator>
77bool _CompareIt(const _Iterator&, const _Iterator&, const forward_iterator_tag &) {
78  _STLP_ASSERT(0)
79  return false;
80}
81
82template <class _Iterator>
83bool _CompareIt(const _Iterator&, const _Iterator&, const bidirectional_iterator_tag &) {
84  _STLP_ASSERT(0)
85  return false;
86}
87
88template <class _Iterator>
89bool _CompareIt(const _Iterator& __x, const _Iterator& __y, const random_access_iterator_tag &)
90{ return __x < __y; }
91
92template <class _Iterator>
93bool _Dereferenceable(const _Iterator& __it)
94{ return (__it._Get_container_ptr() != 0) && !(__it._M_iterator == (__it._Get_container_ptr())->end()); }
95
96template <class _Iterator>
97bool _Incrementable(const _Iterator& __it, ptrdiff_t __n, const forward_iterator_tag &)
98{ return (__n == 1) && _Dereferenceable(__it); }
99
100template <class _Iterator>
101bool _Incrementable(const _Iterator& __it, ptrdiff_t __n, const bidirectional_iterator_tag &) {
102  typedef typename _Iterator::_Container_type __container_type;
103  __container_type* __c = __it._Get_container_ptr();
104  return (__c != 0) && ((__n == 1 && __it._M_iterator != __c->end() ) ||
105                        (__n == -1 && __it._M_iterator != __c->begin()));
106}
107
108template <class _Iterator>
109bool _Incrementable(const _Iterator& __it, ptrdiff_t __n, const random_access_iterator_tag &) {
110  typedef typename _Iterator::_Container_type __container_type;
111  __container_type* __c = __it._Get_container_ptr();
112  if (__c == 0) return false;
113  ptrdiff_t __new_pos = (__it._M_iterator - __c->begin()) + __n;
114  return  (__new_pos >= 0) && (__STATIC_CAST(typename __container_type::size_type, __new_pos) <= __c->size());
115}
116
117
118template <class _Container>
119struct _DBG_iter_base : public __owned_link {
120public:
121  typedef typename _Container::value_type value_type;
122  typedef typename _Container::reference  reference;
123  typedef typename _Container::pointer    pointer;
124  typedef ptrdiff_t difference_type;
125  //private:
126  typedef typename _Container::iterator        _Nonconst_iterator;
127  typedef typename _Container::const_iterator  _Const_iterator;
128  typedef _Container                     _Container_type;
129
130#ifdef _STLP_CLASS_PARTIAL_SPECIALIZATION
131  typedef typename iterator_traits<_Const_iterator>::iterator_category _Iterator_category;
132#else
133  typedef typename _Container::_Iterator_category  _Iterator_category;
134#endif
135  typedef _Iterator_category iterator_category;
136
137  _DBG_iter_base() : __owned_link(0)  {}
138  _DBG_iter_base(const __owned_list* __c, const _Const_iterator& __it) :
139#if defined(__HP_aCC) && (__HP_aCC < 60000)
140  __owned_link(__c), _M_iterator(*__REINTERPRET_CAST(const _Nonconst_iterator *, &__it)) {}
141#else
142    __owned_link(__c), _M_iterator(*(const _Nonconst_iterator*)&__it) {}
143#endif
144  _Container* _Get_container_ptr() const {
145    return (_Container*)__stl_debugger::_Get_container_ptr(this);
146  }
147
148  void __increment();
149  void __decrement();
150  void __advance(ptrdiff_t __n);
151
152// protected:
153  _Nonconst_iterator _M_iterator;
154};
155
156template <class _Container>
157inline void _DBG_iter_base<_Container>::__increment() {
158  _STLP_DEBUG_CHECK(_Incrementable(*this, 1, _Iterator_category()))
159  ++_M_iterator;
160}
161
162template <class _Container>
163inline void _DBG_iter_base<_Container>::__decrement() {
164  _STLP_DEBUG_CHECK(_Incrementable(*this, -1, _Iterator_category()))
165  _Decrement(_M_iterator, _Iterator_category());
166}
167
168template <class _Container>
169inline void _DBG_iter_base<_Container>::__advance(ptrdiff_t __n) {
170  _STLP_DEBUG_CHECK(_Incrementable(*this, __n, _Iterator_category()))
171  _Advance(_M_iterator, __n, _Iterator_category());
172}
173
174template <class _Container>
175ptrdiff_t operator-(const _DBG_iter_base<_Container>& __x,
176                    const _DBG_iter_base<_Container>& __y ) {
177  typedef typename _DBG_iter_base<_Container>::_Iterator_category  _Iterator_category;
178  _STLP_DEBUG_CHECK(__check_same_owner(__x, __y))
179  return _DBG_distance(__x._M_iterator,__y._M_iterator, _Iterator_category());
180}
181
182template <class _Container, class _Traits>
183struct _DBG_iter_mid : public _DBG_iter_base<_Container> {
184  typedef _DBG_iter_mid<_Container, typename _Traits::_NonConstTraits> _Nonconst_self;
185  typedef typename _Container::iterator        _Nonconst_iterator;
186  typedef typename _Container::const_iterator  _Const_iterator;
187
188  _DBG_iter_mid() {}
189
190  explicit _DBG_iter_mid(const _Nonconst_self& __it) :
191      _DBG_iter_base<_Container>(__it) {}
192
193  _DBG_iter_mid(const __owned_list* __c, const _Const_iterator& __it) :
194      _DBG_iter_base<_Container>(__c, __it) {}
195};
196
197template <class _Container, class _Traits>
198struct _DBG_iter : public _DBG_iter_mid<_Container, _Traits> {
199  typedef _DBG_iter_base<_Container>          _Base;
200public:
201  typedef typename _Base::value_type value_type;
202  typedef typename _Base::difference_type difference_type;
203  typedef typename _Traits::reference  reference;
204  typedef typename _Traits::pointer    pointer;
205
206  typedef typename _Base::_Nonconst_iterator _Nonconst_iterator;
207  typedef typename _Base::_Const_iterator _Const_iterator;
208
209private:
210  typedef _DBG_iter<_Container, _Traits>     _Self;
211  typedef _DBG_iter_mid<_Container, typename _Traits::_NonConstTraits> _Nonconst_mid;
212
213public:
214
215#ifdef _STLP_CLASS_PARTIAL_SPECIALIZATION
216  typedef typename _Base::iterator_category iterator_category;
217#endif
218  typedef typename _Base::_Iterator_category  _Iterator_category;
219
220public:
221  _DBG_iter() {}
222    // boris : real type of iter would be nice
223  _DBG_iter(const __owned_list* __c, const _Const_iterator& __it) :
224    _DBG_iter_mid<_Container, _Traits>(__c, __it) {}
225
226  // This allows conversions from iterator to const_iterator without being
227  // redundant with the copy constructor below.
228  _DBG_iter(const _Nonconst_mid& __rhs) :
229    _DBG_iter_mid<_Container, _Traits>(__rhs) {}
230
231  _DBG_iter(const  _Self& __rhs) :
232    _DBG_iter_mid<_Container, _Traits>(__rhs) {}
233
234  // This allows conversions from iterator to const_iterator without being
235  // redundant with the copy assignment operator below.
236  _Self& operator=(const _Nonconst_mid& __rhs) {
237    (_Base&)*this = __rhs;
238    return *this;
239  }
240
241  _Self& operator=(const  _Self& __rhs) {
242    (_Base&)*this = __rhs;
243    return *this;
244  }
245
246  reference operator*() const;
247
248  _STLP_DEFINE_ARROW_OPERATOR
249
250  _Self& operator++() {
251    this->__increment();
252    return *this;
253  }
254  _Self operator++(int) {
255    _Self __tmp = *this;
256    this->__increment();
257    return __tmp;
258  }
259  _Self& operator--() {
260    this->__decrement();
261    return *this;
262  }
263  _Self operator--(int) {
264    _Self __tmp = *this;
265    this->__decrement();
266    return __tmp;
267  }
268
269  _Self& operator+=(difference_type __n) {
270    this->__advance(__n);
271    return *this;
272  }
273
274  _Self& operator-=(difference_type __n) {
275    this->__advance(-__n);
276    return *this;
277  }
278  _Self operator+(difference_type __n) const {
279    _Self __tmp(*this);
280    __tmp.__advance(__n);
281    return __tmp;
282  }
283  _Self operator-(difference_type __n) const {
284    _Self __tmp(*this);
285    __tmp.__advance(-__n);
286    return __tmp;
287  }
288  reference operator[](difference_type __n) const { return *(*this + __n); }
289};
290
291template <class _Container, class _Traits>
292inline
293#if defined (_STLP_NESTED_TYPE_PARAM_BUG)
294_STLP_TYPENAME_ON_RETURN_TYPE _Traits::reference
295#else
296_STLP_TYPENAME_ON_RETURN_TYPE _DBG_iter<_Container, _Traits>::reference
297#endif
298_DBG_iter<_Container, _Traits>::operator*() const {
299  _STLP_DEBUG_CHECK(_Dereferenceable(*this))
300  _STLP_DEBUG_CHECK(_Traits::_Check(*this))
301  return *this->_M_iterator;
302}
303
304template <class _Container>
305inline bool
306operator==(const _DBG_iter_base<_Container>& __x, const _DBG_iter_base<_Container>& __y) {
307  _STLP_DEBUG_CHECK(__check_same_or_null_owner(__x, __y))
308  return __x._M_iterator == __y._M_iterator;
309}
310
311template <class _Container>
312inline bool
313operator<(const _DBG_iter_base<_Container>& __x, const _DBG_iter_base<_Container>& __y) {
314  _STLP_DEBUG_CHECK(__check_same_or_null_owner(__x, __y))
315  typedef typename _DBG_iter_base<_Container>::_Iterator_category _Category;
316  return _CompareIt(__x._M_iterator , __y._M_iterator, _Category());
317}
318
319template <class _Container>
320inline bool
321operator>(const _DBG_iter_base<_Container>& __x,
322       const _DBG_iter_base<_Container>& __y) {
323  typedef typename _DBG_iter_base<_Container>::_Iterator_category _Category;
324  return _CompareIt(__y._M_iterator , __x._M_iterator, _Category());
325}
326
327template <class _Container>
328inline bool
329operator>=(const _DBG_iter_base<_Container>& __x, const _DBG_iter_base<_Container>& __y) {
330  _STLP_DEBUG_CHECK(__check_same_or_null_owner(__x, __y))
331  typedef typename _DBG_iter_base<_Container>::_Iterator_category _Category;
332  return !_CompareIt(__x._M_iterator , __y._M_iterator, _Category());
333}
334
335template <class _Container>
336inline bool
337operator<=(const _DBG_iter_base<_Container>& __x,
338       const _DBG_iter_base<_Container>& __y) {
339  typedef typename _DBG_iter_base<_Container>::_Iterator_category _Category;
340  return !_CompareIt(__y._M_iterator , __x._M_iterator, _Category());
341}
342
343template <class _Container>
344inline bool
345operator!=(const _DBG_iter_base<_Container>& __x,
346        const _DBG_iter_base<_Container>& __y) {
347  _STLP_DEBUG_CHECK(__check_same_or_null_owner(__x, __y))
348  return __x._M_iterator != __y._M_iterator;
349}
350
351//------------------------------------------
352
353template <class _Container, class _Traits>
354inline _DBG_iter<_Container, _Traits>
355operator+(ptrdiff_t __n, const _DBG_iter<_Container, _Traits>& __it) {
356  _DBG_iter<_Container, _Traits> __tmp(__it);
357  return __tmp += __n;
358}
359
360
361template <class _Iterator>
362inline _Iterator _Non_Dbg_iter(_Iterator __it)
363{ return __it; }
364
365#if defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER)
366template <class _Container, class _Traits>
367inline typename _DBG_iter<_Container, _Traits>::_Nonconst_iterator
368_Non_Dbg_iter(const _DBG_iter<_Container, _Traits>& __it)
369{ return __it._M_iterator; }
370#endif
371
372/*
373 * Helper classes to check iterator range or pointer validity
374 * at construction time.
375 */
376template <class _Container>
377class __construct_checker {
378  typedef typename _Container::value_type value_type;
379protected:
380  __construct_checker() {}
381
382  __construct_checker(const value_type* __p) {
383    _STLP_VERBOSE_ASSERT((__p != 0), _StlMsg_INVALID_ARGUMENT)
384  }
385
386#if defined (_STLP_MEMBER_TEMPLATES)
387  template <class _InputIter>
388  __construct_checker(const _InputIter& __f, const _InputIter& __l) {
389    typedef typename _IsIntegral<_InputIter>::_Ret _Integral;
390    _M_check_dispatch(__f, __l, _Integral());
391  }
392
393  template <class _Integer>
394  void _M_check_dispatch(_Integer , _Integer, const __true_type& /*IsIntegral*/) {}
395
396  template <class _InputIter>
397  void _M_check_dispatch(const _InputIter& __f, const _InputIter& __l, const __false_type& /*IsIntegral*/) {
398    _STLP_DEBUG_CHECK(__check_range(__f,__l))
399  }
400#endif
401
402#if !defined (_STLP_MEMBER_TEMPLATES) || !defined (_STLP_NO_METHOD_SPECIALIZATION)
403  __construct_checker(const value_type* __f, const value_type* __l) {
404    _STLP_DEBUG_CHECK(__check_ptr_range(__f,__l))
405  }
406
407  typedef _DBG_iter_base<_Container> _IteType;
408  __construct_checker(const _IteType& __f, const _IteType& __l) {
409    _STLP_DEBUG_CHECK(__check_range(__f,__l))
410  }
411#endif
412#if defined (__BORLANDC__)
413  ~__construct_checker(){}
414#endif
415};
416
417#if defined (_STLP_USE_OLD_HP_ITERATOR_QUERIES)
418#  if defined (_STLP_NESTED_TYPE_PARAM_BUG) ||\
419     (defined (__SUNPRO_CC) && __SUNPRO_CC < 0x600)
420#    define _STLP_DEBUG_USE_DISTINCT_VALUE_TYPE_HELPERS 1
421#  endif
422
423_STLP_MOVE_TO_STD_NAMESPACE
424
425template <class _Container>
426inline ptrdiff_t*
427distance_type(const _STLP_PRIV _DBG_iter_base<_Container>&) { return (ptrdiff_t*) 0; }
428
429#  if !defined (_STLP_DEBUG_USE_DISTINCT_VALUE_TYPE_HELPERS)
430template <class _Container>
431inline _STLP_TYPENAME_ON_RETURN_TYPE _STLP_PRIV _DBG_iter_base<_Container>::value_type*
432value_type(const _STLP_PRIV _DBG_iter_base<_Container>&) {
433  typedef _STLP_TYPENAME _STLP_PRIV _DBG_iter_base<_Container>::value_type _Val;
434  return (_Val*)0;
435}
436
437template <class _Container>
438inline _STLP_TYPENAME_ON_RETURN_TYPE _STLP_PRIV _DBG_iter_base<_Container>::_Iterator_category
439iterator_category(const _STLP_PRIV _DBG_iter_base<_Container>&) {
440  typedef _STLP_TYPENAME _STLP_PRIV _DBG_iter_base<_Container>::_Iterator_category _Category;
441  return _Category();
442}
443#  endif
444
445_STLP_MOVE_TO_PRIV_NAMESPACE
446
447#endif /* _STLP_USE_OLD_HP_ITERATOR_QUERIES */
448
449_STLP_MOVE_TO_STD_NAMESPACE
450
451_STLP_END_NAMESPACE
452
453#endif /* INTERNAL_H */
454
455// Local Variables:
456// mode:C++
457// End:
458