src/ring.h

changeset 19
ed9685f44ab3
child 24
1a0faaaceb84
equal deleted inserted replaced
18:918b6c0f8b5b 19:ed9685f44ab3
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2018 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 #pragma once
20
21 namespace iter
22 {
23 namespace _imp
24 {
25 template<typename T>
26 class RingAdapter;
27 }
28
29 template<typename T>
30 _imp::RingAdapter<T> ring(T& collection);
31
32 template<typename T>
33 _imp::RingAdapter<T> ring(T& collection, int count);
34 }
35
36 /*
37 * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds.
38 * The maximum amount can be specified manually.
39 *
40 * Example:
41 *
42 * int A[] = {10,20,30,40};
43 * ring(A)[0] == A[0 % 4] == A[0]
44 * ring(A)[5] == A[5 % 4] == A[1]
45 * ring(A)[-1] == ring(A)[-1 + 4] == A[3]
46 */
47 template<typename T>
48 class iter::_imp::RingAdapter
49 {
50 private:
51 // The private section must come first because _collection is used in decltype() below.
52 T& collection;
53 const int count;
54
55 public:
56 RingAdapter(T& collection, int count) :
57 collection {collection},
58 count {count} {}
59
60 template<typename IndexType>
61 decltype(collection[IndexType()]) operator[](IndexType index)
62 {
63 if (count == 0)
64 {
65 // Argh! ...let the collection deal with this case.
66 return this->collection[index];
67 }
68 else
69 {
70 index %= this->count;
71
72 // Fix negative modulus...
73 if (index < 0)
74 index += this->count;
75
76 return this->collection[index];
77 }
78 }
79
80 int size() const
81 {
82 return this->count;
83 }
84 };
85
86 /*
87 * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed
88 * to be the amount of elements in the collection.
89 */
90 template<typename T>
91 iter::_imp::RingAdapter<T> iter::ring(T& collection)
92 {
93 return {collection, countof(collection)};
94 }
95
96 /*
97 * Version of ring() that allows manual specification of the count.
98 */
99 template<typename T>
100 iter::_imp::RingAdapter<T> iter::ring(T& collection, int count)
101 {
102 return {collection, count};
103 }
104
105 template<typename T>
106 int countof(const iter::_imp::RingAdapter<T>& ring)
107 {
108 return ring.size();
109 }

mercurial