1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // An Interval<T> is a data structure used to represent a contiguous, mutable
6 // range over an ordered type T. Supported operations include testing a value to
7 // see whether it is included in the interval, comparing two intervals, and
8 // performing their union, intersection, and difference. For the purposes of
9 // this library, an "ordered type" is any type that induces a total order on its
10 // values via its less-than operator (operator<()). Examples of such types are
11 // basic arithmetic types like int and double as well as class types like
14 // An Interval<T> is represented using the usual C++ STL convention, namely as
15 // the half-open interval [min, max). A point p is considered to be contained in
16 // the interval iff p >= min && p < max. One consequence of this definition is
17 // that for any non-empty interval, min is contained in the interval but max is
18 // not. There is no canonical representation for the empty interval; rather, any
19 // interval where max <= min is regarded as empty. As a consequence, two empty
20 // intervals will still compare as equal despite possibly having different
21 // underlying min() or max() values. Also beware of the terminology used here:
22 // the library uses the terms "min" and "max" rather than "begin" and "end" as
23 // is conventional for the STL.
25 // T is required to be default- and copy-constructable, to have an assignment
26 // operator, and the full complement of comparison operators (<, <=, ==, !=, >=,
27 // >). A difference operator (operator-()) is required if Interval<T>::Length
30 // For equality comparisons, Interval<T> supports an Equals() method and an
31 // operator==() which delegates to it. Two intervals are considered equal if
32 // either they are both empty or if their corresponding min and max fields
33 // compare equal. For ordered comparisons, Interval<T> also provides the
34 // comparator Interval<T>::Less and an operator<() which delegates to it.
35 // Unfortunately this comparator is currently buggy because its behavior is
36 // inconsistent with Equals(): two empty ranges with different representations
37 // may be regarded as equivalent by Equals() but regarded as different by
38 // the comparator. Bug 9240050 has been created to address this.
40 // This class is thread-compatible if T is thread-compatible. (See
41 // go/thread-compatible).
44 // Interval<int> r1(0, 100); // The interval [0, 100).
45 // EXPECT_TRUE(r1.Contains(0));
46 // EXPECT_TRUE(r1.Contains(50));
47 // EXPECT_FALSE(r1.Contains(100)); // 100 is just outside the interval.
49 // Interval<int> r2(50, 150); // The interval [50, 150).
50 // EXPECT_TRUE(r1.Intersects(r2));
51 // EXPECT_FALSE(r1.Contains(r2));
52 // EXPECT_TRUE(r1.IntersectWith(r2)); // Mutates r1.
53 // EXPECT_EQ(Interval<int>(50, 100), r1); // r1 is now [50, 100).
55 // Interval<int> r3(1000, 2000); // The interval [1000, 2000).
56 // EXPECT_TRUE(r1.IntersectWith(r3)); // Mutates r1.
57 // EXPECT_TRUE(r1.Empty()); // Now r1 is empty.
58 // EXPECT_FALSE(r1.Contains(r1.min())); // e.g. doesn't contain its own min.
60 #ifndef NET_QUIC_INTERVAL_H_
61 #define NET_QUIC_INTERVAL_H_
75 // TODO(rtenneti): Implement after suupport for std::decay.
77 // Type trait for deriving the return type for Interval::Length. If
78 // operator-() is not defined for T, then the return type is void. This makes
79 // the signature for Length compile so that the class can be used for such T,
80 // but code that calls Length would still generate a compilation error.
82 class DiffTypeOrVoid
{
85 static auto f(const V
* v
) -> decltype(*v
- *v
);
90 using type
= typename
std::decay
<decltype(f
<U
>(0))>::type
;
95 // Compatibility alias.
96 using Less
= std::less
<Interval
>;
98 // Construct an Interval representing an empty interval.
99 Interval() : min_(), max_() {}
101 // Construct an Interval representing the interval [min, max). If min < max,
102 // the constructed object will represent the non-empty interval containing all
103 // values from min up to (but not including) max. On the other hand, if min >=
104 // max, the constructed object will represent the empty interval.
105 Interval(const T
& min
, const T
& max
) : min_(min
), max_(max
) {}
107 const T
& min() const { return min_
; }
108 const T
& max() const { return max_
; }
109 void SetMin(const T
& t
) { min_
= t
; }
110 void SetMax(const T
& t
) { max_
= t
; }
112 void Set(const T
& min
, const T
& max
) {
117 void Clear() { *this = {}; }
118 void CopyFrom(const Interval
& i
) { *this = i
; }
119 bool Equals(const Interval
& i
) const { return *this == i
; }
120 bool Empty() const { return min() >= max(); }
122 // Returns the length of this interval. The value returned is zero if
123 // IsEmpty() is true; otherwise the value returned is max() - min().
124 const T
Length() const { return (min_
>= max_
? min_
: max_
) - min_
; }
126 // Returns true iff t >= min() && t < max().
127 bool Contains(const T
& t
) const { return min() <= t
&& max() > t
; }
129 // Returns true iff *this and i are non-empty, and *this includes i. "*this
130 // includes i" means that for all t, if i.Contains(t) then this->Contains(t).
131 // Note the unintuitive consequence of this definition: this method always
132 // returns false when i is the empty interval.
133 bool Contains(const Interval
& i
) const {
134 return !Empty() && !i
.Empty() && min() <= i
.min() && max() >= i
.max();
137 // Returns true iff there exists some point t for which this->Contains(t) &&
138 // i.Contains(t) evaluates to true, i.e. if the intersection is non-empty.
139 bool Intersects(const Interval
& i
) const {
140 return !Empty() && !i
.Empty() && min() < i
.max() && max() > i
.min();
143 // Returns true iff there exists some point t for which this->Contains(t) &&
144 // i.Contains(t) evaluates to true, i.e. if the intersection is non-empty.
145 // Furthermore, if the intersection is non-empty and the intersection pointer
146 // is not null, this method stores the calculated intersection in
148 bool Intersects(const Interval
& i
, Interval
* out
) const;
150 // Sets *this to be the intersection of itself with i. Returns true iff
151 // *this was modified.
152 bool IntersectWith(const Interval
& i
);
154 // Calculates the smallest interval containing both *this i, and updates *this
155 // to represent that interval, and returns true iff *this was modified.
156 bool SpanningUnion(const Interval
& i
);
158 // Determines the difference between two intervals by finding all points that
159 // are contained in *this but not in i, coalesces those points into the
160 // largest possible contiguous intervals, and appends those intervals to the
161 // *difference vector. Intuitively this can be thought of as "erasing" i from
162 // *this. This will either completely erase *this (leaving nothing behind),
163 // partially erase some of *this from the left or right side (leaving some
164 // residual behind), or erase a hole in the middle of *this (leaving behind an
165 // interval on either side). Therefore, 0, 1, or 2 intervals will be appended
166 // to *difference. The method returns true iff the intersection of *this and i
167 // is non-empty. The caller owns the vector and the Interval* pointers
168 // inside it. The difference vector is required to be non-null.
169 bool Difference(const Interval
& i
, std::vector
<Interval
*>* difference
) const;
171 // Determines the difference between two intervals as in
172 // Difference(Interval&, vector*), but stores the results directly in out
173 // parameters rather than dynamically allocating an Interval* and appending
174 // it to a vector. If two results are generated, the one with the smaller
175 // value of min() will be stored in *lo and the other in *hi. Otherwise (if
176 // fewer than two results are generated), unused arguments will be set to the
177 // empty interval (it is possible that *lo will be empty and *hi non-empty).
178 // The method returns true iff the intersection of *this and i is non-empty.
179 bool Difference(const Interval
& i
, Interval
* lo
, Interval
* hi
) const;
181 friend bool operator==(const Interval
& a
, const Interval
& b
) {
185 return true; // All empties are equal.
187 return false; // Empty cannot equal nonempty.
188 return a
.min() == b
.min() && a
.max() == b
.max();
191 friend bool operator!=(const Interval
& a
, const Interval
& b
) {
195 // Defines a comparator which can be used to induce an order on Intervals, so
196 // that, for example, they can be stored in an ordered container such as
197 // std::set. The ordering is arbitrary, but does provide the guarantee that,
198 // for non-empty intervals X and Y, if X contains Y, then X <= Y.
199 // TODO(kosak): The current implementation of this comparator has a problem
200 // because the ordering it induces is inconsistent with that of Equals(). In
201 // particular, this comparator does not properly consider all empty intervals
202 // equivalent. Bug b/9240050 has been created to track this.
203 friend bool operator<(const Interval
& a
, const Interval
& b
) {
204 return a
.min() < b
.min() || (a
.min() == b
.min() && a
.max() > b
.max());
207 friend std::ostream
& operator<<(std::ostream
& out
, const Interval
& i
) {
208 return out
<< "[" << i
.min() << ", " << i
.max() << ")";
212 T min_
; // Inclusive lower bound.
213 T max_
; // Exclusive upper bound.
216 //==============================================================================
217 // Implementation details: Clients can stop reading here.
219 template <typename T
>
220 bool Interval
<T
>::Intersects(const Interval
& i
, Interval
* out
) const {
223 if (out
!= nullptr) {
224 *out
= Interval(std::max(min(), i
.min()), std::min(max(), i
.max()));
229 template <typename T
>
230 bool Interval
<T
>::IntersectWith(const Interval
& i
) {
233 bool modified
= false;
234 if (i
.min() > min()) {
238 if (i
.max() < max()) {
245 template <typename T
>
246 bool Interval
<T
>::SpanningUnion(const Interval
& i
) {
253 bool modified
= false;
254 if (i
.min() < min()) {
258 if (i
.max() > max()) {
265 template <typename T
>
266 bool Interval
<T
>::Difference(const Interval
& i
,
267 std::vector
<Interval
*>* difference
) const {
269 // <empty> - <i> = <empty>
273 // <this> - <empty> = <this>
274 difference
->push_back(new Interval(*this));
277 if (min() < i
.max() && min() >= i
.min() && max() > i
.max()) {
278 // [------ this ------)
281 difference
->push_back(new Interval(i
.max(), max()));
284 if (max() > i
.min() && max() <= i
.max() && min() < i
.min()) {
285 // [------ this ------)
288 difference
->push_back(new Interval(min(), i
.min()));
291 if (min() < i
.min() && max() > i
.max()) {
292 // [------- this --------)
295 // There are two results: R1 and R2.
296 difference
->push_back(new Interval(min(), i
.min()));
297 difference
->push_back(new Interval(i
.max(), max()));
300 if (min() >= i
.min() && max() <= i
.max()) {
302 // [------ i --------)
303 // Intersection is <this>, so difference yields the empty interval.
304 // Nothing is appended to *difference.
307 // No intersection. Append <this>.
308 difference
->push_back(new Interval(*this));
312 template <typename T
>
313 bool Interval
<T
>::Difference(const Interval
& i
,
315 Interval
* hi
) const {
316 // Initialize *lo and *hi to empty
325 if (min() < i
.max() && min() >= i
.min() && max() > i
.max()) {
326 // [------ this ------)
329 *hi
= Interval(i
.max(), max());
332 if (max() > i
.min() && max() <= i
.max() && min() < i
.min()) {
333 // [------ this ------)
336 *lo
= Interval(min(), i
.min());
339 if (min() < i
.min() && max() > i
.max()) {
340 // [------- this --------)
343 // There are two results: R1 and R2.
344 *lo
= Interval(min(), i
.min());
345 *hi
= Interval(i
.max(), max());
348 if (min() >= i
.min() && max() <= i
.max()) {
350 // [------ i --------)
351 // Intersection is <this>, so difference yields the empty interval.
354 *lo
= *this; // No intersection.
360 #endif // NET_QUIC_INTERVAL_H_