1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// File: iterator_util.h
6//
7
8//
9
10//
11// ============================================================================
12
13#ifndef _ITERATOR_UTIL_H_
14#define _ITERATOR_UTIL_H_
15
16namespace IteratorUtil
17{
18
19// **************************************************************************************
20template <typename ElementType>
21class ArrayIteratorBase
22{
23public:
24 typedef DPTR(ElementType) PTR_ElementType;
25 typedef ArrayIteratorBase<ElementType> MyType;
26
27 // ----------------------------------------------------------------------------------
28 ArrayIteratorBase(
29 PTR_ElementType pStart,
30 size_t cEntries)
31 : m_pCur(pStart),
32 m_pStart(pStart),
33 m_pEnd(pStart + cEntries)
34 { LIMITED_METHOD_CONTRACT; }
35
36 // ----------------------------------------------------------------------------------
37 ArrayIteratorBase(
38 PTR_ElementType pStart,
39 PTR_ElementType pEnd)
40 : m_pCur(pStart),
41 m_pStart(pStart),
42 m_pEnd(pEnd)
43 { LIMITED_METHOD_CONTRACT; }
44
45 // ----------------------------------------------------------------------------------
46 ArrayIteratorBase(
47 const MyType &it)
48 : m_pCur(it.m_pCur),
49 m_pStart(it.m_pStart),
50 m_pEnd(it.m_pEnd)
51 { LIMITED_METHOD_CONTRACT; }
52
53 // ----------------------------------------------------------------------------------
54 bool
55 AtStart() const
56 { LIMITED_METHOD_CONTRACT; return m_pCur == m_pStart; }
57
58 // ----------------------------------------------------------------------------------
59 bool
60 AtEnd() const
61 { LIMITED_METHOD_CONTRACT; return m_pCur == m_pEnd; }
62
63 // ----------------------------------------------------------------------------------
64 void
65 ResetToStart()
66 { LIMITED_METHOD_CONTRACT; m_pCur = m_pStart; }
67
68 // ----------------------------------------------------------------------------------
69 void
70 ResetToEnd()
71 { LIMITED_METHOD_CONTRACT; m_pCur = m_pEnd; }
72
73 // ----------------------------------------------------------------------------------
74 ElementType &
75 Value()
76 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(!AtEnd()); return *m_pCur; }
77
78 // ----------------------------------------------------------------------------------
79 ElementType &
80 operator*()
81 { WRAPPER_NO_CONTRACT; return Value(); }
82
83 // ----------------------------------------------------------------------------------
84 ElementType &
85 operator[](size_t idx)
86 {
87 LIMITED_METHOD_CONTRACT;
88 CONSISTENCY_CHECK(m_pStart + idx < m_pEnd);
89 return m_pStart[idx];
90 }
91
92 // ----------------------------------------------------------------------------------
93 size_t
94 CurrentIndex()
95 { LIMITED_METHOD_CONTRACT; return m_pCur - m_pStart; }
96
97 // ----------------------------------------------------------------------------------
98 void
99 MoveTo(size_t idx)
100 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(m_pStart + idx < m_pEnd); m_pCur = m_pStart + idx; }
101
102 // ----------------------------------------------------------------------------------
103 bool
104 Next()
105 {
106 WRAPPER_NO_CONTRACT;
107 if (AtEnd())
108 {
109 return false;
110 }
111
112 m_pCur++;
113
114 return !AtEnd();
115 }
116
117 // ----------------------------------------------------------------------------------
118 bool
119 Prev()
120 {
121 if (AtStart())
122 {
123 return false;
124 }
125
126 m_pCur--;
127
128 return true;
129 }
130
131 MyType &
132 operator++()
133 { WRAPPER_NO_CONTRACT; CONSISTENCY_CHECK(!AtEnd()); Next(); return *this; }
134
135protected:
136 // ----------------------------------------------------------------------------------
137 PTR_ElementType m_pCur;
138 PTR_ElementType m_pStart;
139 PTR_ElementType m_pEnd;
140
141 // ----------------------------------------------------------------------------------
142 // Do not allow address to be taken of what should be a by-val or by-ref.
143 ArrayIteratorBase<ElementType> *
144 operator&()
145 { LIMITED_METHOD_CONTRACT; }
146};
147
148// **************************************************************************************
149template <typename ElementType>
150class ArrayIterator
151 : public ArrayIteratorBase<ElementType>
152{
153public:
154 typedef ArrayIteratorBase<ElementType> _BaseTy;
155 typedef typename _BaseTy::PTR_ElementType PTR_ElementType;
156
157 // ----------------------------------------------------------------------------------
158 ArrayIterator(
159 PTR_ElementType pStart,
160 size_t cEntries)
161 : _BaseTy(pStart, cEntries)
162 { LIMITED_METHOD_CONTRACT; }
163
164 // ----------------------------------------------------------------------------------
165 ArrayIterator(
166 PTR_ElementType pStart,
167 PTR_ElementType pEnd)
168 : _BaseTy(pStart, pEnd)
169 { LIMITED_METHOD_CONTRACT; }
170
171 // ----------------------------------------------------------------------------------
172 ArrayIterator(
173 const ArrayIterator &it)
174 : _BaseTy(it)
175 { LIMITED_METHOD_CONTRACT; }
176
177 // ----------------------------------------------------------------------------------
178 PTR_ElementType
179 operator->()
180 { WRAPPER_NO_CONTRACT; return &this->Value(); }
181
182#ifdef DACCESS_COMPILE
183private:
184 // ----------------------------------------------------------------------------------
185 // You are trying to instantiate the iterator over a non DACized array.
186 // Make sure you pass in "DPTR(ElementType)" or "PTR_ElementType" and
187 // not "ElementType *" as the argument type.
188 ArrayIterator(
189 ElementType * pStart,
190 size_t cEntries);
191
192 // ----------------------------------------------------------------------------------
193 // You are trying to instantiate the iterator over a non DACized array.
194 // Make sure you pass in "DPTR(ElementType)" or "PTR_ElementType" and
195 // not "ElementType *" as the argument type.
196 ArrayIterator(
197 ElementType * pStart,
198 ElementType * pEnd);
199#endif
200};
201
202// **************************************************************************************
203template <typename ValueType>
204class ArrayIterator<ValueType *>
205 : public ArrayIteratorBase<DPTR(ValueType)>
206{
207public:
208 typedef ArrayIteratorBase<DPTR(ValueType)> _BaseTy;
209 typedef typename _BaseTy::PTR_ElementType PTR_ElementType;
210
211 // ----------------------------------------------------------------------------------
212 ArrayIterator(
213 PTR_ElementType pStart,
214 size_t cEntries)
215 : _BaseTy(pStart, cEntries)
216 { LIMITED_METHOD_CONTRACT; }
217
218 // ----------------------------------------------------------------------------------
219 ArrayIterator(
220 PTR_ElementType pStart,
221 PTR_ElementType pEnd)
222 : _BaseTy(pStart, pEnd)
223 { LIMITED_METHOD_CONTRACT; }
224
225 // ----------------------------------------------------------------------------------
226 ArrayIterator(
227 const ArrayIterator &it)
228 : _BaseTy(it)
229 { LIMITED_METHOD_CONTRACT; }
230
231 // ----------------------------------------------------------------------------------
232 DPTR(ValueType)
233 operator->()
234 { WRAPPER_NO_CONTRACT; return this->Value(); }
235
236#ifdef DACCESS_COMPILE
237private:
238 // ----------------------------------------------------------------------------------
239 // You are trying to instantiate the iterator over a non DACized array.
240 // Make sure you pass in "DPTR(ElementType)" or "PTR_ElementType" and
241 // not "ElementType *" as the argument type.
242 ArrayIterator(
243 ValueType ** pStart,
244 size_t cEntries);
245
246 // ----------------------------------------------------------------------------------
247 // You are trying to instantiate the iterator over a non DACized array.
248 // Make sure you pass in "DPTR(ElementType)" or "PTR_ElementType" and
249 // not "ElementType *" as the argument type.
250 ArrayIterator(
251 ValueType ** pStart,
252 ValueType ** pEnd);
253#endif
254};
255
256#if 0
257// **************************************************************************************
258// It's important to note that ElemType is expected to have a public instance method:
259// ElemType * GetNext();
260
261template <typename ElemType>
262class SListIterator
263{
264public:
265 // ----------------------------------------------------------------------------------
266 SListIterator(
267 ElemType * pHead)
268 : m_pCur(pHead),
269 m_pHead(pHead)
270 { LIMITED_METHOD_CONTRACT; }
271
272 // ----------------------------------------------------------------------------------
273 bool
274 AtStart() const
275 { LIMITED_METHOD_CONTRACT; return m_pCur == m_pHead; }
276
277 // ----------------------------------------------------------------------------------
278 bool
279 AtEnd() const
280 { LIMITED_METHOD_CONTRACT; return m_pCur == NULL; }
281
282 // ----------------------------------------------------------------------------------
283 void
284 ResetToStart()
285 { LIMITED_METHOD_CONTRACT; m_pCur = m_pHead; }
286
287 // ----------------------------------------------------------------------------------
288 ElemType &
289 Value()
290 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(!AtEnd()); return *m_pCur; }
291
292 // ----------------------------------------------------------------------------------
293 ElemType &
294 operator*()
295 { WRAPPER_NO_CONTRACT; return Value(); }
296
297 // ----------------------------------------------------------------------------------
298 ElemType *
299 operator->()
300 { WRAPPER_NO_CONTRACT; return &Value(); }
301
302 // ----------------------------------------------------------------------------------
303 bool
304 Next()
305 {
306 WRAPPER_NO_CONTRACT;
307 if (AtEnd())
308 {
309 return false;
310 }
311
312 m_pCur = m_pCur->GetNext();
313
314 return !AtEnd();
315 }
316
317protected:
318 // ----------------------------------------------------------------------------------
319 ElemType * m_pCur;
320 ElemType * m_pHead;
321
322 // ----------------------------------------------------------------------------------
323 // Do not allow address to be taken of what should be a by-val or by-ref.
324 SListIterator<ElemType> *
325 operator&()
326 { LIMITED_METHOD_CONTRACT; }
327};
328#endif
329
330} // IteratorUtil
331
332
333#endif // _ITERATOR_UTIL_H_
334