-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
number-iterator.spice
106 lines (94 loc) · 2.81 KB
/
number-iterator.spice
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
import "std/iterator/iterator";
import "std/data/pair";
// Generic type definitions
type N int|long|short;
/**
* A NumberIterator in Spice can be used to iterate over a range of numbers
*/
public type NumberIterator<N> struct : IIterator<N> {
N currentNumber
N lowerBound // Inclusive
N upperBound // Inclusive
}
public p NumberIterator.ctor(N lowerBound, N upperBound) {
if lowerBound > upperBound { panic(Error("Upper bound is below lower bound")); }
this.currentNumber = lowerBound;
this.lowerBound = lowerBound;
this.upperBound = upperBound;
}
/**
* Returns the current number of the number range
*
* @return Reference to the current number
*/
public inline f<N&> NumberIterator.get() {
return this.currentNumber;
}
/**
* Returns the current index and the current number of the number range
*
* @return Pair of current index and a reference to the current number
*/
public inline f<Pair<unsigned long, N&>> NumberIterator.getIdx() {
unsigned long idx = (unsigned long) this.currentNumber - this.lowerBound;
return Pair<unsigned long, N&>(idx, this.currentNumber);
}
/**
* Check if the iterator is valid
*
* @return true or false
*/
public inline f<bool> NumberIterator.isValid() {
return this.currentNumber <= this.upperBound;
}
/**
* Returns the current number of the number range and moves the cursor to the next item
*/
public inline p NumberIterator.next() {
if !this.isValid() { panic(Error("Calling next() on invalid iterator")); }
this.currentNumber++;
}
/**
* Advances the cursor by one
*
* @param it NumberIterator
*/
public inline p operator++<N>(NumberIterator<N>& it) {
if it.currentNumber > it.upperBound { panic(Error("Iterator out of bounds")); }
it.currentNumber++;
}
/**
* Move the cursor back by one
*
* @param it NumberIterator
*/
public inline p operator--<N>(NumberIterator<N>& it) {
if it.currentNumber <= it.lowerBound { panic(Error("Iterator out of bounds")); }
it.currentNumber--;
}
/**
* Advances the cursor by the given offset
*
* @param it NumberIterator
* @param offset Offset
*/
public inline p operator+=<N>(NumberIterator<N>& it, N offset) {
if it.currentNumber + offset > it.upperBound || it.currentNumber + offset < it.lowerBound { panic(Error("Iterator out of bounds")); }
it.currentNumber += offset;
}
/**
* Move the cursor back by the given offset
*
* @param it NumberIterator
* @param offset Offset
*/
public inline p operator-=<N>(NumberIterator<N>& it, N offset) {
if it.currentNumber - offset > it.upperBound || it.currentNumber - offset < it.lowerBound { panic(Error("Iterator out of bounds")); }
it.currentNumber -= offset;
}
/**
* Convenience wrapper for creating a simple number iterator
*/
public inline f<NumberIterator<N>> range<N>(N begin, N end) {
return NumberIterator<N>(begin, end);
}