1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #ifndef INCLUDED_O3TL_RANGE_HXX
25 #define INCLUDED_O3TL_RANGE_HXX
26
27
28 #include <cstring> // for std::size_t
29 #include <boost/assert.hpp>
30
31
32
33 namespace o3tl
34 {
35 /** Represents a range of integer or iterator values.
36
37 @tpl T
38 Has to be assignable, add- and subtractable. That is:
39 either it is
40 - an integral type
41 - or a random access iterator.
42 */
43 template <class T>
44 class range
45 {
46 public:
47 typedef T element_type; /// Provided for generic programming.
48 typedef range<T> self;
49
50 // LIFECYCLE
51 range(
52 T i_inclusiveLowerBorder,
53 T i_exclusiveUpperBorder );
54 ~range();
55 // INQUIRY
56 T begin() const;
57 T end() const;
58 std::size_t size() const;
59
60 bool contains(
61 T i_value ) const;
62 bool contains(
63 const self & i_other ) const;
64 bool overlaps(
65 const self & i_other ) const;
66 /// @return i_other.begin() - this->end()
67 long distance_to(
68 const self & i_other ) const;
69 private:
70 // DATA
71 T nBegin;
72 T nEnd;
73 };
74
75
76 template <class T>
77 inline range<T>
make_range(T i1,T i2)78 make_range(T i1, T i2)
79 {
80 return range<T>(i1, i2);
81 }
82
83 template <class T>
84 inline range<typename T::const_iterator>
range_of(const T & i_container)85 range_of(const T & i_container)
86 {
87 return make_range( i_container.begin(),
88 i_container.end()
89 );
90 }
91
92 template <class T>
93 inline range<typename T::iterator>
range_of(T & io_container)94 range_of(T & io_container)
95 {
96 return make_range( io_container.begin(),
97 io_container.end()
98 );
99 }
100
101
102
103
104
105 // IMPLEMENTATION
106
107 template <class T>
range(T i_inclusiveLowerBorder,T i_exclusiveUpperBorder)108 range<T>::range( T i_inclusiveLowerBorder,
109 T i_exclusiveUpperBorder )
110 : nBegin(i_inclusiveLowerBorder),
111 nEnd(i_exclusiveUpperBorder)
112 {
113 BOOST_ASSERT( nBegin <= nEnd
114 && "Invalid parameters for range<> constructor.");
115 }
116
117 template <class T>
~range()118 range<T>::~range()
119 {
120 }
121
122 template <class T>
123 inline T
begin() const124 range<T>::begin() const
125 {
126 return nBegin;
127 }
128
129 template <class T>
130 inline T
end() const131 range<T>::end() const
132 {
133 return nEnd;
134 }
135
136 template <class T>
137 inline std::size_t
size() const138 range<T>::size() const
139 {
140 BOOST_ASSERT( nBegin <= nEnd
141 && "Invalid range limits in range<>::size().");
142 return static_cast<std::size_t>( end() - begin() );
143 }
144
145 template <class T>
146 bool
contains(T i_value) const147 range<T>::contains(T i_value ) const
148 {
149 return begin() <= i_value
150 && i_value < end();
151 }
152
153 template <class T>
154 bool
contains(const self & i_other) const155 range<T>::contains(const self & i_other) const
156 {
157 // This is subtle, because this would be wrong:
158 // begin() <= i_other.begin()
159 // && i_other.end() <= end();
160 // An empty range that begins and starts at my end()
161 // must not be contained.
162
163 return contains(i_other.begin())
164 && i_other.end() <= end();
165 }
166
167 template <class T>
168 bool
overlaps(const self & i_other) const169 range<T>::overlaps(const self & i_other) const
170 {
171 return contains(i_other.begin())
172 || i_other.contains(begin());
173 }
174
175 template <class T>
176 long
distance_to(const self & i_other) const177 range<T>::distance_to(const self & i_other) const
178 {
179 return i_other.begin() - end();
180 }
181
182
183
184 } // namespace o3tl
185 #endif
186