summaryrefslogtreecommitdiff
path: root/libxsd/xsd/cxx/tree/iterator-adapter.hxx
blob: 5b4742120b4f408066b13a6c92369e6eb636608c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
// file      : xsd/cxx/tree/iterator-adapter.hxx
// copyright : Copyright (c) 2005-2017 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSD_CXX_TREE_ITERATOR_ADAPTER_HXX
#define XSD_CXX_TREE_ITERATOR_ADAPTER_HXX

#include <cstddef>  // std::ptrdiff_t
#include <iterator> // std::iterator_traits

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      // Sun CC's <iterator> does not have iterator_traits. To overcome
      // this, we will wrap std::iterator_traits into our own and also
      // specialize it for pointer types. Since Sun CC uses pointer
      // for vector::iterator, it will use the specialization and won't
      // notice the std::iterator_traits.
      //
#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC
      template <typename I>
      struct iterator_traits
      {
        typedef
        typename std::iterator_traits<I>::iterator_category
        iterator_category;

        typedef
        typename std::iterator_traits<I>::value_type
        value_type;

        typedef
        typename std::iterator_traits<I>::difference_type
        difference_type;
      };
#else
      // The Pointer specialization does not work for reverse and
      // set iterators. But these iterators are user-dfined types
      // and have suitable typedefs that we can use.
      //
      template <typename I>
      struct iterator_traits
      {
        typedef typename I::iterator_category iterator_category;
        typedef typename I::value_type value_type;
        typedef typename I::difference_type difference_type;
      };

      template <typename T>
      struct iterator_traits<T*>
      {
        typedef std::random_access_iterator_tag iterator_category;
        typedef T value_type;
        typedef std::ptrdiff_t difference_type;
      };
#endif

      // Iterator adapter for complex types. It expects I to point to
      // a smart pointer-like object that has operator*() that returns
      // a refernce to a type static_cast'able to T and get() that
      // returns a pointer to a type static_cast'able to T.
      //

      template <typename I, typename T>
      struct iterator_adapter
      {
        typedef T value_type;
        typedef value_type& reference;
        typedef value_type* pointer;

        typedef
        typename iterator_traits<I>::iterator_category
        iterator_category;

        typedef
        typename iterator_traits<I>::difference_type
        difference_type;


      public:
        iterator_adapter ()
            : i_ () // i_ can be of a pointer type.
        {
        }

        // Allow iterator to const_iterator conversion.
        //
        template <typename J, typename T2>
        iterator_adapter (const iterator_adapter<J, T2>& j)
            : i_ (j.base ())
        {
        }

        explicit
        iterator_adapter (const I& i)
            : i_ (i)
        {
        }

      public:
        // Forward iterator requirements.
        //
        reference
        operator* () const
        {
          return static_cast<reference> (**i_);
        }

        pointer
        operator-> () const
        {
          return static_cast<pointer> (i_->get ());
        }

        iterator_adapter&
        operator++ ()
        {
          ++i_;
          return *this;
        }

        iterator_adapter
        operator++ (int)
        {
          iterator_adapter r (*this);
          ++i_;
          return r;
        }

        // Bidirectional iterator requirements.
        //
        iterator_adapter&
        operator-- ()
        {
          --i_;
          return *this;
        }

        iterator_adapter
        operator-- (int)
        {
          iterator_adapter r (*this);
          --i_;
          return r;
        }

        // Random access iterator requirements.
        //
        reference
        operator[] (difference_type n) const
        {
          return static_cast<reference> (*(i_[n]));
        }

        iterator_adapter&
        operator+= (difference_type n)
        {
          i_ += n;
          return *this;
        }

        iterator_adapter
        operator+ (difference_type n) const
        {
          return iterator_adapter (i_ + n);
        }

        iterator_adapter&
        operator-= (difference_type n)
        {
          i_ -= n;
          return *this;
        }

        iterator_adapter
        operator- (difference_type n) const
        {
          return iterator_adapter (i_ - n);
        }

      public:
        const I&
        base () const
        {
          return i_;
        }

      private:
        I i_;
      };

      // Note: We use different types for left- and right-hand-side
      // arguments to allow comparison between iterator and const_iterator.
      //

      // Forward iterator requirements.
      //
      template <typename I, typename J, typename T1, typename T2>
      inline bool
      operator== (const iterator_adapter<I, T1>& i,
                  const iterator_adapter<J, T2>& j)
      {
        return i.base () == j.base ();
      }

      template <typename I, typename J, typename T1, typename T2>
      inline bool
      operator!= (const iterator_adapter<I, T1>& i,
                  const iterator_adapter<J, T2>& j)
      {
        return i.base () != j.base ();
      }

      // Random access iterator requirements
      //
      template <typename I, typename J, typename T1, typename T2>
      inline bool
      operator< (const iterator_adapter<I, T1>& i,
                 const iterator_adapter<J, T2>& j)
      {
        return i.base () < j.base ();
      }

      template <typename I, typename J, typename T1, typename T2>
      inline bool
      operator> (const iterator_adapter<I, T1>& i,
                 const iterator_adapter<J, T2>& j)
      {
        return i.base () > j.base ();
      }

      template <typename I, typename J, typename T1, typename T2>
      inline bool
      operator<= (const iterator_adapter<I, T1>& i,
                  const iterator_adapter<J, T2>& j)
      {
        return i.base () <= j.base ();
      }

      template <typename I, typename J, typename T1, typename T2>
      inline bool
      operator>= (const iterator_adapter<I, T1>& i,
                  const iterator_adapter<J, T2>& j)
      {
        return i.base () >= j.base ();
      }

      template <typename I, typename J, typename T1, typename T2>
      inline typename iterator_adapter<I, T1>::difference_type
      operator- (const iterator_adapter<I, T1>& i,
                 const iterator_adapter<J, T2>& j)
      {
        return i.base () - j.base ();
      }

      template <typename I, typename T>
      inline iterator_adapter<I, T>
      operator+ (typename iterator_adapter<I, T>::difference_type n,
                 const iterator_adapter<I, T>& i)
      {
        return iterator_adapter<I, T> (i.base () + n);
      }
    }
  }
}

#endif  // XSD_CXX_TREE_ITERATOR_ADAPTER_HXX