addr_range.hh revision 2
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 <assert.h>
33
34#include "str.hh"
35#include "intmath.h"
36
37template<class T>
38class Range
39{
40  private:
41    bool valid;
42
43  public:
44    T start;
45    T end;
46
47  public:
48    Range() {}
49
50    Range(const Range &r) { operator=(r); }
51
52    Range(const T& s, const T& e)
53        : start(s), end(e)
54    {
55        valid = (start <= end);
56    }
57
58    Range(const std::string &s) { valid = parse(s); }
59
60    ~Range() {}
61
62    int compare(const T &p);
63    bool parse(const std::string &s);
64    const Range &operator=(const Range &r);
65
66    bool isValid() const { return valid; }
67};
68
69
70template<class T>
71inline int
72Range<T>::compare(const T &p)
73{
74    assert(isValid());
75
76    if (p < start)
77        return -1;
78    else if (p > end)
79        return 1;
80    else
81        return 0;
82}
83
84// Parse a range string
85//
86// Ranges are in the following format:
87//    <range> := {<start_val>}:{<end>}
88//    <end>   := <end_val> | +<delta>
89template<class T>
90inline bool
91Range<T>::parse(const std::string &str)
92{
93    std::vector<std::string> values;
94    tokenize(values, str, ':');
95
96    T thestart, theend;
97
98    if (values.size() != 2)
99        return false;
100
101    std::string s = values[0];
102    std::string e = values[1];
103
104    if (!to_number(s, thestart))
105        return false;
106
107    bool increment = (e[0] == '+');
108    if (increment)
109        e = e.substr(1);
110
111    if (!to_number(e, theend))
112        return false;
113
114    if (increment)
115        theend += thestart;
116
117    start = thestart;
118    end = theend;
119
120    if (start > end)
121        return false;
122
123    return true;
124}
125
126
127template<class T>
128inline const Range<T> &
129Range<T>::operator=(const Range<T> &r)
130{
131    if (this != &r) {
132        start = r.start;
133        end = r.end;
134
135        valid = r.valid;
136    }
137    else {
138        valid = false;
139    }
140
141    return *this;
142}
143
144template<class T>
145inline std::ostream &
146operator<<(std::ostream &o, const Range<T> &r)
147{
148    // don't currently support output of invalid ranges
149    assert(r.isValid());
150    o << r.start << ":" << r.end;
151    return o;
152}
153
154//////////////////////////////////////////
155//
156// Compare two ranges
157//
158template<class T>
159inline bool
160operator==(const Range<T> &l, const Range<T> &r)
161{
162    // ranges must both be valid to be equal
163    return (l.isValid() && r.isValid() &&
164            (l.start == r.start) && (l.end == r.end));
165}
166
167template<class T>
168inline bool
169operator!=(const Range<T> &l, const Range<T> &r)
170{
171    // for symmetry with ==, an invalid range is not equal to any other
172    return (!l.isValid() || !r.isValid() ||
173            (l.start != r.start) || (l.end != r.end));
174}
175
176//////////////////////////////////////////
177//
178// Compare position to a range
179//
180// - 'pos == range' indicates that position pos is within the given range.
181//   This test always returns false if the range is invalid.
182//
183// - 'pos < range' and 'pos > range' indicate that the position is
184//   before the start of or after the end of the range, respectively.
185//   The range must be valid for these comparisons to be made.
186//
187// All other comparisons do the obvious thing based on these definitions.
188//
189//
190
191//
192// Basic comparisons
193//
194template<class T>
195inline bool
196operator==(const T &pos, const Range<T> &range)
197{  return range.isValid() && pos >= range.start && pos <= range.end; }
198
199template<class T>
200inline bool
201operator<(const T &pos, const Range<T> &range)
202{  assert(range.isValid()); return pos < range.start; }
203
204template<class T>
205inline bool
206operator>(const T &pos, const Range<T> &range)
207{  assert(range.isValid()); return pos > range.end; }
208
209//
210// Derived comparisons
211//
212template<class T>
213inline bool
214operator<=(const T &pos, const Range<T> &range)
215{  assert(range.isValid()); return pos <= range.end; }
216
217template<class T>
218inline bool
219operator>=(const T &pos, const Range<T> &range)
220{  assert(range.isValid()); return pos >= range.start; }
221
222template<class T>
223inline bool
224operator!=(const T &pos, const Range<T> &range)
225{  return !(pos == range); }
226
227//
228// Define symmetric comparisons based on above
229//
230template<class T>
231inline bool
232operator>(const Range<T> &range, const T &pos)
233{  return pos < range; }
234
235template<class T>
236inline bool
237operator<(const Range<T> &range, const T &pos)
238{  return pos > range; }
239
240template<class T>
241inline bool
242operator<=(const Range<T> &range, const T &pos)
243{  return pos >= range; }
244
245template<class T>
246inline bool
247operator>=(const Range<T> &range, const T &pos)
248{  return pos <= range; }
249
250template<class T>
251inline bool
252operator==(const Range<T> &range, const T &pos)
253{  return (pos == range); }
254
255template<class T>
256inline bool
257operator!=(const Range<T> &range, const T &pos)
258{  return (pos != range); }
259
260#endif // __RANGE_HH__
261