diff -r 918b6c0f8b5b -r ed9685f44ab3 src/ring.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ring.h Sat Dec 14 22:36:06 2019 +0200
@@ -0,0 +1,109 @@
+/*
+ * LDForge: LDraw parts authoring CAD
+ * Copyright (C) 2013 - 2018 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 .
+ */
+
+#pragma once
+
+namespace iter
+{
+ namespace _imp
+ {
+ template
+ class RingAdapter;
+ }
+
+ template
+ _imp::RingAdapter ring(T& collection);
+
+ template
+ _imp::RingAdapter ring(T& collection, int count);
+}
+
+/*
+ * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds.
+ * The maximum amount can be specified manually.
+ *
+ * Example:
+ *
+ * int A[] = {10,20,30,40};
+ * ring(A)[0] == A[0 % 4] == A[0]
+ * ring(A)[5] == A[5 % 4] == A[1]
+ * ring(A)[-1] == ring(A)[-1 + 4] == A[3]
+ */
+template
+class iter::_imp::RingAdapter
+{
+private:
+ // The private section must come first because _collection is used in decltype() below.
+ T& collection;
+ const int count;
+
+public:
+ RingAdapter(T& collection, int count) :
+ collection {collection},
+ count {count} {}
+
+ template
+ decltype(collection[IndexType()]) operator[](IndexType index)
+ {
+ if (count == 0)
+ {
+ // Argh! ...let the collection deal with this case.
+ return this->collection[index];
+ }
+ else
+ {
+ index %= this->count;
+
+ // Fix negative modulus...
+ if (index < 0)
+ index += this->count;
+
+ return this->collection[index];
+ }
+ }
+
+ int size() const
+ {
+ return this->count;
+ }
+};
+
+/*
+ * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed
+ * to be the amount of elements in the collection.
+ */
+template
+iter::_imp::RingAdapter iter::ring(T& collection)
+{
+ return {collection, countof(collection)};
+}
+
+/*
+ * Version of ring() that allows manual specification of the count.
+ */
+template
+iter::_imp::RingAdapter iter::ring(T& collection, int count)
+{
+ return {collection, count};
+}
+
+template
+int countof(const iter::_imp::RingAdapter& ring)
+{
+ return ring.size();
+}