// // srecord - manipulate eprom load files // Copyright (C) 1998-2000, 2002-2007 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #ifndef INCLUDE_INTERVAL_H #define INCLUDE_INTERVAL_H #include #include using namespace std; /** * The interval class is used to represent a set of integer values, * usually composed of runs of adjacent value. Set arithmetic is * implemented on these intervals. */ class interval { public: /** * The destructor. It isn't virtual, so don't derive from this class. */ ~interval(); /** * The data_t type is used to parameterize the integr type used in * the interval. */ typedef unsigned long data_t; typedef unsigned long long data64_t; /** * The default constructor. The interval is empty. */ interval(); /** * The constructor. The interval contains the single integer supplied. * * \param val * The interval is constructed to contain the single interger * value supplied. */ interval(data_t val); /** * The constructor. The interval contains all values >= lo and < hi. * * \param lo * The lower bound of the integers in the initial interval. * \param hi * The upper bound of the integers in the initial interval; * this value is not included. */ interval(data_t lo, data_t hi); /** * The copy constructor. */ interval(const interval &); /** * The assignment operator. */ interval &operator=(const interval &); /** * The union_ class method is used to calculate the set union of * two intervals. */ static interval union_(const interval &, const interval &); /** * The intersection class method is used to calculate the set * intersection of two intervals. */ static interval intersection(const interval &, const interval &); /** * The difference class method is used to calculate the set * difference of two intervals. */ static interval difference(const interval &, const interval &); /** * The equal class method is used to test the equality of two * intervals. */ static bool equal(const interval &, const interval &); /** * The member method is used to test whether a given value is a * member of the interval. * * \param val * The value to test for membership * \returns * True if the given value is a member of the interval, * false if it is not. */ bool member(data_t val) const; /** * The empty method is used to test whether the interval is empty. * * \returns * True if the interval is empty, * false if the interval is not empty. */ bool empty() const; /** * The first_interval_only method is used to crop the interval to the * first (numerically least) run of consecutive integers in the set. */ void first_interval_only(); /** * The interval_scan_begin method is used to start traversing every * integer value in the interval. */ void scan_begin(); /** * The interval_scan_next method is used to traverse every integer * value in the interval. */ bool scan_next(data_t &); /** * The interval_scan_end method is used to finish traversing every * integer value in the interval. */ void scan_end(); /** * The get_lowest method is used to obtain the lower bound of * the interval. It is inclusive. */ data_t get_lowest() const; /** * The get_highest method is used to obtain the upper bound of * the interval. It is exclusive (i.e. one beyond the highest * integer in the set). */ data_t get_highest() const; /** * The print method is used to print an interval on an output stream. */ void print(ostream &) const; /** * The pad method is used to expand an interval by padding each * sub-interval. For each sub-interval the minimum is rounded * down to a multiple of x, and the upper bound is rounded up to a * multiple of x. * * @param x * The multiple to expand to. No action is taken if x < 2. * @returns * new padded interval. */ interval pad(int x) const; /** * The representation method is used to manufacture a textural * representation of this interval. */ string representation() const; private: /** * The length instance variable is used to remember the length of * the data instance variable. This is almost always even, because * the internal is a series of [lo, hi) sub-intervals. */ size_t length; /** * The size instance variable is used to remember the maximum size * of the data instance variable. The length can go up and down * depending on the calculation, but the size only ever rises. */ size_t size; /** * The scan_index instance variable is used to remember where the * scan us up to. Used by the scan_next method, et al. */ size_t scan_index; /** * The scan_next_datum instance variable is used to remember where * the scan us up to. Used by the scan_next method, et al. */ data_t scan_next_datum; /** * The data instance variable is used to remember a pointer to * the base of an array of interger values. They come in [lo, hi) * pairs. As a sanity check, there is an extra item, wich contains * the same value as the length instance variable. */ data_t *data; /** * The valid method is used to test whether the interval is * internally self-consistent. Principally of use when debugging. */ bool valid() const; /** * The append method is used to append another value to the end * of an interval under construction. This breaks the "length is * even" assertion which usually applies; for this reason it is * only to be used by the arithmetic operator implementations when * calculating their results. */ void append(data_t); }; /** * The equality operator is used to determine if two intervals are the * same. */ inline bool operator == (const interval &lhs, const interval &rhs) { return interval::equal(lhs, rhs); } /** * The inequality operator is used to determine if two intervals are * different. */ inline bool operator != (const interval &lhs, const interval &rhs) { return !interval::equal(lhs, rhs); } /** * The binary star operator is used to calculate the intersection of * two intervals. */ inline interval operator * (const interval &lhs, const interval &rhs) { return interval::intersection(lhs, rhs); } /** * The star-and-replace operator is used to calculate the intersection * of two intervals, and assign the result to the left-hand-side. */ inline interval & operator *= (interval &lhs, const interval &rhs) { lhs = interval::intersection(lhs, rhs); return lhs; } /** * The binary plus operator is used to calculate the union of two * intervals. */ inline interval operator + (const interval &lhs, const interval &rhs) { return interval::union_(lhs, rhs); } /** * The plus-and-replace operator is used to calculate the union of two * intervals, and assign the result to the left-hand-side. */ inline interval & operator += (interval &lhs, const interval &rhs) { lhs = interval::union_(lhs, rhs); return lhs; } /** * The binary minus operator is used to calculate the difference of two * intervals. */ inline interval operator - (const interval &lhs, const interval &rhs) { return interval::difference(lhs, rhs); } /** * The minus-and-replace operator is used to calculate the difference * of two intervals, and assign the result to the left-hand-side. */ inline interval & operator -= (interval &lhs, const interval &rhs) { lhs = interval::difference(lhs, rhs); return lhs; } /** * The unary minus operator is used to calculate the logical complement * (inverse, negative) of an interval. */ inline interval operator - (const interval &arg) { return (interval(0, 0) - arg); } /** * The binary left-shift operator is used to print an interval on an * output stream. */ inline ostream & operator << (ostream &os, const interval &val) { val.print(os); return os; } #endif // INCLUDE_INTERVAL_H