1 // ==========================================================================
2 //                 SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 //       notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above copyright
13 //       notice, this list of conditions and the following disclaimer in the
14 //       documentation and/or other materials provided with the distribution.
15 //     * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 //       its contributors may be used to endorse or promote products derived
17 //       from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Enrico Siragusa <enrico.siragusa@fu-berlin.de>
33 // ==========================================================================
34 // Counting iterator implementation.
35 // ==========================================================================
36 
37 #ifndef SEQAN_BASIC_ITERATOR_COUNTING_H_
38 #define SEQAN_BASIC_ITERATOR_COUNTING_H_
39 
40 namespace seqan {
41 
42 // ============================================================================
43 // Tags
44 // ============================================================================
45 
46 template <typename TSpec = void>
47 struct CountingIteratorImpl_;
48 
49 typedef CountingIteratorImpl_<void> CountingIterator;
50 
51 // ============================================================================
52 // Classes
53 // ============================================================================
54 
55 template <typename TSpec, typename TIncrementable>
56 class Iter<TIncrementable, CountingIteratorImpl_<TSpec> >
57 {
58 public:
59     TIncrementable data_position;
60 
61     // ------------------------------------------------------------------------
62     // Constructors
63     // ------------------------------------------------------------------------
64 
65     Iter(TIncrementable position = 0) :
data_position(position)66         data_position(position)
67     {}
68 
69     template <typename TOther>
Iter(TOther position)70     Iter(TOther position) :
71         data_position(position)
72     {}
73 
Iter(Iter const & other)74     Iter(Iter const & other) :
75         data_position(other.data_position)
76     {}
77 };
78 
79 // ============================================================================
80 // Metafunctions
81 // ============================================================================
82 
83 template <typename TSpec, typename TIncrementable>
84 struct Size<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >
85 {
86     typedef TIncrementable Type;
87 };
88 
89 template <typename TSpec, typename TIncrementable>
90 struct Position<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >
91 {
92     typedef TIncrementable Type;
93 };
94 
95 template <typename TSpec, typename TIncrementable>
96 struct Difference<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >
97 {
98     typedef typename MakeSigned<TIncrementable>::Type Type;
99 };
100 
101 template <typename TSpec, typename TIncrementable>
102 struct Value<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >
103 {
104     typedef TIncrementable Type;
105 };
106 
107 template <typename TSpec, typename TIncrementable>
108 struct GetValue<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >
109 {
110     typedef TIncrementable Type;
111 };
112 
113 template <typename TSpec, typename TIncrementable>
114 struct Reference<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >
115 {
116     typedef TIncrementable Type;
117 };
118 
119 template <typename TSpec, typename TIncrementable>
120 struct Reference<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const>
121 {
122     typedef TIncrementable const Type;
123 };
124 
125 // ============================================================================
126 // Functions
127 // ============================================================================
128 
129 // ----------------------------------------------------------------------------
130 // Function position()
131 // ----------------------------------------------------------------------------
132 
133 template <typename TSpec, typename TIncrementable>
134 inline typename Position<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >::Type
135 position(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & me)
136 {
137     return me.data_position;
138 }
139 
140 template <typename TSpec, typename TIncrementable>
141 inline typename Position<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const>::Type
142 position(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & me)
143 {
144     return me.data_position;
145 }
146 
147 // ----------------------------------------------------------------------------
148 // Function setPosition()
149 // ----------------------------------------------------------------------------
150 
151 template <typename TIncrementable, typename TSpec, typename TPosition>
152 inline void
153 setPosition(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & me, TPosition position_)
154 {
155     me.data_position = position_;
156 }
157 
158 // ----------------------------------------------------------------------------
159 // Function value()
160 // ----------------------------------------------------------------------------
161 
162 template <typename TSpec, typename TIncrementable>
163 inline typename Reference<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >::Type
164 value(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & me)
165 {
166     return position(me);
167 }
168 
169 template <typename TSpec, typename TIncrementable>
170 inline typename Reference<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const>::Type
171 value(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & me)
172 {
173     return position(me);
174 }
175 
176 // ----------------------------------------------------------------------------
177 // Function assignValue()
178 // ----------------------------------------------------------------------------
179 
180 template <typename TIncrementable, typename TSpec, typename TValue>
181 inline void
182 assignValue(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & me, TValue _value)
183 {
184     setPosition(me, _value);
185 }
186 
187 // ----------------------------------------------------------------------------
188 // Function operator==()
189 // ----------------------------------------------------------------------------
190 
191 //NOTE(h-2): the other operators should get a similar const-container-tolerant interface
192 template <typename TSpec, typename TIncrementable, typename TIncrementable2>
193 inline SEQAN_FUNC_ENABLE_IF(IsSameType<TIncrementable const &, TIncrementable2 const &>, bool)
194 operator==(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
195            Iter<TIncrementable2, CountingIteratorImpl_<TSpec> > const & right)
196 {
197     return position(left) == position(right);
198 }
199 
200 // ----------------------------------------------------------------------------
201 // Function operator!=()
202 // ----------------------------------------------------------------------------
203 
204 template <typename TSpec, typename TIncrementable>
205 inline bool
206 operator!=(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
207            Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
208 {
209     return position(left) != position(right);
210 }
211 
212 // ----------------------------------------------------------------------------
213 // Function operator<()
214 // ----------------------------------------------------------------------------
215 
216 template <typename TSpec, typename TIncrementable>
217 inline bool
218 operator<(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
219           Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
220 {
221     return position(left) < position(right);
222 }
223 
224 template <typename TSpec, typename TIncrementable>
225 inline bool
226 operator>(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
227           Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
228 {
229     return position(left) > position(right);
230 }
231 
232 // ----------------------------------------------------------------------------
233 // Function operator<=()
234 // ----------------------------------------------------------------------------
235 
236 template <typename TSpec, typename TIncrementable>
237 inline bool
238 operator<=(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
239            Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
240 {
241     return position(left) <= position(right);
242 }
243 
244 // ----------------------------------------------------------------------------
245 // Function operator>=()
246 // ----------------------------------------------------------------------------
247 
248 template <typename TSpec, typename TIncrementable>
249 inline bool
250 operator>=(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
251            Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
252 {
253     return position(left) >= position(right);
254 }
255 
256 // ----------------------------------------------------------------------------
257 // Function goNext()
258 // ----------------------------------------------------------------------------
259 
260 template <typename TSpec, typename TIncrementable>
261 inline void
262 goNext(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & me)
263 {
264     setPosition(me, position(me) + 1);
265 }
266 
267 // ----------------------------------------------------------------------------
268 // Function goPrevious()
269 // ----------------------------------------------------------------------------
270 
271 template <typename TSpec, typename TIncrementable>
272 inline void
273 goPrevious(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & me)
274 {
275     setPosition(me, position(me) - 1);
276 }
277 
278 // ----------------------------------------------------------------------------
279 // Function operator+()
280 // ----------------------------------------------------------------------------
281 
282 template <typename TIncrementable, typename TSpec, typename TIntegral>
283 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TIntegral> >, Iter<TIncrementable, CountingIteratorImpl_<TSpec> >)
284 operator+(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left, TIntegral right)
285 {
286     Iter<TIncrementable, CountingIteratorImpl_<TSpec> > tmp(left);
287     setPosition(tmp, position(left) + right);
288     return tmp;
289 }
290 
291 template <typename TIncrementable, typename TSpec, typename TIntegral>
292 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TIntegral> >, Iter<TIncrementable, CountingIteratorImpl_<TSpec> >)
293 operator+(TIntegral left, Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
294 {
295     Iter<TIncrementable, CountingIteratorImpl_<TSpec> > tmp(right);
296     setPosition(tmp, position(right) + left);
297     return tmp;
298 }
299 
300 // ----------------------------------------------------------------------------
301 // Function operator+=()
302 // ----------------------------------------------------------------------------
303 
304 template <typename TIncrementable, typename TSpec, typename TIntegral>
305 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TIntegral> >, Iter<TIncrementable, CountingIteratorImpl_<TSpec> > &)
306 operator+=(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & left, TIntegral right)
307 {
308     setPosition(left, position(left) + right);
309     return left;
310 }
311 
312 // ----------------------------------------------------------------------------
313 // Function operator-()
314 // ----------------------------------------------------------------------------
315 
316 template <typename TIncrementable, typename TSpec, typename TIntegral>
317 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TIntegral> >, Iter<TIncrementable, CountingIteratorImpl_<TSpec> >)
318 operator-(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left, TIntegral right)
319 {
320     Iter<TIncrementable, CountingIteratorImpl_<TSpec> > tmp(left);
321     setPosition(tmp, position(left) - right);
322     return tmp;
323 }
324 
325 template <typename TSpec, typename TIncrementable>
326 inline typename Difference<Iter<TIncrementable, CountingIteratorImpl_<TSpec> > >::Type
327 operator-(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & left,
328           Iter<TIncrementable, CountingIteratorImpl_<TSpec> > const & right)
329 {
330     return position(left) - position(right);
331 }
332 
333 // ----------------------------------------------------------------------------
334 // Function operator-=()
335 // ----------------------------------------------------------------------------
336 
337 template <typename TIncrementable, typename TSpec, typename TIntegral>
338 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TIntegral> >, Iter<TIncrementable, CountingIteratorImpl_<TSpec> > &)
339 operator-=(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & left, TIntegral right)
340 {
341     setPosition(left, position(left) - right);
342     return left;
343 }
344 
345 // ----------------------------------------------------------------------------
346 // Function assign()
347 // ----------------------------------------------------------------------------
348 
349 // Conversion assignment.
350 template <typename TIncrementable, typename TSpec, typename TSource>
351 inline void
352 assign(Iter<TIncrementable, CountingIteratorImpl_<TSpec> > & target, TSource const & source)
353 {
354     setPosition(target, position(source));
355 }
356 
357 }  // namespace seqan
358 
359 #endif  // #ifndef SEQAN_BASIC_ITERATOR_COUNTING_H_
360