addr_range.hh revision 1762
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef __BASE_RANGE_HH__
30#define __BASE_RANGE_HH__
31
32#include <cassert>
33#include <iostream>
34#include <string>
35
36/**
37 * @param s range string
38 * EndExclusive Ranges are in the following format:
39 *    <range> := {<start_val>}:{<end>}
40 *    <start>   := <end_val> | +<delta>
41 */
42template <class T>
43bool __parse_range(const std::string &s, T &start, T &end);
44
45template <class T>
46struct Range
47{
48    T start;
49    T end;
50
51    Range() { invalidate(); }
52
53    template <class U>
54    Range(const std::pair<U, U> &r)
55        : start(r.first), end(r.second)
56    {}
57
58    template <class U>
59    Range(const Range<U> &r)
60        : start(r.start), end(r.end)
61    {}
62
63    Range(const std::string &s)
64    {
65        if (!__parse_range(s, start, end))
66            invalidate();
67    }
68
69    template <class U>
70    const Range<T> &operator=(const Range<U> &r)
71    {
72        start = r.start;
73        end = r.end;
74        return *this;
75    }
76
77    template <class U>
78    const Range<T> &operator=(const std::pair<U, U> &r)
79    {
80        start = r.first;
81        end = r.second;
82        return *this;
83    }
84
85    const Range &operator=(const std::string &s)
86    {
87        if (!__parse_range(s, start, end))
88            invalidate();
89        return *this;
90    }
91
92    void invalidate() { start = 1; end = 0; }
93    T size() const { return end - start + 1; }
94    bool valid() const { return start < end; }
95};
96
97template <class T>
98inline std::ostream &
99operator<<(std::ostream &o, const Range<T> &r)
100{
101    o << '[' << r.start << "," << r.end << ']';
102    return o;
103}
104
105template <class T>
106inline Range<T>
107RangeEx(T start, T end)
108{ return std::make_pair(start, end - 1); }
109
110template <class T>
111inline Range<T>
112RangeIn(T start, T end)
113{ return std::make_pair(start, end); }
114
115template <class T, class U>
116inline Range<T>
117RangeSize(T start, U size)
118{ return std::make_pair(start, start + size - 1); }
119
120////////////////////////////////////////////////////////////////////////
121//
122// Range to Range Comparisons
123//
124
125/**
126 * @param range1 is a range.
127 * @param range2 is a range.
128 * @return if range1 and range2 are identical.
129 */
130template <class T, class U>
131inline bool
132operator==(const Range<T> &range1, const Range<U> &range2)
133{
134    return range1.start == range2.start && range1.end == range2.end;
135}
136
137/**
138 * @param range1 is a range.
139 * @param range2 is a range.
140 * @return if range1 and range2 are not identical.
141 */
142template <class T, class U>
143inline bool
144operator!=(const Range<T> &range1, const Range<U> &range2)
145{
146    return range1.start != range2.start || range1.end != range2.end;
147}
148
149/**
150 * @param range1 is a range.
151 * @param range2 is a range.
152 * @return if range1 is less than range2 and does not overlap range1.
153 */
154template <class T, class U>
155inline bool
156operator<(const Range<T> &range1, const Range<U> &range2)
157{
158    return range1.start < range2.start;
159}
160
161/**
162 * @param range1 is a range.
163 * @param range2 is a range.
164 * @return if range1 is less than range2.  range1 may overlap range2,
165 * but not extend beyond the end of range2.
166 */
167template <class T, class U>
168inline bool
169operator<=(const Range<T> &range1, const Range<U> &range2)
170{
171    return range1.start <= range2.start;
172}
173
174/**
175 * @param range1 is a range.
176 * @param range2 is a range.
177 * @return if range1 is greater than range2 and does not overlap range2.
178 */
179template <class T, class U>
180inline bool
181operator>(const Range<T> &range1, const Range<U> &range2)
182{
183    return range1.start > range2.start;
184}
185
186/**
187 * @param range1 is a range.
188 * @param range2 is a range.
189 * @return if range1 is greater than range2.  range1 may overlap range2,
190 * but not extend beyond the beginning of range2.
191 */
192template <class T, class U>
193inline bool
194operator>=(const Range<T> &range1, const Range<U> &range2)
195{
196    return range1.start >= range2.start;
197}
198
199////////////////////////////////////////////////////////////////////////
200//
201// Position to Range Comparisons
202//
203
204/**
205 * @param pos position compared to the range.
206 * @param range range compared against.
207 * @return indicates that position pos is within the range.
208 */
209template <class T, class U>
210inline bool
211operator==(const T &pos, const Range<U> &range)
212{
213    return pos >= range.start && pos <= range.end;
214}
215
216/**
217 * @param pos position compared to the range.
218 * @param range range compared against.
219 * @return indicates that position pos is not within the range.
220 */
221template <class T, class U>
222inline bool
223operator!=(const T &pos, const Range<U> &range)
224{
225    return pos < range.start || pos > range.end;
226}
227
228/**
229 * @param pos position compared to the range.
230 * @param range range compared against.
231 * @return indicates that position pos is below the range.
232 */
233template <class T, class U>
234inline bool
235operator<(const T &pos, const Range<U> &range)
236{
237    return pos < range.start;
238}
239
240/**
241 * @param pos position compared to the range.
242 * @param range range compared against.
243 * @return indicates that position pos is below or in the range.
244 */
245template <class T, class U>
246inline bool
247operator<=(const T &pos, const Range<U> &range)
248{
249    return pos <= range.end;
250}
251
252/**
253 * @param pos position compared to the range.
254 * @param range range compared against.
255 * @return indicates that position pos is above the range.
256 */
257template <class T, class U>
258inline bool
259operator>(const T &pos, const Range<U> &range)
260{
261    return pos > range.end;
262}
263
264/**
265 * @param pos position compared to the range.
266 * @param range range compared against.
267 * @return indicates that position pos is above or in the range.
268 */
269template <class T, class U>
270inline bool
271operator>=(const T &pos, const Range<U> &range)
272{
273    return pos >= range.start;
274}
275
276////////////////////////////////////////////////////////////////////////
277//
278// Range to Position Comparisons (for symmetry)
279//
280
281/**
282 * @param range range compared against.
283 * @param pos position compared to the range.
284 * @return indicates that position pos is within the range.
285 */
286template <class T, class U>
287inline bool
288operator==(const Range<T> &range, const U &pos)
289{
290    return pos >= range.start && pos <= range.end;
291}
292
293/**
294 * @param range range compared against.
295 * @param pos position compared to the range.
296 * @return indicates that position pos is not within the range.
297 */
298template <class T, class U>
299inline bool
300operator!=(const Range<T> &range, const U &pos)
301{
302    return pos < range.start || pos > range.end;
303}
304
305/**
306 * @param range range compared against.
307 * @param pos position compared to the range.
308 * @return indicates that position pos is above the range.
309 */
310template <class T, class U>
311inline bool
312operator<(const Range<T> &range, const U &pos)
313{
314    return range.end < pos;
315}
316
317/**
318 * @param range range compared against.
319 * @param pos position compared to the range.
320 * @return indicates that position pos is above or in the range.
321 */
322template <class T, class U>
323inline bool
324operator<=(const Range<T> &range, const U &pos)
325{
326    return range.start <= pos;
327}
328
329/**
330 * @param range range compared against.
331 * @param pos position compared to the range.
332 * 'range > pos' indicates that position pos is below the range.
333 */
334template <class T, class U>
335inline bool
336operator>(const Range<T> &range, const U &pos)
337{
338    return range.start > pos;
339}
340
341/**
342 * @param range range compared against.
343 * @param pos position compared to the range.
344 * 'range >= pos' indicates that position pos is below or in the range.
345 */
346template <class T, class U>
347inline bool
348operator>=(const Range<T> &range, const U &pos)
349{
350    return range.end >= pos;
351}
352
353#endif // __BASE_RANGE_HH__
354