srecord  1.65.0
interval.h
Go to the documentation of this file.
1 //
2 // srecord - manipulate eprom load files
3 // Copyright (C) 1998-2000, 2002-2010 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19 
20 #ifndef SRECORD_INTERVAL_H
21 #define SRECORD_INTERVAL_H
22 
23 #include <cstddef>
24 #include <stdint.h>
25 #include <iostream>
26 
27 namespace srecord
28 {
29 
30 /**
31  * The interval class is used to represent a set of integer values,
32  * usually composed of runs of adjacent value. Set arithmetic is
33  * implemented on these intervals.
34  */
35 class interval
36 {
37 public:
38  /**
39  * The destructor. It isn't virtual, so don't derive from this class.
40  */
42 
43  /**
44  * The data_t type is used to parameterize the integr type used in
45  * the interval.
46  */
47  typedef uint32_t data_t;
48  typedef uint64_t long_data_t;
49 
50  /**
51  * The default constructor. The interval is empty.
52  */
54 
55  /**
56  * The constructor. The interval contains the single integer supplied.
57  *
58  * \param val
59  * The interval is constructed to contain the single interger
60  * value supplied.
61  */
63 
64  /**
65  * The constructor. The interval contains all values >= lo and < hi.
66  *
67  * \param lo
68  * The lower bound of the integers in the initial interval.
69  * \param hi
70  * The upper bound of the integers in the initial interval;
71  * this value is not included.
72  */
74 
75  /**
76  * The copy constructor.
77  */
78  interval(const interval &);
79 
80  /**
81  * The assignment operator.
82  */
84 
85  /**
86  * The union_ class method is used to calculate the set union of
87  * two intervals.
88  */
89  static interval union_(const interval &, const interval &);
90 
91  /**
92  * The intersection class method is used to calculate the set
93  * intersection of two intervals.
94  */
95  static interval intersection(const interval &, const interval &);
96 
97  /**
98  * The difference class method is used to calculate the set
99  * difference of two intervals.
100  */
101  static interval difference(const interval &, const interval &);
102 
103  /**
104  * The equal class method is used to test the equality of two
105  * intervals.
106  */
107  static bool equal(const interval &, const interval &);
108 
109  /**
110  * The member method is used to test whether a given value is a
111  * member of the interval.
112  *
113  * \param val
114  * The value to test for membership
115  * \returns
116  * True if the given value is a member of the interval,
117  * false if it is not.
118  */
119  bool member(data_t val) const;
120 
121  /**
122  * The empty method is used to test whether the interval is empty.
123  *
124  * \returns
125  * True if the interval is empty,
126  * false if the interval is not empty.
127  */
128  bool empty() const;
129 
130  /**
131  * The first_interval_only method is used to crop the interval to the
132  * first (numerically least) run of consecutive integers in the set.
133  */
135 
136  /**
137  * The interval_scan_begin method is used to start traversing every
138  * integer value in the interval.
139  */
140  void scan_begin();
141 
142  /**
143  * The interval_scan_next method is used to traverse every integer
144  * value in the interval.
145  */
146  bool scan_next(data_t &);
147 
148  /**
149  * The interval_scan_end method is used to finish traversing every
150  * integer value in the interval.
151  */
152  void scan_end();
153 
154  /**
155  * The get_lowest method is used to obtain the lower bound of
156  * the interval. It is inclusive.
157  */
159 
160  /**
161  * The get_highest method is used to obtain the upper bound of
162  * the interval. It is exclusive (i.e. one beyond the highest
163  * integer in the set).
164  */
166 
167  /**
168  * The print method is used to print an interval on an output stream.
169  */
170  void print(std::ostream &) const;
171 
172  /**
173  * The pad method is used to expand an interval by padding each
174  * sub-interval. For each sub-interval the minimum is rounded
175  * down to a multiple of x, and the upper bound is rounded up to a
176  * multiple of x.
177  *
178  * @param x
179  * The multiple to expand to. No action is taken if x < 2.
180  * @returns
181  * new padded interval.
182  */
183  interval pad(int x) const;
184 
185  /**
186  * The representation method is used to manufacture a textural
187  * representation of this interval.
188  */
189  std::string representation() const;
190 
191  /**
192  * The flatten method is used to convert an interval with holes
193  * in it to a simple interval with no holes in it, by using the
194  * mimimum and maximum values.
195  */
196  interval flatten() const;
197 
198  /**
199  * The coverage method is used to obtain the size of the interval
200  * in bytes.
201  *
202  * @returns
203  * The number of bytes cobered by the interval, NOT including
204  * holes. Because the result could be 2**32, the 64-bit result
205  * is used so that this is representable.
206  */
208 
209 private:
210  /**
211  * The length instance variable is used to remember the length of
212  * the data instance variable. This is almost always even, because
213  * the internal is a series of [lo, hi) sub-intervals.
214  */
215  size_t length;
216 
217  /**
218  * The size instance variable is used to remember the maximum size
219  * of the data instance variable. The length can go up and down
220  * depending on the calculation, but the size only ever rises.
221  */
222  size_t size;
223 
224  /**
225  * The scan_index instance variable is used to remember where the
226  * scan us up to. Used by the scan_next method, et al.
227  */
228  size_t scan_index;
229 
230  /**
231  * The scan_next_datum instance variable is used to remember where
232  * the scan us up to. Used by the scan_next method, et al.
233  */
234  data_t scan_next_datum;
235 
236  /**
237  * The data instance variable is used to remember a pointer to
238  * the base of an array of interger values. They come in [lo, hi)
239  * pairs. As a sanity check, there is an extra item, wich contains
240  * the same value as the length instance variable.
241  */
242  data_t *data;
243 
244  /**
245  * The valid method is used to test whether the interval is
246  * internally self-consistent. Principally of use when debugging.
247  */
248  bool valid() const;
249 
250  /**
251  * The append method is used to append another value to the end
252  * of an interval under construction. This breaks the "length is
253  * even" assertion which usually applies; for this reason it is
254  * only to be used by the arithmetic operator implementations when
255  * calculating their results.
256  */
257  void append(data_t);
258 };
259 
260 /**
261  * The equality operator is used to determine if two intervals are the
262  * same.
263  */
264 inline bool
265 operator == (const interval &lhs, const interval &rhs)
266 {
267  return interval::equal(lhs, rhs);
268 }
269 
270 /**
271  * The inequality operator is used to determine if two intervals are
272  * different.
273  */
274 inline bool
275 operator != (const interval &lhs, const interval &rhs)
276 {
277  return !interval::equal(lhs, rhs);
278 }
279 
280 /**
281  * The binary star operator is used to calculate the intersection of
282  * two intervals.
283  */
284 inline interval
285 operator * (const interval &lhs, const interval &rhs)
286 {
287  return interval::intersection(lhs, rhs);
288 }
289 
290 /**
291  * The star-and-replace operator is used to calculate the intersection
292  * of two intervals, and assign the result to the left-hand-side.
293  */
294 inline interval &
295 operator *= (interval &lhs, const interval &rhs)
296 {
297  lhs = interval::intersection(lhs, rhs);
298  return lhs;
299 }
300 
301 /**
302  * The binary plus operator is used to calculate the union of two
303  * intervals.
304  */
305 inline interval
306 operator + (const interval &lhs, const interval &rhs)
307 {
308  return interval::union_(lhs, rhs);
309 }
310 
311 /**
312  * The plus-and-replace operator is used to calculate the union of two
313  * intervals, and assign the result to the left-hand-side.
314  */
315 inline interval &
316 operator += (interval &lhs, const interval &rhs)
317 {
318  lhs = interval::union_(lhs, rhs);
319  return lhs;
320 }
321 
322 /**
323  * The binary minus operator is used to calculate the difference of two
324  * intervals.
325  */
326 inline interval
327 operator - (const interval &lhs, const interval &rhs)
328 {
329  return interval::difference(lhs, rhs);
330 }
331 
332 /**
333  * The minus-and-replace operator is used to calculate the difference
334  * of two intervals, and assign the result to the left-hand-side.
335  */
336 inline interval &
337 operator -= (interval &lhs, const interval &rhs)
338 {
339  lhs = interval::difference(lhs, rhs);
340  return lhs;
341 }
342 
343 /**
344  * The unary minus operator is used to calculate the logical complement
345  * (inverse, negative) of an interval.
346  */
347 inline interval
349 {
350  return (interval(0, 0) - arg);
351 }
352 
353 /**
354  * The binary left-shift operator is used to print an interval on an
355  * output stream.
356  */
357 inline std::ostream &
358 operator << (std::ostream &os, const interval &val)
359 {
360  val.print(os);
361  return os;
362 }
363 
364 };
365 
366 #endif // SRECORD_INTERVAL_H
The interval class is used to represent a set of integer values, usually composed of runs of adjacent...
Definition: interval.h:36
interval(const interval &)
The copy constructor.
void print(std::ostream &) const
The print method is used to print an interval on an output stream.
static bool equal(const interval &, const interval &)
The equal class method is used to test the equality of two intervals.
long_data_t coverage() const
The coverage method is used to obtain the size of the interval in bytes.
static interval difference(const interval &, const interval &)
The difference class method is used to calculate the set difference of two intervals.
uint64_t long_data_t
Definition: interval.h:48
void first_interval_only()
The first_interval_only method is used to crop the interval to the first (numerically least) run of c...
interval pad(int x) const
The pad method is used to expand an interval by padding each sub-interval.
uint32_t data_t
The data_t type is used to parameterize the integr type used in the interval.
Definition: interval.h:47
data_t get_lowest() const
The get_lowest method is used to obtain the lower bound of the interval.
void scan_begin()
The interval_scan_begin method is used to start traversing every integer value in the interval.
~interval()
The destructor.
interval flatten() const
The flatten method is used to convert an interval with holes in it to a simple interval with no holes...
bool empty() const
The empty method is used to test whether the interval is empty.
data_t get_highest() const
The get_highest method is used to obtain the upper bound of the interval.
static interval union_(const interval &, const interval &)
The union_ class method is used to calculate the set union of two intervals.
interval()
The default constructor.
interval(data_t lo, data_t hi)
The constructor.
interval(data_t val)
The constructor.
std::string representation() const
The representation method is used to manufacture a textural representation of this interval.
bool scan_next(data_t &)
The interval_scan_next method is used to traverse every integer value in the interval.
void scan_end()
The interval_scan_end method is used to finish traversing every integer value in the interval.
interval & operator=(const interval &)
The assignment operator.
bool member(data_t val) const
The member method is used to test whether a given value is a member of the interval.
static interval intersection(const interval &, const interval &)
The intersection class method is used to calculate the set intersection of two intervals.
interval & operator*=(interval &lhs, const interval &rhs)
The star-and-replace operator is used to calculate the intersection of two intervals,...
Definition: interval.h:295
interval operator*(const interval &lhs, const interval &rhs)
The binary star operator is used to calculate the intersection of two intervals.
Definition: interval.h:285
std::ostream & operator<<(std::ostream &os, const interval &val)
The binary left-shift operator is used to print an interval on an output stream.
Definition: interval.h:358
interval & operator+=(interval &lhs, const interval &rhs)
The plus-and-replace operator is used to calculate the union of two intervals, and assign the result ...
Definition: interval.h:316
interval operator+(const interval &lhs, const interval &rhs)
The binary plus operator is used to calculate the union of two intervals.
Definition: interval.h:306
interval operator-(const interval &lhs, const interval &rhs)
The binary minus operator is used to calculate the difference of two intervals.
Definition: interval.h:327
bool operator==(const interval &lhs, const interval &rhs)
The equality operator is used to determine if two intervals are the same.
Definition: interval.h:265
bool operator!=(const interval &lhs, const interval &rhs)
The inequality operator is used to determine if two intervals are different.
Definition: interval.h:275
interval & operator-=(interval &lhs, const interval &rhs)
The minus-and-replace operator is used to calculate the difference of two intervals,...
Definition: interval.h:337