1 // Copyright (c) 2019 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.
4
5 #ifndef QUICHE_QUIC_CORE_QUIC_INTERVAL_SET_H_
6 #define QUICHE_QUIC_CORE_QUIC_INTERVAL_SET_H_
7
8 // QuicIntervalSet<T> is a data structure used to represent a sorted set of
9 // non-empty, non-adjacent, and mutually disjoint intervals. Mutations to an
10 // interval set preserve these properties, altering the set as needed. For
11 // example, adding [2, 3) to a set containing only [1, 2) would result in the
12 // set containing the single interval [1, 3).
13 //
14 // Supported operations include testing whether an Interval is contained in the
15 // QuicIntervalSet, comparing two QuicIntervalSets, and performing
16 // QuicIntervalSet union, intersection, and difference.
17 //
18 // QuicIntervalSet maintains the minimum number of entries needed to represent
19 // the set of underlying intervals. When the QuicIntervalSet is modified (e.g.
20 // due to an Add operation), other interval entries may be coalesced, removed,
21 // or otherwise modified in order to maintain this invariant. The intervals are
22 // maintained in sorted order, by ascending min() value.
23 //
24 // The reader is cautioned to beware of the terminology used here: this library
25 // uses the terms "min" and "max" rather than "begin" and "end" as is
26 // conventional for the STL. The terminology [min, max) refers to the half-open
27 // interval which (if the interval is not empty) contains min but does not
28 // contain max. An interval is considered empty if min >= max.
29 //
30 // T is required to be default- and copy-constructible, to have an assignment
31 // operator, a difference operator (operator-()), and the full complement of
32 // comparison operators (<, <=, ==, !=, >=, >). These requirements are inherited
33 // from value_type.
34 //
35 // QuicIntervalSet has constant-time move operations.
36 //
37 //
38 // Examples:
39 // QuicIntervalSet<int> intervals;
40 // intervals.Add(Interval<int>(10, 20));
41 // intervals.Add(Interval<int>(30, 40));
42 // // intervals contains [10,20) and [30,40).
43 // intervals.Add(Interval<int>(15, 35));
44 // // intervals has been coalesced. It now contains the single range [10,40).
45 // EXPECT_EQ(1, intervals.Size());
46 // EXPECT_TRUE(intervals.Contains(Interval<int>(10, 40)));
47 //
48 // intervals.Difference(Interval<int>(10, 20));
49 // // intervals should now contain the single range [20, 40).
50 // EXPECT_EQ(1, intervals.Size());
51 // EXPECT_TRUE(intervals.Contains(Interval<int>(20, 40)));
52
53 #include <stddef.h>
54
55 #include <algorithm>
56 #include <initializer_list>
57 #include <set>
58 #include <sstream>
59 #include <string>
60 #include <utility>
61 #include <vector>
62
63 #include "quiche/quic/core/quic_interval.h"
64 #include "quiche/quic/platform/api/quic_flags.h"
65 #include "quiche/common/platform/api/quiche_containers.h"
66 #include "quiche/common/platform/api/quiche_logging.h"
67
68 namespace quic {
69
70 template <typename T>
71 class QUICHE_NO_EXPORT QuicIntervalSet {
72 public:
73 using value_type = QuicInterval<T>;
74
75 private:
76 struct QUICHE_NO_EXPORT IntervalLess {
77 using is_transparent = void;
78 bool operator()(const value_type& a, const value_type& b) const;
79 // These transparent overloads are used when we do all of our searches (via
80 // Set::lower_bound() and Set::upper_bound()), which avoids the need to
81 // construct an interval when we are looking for a point and also avoids
82 // needing to worry about comparing overlapping intervals in the overload
83 // that takes two value_types (the one just above this comment).
84 bool operator()(const value_type& a, const T& point) const;
85 bool operator()(const value_type& a, T&& point) const;
86 bool operator()(const T& point, const value_type& a) const;
87 bool operator()(T&& point, const value_type& a) const;
88 };
89
90 using Set = quiche::QuicheSmallOrderedSet<value_type, IntervalLess>;
91
92 public:
93 using const_iterator = typename Set::const_iterator;
94 using const_reverse_iterator = typename Set::const_reverse_iterator;
95
96 // Instantiates an empty QuicIntervalSet.
97 QuicIntervalSet() = default;
98
99 // Instantiates a QuicIntervalSet containing exactly one initial half-open
100 // interval [min, max), unless the given interval is empty, in which case the
101 // QuicIntervalSet will be empty.
QuicIntervalSet(const value_type & interval)102 explicit QuicIntervalSet(const value_type& interval) { Add(interval); }
103
104 // Instantiates a QuicIntervalSet containing the half-open interval [min,
105 // max).
QuicIntervalSet(const T & min,const T & max)106 QuicIntervalSet(const T& min, const T& max) { Add(min, max); }
107
QuicIntervalSet(std::initializer_list<value_type> il)108 QuicIntervalSet(std::initializer_list<value_type> il) { assign(il); }
109
110 // Clears this QuicIntervalSet.
Clear()111 void Clear() { intervals_.clear(); }
112
113 // Returns the number of disjoint intervals contained in this QuicIntervalSet.
Size()114 size_t Size() const { return intervals_.size(); }
115
116 // Returns the smallest interval that contains all intervals in this
117 // QuicIntervalSet, or the empty interval if the set is empty.
118 value_type SpanningInterval() const;
119
120 // Adds "interval" to this QuicIntervalSet. Adding the empty interval has no
121 // effect.
122 void Add(const value_type& interval);
123
124 // Adds the interval [min, max) to this QuicIntervalSet. Adding the empty
125 // interval has no effect.
Add(const T & min,const T & max)126 void Add(const T& min, const T& max) { Add(value_type(min, max)); }
127
128 // Same semantics as Add(const value_type&), but optimized for the case where
129 // rbegin()->min() <= |interval|.min() <= rbegin()->max().
AddOptimizedForAppend(const value_type & interval)130 void AddOptimizedForAppend(const value_type& interval) {
131 if (Empty() || !GetQuicFlag(quic_interval_set_enable_add_optimization)) {
132 Add(interval);
133 return;
134 }
135
136 const_reverse_iterator last_interval = intervals_.rbegin();
137
138 // If interval.min() is outside of [last_interval->min, last_interval->max],
139 // we can not simply extend last_interval->max.
140 if (interval.min() < last_interval->min() ||
141 interval.min() > last_interval->max()) {
142 Add(interval);
143 return;
144 }
145
146 if (interval.max() <= last_interval->max()) {
147 // interval is fully contained by last_interval.
148 return;
149 }
150
151 // Extend last_interval.max to interval.max, in place.
152 //
153 // Set does not allow in-place updates due to the potential of violating its
154 // ordering requirements. But we know setting the max of the last interval
155 // is safe w.r.t set ordering and other invariants of QuicIntervalSet, so we
156 // force an in-place update for performance.
157 const_cast<value_type*>(&(*last_interval))->SetMax(interval.max());
158 }
159
160 // Same semantics as Add(const T&, const T&), but optimized for the case where
161 // rbegin()->max() == |min|.
AddOptimizedForAppend(const T & min,const T & max)162 void AddOptimizedForAppend(const T& min, const T& max) {
163 AddOptimizedForAppend(value_type(min, max));
164 }
165
166 // TODO(wub): Similar to AddOptimizedForAppend, we can also have a
167 // AddOptimizedForPrepend if there is a use case.
168
169 // Remove the first interval.
170 // REQUIRES: !Empty()
PopFront()171 void PopFront() {
172 QUICHE_DCHECK(!Empty());
173 intervals_.erase(intervals_.begin());
174 }
175
176 // Trim all values that are smaller than |value|. Which means
177 // a) If all values in an interval is smaller than |value|, the entire
178 // interval is removed.
179 // b) If some but not all values in an interval is smaller than |value|, the
180 // min of that interval is raised to |value|.
181 // Returns true if some intervals are trimmed.
TrimLessThan(const T & value)182 bool TrimLessThan(const T& value) {
183 // Number of intervals that are fully or partially trimmed.
184 size_t num_intervals_trimmed = 0;
185
186 while (!intervals_.empty()) {
187 const_iterator first_interval = intervals_.begin();
188 if (first_interval->min() >= value) {
189 break;
190 }
191
192 ++num_intervals_trimmed;
193
194 if (first_interval->max() <= value) {
195 // a) Trim the entire interval.
196 intervals_.erase(first_interval);
197 continue;
198 }
199
200 // b) Trim a prefix of the interval.
201 //
202 // Set does not allow in-place updates due to the potential of violating
203 // its ordering requirements. But increasing the min of the first interval
204 // will not break the ordering, hence the const_cast.
205 const_cast<value_type*>(&(*first_interval))->SetMin(value);
206 break;
207 }
208
209 return num_intervals_trimmed != 0;
210 }
211
212 // Returns true if this QuicIntervalSet is empty.
Empty()213 bool Empty() const { return intervals_.empty(); }
214
215 // Returns true if any interval in this QuicIntervalSet contains the indicated
216 // value.
217 bool Contains(const T& value) const;
218
219 // Returns true if there is some interval in this QuicIntervalSet that wholly
220 // contains the given interval. An interval O "wholly contains" a non-empty
221 // interval I if O.Contains(p) is true for every p in I. This is the same
222 // definition used by value_type::Contains(). This method returns false on
223 // the empty interval, due to a (perhaps unintuitive) convention inherited
224 // from value_type.
225 // Example:
226 // Assume an QuicIntervalSet containing the entries { [10,20), [30,40) }.
227 // Contains(Interval(15, 16)) returns true, because [10,20) contains
228 // [15,16). However, Contains(Interval(15, 35)) returns false.
229 bool Contains(const value_type& interval) const;
230
231 // Returns true if for each interval in "other", there is some (possibly
232 // different) interval in this QuicIntervalSet which wholly contains it. See
233 // Contains(const value_type& interval) for the meaning of "wholly contains".
234 // Perhaps unintuitively, this method returns false if "other" is the empty
235 // set. The algorithmic complexity of this method is O(other.Size() *
236 // log(this->Size())). The method could be rewritten to run in O(other.Size()
237 // + this->Size()), and this alternative could be implemented as a free
238 // function using the public API.
239 bool Contains(const QuicIntervalSet<T>& other) const;
240
241 // Returns true if there is some interval in this QuicIntervalSet that wholly
242 // contains the interval [min, max). See Contains(const value_type&).
Contains(const T & min,const T & max)243 bool Contains(const T& min, const T& max) const {
244 return Contains(value_type(min, max));
245 }
246
247 // Returns true if for some interval in "other", there is some interval in
248 // this QuicIntervalSet that intersects with it. See value_type::Intersects()
249 // for the definition of interval intersection. Runs in time O(n+m) where n
250 // is the number of intervals in this and m is the number of intervals in
251 // other.
252 bool Intersects(const QuicIntervalSet& other) const;
253
254 // Returns an iterator to the value_type in the QuicIntervalSet that contains
255 // the given value. In other words, returns an iterator to the unique interval
256 // [min, max) in the QuicIntervalSet that has the property min <= value < max.
257 // If there is no such interval, this method returns end().
258 const_iterator Find(const T& value) const;
259
260 // Returns an iterator to the value_type in the QuicIntervalSet that wholly
261 // contains the given interval. In other words, returns an iterator to the
262 // unique interval outer in the QuicIntervalSet that has the property that
263 // outer.Contains(interval). If there is no such interval, or if interval is
264 // empty, returns end().
265 const_iterator Find(const value_type& interval) const;
266
267 // Returns an iterator to the value_type in the QuicIntervalSet that wholly
268 // contains [min, max). In other words, returns an iterator to the unique
269 // interval outer in the QuicIntervalSet that has the property that
270 // outer.Contains(Interval<T>(min, max)). If there is no such interval, or if
271 // interval is empty, returns end().
Find(const T & min,const T & max)272 const_iterator Find(const T& min, const T& max) const {
273 return Find(value_type(min, max));
274 }
275
276 // Returns an iterator pointing to the first value_type which contains or
277 // goes after the given value.
278 //
279 // Example:
280 // [10, 20) [30, 40)
281 // ^ LowerBound(10)
282 // ^ LowerBound(15)
283 // ^ LowerBound(20)
284 // ^ LowerBound(25)
285 const_iterator LowerBound(const T& value) const;
286
287 // Returns an iterator pointing to the first value_type which goes after
288 // the given value.
289 //
290 // Example:
291 // [10, 20) [30, 40)
292 // ^ UpperBound(10)
293 // ^ UpperBound(15)
294 // ^ UpperBound(20)
295 // ^ UpperBound(25)
296 const_iterator UpperBound(const T& value) const;
297
298 // Returns true if every value within the passed interval is not Contained
299 // within the QuicIntervalSet.
300 // Note that empty intervals are always considered disjoint from the
301 // QuicIntervalSet (even though the QuicIntervalSet doesn't `Contain` them).
302 bool IsDisjoint(const value_type& interval) const;
303
304 // Merges all the values contained in "other" into this QuicIntervalSet.
305 //
306 // Performance: Let n == Size() and m = other.Size(). Union() runs in O(m)
307 // Set operations, so that if Set is a tree, it runs in time O(m log(n+m)) and
308 // if Set is a flat_set it runs in time O(m(n+m)). In principle, for the
309 // flat_set, we should be able to make this run in time O(n+m).
310 //
311 // TODO(bradleybear): Make Union() run in time O(n+m) for flat_set. This may
312 // require an additional template parameter to indicate that the Set is a
313 // linear-time data structure instead of a log-time data structure.
314 void Union(const QuicIntervalSet& other);
315
316 // Modifies this QuicIntervalSet so that it contains only those values that
317 // are currently present both in *this and in the QuicIntervalSet "other".
318 void Intersection(const QuicIntervalSet& other);
319
320 // Mutates this QuicIntervalSet so that it contains only those values that are
321 // currently in *this but not in "interval".
322 void Difference(const value_type& interval);
323
324 // Mutates this QuicIntervalSet so that it contains only those values that are
325 // currently in *this but not in the interval [min, max).
326 void Difference(const T& min, const T& max);
327
328 // Mutates this QuicIntervalSet so that it contains only those values that are
329 // currently in *this but not in the QuicIntervalSet "other". Runs in time
330 // O(n+m) where n is this->Size(), m is other.Size(), regardless of whether
331 // the Set is a flat_set or a std::set.
332 void Difference(const QuicIntervalSet& other);
333
334 // Mutates this QuicIntervalSet so that it contains only those values that are
335 // in [min, max) but not currently in *this.
336 void Complement(const T& min, const T& max);
337
338 // QuicIntervalSet's begin() iterator. The invariants of QuicIntervalSet
339 // guarantee that for each entry e in the set, e.min() < e.max() (because the
340 // entries are non-empty) and for each entry f that appears later in the set,
341 // e.max() < f.min() (because the entries are ordered, pairwise-disjoint, and
342 // non-adjacent). Modifications to this QuicIntervalSet invalidate these
343 // iterators.
begin()344 const_iterator begin() const { return intervals_.begin(); }
345
346 // QuicIntervalSet's end() iterator.
end()347 const_iterator end() const { return intervals_.end(); }
348
349 // QuicIntervalSet's rbegin() and rend() iterators. Iterator invalidation
350 // semantics are the same as those for begin() / end().
rbegin()351 const_reverse_iterator rbegin() const { return intervals_.rbegin(); }
352
rend()353 const_reverse_iterator rend() const { return intervals_.rend(); }
354
355 template <typename Iter>
assign(Iter first,Iter last)356 void assign(Iter first, Iter last) {
357 Clear();
358 for (; first != last; ++first) Add(*first);
359 }
360
assign(std::initializer_list<value_type> il)361 void assign(std::initializer_list<value_type> il) {
362 assign(il.begin(), il.end());
363 }
364
365 // Returns a human-readable representation of this set. This will typically be
366 // (though is not guaranteed to be) of the form
367 // "[a1, b1) [a2, b2) ... [an, bn)"
368 // where the intervals are in the same order as given by traversal from
369 // begin() to end(). This representation is intended for human consumption;
370 // computer programs should not rely on the output being in exactly this form.
371 std::string ToString() const;
372
373 QuicIntervalSet& operator=(std::initializer_list<value_type> il) {
374 assign(il.begin(), il.end());
375 return *this;
376 }
377
378 friend bool operator==(const QuicIntervalSet& a, const QuicIntervalSet& b) {
379 return a.Size() == b.Size() &&
380 std::equal(a.begin(), a.end(), b.begin(), NonemptyIntervalEq());
381 }
382
383 friend bool operator!=(const QuicIntervalSet& a, const QuicIntervalSet& b) {
384 return !(a == b);
385 }
386
387 private:
388 // Simple member-wise equality, since all intervals are non-empty.
389 struct QUICHE_NO_EXPORT NonemptyIntervalEq {
operatorNonemptyIntervalEq390 bool operator()(const value_type& a, const value_type& b) const {
391 return a.min() == b.min() && a.max() == b.max();
392 }
393 };
394
395 // Returns true if this set is valid (i.e. all intervals in it are non-empty,
396 // non-adjacent, and mutually disjoint). Currently this is used as an
397 // integrity check by the Intersection() and Difference() methods, but is only
398 // invoked for debug builds (via QUICHE_DCHECK).
399 bool Valid() const;
400
401 // Finds the first interval that potentially intersects 'other'.
402 const_iterator FindIntersectionCandidate(const QuicIntervalSet& other) const;
403
404 // Finds the first interval that potentially intersects 'interval'. More
405 // precisely, return an interator it pointing at the last interval J such that
406 // interval <= J. If all the intervals are > J then return begin().
407 const_iterator FindIntersectionCandidate(const value_type& interval) const;
408
409 // Helper for Intersection() and Difference(): Finds the next pair of
410 // intervals from 'x' and 'y' that intersect. 'mine' is an iterator
411 // over x->intervals_. 'theirs' is an iterator over y.intervals_. 'mine'
412 // and 'theirs' are advanced until an intersecting pair is found.
413 // Non-intersecting intervals (aka "holes") from x->intervals_ can be
414 // optionally erased by "on_hole". "on_hole" must return an iterator to the
415 // first element in 'x' after the hole, or x->intervals_.end() if no elements
416 // exist after the hole.
417 template <typename X, typename Func>
418 static bool FindNextIntersectingPairImpl(X* x, const QuicIntervalSet& y,
419 const_iterator* mine,
420 const_iterator* theirs,
421 Func on_hole);
422
423 // The variant of the above method that doesn't mutate this QuicIntervalSet.
FindNextIntersectingPair(const QuicIntervalSet & other,const_iterator * mine,const_iterator * theirs)424 bool FindNextIntersectingPair(const QuicIntervalSet& other,
425 const_iterator* mine,
426 const_iterator* theirs) const {
427 return FindNextIntersectingPairImpl(
428 this, other, mine, theirs,
429 [](const QuicIntervalSet*, const_iterator, const_iterator end) {
430 return end;
431 });
432 }
433
434 // The variant of the above method that mutates this QuicIntervalSet by
435 // erasing holes.
FindNextIntersectingPairAndEraseHoles(const QuicIntervalSet & other,const_iterator * mine,const_iterator * theirs)436 bool FindNextIntersectingPairAndEraseHoles(const QuicIntervalSet& other,
437 const_iterator* mine,
438 const_iterator* theirs) {
439 return FindNextIntersectingPairImpl(
440 this, other, mine, theirs,
441 [](QuicIntervalSet* x, const_iterator from, const_iterator to) {
442 return x->intervals_.erase(from, to);
443 });
444 }
445
446 // The representation for the intervals. The intervals in this set are
447 // non-empty, pairwise-disjoint, non-adjacent and ordered in ascending order
448 // by min().
449 Set intervals_;
450 };
451
452 template <typename T>
453 auto operator<<(std::ostream& out, const QuicIntervalSet<T>& seq)
454 -> decltype(out << *seq.begin()) {
455 out << "{";
456 for (const auto& interval : seq) {
457 out << " " << interval;
458 }
459 out << " }";
460
461 return out;
462 }
463
464 //==============================================================================
465 // Implementation details: Clients can stop reading here.
466
467 template <typename T>
SpanningInterval()468 typename QuicIntervalSet<T>::value_type QuicIntervalSet<T>::SpanningInterval()
469 const {
470 value_type result;
471 if (!intervals_.empty()) {
472 result.SetMin(intervals_.begin()->min());
473 result.SetMax(intervals_.rbegin()->max());
474 }
475 return result;
476 }
477
478 template <typename T>
Add(const value_type & interval)479 void QuicIntervalSet<T>::Add(const value_type& interval) {
480 if (interval.Empty()) return;
481 const_iterator it = intervals_.lower_bound(interval.min());
482 value_type the_union = interval;
483 if (it != intervals_.begin()) {
484 --it;
485 if (it->Separated(the_union)) {
486 ++it;
487 }
488 }
489 // Don't erase the elements one at a time, since that will produce quadratic
490 // work on a flat_set, and apparently an extra log-factor of work for a
491 // tree-based set. Instead identify the first and last intervals that need to
492 // be erased, and call erase only once.
493 const_iterator start = it;
494 while (it != intervals_.end() && !it->Separated(the_union)) {
495 the_union.SpanningUnion(*it);
496 ++it;
497 }
498 intervals_.erase(start, it);
499 intervals_.insert(the_union);
500 }
501
502 template <typename T>
Contains(const T & value)503 bool QuicIntervalSet<T>::Contains(const T& value) const {
504 // Find the first interval with min() > value, then move back one step
505 const_iterator it = intervals_.upper_bound(value);
506 if (it == intervals_.begin()) return false;
507 --it;
508 return it->Contains(value);
509 }
510
511 template <typename T>
Contains(const value_type & interval)512 bool QuicIntervalSet<T>::Contains(const value_type& interval) const {
513 // Find the first interval with min() > value, then move back one step.
514 const_iterator it = intervals_.upper_bound(interval.min());
515 if (it == intervals_.begin()) return false;
516 --it;
517 return it->Contains(interval);
518 }
519
520 template <typename T>
Contains(const QuicIntervalSet<T> & other)521 bool QuicIntervalSet<T>::Contains(const QuicIntervalSet<T>& other) const {
522 if (!SpanningInterval().Contains(other.SpanningInterval())) {
523 return false;
524 }
525
526 for (const_iterator i = other.begin(); i != other.end(); ++i) {
527 // If we don't contain the interval, can return false now.
528 if (!Contains(*i)) {
529 return false;
530 }
531 }
532 return true;
533 }
534
535 // This method finds the interval that Contains() "value", if such an interval
536 // exists in the QuicIntervalSet. The way this is done is to locate the
537 // "candidate interval", the only interval that could *possibly* contain value,
538 // and test it using Contains(). The candidate interval is the interval with the
539 // largest min() having min() <= value.
540 //
541 // Another detail involves the choice of which Set method to use to try to find
542 // the candidate interval. The most appropriate entry point is
543 // Set::upper_bound(), which finds the least interval with a min > the
544 // value. The semantics of upper_bound() are slightly different from what we
545 // want (namely, to find the greatest interval which is <= the probe interval)
546 // but they are close enough; the interval found by upper_bound() will always be
547 // one step past the interval we are looking for (if it exists) or at begin()
548 // (if it does not). Getting to the proper interval is a simple matter of
549 // decrementing the iterator.
550 template <typename T>
Find(const T & value)551 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::Find(
552 const T& value) const {
553 const_iterator it = intervals_.upper_bound(value);
554 if (it == intervals_.begin()) return intervals_.end();
555 --it;
556 if (it->Contains(value))
557 return it;
558 else
559 return intervals_.end();
560 }
561
562 // This method finds the interval that Contains() the interval "probe", if such
563 // an interval exists in the QuicIntervalSet. The way this is done is to locate
564 // the "candidate interval", the only interval that could *possibly* contain
565 // "probe", and test it using Contains(). We use the same algorithm as for
566 // Find(value), except that instead of checking that the value is contained, we
567 // check that the probe is contained.
568 template <typename T>
Find(const value_type & probe)569 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::Find(
570 const value_type& probe) const {
571 const_iterator it = intervals_.upper_bound(probe.min());
572 if (it == intervals_.begin()) return intervals_.end();
573 --it;
574 if (it->Contains(probe))
575 return it;
576 else
577 return intervals_.end();
578 }
579
580 template <typename T>
LowerBound(const T & value)581 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::LowerBound(
582 const T& value) const {
583 const_iterator it = intervals_.lower_bound(value);
584 if (it == intervals_.begin()) {
585 return it;
586 }
587
588 // The previous intervals_.lower_bound() checking is essentially based on
589 // interval.min(), so we need to check whether the `value` is contained in
590 // the previous interval.
591 --it;
592 if (it->Contains(value)) {
593 return it;
594 } else {
595 return ++it;
596 }
597 }
598
599 template <typename T>
UpperBound(const T & value)600 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::UpperBound(
601 const T& value) const {
602 return intervals_.upper_bound(value);
603 }
604
605 template <typename T>
IsDisjoint(const value_type & interval)606 bool QuicIntervalSet<T>::IsDisjoint(const value_type& interval) const {
607 if (interval.Empty()) return true;
608 // Find the first interval with min() > interval.min()
609 const_iterator it = intervals_.upper_bound(interval.min());
610 if (it != intervals_.end() && interval.max() > it->min()) return false;
611 if (it == intervals_.begin()) return true;
612 --it;
613 return it->max() <= interval.min();
614 }
615
616 template <typename T>
Union(const QuicIntervalSet & other)617 void QuicIntervalSet<T>::Union(const QuicIntervalSet& other) {
618 for (const value_type& interval : other.intervals_) {
619 Add(interval);
620 }
621 }
622
623 template <typename T>
624 typename QuicIntervalSet<T>::const_iterator
FindIntersectionCandidate(const QuicIntervalSet & other)625 QuicIntervalSet<T>::FindIntersectionCandidate(
626 const QuicIntervalSet& other) const {
627 return FindIntersectionCandidate(*other.intervals_.begin());
628 }
629
630 template <typename T>
631 typename QuicIntervalSet<T>::const_iterator
FindIntersectionCandidate(const value_type & interval)632 QuicIntervalSet<T>::FindIntersectionCandidate(
633 const value_type& interval) const {
634 // Use upper_bound to efficiently find the first interval in intervals_
635 // where min() is greater than interval.min(). If the result
636 // isn't the beginning of intervals_ then move backwards one interval since
637 // the interval before it is the first candidate where max() may be
638 // greater than interval.min().
639 // In other words, no interval before that can possibly intersect with any
640 // of other.intervals_.
641 const_iterator mine = intervals_.upper_bound(interval.min());
642 if (mine != intervals_.begin()) {
643 --mine;
644 }
645 return mine;
646 }
647
648 template <typename T>
649 template <typename X, typename Func>
FindNextIntersectingPairImpl(X * x,const QuicIntervalSet & y,const_iterator * mine,const_iterator * theirs,Func on_hole)650 bool QuicIntervalSet<T>::FindNextIntersectingPairImpl(X* x,
651 const QuicIntervalSet& y,
652 const_iterator* mine,
653 const_iterator* theirs,
654 Func on_hole) {
655 QUICHE_CHECK(x != nullptr);
656 if ((*mine == x->intervals_.end()) || (*theirs == y.intervals_.end())) {
657 return false;
658 }
659 while (!(**mine).Intersects(**theirs)) {
660 const_iterator erase_first = *mine;
661 // Skip over intervals in 'mine' that don't reach 'theirs'.
662 while (*mine != x->intervals_.end() && (**mine).max() <= (**theirs).min()) {
663 ++(*mine);
664 }
665 *mine = on_hole(x, erase_first, *mine);
666 // We're done if the end of intervals_ is reached.
667 if (*mine == x->intervals_.end()) {
668 return false;
669 }
670 // Skip over intervals 'theirs' that don't reach 'mine'.
671 while (*theirs != y.intervals_.end() &&
672 (**theirs).max() <= (**mine).min()) {
673 ++(*theirs);
674 }
675 // If the end of other.intervals_ is reached, we're done.
676 if (*theirs == y.intervals_.end()) {
677 on_hole(x, *mine, x->intervals_.end());
678 return false;
679 }
680 }
681 return true;
682 }
683
684 template <typename T>
Intersection(const QuicIntervalSet & other)685 void QuicIntervalSet<T>::Intersection(const QuicIntervalSet& other) {
686 if (!SpanningInterval().Intersects(other.SpanningInterval())) {
687 intervals_.clear();
688 return;
689 }
690
691 const_iterator mine = FindIntersectionCandidate(other);
692 // Remove any intervals that cannot possibly intersect with other.intervals_.
693 mine = intervals_.erase(intervals_.begin(), mine);
694 const_iterator theirs = other.FindIntersectionCandidate(*this);
695
696 while (FindNextIntersectingPairAndEraseHoles(other, &mine, &theirs)) {
697 // OK, *mine and *theirs intersect. Now, we find the largest
698 // span of intervals in other (starting at theirs) - say [a..b]
699 // - that intersect *mine, and we replace *mine with (*mine
700 // intersect x) for all x in [a..b] Note that subsequent
701 // intervals in this can't intersect any intervals in [a..b) --
702 // they may only intersect b or subsequent intervals in other.
703 value_type i(*mine);
704 intervals_.erase(mine);
705 mine = intervals_.end();
706 value_type intersection;
707 while (theirs != other.intervals_.end() &&
708 i.Intersects(*theirs, &intersection)) {
709 std::pair<const_iterator, bool> ins = intervals_.insert(intersection);
710 QUICHE_DCHECK(ins.second);
711 mine = ins.first;
712 ++theirs;
713 }
714 QUICHE_DCHECK(mine != intervals_.end());
715 --theirs;
716 ++mine;
717 }
718 QUICHE_DCHECK(Valid());
719 }
720
721 template <typename T>
Intersects(const QuicIntervalSet & other)722 bool QuicIntervalSet<T>::Intersects(const QuicIntervalSet& other) const {
723 // Don't bother to handle nonoverlapping spanning intervals as a special case.
724 // This code runs in time O(n+m), as guaranteed, even for that case .
725 // Handling the nonoverlapping spanning intervals as a special case doesn't
726 // improve the asymptotics but does make the code more complex.
727 auto mine = intervals_.begin();
728 auto theirs = other.intervals_.begin();
729 while (mine != intervals_.end() && theirs != other.intervals_.end()) {
730 if (mine->Intersects(*theirs))
731 return true;
732 else if (*mine < *theirs)
733 ++mine;
734 else
735 ++theirs;
736 }
737 return false;
738 }
739
740 template <typename T>
Difference(const value_type & interval)741 void QuicIntervalSet<T>::Difference(const value_type& interval) {
742 if (!SpanningInterval().Intersects(interval)) {
743 return;
744 }
745 Difference(QuicIntervalSet<T>(interval));
746 }
747
748 template <typename T>
Difference(const T & min,const T & max)749 void QuicIntervalSet<T>::Difference(const T& min, const T& max) {
750 Difference(value_type(min, max));
751 }
752
753 template <typename T>
Difference(const QuicIntervalSet & other)754 void QuicIntervalSet<T>::Difference(const QuicIntervalSet& other) {
755 // In order to avoid quadratic-time when using a flat set, we don't try to
756 // update intervals_ in place. Instead we build up a new result_, always
757 // inserting at the end which is O(1) time per insertion. Since the number of
758 // elements in the result is O(Size() + other.Size()), the cost for all the
759 // insertions is also O(Size() + other.Size()).
760 //
761 // We look at all the elements of intervals_, so that's O(Size()).
762 //
763 // We also look at all the elements of other.intervals_, for O(other.Size()).
764 if (Empty()) return;
765 Set result;
766 const_iterator mine = intervals_.begin();
767 value_type myinterval = *mine;
768 const_iterator theirs = other.intervals_.begin();
769 while (mine != intervals_.end()) {
770 // Loop invariants:
771 // myinterval is nonempty.
772 // mine points at a range that is a suffix of myinterval.
773 QUICHE_DCHECK(!myinterval.Empty());
774 QUICHE_DCHECK(myinterval.max() == mine->max());
775
776 // There are 3 cases.
777 // myinterval is completely before theirs (treat theirs==end() as if it is
778 // infinity).
779 // --> consume myinterval into result.
780 // myinterval is completely after theirs
781 // --> theirs can no longer affect us, so ++theirs.
782 // myinterval touches theirs with a prefix of myinterval not touching
783 // *theirs.
784 // --> consume the prefix of myinterval into the result.
785 // myinterval touches theirs, with the first element of myinterval in
786 // *theirs.
787 // -> reduce myinterval
788 if (theirs == other.intervals_.end() || myinterval.max() <= theirs->min()) {
789 // Keep all of my_interval.
790 result.insert(result.end(), myinterval);
791 myinterval.Clear();
792 } else if (theirs->max() <= myinterval.min()) {
793 ++theirs;
794 } else if (myinterval.min() < theirs->min()) {
795 // Keep a nonempty prefix of my interval.
796 result.insert(result.end(), value_type(myinterval.min(), theirs->min()));
797 myinterval.SetMin(theirs->max());
798 } else {
799 // myinterval starts at or after *theirs, chop down myinterval.
800 myinterval.SetMin(theirs->max());
801 }
802 // if myinterval became empty, find the next interval
803 if (myinterval.Empty()) {
804 ++mine;
805 if (mine != intervals_.end()) {
806 myinterval = *mine;
807 }
808 }
809 }
810 std::swap(result, intervals_);
811 QUICHE_DCHECK(Valid());
812 }
813
814 template <typename T>
Complement(const T & min,const T & max)815 void QuicIntervalSet<T>::Complement(const T& min, const T& max) {
816 QuicIntervalSet<T> span(min, max);
817 span.Difference(*this);
818 intervals_.swap(span.intervals_);
819 }
820
821 template <typename T>
ToString()822 std::string QuicIntervalSet<T>::ToString() const {
823 std::ostringstream os;
824 os << *this;
825 return os.str();
826 }
827
828 template <typename T>
Valid()829 bool QuicIntervalSet<T>::Valid() const {
830 const_iterator prev = end();
831 for (const_iterator it = begin(); it != end(); ++it) {
832 // invalid or empty interval.
833 if (it->min() >= it->max()) return false;
834 // Not sorted, not disjoint, or adjacent.
835 if (prev != end() && prev->max() >= it->min()) return false;
836 prev = it;
837 }
838 return true;
839 }
840
841 // This comparator orders intervals first by ascending min(). The Set never
842 // contains overlapping intervals, so that suffices.
843 template <typename T>
operator()844 bool QuicIntervalSet<T>::IntervalLess::operator()(const value_type& a,
845 const value_type& b) const {
846 // This overload is probably used only by Set::insert().
847 return a.min() < b.min();
848 }
849
850 // It appears that the Set::lower_bound(T) method uses only two overloads of the
851 // comparison operator that take a T as the second argument.. In contrast
852 // Set::upper_bound(T) uses the two overloads that take T as the first argument.
853 template <typename T>
operator()854 bool QuicIntervalSet<T>::IntervalLess::operator()(const value_type& a,
855 const T& point) const {
856 // Compare an interval to a point.
857 return a.min() < point;
858 }
859
860 template <typename T>
operator()861 bool QuicIntervalSet<T>::IntervalLess::operator()(const value_type& a,
862 T&& point) const {
863 // Compare an interval to a point
864 return a.min() < point;
865 }
866
867 // It appears that the Set::upper_bound(T) method uses only the next two
868 // overloads of the comparison operator.
869 template <typename T>
operator()870 bool QuicIntervalSet<T>::IntervalLess::operator()(const T& point,
871 const value_type& a) const {
872 // Compare an interval to a point.
873 return point < a.min();
874 }
875
876 template <typename T>
operator()877 bool QuicIntervalSet<T>::IntervalLess::operator()(T&& point,
878 const value_type& a) const {
879 // Compare an interval to a point.
880 return point < a.min();
881 }
882
883 } // namespace quic
884
885 #endif // QUICHE_QUIC_CORE_QUIC_INTERVAL_SET_H_
886