1+ using System ;
2+ using Whathecode . System . Collections . Generic ;
3+
4+
5+ namespace Whathecode . System
6+ {
7+ public partial class AbstractInterval < T , TSize >
8+ {
9+ /// <summary>
10+ /// Enumerator which allows you to walk across values inside an interval.
11+ /// TODO: Having to pass the methods to operate on the generic type here is quite messy. Is there a better way around this?
12+ /// </summary>
13+ /// <typeparam name = "T">The type used to specify the interval, and used for the calculations.</typeparam>
14+ /// <typeparam name = "TSize">The type used to specify distances in between two values of <see cref="T" />.</typeparam>
15+ private class Enumerator : AbstractEnumerator < T >
16+ {
17+ readonly IInterval < T , TSize > _interval ;
18+ readonly TSize _step ;
19+ readonly Func < T , T , TSize > _subtract ;
20+ readonly Func < T , TSize , T > _addSize ;
21+ readonly Func < TSize , double > _convertSizeToDouble ;
22+ readonly Func < double , TSize > _convertDoubleToSize ;
23+ readonly Func < T , bool , T , bool , IInterval < T , TSize > > _createInstance ;
24+
25+ readonly bool _isAnchorSet ;
26+ readonly T _anchor ;
27+
28+
29+ /// <summary>
30+ /// Create a new enumerator which traverses across an interval in specified steps.
31+ /// </summary>
32+ /// <param name = "interval">The interval which to traverse.</param>
33+ /// <param name = "step">The steps to step forward each time.</param>
34+ public Enumerator (
35+ IInterval < T , TSize > interval , TSize step ,
36+ Func < T , T , TSize > subtract ,
37+ Func < T , TSize , T > addSize ,
38+ Func < TSize , double > convertSizeToDouble ,
39+ Func < double , TSize > convertDoubeToSize ,
40+ Func < T , bool , T , bool , IInterval < T , TSize > > createInstance )
41+ {
42+ _interval = interval ;
43+ _step = step ;
44+ _subtract = subtract ;
45+ _addSize = addSize ;
46+ _convertSizeToDouble = convertSizeToDouble ;
47+ _convertDoubleToSize = convertDoubeToSize ;
48+ _createInstance = createInstance ;
49+ }
50+
51+ public Enumerator (
52+ IInterval < T , TSize > interval , TSize step ,
53+ Func < T , T , TSize > subtract ,
54+ Func < T , TSize , T > addSize ,
55+ Func < TSize , double > convertSizeToDouble ,
56+ Func < double , TSize > convertDoubeToSize ,
57+ Func < T , bool , T , bool , IInterval < T , TSize > > createInstance ,
58+ T anchorAt )
59+ : this ( interval , step , subtract , addSize , convertSizeToDouble , convertDoubeToSize , createInstance )
60+ {
61+ _isAnchorSet = true ;
62+ _anchor = anchorAt ;
63+ }
64+
65+
66+ protected override T GetFirst ( )
67+ {
68+ IInterval < T , TSize > interval = _interval ;
69+
70+ // When anchor is set, start the interval at the next anchor position.
71+ if ( _isAnchorSet )
72+ {
73+ TSize anchorDiff = _subtract ( _interval . Start , _anchor ) ;
74+ double stepSize = _convertSizeToDouble ( _step ) ;
75+ double diff = Math . Abs ( _convertSizeToDouble ( anchorDiff ) ) % stepSize ;
76+ if ( diff > 0 )
77+ {
78+ if ( _anchor . CompareTo ( _interval . Start ) < 0 )
79+ {
80+ diff = stepSize - diff ;
81+ }
82+ TSize addition = _convertDoubleToSize ( diff ) ;
83+ interval = _createInstance (
84+ _addSize ( _interval . Start , addition ) , true ,
85+ _interval . End , _interval . IsEndIncluded ) ;
86+ }
87+ }
88+
89+ // When first value doesn't lie in interval, immediately step.
90+ return interval . IsStartIncluded ? interval . Start : _addSize ( interval . Start , _step ) ;
91+ }
92+
93+ protected override T GetNext ( int enumeratedAlready , T previous )
94+ {
95+ return _addSize ( previous , _step ) ;
96+ }
97+
98+ protected override bool HasElements ( )
99+ {
100+ bool nextInInterval = _interval . LiesInInterval ( _addSize ( _interval . Start , _step ) ) ;
101+ return _interval . IsStartIncluded || nextInInterval ;
102+ }
103+
104+ protected override bool HasMoreElements ( int enumeratedAlready , T previous )
105+ {
106+ if ( _convertSizeToDouble ( _step ) == 0 && enumeratedAlready == 1 )
107+ {
108+ return false ;
109+ }
110+
111+ return _interval . LiesInInterval ( _addSize ( previous , _step ) ) ;
112+ }
113+
114+ public override void Dispose ( )
115+ {
116+ // TODO: Nothing to do?
117+ }
118+ }
119+ }
120+ }
0 commit comments