InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
index_based_iterator.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Florin Trofin
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //
23 // Iterator adapter for containers that support indexes.
24 // Most iterators are implemented with straight pointers. However, those will not work
25 // with containers that implement copy-on-write (COW). In that case the containers
26 // will share the same storage until a non-const operation occurs (like changing a value) when
27 // a separate copy of the existing storage needs to be made which will invalidate all iterators.
28 // Because this iterator uses indexes rather than pointers, it does not suffer from that problem.
29 //
30 // INTERNAL USE ONLY! Do not use this class directly.
31 //
32 //========================================================================================
33 
34 #ifndef __INDEX_BASED_ITERATOR__
35 #define __INDEX_BASED_ITERATOR__
36 
37 #include <boost/iterator/iterator_facade.hpp>
38 #include <boost/type_traits.hpp>
39 
40 # ifndef BOOST_NO_SFINAE
41 # include <boost/type_traits/is_convertible.hpp>
42 # include <boost/utility/enable_if.hpp>
43 # endif
44 
54 template<class T, typename R>
56  public boost::iterator_facade<
57  index_based_iterator<T, R>,
58  R,
59  boost::random_access_traversal_tag>
60 {
61  // Helper for special constructor
62  struct conversion_enabler {};
63 
64 public:
65  typedef typename T::difference_type difference_type;
66 
68  : fContainer(nil), fPos(0)
69  {
70  }
71  explicit index_based_iterator(T const& storage, difference_type pos)
72  : fContainer(&storage), fPos(pos)
73  {
74  }
75  // This constructor ensures conversion from iterator to const_iterator
76  // but not viceversa (the second parameter of the constructor
77  template<typename OtherValue>
79  typename boost::enable_if<boost::is_convertible<OtherValue*, R*>, conversion_enabler>::type = conversion_enabler() )
80  : fContainer(other.fContainer), fPos(other.fPos)
81  {
82  }
83 
84 #ifdef DEBUG
85  // These functions are for DEBUG purposes only! use them only in ASSERTS!
86 
87  // Checks if the iterator is within the valid range [begin, end]
88  // Note that end is a valid position for the iterator, but it should not be dereferenced.
89  bool is_valid() const
90  {
91  return fContainer && fPos >=0 && fPos <= (difference_type)fContainer->size();
92  }
93 
94  // Retrieves the container to which this iterator belongs
95  T const* get_container() const
96  {
97  return fContainer;
98  }
99 #endif
100 
101  // Data members
102 private:
103  difference_type fPos;
104  T const* fContainer;
105 
106  // The base class will call these core functions to do it's work
107 private:
108  friend class boost::iterator_core_access; // grant access to base class
109  template <class, typename> friend class index_based_iterator;
110 
111  void increment()
112  {
113 #ifdef DEBUG
114  ASSERT(is_valid());
115 #endif
116  ++fPos;
117  }
118 
119  void decrement()
120  {
121 #ifdef DEBUG
122  ASSERT(is_valid());
123 #endif
124  --fPos;
125  }
126 
127  void advance(difference_type n)
128  {
129  ASSERT(fContainer);
130  fPos += n;
131 #ifdef DEBUG
132  ASSERT(is_valid());
133 #endif
134  }
135 
136  template<typename OtherValue>
137  difference_type distance_to(index_based_iterator<T, OtherValue> const& rhs) const
138  {
139  ASSERT(fContainer == rhs.fContainer);
140  return rhs.fPos - fPos;
141  }
142 
143  template<typename OtherValue>
144  bool equal(index_based_iterator<T, OtherValue> const& rhs) const
145  {
146  ASSERT(fContainer == rhs.fContainer);
147  return fPos == rhs.fPos;
148  }
149 
150  template <bool> class Selector {};
151 
152  // delegates to specific implementations (const and non-const)
153  R& dereference() const
154  {
155  ASSERT(fContainer && fPos >=0 && fPos < (difference_type)fContainer->size());
156  return dereference_impl(Selector<boost::is_const<R>::value>());
157  }
158 
159  // mutable access
160  R& dereference_impl(Selector<false>) const
161  {
162  return const_cast<T&>(*fContainer).get_ref(fPos);
163  }
164 
165  // const read access
166  R& dereference_impl(Selector<true>) const
167  {
168  return fContainer->get_const_ref(fPos);
169  }
170 }; // index_based_iterator
171 
172 #endif // __INDEX_BASED_ITERATOR__
173