summaryrefslogtreecommitdiff
path: root/base/range.hh
diff options
context:
space:
mode:
Diffstat (limited to 'base/range.hh')
-rw-r--r--base/range.hh260
1 files changed, 260 insertions, 0 deletions
diff --git a/base/range.hh b/base/range.hh
new file mode 100644
index 000000000..254e71460
--- /dev/null
+++ b/base/range.hh
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RANGE_HH__
+#define __RANGE_HH__
+
+#include <assert.h>
+
+#include "str.hh"
+#include "intmath.h"
+
+template<class T>
+class Range
+{
+ private:
+ bool valid;
+
+ public:
+ T start;
+ T end;
+
+ public:
+ Range() {}
+
+ Range(const Range &r) { operator=(r); }
+
+ Range(const T& s, const T& e)
+ : start(s), end(e)
+ {
+ valid = (start <= end);
+ }
+
+ Range(const std::string &s) { valid = parse(s); }
+
+ ~Range() {}
+
+ int compare(const T &p);
+ bool parse(const std::string &s);
+ const Range &operator=(const Range &r);
+
+ bool isValid() const { return valid; }
+};
+
+
+template<class T>
+inline int
+Range<T>::compare(const T &p)
+{
+ assert(isValid());
+
+ if (p < start)
+ return -1;
+ else if (p > end)
+ return 1;
+ else
+ return 0;
+}
+
+// Parse a range string
+//
+// Ranges are in the following format:
+// <range> := {<start_val>}:{<end>}
+// <end> := <end_val> | +<delta>
+template<class T>
+inline bool
+Range<T>::parse(const std::string &str)
+{
+ std::vector<std::string> values;
+ tokenize(values, str, ':');
+
+ T thestart, theend;
+
+ if (values.size() != 2)
+ return false;
+
+ std::string s = values[0];
+ std::string e = values[1];
+
+ if (!to_number(s, thestart))
+ return false;
+
+ bool increment = (e[0] == '+');
+ if (increment)
+ e = e.substr(1);
+
+ if (!to_number(e, theend))
+ return false;
+
+ if (increment)
+ theend += thestart;
+
+ start = thestart;
+ end = theend;
+
+ if (start > end)
+ return false;
+
+ return true;
+}
+
+
+template<class T>
+inline const Range<T> &
+Range<T>::operator=(const Range<T> &r)
+{
+ if (this != &r) {
+ start = r.start;
+ end = r.end;
+
+ valid = r.valid;
+ }
+ else {
+ valid = false;
+ }
+
+ return *this;
+}
+
+template<class T>
+inline std::ostream &
+operator<<(std::ostream &o, const Range<T> &r)
+{
+ // don't currently support output of invalid ranges
+ assert(r.isValid());
+ o << r.start << ":" << r.end;
+ return o;
+}
+
+//////////////////////////////////////////
+//
+// Compare two ranges
+//
+template<class T>
+inline bool
+operator==(const Range<T> &l, const Range<T> &r)
+{
+ // ranges must both be valid to be equal
+ return (l.isValid() && r.isValid() &&
+ (l.start == r.start) && (l.end == r.end));
+}
+
+template<class T>
+inline bool
+operator!=(const Range<T> &l, const Range<T> &r)
+{
+ // for symmetry with ==, an invalid range is not equal to any other
+ return (!l.isValid() || !r.isValid() ||
+ (l.start != r.start) || (l.end != r.end));
+}
+
+//////////////////////////////////////////
+//
+// Compare position to a range
+//
+// - 'pos == range' indicates that position pos is within the given range.
+// This test always returns false if the range is invalid.
+//
+// - 'pos < range' and 'pos > range' indicate that the position is
+// before the start of or after the end of the range, respectively.
+// The range must be valid for these comparisons to be made.
+//
+// All other comparisons do the obvious thing based on these definitions.
+//
+//
+
+//
+// Basic comparisons
+//
+template<class T>
+inline bool
+operator==(const T &pos, const Range<T> &range)
+{ return range.isValid() && pos >= range.start && pos <= range.end; }
+
+template<class T>
+inline bool
+operator<(const T &pos, const Range<T> &range)
+{ assert(range.isValid()); return pos < range.start; }
+
+template<class T>
+inline bool
+operator>(const T &pos, const Range<T> &range)
+{ assert(range.isValid()); return pos > range.end; }
+
+//
+// Derived comparisons
+//
+template<class T>
+inline bool
+operator<=(const T &pos, const Range<T> &range)
+{ assert(range.isValid()); return pos <= range.end; }
+
+template<class T>
+inline bool
+operator>=(const T &pos, const Range<T> &range)
+{ assert(range.isValid()); return pos >= range.start; }
+
+template<class T>
+inline bool
+operator!=(const T &pos, const Range<T> &range)
+{ return !(pos == range); }
+
+//
+// Define symmetric comparisons based on above
+//
+template<class T>
+inline bool
+operator>(const Range<T> &range, const T &pos)
+{ return pos < range; }
+
+template<class T>
+inline bool
+operator<(const Range<T> &range, const T &pos)
+{ return pos > range; }
+
+template<class T>
+inline bool
+operator<=(const Range<T> &range, const T &pos)
+{ return pos >= range; }
+
+template<class T>
+inline bool
+operator>=(const Range<T> &range, const T &pos)
+{ return pos <= range; }
+
+template<class T>
+inline bool
+operator==(const Range<T> &range, const T &pos)
+{ return (pos == range); }
+
+template<class T>
+inline bool
+operator!=(const Range<T> &range, const T &pos)
+{ return (pos != range); }
+
+#endif // __RANGE_HH__