src/generics/range.h

changeset 1273
900f1dfae46b
child 1326
69a90bd2dba2
equal deleted inserted replaced
1272:bf0ac547b934 1273:900f1dfae46b
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2017 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20 #pragma once
21
22 /*
23 * Range
24 *
25 * This class models a range of values (by default integers but anything with a
26 * total order qualifies) The value type must be constructible with 0 and 1 for
27 * the sake of default values.
28 *
29 * The range may be iterated, in which case the first value yielded will be the
30 * lower bound. Then, the iterator's value is incremented by a certain step
31 * value, yielding the next value. This is continued until the iterator would
32 * yield a value larger than upper bound.
33 *
34 * A range can be constructed in a number of ways:
35 * - Range<>()
36 * default-construction, lower and upper bounds will be set to 0.
37 * - Range<>(first, end)
38 * the range contains the values [first, end - 1].
39 * Iteration of this range yields: first, first + 1, ..., end - 1.
40 * - Range<>(first, second, end)
41 * the range contains the values [first, end - 1].
42 * Iteration of this range yields:
43 * - first
44 * - first + (second - first)
45 * - first + 2*(second - first)
46 * - end - 1 (assuming that (end - 1) can be represented with
47 * (first + n*(second - first)) with some n
48 *
49 * The function range() is provided to avoid the angle brackets for the common
50 * use case where T = int.
51 */
52 template<typename T = int>
53 class Range
54 {
55 struct Iterator
56 {
57 const T baseValue;
58 const T stepValue;
59 int stepCount = 0;
60
61 Iterator() :
62 baseValue {0},
63 stepValue {1},
64 stepCount {0} {}
65
66 Iterator(T value, T stepValue, T stepCount) :
67 baseValue {value},
68 stepValue {stepValue},
69 stepCount {stepCount} {}
70
71 T operator*() const
72 {
73 return baseValue + stepCount * stepValue;
74 }
75
76 bool operator!=(const Iterator& other) const
77 {
78 return stepCount != other.stepCount;
79 }
80
81 Iterator& operator++()
82 {
83 stepCount += 1;
84 return *this;
85 }
86
87 Iterator& operator--()
88 {
89 stepCount -= 1;
90 return *this;
91 }
92 };
93
94 public:
95 Range() :
96 beginValue {0},
97 endValue {0},
98 step {1} {}
99
100 Range(T first, T second, T last) :
101 beginValue {first},
102 endValue {last + (second - first)},
103 step {second - first} {}
104
105 Iterator begin() const
106 {
107 return {beginValue, step, 0};
108 }
109
110 bool contains(T value) const
111 {
112 return value >= beginValue and value < endValue;
113 }
114
115 Iterator end() const
116 {
117 return {beginValue, step, (endValue - beginValue) / step};
118 }
119
120 bool overlaps(const Range<T>& other) const
121 {
122 return contains(other.beginValue) or contains(other.endValue - 1);
123 }
124
125 bool operator==(const Range<T>& other) const
126 {
127 return beginValue == other.beginValue
128 and endValue == other.endValue
129 and step == other.step;
130 }
131
132 bool operator!=(Range<T> const& other) const
133 {
134 return not operator==(other);
135 }
136
137 private:
138 T beginValue;
139 T endValue;
140 T step;
141 };
142
143 /*
144 * Returns a range from [first, second, ..., last]
145 */
146 template<typename T = int>
147 Range<T> range(T first, T second, T last)
148 {
149 return {first, second, last};
150 }
151
152 /*
153 * Returns a range from [first, first + 1, ..., end - 1]
154 */
155 /*
156 template<typename T = int>
157 Range<T> range(T end)
158 {
159 return range<T>(0, 1, end - 1);
160 }
161 */

mercurial