addr_range.hh revision 532
1/*
2 * Copyright (c) 2003 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 __RANGE_HH__
30#define __RANGE_HH__
31
32#include <cassert>
33#include <string>
34
35template <class T>
36bool __parse_range(const std::string &s, T &start, T &end);
37
38template <class T>
39struct Range
40{
41  private:
42    /**
43     * @param s range string
44     * Ranges are in the following format:
45     *    <range> := {<start_val>}:{<end>}
46     *    <end>   := <end_val> | +<delta>
47     */
48    void
49    parse(const std::string &s)
50    {
51        if (!__parse_range(s, start, end))
52            invalidate();
53    }
54
55  public:
56    T start;
57    T end;
58
59  public:
60    Range()
61    {
62        invalidate();
63    }
64
65    Range(T first, T second)
66        : start(first), end(second)
67    {}
68
69    template <class U>
70    Range(const Range<U> &r)
71        : start(r.start), end(r.end)
72    {}
73
74    template <class U>
75    Range(const std::pair<U, U> &r)
76        : start(r.first), end(r.second)
77    {}
78
79    Range(const std::string &s)
80    {
81        parse(s);
82    }
83
84    template <class U>
85    const Range<T> &operator=(const Range<U> &r)
86    {
87        start = r.start;
88        end = r.end;
89        return *this;
90    }
91
92    template <class U>
93    const Range<T> &operator=(const std::pair<U, U> &r)
94    {
95        start = r.first;
96        end = r.second;
97        return *this;
98    }
99
100    const Range &operator=(const std::string &s)
101    {
102        parse(s);
103        return *this;
104    }
105
106    void invalidate() { start = 0; end = 0; }
107    T size() const { return end - start; }
108    bool valid() const { return start < end; }
109};
110
111template <class T>
112inline Range<T>
113make_range(T start, T end)
114{
115    return Range<T>(start, end);
116}
117
118template <class T>
119inline std::ostream &
120operator<<(std::ostream &o, const Range<T> &r)
121{
122    // don't currently support output of invalid ranges
123    assert(r.valid());
124    o << r.start << ":" << r.end;
125    return o;
126}
127
128////////////////////////////////////////////////////////////////////////
129//
130// Range to Range Comparisons
131//
132
133/**
134 * @param range1 is a range.
135 * @param range2 is a range.
136 * @return if range1 and range2 are identical.
137 */
138template <class T, class U>
139inline bool
140operator==(const Range<T> &range1, const Range<U> &range2)
141{
142    assert(range1.valid() && range2.valid());
143    return range1.start == range2.start && range1.end == range2.end;
144}
145
146/**
147 * @param range1 is a range.
148 * @param range2 is a range.
149 * @return if range1 and range2 are not identical.
150 */
151template <class T, class U>
152inline bool
153operator!=(const Range<T> &range1, const Range<U> &range2)
154{
155    assert(range1.valid() && range2.valid());
156    return range1.start != range2.start || range1.end != range2.end;
157}
158
159/**
160 * @param range1 is a range.
161 * @param range2 is a range.
162 * @return if range1 is less than range2 and does not overlap range1.
163 */
164template <class T, class U>
165inline bool
166operator<(const Range<T> &range1, const Range<U> &range2)
167{
168    assert(range1.valid() && range2.valid());
169    return range1.end <= range2.start;
170}
171
172/**
173 * @param range1 is a range.
174 * @param range2 is a range.
175 * @return if range1 is less than range2.  range1 may overlap range2,
176 * but not extend beyond the end of range2.
177 */
178template <class T, class U>
179inline bool
180operator<=(const Range<T> &range1, const Range<U> &range2)
181{
182    assert(range1.valid() && range2.valid());
183    return range1.start <= range2.start && range1.end <= range2.end;
184}
185
186/**
187 * @param range1 is a range.
188 * @param range2 is a range.
189 * @return if range1 is greater than range2 and does not overlap range2.
190 */
191template <class T, class U>
192inline bool
193operator>(const Range<T> &range1, const Range<U> &range2)
194{
195    assert(range1.valid() && range2.valid());
196    return range1.start >= range2.end;
197}
198
199/**
200 * @param range1 is a range.
201 * @param range2 is a range.
202 * @return if range1 is greater than range2.  range1 may overlap range2,
203 * but not extend beyond the beginning of range2.
204 */
205template <class T, class U>
206inline bool
207operator>=(const Range<T> &range1, const Range<U> &range2)
208{
209    assert(range1.valid() && range2.valid());
210    return range1.start >= range2.start && range1.end >= range2.end;
211}
212
213////////////////////////////////////////////////////////////////////////
214//
215// Position to Range Comparisons
216//
217
218/**
219 * @param pos position compared to the range.
220 * @param range range compared against.
221 * @return indicates that position pos is within the range.
222 */
223template <class T, class U>
224inline bool
225operator==(const T &pos, const Range<U> &range)
226{
227    assert(range.valid());
228    return pos >= range.start && pos < range.end;
229}
230
231/**
232 * @param pos position compared to the range.
233 * @param range range compared against.
234 * @return indicates that position pos is not within the range.
235 */
236template <class T, class U>
237inline bool
238operator!=(const T &pos, const Range<U> &range)
239{
240    assert(range.valid());
241    return pos < range.start || pos >= range.end;
242}
243
244/**
245 * @param pos position compared to the range.
246 * @param range range compared against.
247 * @return indicates that position pos is below the range.
248 */
249template <class T, class U>
250inline bool
251operator<(const T &pos, const Range<U> &range)
252{
253    assert(range.valid());
254    return pos < range.start;
255}
256
257/**
258 * @param pos position compared to the range.
259 * @param range range compared against.
260 * @return indicates that position pos is below or in the range.
261 */
262template <class T, class U>
263inline bool
264operator<=(const T &pos, const Range<U> &range)
265{
266    assert(range.valid());
267    return pos < range.end;
268}
269
270/**
271 * @param pos position compared to the range.
272 * @param range range compared against.
273 * @return indicates that position pos is above the range.
274 */
275template <class T, class U>
276inline bool
277operator>(const T &pos, const Range<U> &range)
278{
279    assert(range.valid());
280    return pos >= range.end;
281}
282
283/**
284 * @param pos position compared to the range.
285 * @param range range compared against.
286 * @return indicates that position pos is above or in the range.
287 */
288template <class T, class U>
289inline bool
290operator>=(const T &pos, const Range<U> &range)
291{
292    assert(range.valid());
293    return pos >= range.start;
294}
295
296////////////////////////////////////////////////////////////////////////
297//
298// Range to Position Comparisons (for symmetry)
299//
300
301/**
302 * @param range range compared against.
303 * @param pos position compared to the range.
304 * @return indicates that position pos is within the range.
305 */
306template <class T, class U>
307inline bool
308operator==(const Range<T> &range, const U &pos)
309{
310    assert(range.valid());
311    return pos >= range.start && pos < range.end;
312}
313
314/**
315 * @param range range compared against.
316 * @param pos position compared to the range.
317 * @return indicates that position pos is not within the range.
318 */
319template <class T, class U>
320inline bool
321operator!=(const Range<T> &range, const U &pos)
322{
323    assert(range.valid());
324    return pos < range.start || pos >= range.end;
325}
326
327/**
328 * @param range range compared against.
329 * @param pos position compared to the range.
330 * @return indicates that position pos is above the range.
331 */
332template <class T, class U>
333inline bool
334operator<(const Range<T> &range, const U &pos)
335{
336    assert(range.valid());
337    return range.end <= pos;
338}
339
340/**
341 * @param range range compared against.
342 * @param pos position compared to the range.
343 * @return indicates that position pos is above or in the range.
344 */
345template <class T, class U>
346inline bool
347operator<=(const Range<T> &range, const U &pos)
348{
349    assert(range.valid());
350    return range.start <= pos;
351}
352
353/**
354 * @param range range compared against.
355 * @param pos position compared to the range.
356 * 'range > pos' indicates that position pos is below the range.
357 */
358template <class T, class U>
359inline bool
360operator>(const Range<T> &range, const U &pos)
361{
362    assert(range.valid());
363    return range.start > pos;
364}
365
366/**
367 * @param range range compared against.
368 * @param pos position compared to the range.
369 * 'range >= pos' indicates that position pos is below or in the range.
370 */
371template <class T, class U>
372inline bool
373operator>=(const Range<T> &range, const U &pos)
374{
375    assert(range.valid());
376    return range.end > pos;
377}
378
379#endif // __RANGE_HH__
380