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