src/generics/range.h

changeset 1273
900f1dfae46b
child 1326
69a90bd2dba2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/generics/range.h	Tue Mar 06 23:29:40 2018 +0200
@@ -0,0 +1,161 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2017 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+/*
+ * Range
+ *
+ * This class models a range of values (by default integers but anything with a
+ * total order qualifies) The value type must be constructible with 0 and 1 for
+ * the sake of default values.
+ *
+ * The range may be iterated, in which case the first value yielded will be the
+ * lower bound. Then, the iterator's value is incremented by a certain step
+ * value, yielding the next value. This is continued until the iterator would
+ * yield a value larger than upper bound.
+ *
+ * A range can be constructed in a number of ways:
+ *	 - Range<>()
+ *		 default-construction, lower and upper bounds will be set to 0.
+ *	 - Range<>(first, end)
+ *		 the range contains the values [first, end - 1].
+ *		 Iteration of this range yields: first, first + 1, ..., end - 1.
+ *	 - Range<>(first, second, end)
+ *		 the range contains the values [first, end - 1].
+ *		 Iteration of this range yields:
+ *			 - first
+ *			 - first + (second - first)
+ *			 - first + 2*(second - first)
+ *			 - end - 1 (assuming that (end - 1) can be represented with 
+ *			 (first + n*(second - first)) with some n
+ *
+ * The function range() is provided to avoid the angle brackets for the common
+ * use case where T = int.
+ */
+template<typename T = int>
+class Range
+{
+	struct Iterator
+	{
+		const T baseValue;
+		const T stepValue;
+		int stepCount = 0;
+
+		Iterator() :
+			baseValue {0},
+			stepValue {1},
+			stepCount {0} {}
+
+		Iterator(T value, T stepValue, T stepCount) :
+			baseValue {value},
+			stepValue {stepValue},
+			stepCount {stepCount} {}
+
+		T operator*() const
+		{
+			return baseValue + stepCount * stepValue;
+		}
+
+		bool operator!=(const Iterator& other) const
+		{
+			return stepCount != other.stepCount;
+		}
+
+		Iterator& operator++()
+		{
+			stepCount += 1;
+			return *this;
+		}
+
+		Iterator& operator--()
+		{
+			stepCount -= 1;
+			return *this;
+		}
+	};
+
+public:
+	Range() :
+		beginValue {0},
+		endValue {0},
+		step {1} {}
+
+	Range(T first, T second, T last) :
+		beginValue {first},
+		endValue {last + (second - first)},
+		step {second - first} {}
+
+	Iterator begin() const
+	{
+		return {beginValue, step, 0};
+	}
+
+	bool contains(T value) const
+	{
+		return value >= beginValue and value < endValue;
+	}
+
+	Iterator end() const
+	{
+		return {beginValue, step, (endValue - beginValue) / step};
+	}
+
+	bool overlaps(const Range<T>& other) const
+	{
+		return contains(other.beginValue) or contains(other.endValue - 1);
+	}
+
+	bool operator==(const Range<T>& other) const
+	{
+		return beginValue == other.beginValue
+			and endValue == other.endValue
+			and step == other.step;
+	}
+
+	bool operator!=(Range<T> const& other) const
+	{
+		return not operator==(other);
+	}
+
+private:
+	T beginValue;
+	T endValue;
+	T step;
+};
+
+/*
+ * Returns a range from [first, second, ..., last]
+ */
+template<typename T = int>
+Range<T> range(T first, T second, T last)
+{
+	return {first, second, last};
+}
+
+/*
+ * Returns a range from [first, first + 1, ..., end - 1]
+ */
+/*
+template<typename T = int>
+Range<T> range(T end)
+{
+	return range<T>(0, 1, end - 1);
+}
+*/

mercurial