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 #include <algorithm>
55 #include <initializer_list>
56 #include <set>
57 #include <utility>
58 #include <vector>
59 
60 #include <string>
61 
62 #include "net/third_party/quiche/src/quic/core/quic_interval.h"
63 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
64 
65 namespace quic {
66 
67 template <typename T>
68 class QUIC_NO_EXPORT QuicIntervalSet {
69  public:
70   using value_type = QuicInterval<T>;
71 
72  private:
73   struct QUIC_NO_EXPORT IntervalLess {
74     bool operator()(const value_type& a, const value_type& b) const;
75   };
76   // TODO(wub): Switch to absl::btree_set when it is available in Chromium.
77   using Set = std::set<value_type, IntervalLess>;
78 
79  public:
80   using const_iterator = typename Set::const_iterator;
81   using const_reverse_iterator = typename Set::const_reverse_iterator;
82 
83   // Instantiates an empty QuicIntervalSet.
QuicIntervalSet()84   QuicIntervalSet() {}
85 
86   // Instantiates an QuicIntervalSet containing exactly one initial half-open
87   // interval [min, max), unless the given interval is empty, in which case the
88   // QuicIntervalSet will be empty.
QuicIntervalSet(const value_type & interval)89   explicit QuicIntervalSet(const value_type& interval) { Add(interval); }
90 
91   // Instantiates an QuicIntervalSet containing the half-open interval [min,
92   // max).
QuicIntervalSet(const T & min,const T & max)93   QuicIntervalSet(const T& min, const T& max) { Add(min, max); }
94 
QuicIntervalSet(std::initializer_list<value_type> il)95   QuicIntervalSet(std::initializer_list<value_type> il) { assign(il); }
96 
97   // Clears this QuicIntervalSet.
Clear()98   void Clear() { intervals_.clear(); }
99 
100   // Returns the number of disjoint intervals contained in this QuicIntervalSet.
Size()101   size_t Size() const { return intervals_.size(); }
102 
103   // Returns the smallest interval that contains all intervals in this
104   // QuicIntervalSet, or the empty interval if the set is empty.
105   value_type SpanningInterval() const;
106 
107   // Adds "interval" to this QuicIntervalSet. Adding the empty interval has no
108   // effect.
109   void Add(const value_type& interval);
110 
111   // Adds the interval [min, max) to this QuicIntervalSet. Adding the empty
112   // interval has no effect.
Add(const T & min,const T & max)113   void Add(const T& min, const T& max) { Add(value_type(min, max)); }
114 
115   // Same semantics as Add(const value_type&), but optimized for the case where
116   // rbegin()->min() <= |interval|.min() <= rbegin()->max().
AddOptimizedForAppend(const value_type & interval)117   void AddOptimizedForAppend(const value_type& interval) {
118     if (Empty()) {
119       Add(interval);
120       return;
121     }
122 
123     const_reverse_iterator last_interval = intervals_.rbegin();
124 
125     // If interval.min() is outside of [last_interval->min, last_interval->max],
126     // we can not simply extend last_interval->max.
127     if (interval.min() < last_interval->min() ||
128         interval.min() > last_interval->max()) {
129       Add(interval);
130       return;
131     }
132 
133     if (interval.max() <= last_interval->max()) {
134       // interval is fully contained by last_interval.
135       return;
136     }
137 
138     // Extend last_interval.max to interval.max, in place.
139     //
140     // Set does not allow in-place updates due to the potential of violating its
141     // ordering requirements. But we know setting the max of the last interval
142     // is safe w.r.t set ordering and other invariants of QuicIntervalSet, so we
143     // force an in-place update for performance.
144     const_cast<value_type*>(&(*last_interval))->SetMax(interval.max());
145   }
146 
147   // Same semantics as Add(const T&, const T&), but optimized for the case where
148   // rbegin()->max() == |min|.
AddOptimizedForAppend(const T & min,const T & max)149   void AddOptimizedForAppend(const T& min, const T& max) {
150     AddOptimizedForAppend(value_type(min, max));
151   }
152 
153   // TODO(wub): Similar to AddOptimizedForAppend, we can also have a
154   // AddOptimizedForPrepend if there is a use case.
155 
156   // Remove the first interval.
157   // REQUIRES: !Empty()
PopFront()158   void PopFront() {
159     DCHECK(!Empty());
160     intervals_.erase(intervals_.begin());
161   }
162 
163   // Trim all values that is smaller than |value|. Which means
164   // a) If all values in an interval is smaller than |value|, the entire
165   //    interval is removed.
166   // b) If some but not all values in an interval is smaller than |value|, the
167   //    min of that interval is raised to |value|.
168   // Returns true if some intervals are trimmed.
TrimLessThan(const T & value)169   bool TrimLessThan(const T& value) {
170     // Number of intervals that are fully or partially trimmed.
171     size_t num_intervals_trimmed = 0;
172 
173     while (!intervals_.empty()) {
174       const_iterator first_interval = intervals_.begin();
175       if (first_interval->min() >= value) {
176         break;
177       }
178 
179       ++num_intervals_trimmed;
180 
181       if (first_interval->max() <= value) {
182         // a) Trim the entire interval.
183         intervals_.erase(first_interval);
184         continue;
185       }
186 
187       // b) Trim a prefix of the interval.
188       //
189       // Set does not allow in-place updates due to the potential of violating
190       // its ordering requirements. But increasing the min of the first interval
191       // will not break the ordering, hence the const_cast.
192       const_cast<value_type*>(&(*first_interval))->SetMin(value);
193       break;
194     }
195 
196     return num_intervals_trimmed != 0;
197   }
198 
199   // Returns true if this QuicIntervalSet is empty.
Empty()200   bool Empty() const { return intervals_.empty(); }
201 
202   // Returns true if any interval in this QuicIntervalSet contains the indicated
203   // value.
204   bool Contains(const T& value) const;
205 
206   // Returns true if there is some interval in this QuicIntervalSet that wholly
207   // contains the given interval. An interval O "wholly contains" a non-empty
208   // interval I if O.Contains(p) is true for every p in I. This is the same
209   // definition used by value_type::Contains(). This method returns false on
210   // the empty interval, due to a (perhaps unintuitive) convention inherited
211   // from value_type.
212   // Example:
213   //   Assume an QuicIntervalSet containing the entries { [10,20), [30,40) }.
214   //   Contains(Interval(15, 16)) returns true, because [10,20) contains
215   //   [15,16). However, Contains(Interval(15, 35)) returns false.
216   bool Contains(const value_type& interval) const;
217 
218   // Returns true if for each interval in "other", there is some (possibly
219   // different) interval in this QuicIntervalSet which wholly contains it. See
220   // Contains(const value_type& interval) for the meaning of "wholly contains".
221   // Perhaps unintuitively, this method returns false if "other" is the empty
222   // set. The algorithmic complexity of this method is O(other.Size() *
223   // log(this->Size())). The method could be rewritten to run in O(other.Size()
224   // + this->Size()), and this alternative could be implemented as a free
225   // function using the public API.
226   bool Contains(const QuicIntervalSet<T>& other) const;
227 
228   // Returns true if there is some interval in this QuicIntervalSet that wholly
229   // contains the interval [min, max). See Contains(const value_type&).
Contains(const T & min,const T & max)230   bool Contains(const T& min, const T& max) const {
231     return Contains(value_type(min, max));
232   }
233 
234   // Returns true if for some interval in "other", there is some interval in
235   // this QuicIntervalSet that intersects with it. See value_type::Intersects()
236   // for the definition of interval intersection.
237   bool Intersects(const QuicIntervalSet& other) const;
238 
239   // Returns an iterator to the value_type in the QuicIntervalSet that contains
240   // the given value. In other words, returns an iterator to the unique interval
241   // [min, max) in the QuicIntervalSet that has the property min <= value < max.
242   // If there is no such interval, this method returns end().
243   const_iterator Find(const T& value) const;
244 
245   // Returns an iterator to the value_type in the QuicIntervalSet that wholly
246   // contains the given interval. In other words, returns an iterator to the
247   // unique interval outer in the QuicIntervalSet that has the property that
248   // outer.Contains(interval). If there is no such interval, or if interval is
249   // empty, returns end().
250   const_iterator Find(const value_type& interval) const;
251 
252   // Returns an iterator to the value_type in the QuicIntervalSet that wholly
253   // contains [min, max). In other words, returns an iterator to the unique
254   // interval outer in the QuicIntervalSet that has the property that
255   // outer.Contains(Interval<T>(min, max)). If there is no such interval, or if
256   // interval is empty, returns end().
Find(const T & min,const T & max)257   const_iterator Find(const T& min, const T& max) const {
258     return Find(value_type(min, max));
259   }
260 
261   // Returns an iterator pointing to the first value_type which contains or
262   // goes after the given value.
263   //
264   // Example:
265   //   [10, 20)  [30, 40)
266   //   ^                    LowerBound(10)
267   //   ^                    LowerBound(15)
268   //             ^          LowerBound(20)
269   //             ^          LowerBound(25)
270   const_iterator LowerBound(const T& value) const;
271 
272   // Returns an iterator pointing to the first value_type which goes after
273   // the given value.
274   //
275   // Example:
276   //   [10, 20)  [30, 40)
277   //             ^          UpperBound(10)
278   //             ^          UpperBound(15)
279   //             ^          UpperBound(20)
280   //             ^          UpperBound(25)
281   const_iterator UpperBound(const T& value) const;
282 
283   // Returns true if every value within the passed interval is not Contained
284   // within the QuicIntervalSet.
285   // Note that empty intervals are always considered disjoint from the
286   // QuicIntervalSet (even though the QuicIntervalSet doesn't `Contain` them).
287   bool IsDisjoint(const value_type& interval) const;
288 
289   // Merges all the values contained in "other" into this QuicIntervalSet.
290   void Union(const QuicIntervalSet& other);
291 
292   // Modifies this QuicIntervalSet so that it contains only those values that
293   // are currently present both in *this and in the QuicIntervalSet "other".
294   void Intersection(const QuicIntervalSet& other);
295 
296   // Mutates this QuicIntervalSet so that it contains only those values that are
297   // currently in *this but not in "interval".
298   void Difference(const value_type& interval);
299 
300   // Mutates this QuicIntervalSet so that it contains only those values that are
301   // currently in *this but not in the interval [min, max).
302   void Difference(const T& min, const T& max);
303 
304   // Mutates this QuicIntervalSet so that it contains only those values that are
305   // currently in *this but not in the QuicIntervalSet "other".
306   void Difference(const QuicIntervalSet& other);
307 
308   // Mutates this QuicIntervalSet so that it contains only those values that are
309   // in [min, max) but not currently in *this.
310   void Complement(const T& min, const T& max);
311 
312   // QuicIntervalSet's begin() iterator. The invariants of QuicIntervalSet
313   // guarantee that for each entry e in the set, e.min() < e.max() (because the
314   // entries are non-empty) and for each entry f that appears later in the set,
315   // e.max() < f.min() (because the entries are ordered, pairwise-disjoint, and
316   // non-adjacent). Modifications to this QuicIntervalSet invalidate these
317   // iterators.
begin()318   const_iterator begin() const { return intervals_.begin(); }
319 
320   // QuicIntervalSet's end() iterator.
end()321   const_iterator end() const { return intervals_.end(); }
322 
323   // QuicIntervalSet's rbegin() and rend() iterators. Iterator invalidation
324   // semantics are the same as those for begin() / end().
rbegin()325   const_reverse_iterator rbegin() const { return intervals_.rbegin(); }
326 
rend()327   const_reverse_iterator rend() const { return intervals_.rend(); }
328 
329   template <typename Iter>
assign(Iter first,Iter last)330   void assign(Iter first, Iter last) {
331     Clear();
332     for (; first != last; ++first)
333       Add(*first);
334   }
335 
assign(std::initializer_list<value_type> il)336   void assign(std::initializer_list<value_type> il) {
337     assign(il.begin(), il.end());
338   }
339 
340   // Returns a human-readable representation of this set. This will typically be
341   // (though is not guaranteed to be) of the form
342   //   "[a1, b1) [a2, b2) ... [an, bn)"
343   // where the intervals are in the same order as given by traversal from
344   // begin() to end(). This representation is intended for human consumption;
345   // computer programs should not rely on the output being in exactly this form.
346   std::string ToString() const;
347 
348   QuicIntervalSet& operator=(std::initializer_list<value_type> il) {
349     assign(il.begin(), il.end());
350     return *this;
351   }
352 
353   friend bool operator==(const QuicIntervalSet& a, const QuicIntervalSet& b) {
354     return a.Size() == b.Size() &&
355            std::equal(a.begin(), a.end(), b.begin(), NonemptyIntervalEq());
356   }
357 
358   friend bool operator!=(const QuicIntervalSet& a, const QuicIntervalSet& b) {
359     return !(a == b);
360   }
361 
362  private:
363   // Simple member-wise equality, since all intervals are non-empty.
364   struct QUIC_NO_EXPORT NonemptyIntervalEq {
operatorNonemptyIntervalEq365     bool operator()(const value_type& a, const value_type& b) const {
366       return a.min() == b.min() && a.max() == b.max();
367     }
368   };
369 
370   // Removes overlapping ranges and coalesces adjacent intervals as needed.
371   void Compact(const typename Set::iterator& begin,
372                const typename Set::iterator& end);
373 
374   // Returns true if this set is valid (i.e. all intervals in it are non-empty,
375   // non-adjacent, and mutually disjoint). Currently this is used as an
376   // integrity check by the Intersection() and Difference() methods, but is only
377   // invoked for debug builds (via DCHECK).
378   bool Valid() const;
379 
380   // Finds the first interval that potentially intersects 'other'.
381   const_iterator FindIntersectionCandidate(const QuicIntervalSet& other) const;
382 
383   // Finds the first interval that potentially intersects 'interval'.
384   const_iterator FindIntersectionCandidate(const value_type& interval) const;
385 
386   // Helper for Intersection() and Difference(): Finds the next pair of
387   // intervals from 'x' and 'y' that intersect. 'mine' is an iterator
388   // over x->intervals_. 'theirs' is an iterator over y.intervals_. 'mine'
389   // and 'theirs' are advanced until an intersecting pair is found.
390   // Non-intersecting intervals (aka "holes") from x->intervals_ can be
391   // optionally erased by "on_hole".
392   template <typename X, typename Func>
393   static bool FindNextIntersectingPairImpl(X* x,
394                                            const QuicIntervalSet& y,
395                                            const_iterator* mine,
396                                            const_iterator* theirs,
397                                            Func on_hole);
398 
399   // The variant of the above method that doesn't mutate this QuicIntervalSet.
FindNextIntersectingPair(const QuicIntervalSet & other,const_iterator * mine,const_iterator * theirs)400   bool FindNextIntersectingPair(const QuicIntervalSet& other,
401                                 const_iterator* mine,
402                                 const_iterator* theirs) const {
403     return FindNextIntersectingPairImpl(
404         this, other, mine, theirs,
405         [](const QuicIntervalSet*, const_iterator, const_iterator) {});
406   }
407 
408   // The variant of the above method that mutates this QuicIntervalSet by
409   // erasing holes.
FindNextIntersectingPairAndEraseHoles(const QuicIntervalSet & other,const_iterator * mine,const_iterator * theirs)410   bool FindNextIntersectingPairAndEraseHoles(const QuicIntervalSet& other,
411                                              const_iterator* mine,
412                                              const_iterator* theirs) {
413     return FindNextIntersectingPairImpl(
414         this, other, mine, theirs,
415         [](QuicIntervalSet* x, const_iterator from, const_iterator to) {
416           x->intervals_.erase(from, to);
417         });
418   }
419 
420   // The representation for the intervals. The intervals in this set are
421   // non-empty, pairwise-disjoint, non-adjacent and ordered in ascending order
422   // by min().
423   Set intervals_;
424 };
425 
426 template <typename T>
427 auto operator<<(std::ostream& out, const QuicIntervalSet<T>& seq)
428     -> decltype(out << *seq.begin()) {
429   out << "{";
430   for (const auto& interval : seq) {
431     out << " " << interval;
432   }
433   out << " }";
434 
435   return out;
436 }
437 
438 //==============================================================================
439 // Implementation details: Clients can stop reading here.
440 
441 template <typename T>
SpanningInterval()442 typename QuicIntervalSet<T>::value_type QuicIntervalSet<T>::SpanningInterval()
443     const {
444   value_type result;
445   if (!intervals_.empty()) {
446     result.SetMin(intervals_.begin()->min());
447     result.SetMax(intervals_.rbegin()->max());
448   }
449   return result;
450 }
451 
452 template <typename T>
Add(const value_type & interval)453 void QuicIntervalSet<T>::Add(const value_type& interval) {
454   if (interval.Empty())
455     return;
456   std::pair<typename Set::iterator, bool> ins = intervals_.insert(interval);
457   if (!ins.second) {
458     // This interval already exists.
459     return;
460   }
461   // Determine the minimal range that will have to be compacted.  We know that
462   // the QuicIntervalSet was valid before the addition of the interval, so only
463   // need to start with the interval itself (although Compact takes an open
464   // range so begin needs to be the interval to the left).  We don't know how
465   // many ranges this interval may cover, so we need to find the appropriate
466   // interval to end with on the right.
467   typename Set::iterator begin = ins.first;
468   if (begin != intervals_.begin())
469     --begin;
470   const value_type target_end(interval.max(), interval.max());
471   const typename Set::iterator end = intervals_.upper_bound(target_end);
472   Compact(begin, end);
473 }
474 
475 template <typename T>
Contains(const T & value)476 bool QuicIntervalSet<T>::Contains(const T& value) const {
477   value_type tmp(value, value);
478   // Find the first interval with min() > value, then move back one step
479   const_iterator it = intervals_.upper_bound(tmp);
480   if (it == intervals_.begin())
481     return false;
482   --it;
483   return it->Contains(value);
484 }
485 
486 template <typename T>
Contains(const value_type & interval)487 bool QuicIntervalSet<T>::Contains(const value_type& interval) const {
488   // Find the first interval with min() > value, then move back one step.
489   const_iterator it = intervals_.upper_bound(interval);
490   if (it == intervals_.begin())
491     return false;
492   --it;
493   return it->Contains(interval);
494 }
495 
496 template <typename T>
Contains(const QuicIntervalSet<T> & other)497 bool QuicIntervalSet<T>::Contains(const QuicIntervalSet<T>& other) const {
498   if (!SpanningInterval().Contains(other.SpanningInterval())) {
499     return false;
500   }
501 
502   for (const_iterator i = other.begin(); i != other.end(); ++i) {
503     // If we don't contain the interval, can return false now.
504     if (!Contains(*i)) {
505       return false;
506     }
507   }
508   return true;
509 }
510 
511 // This method finds the interval that Contains() "value", if such an interval
512 // exists in the QuicIntervalSet. The way this is done is to locate the
513 // "candidate interval", the only interval that could *possibly* contain value,
514 // and test it using Contains(). The candidate interval is the interval with the
515 // largest min() having min() <= value.
516 //
517 // Determining the candidate interval takes a couple of steps. First, since the
518 // underlying std::set stores intervals, not values, we need to create a "probe
519 // interval" suitable for use as a search key. The probe interval used is
520 // [value, value). Now we can restate the problem as finding the largest
521 // interval in the QuicIntervalSet that is <= the probe interval.
522 //
523 // This restatement only works if the set's comparator behaves in a certain way.
524 // In particular it needs to order first by ascending min(), and then by
525 // descending max(). The comparator used by this library is defined in exactly
526 // this way. To see why descending max() is required, consider the following
527 // example. Assume an QuicIntervalSet containing these intervals:
528 //
529 //   [0, 5)  [10, 20)  [50, 60)
530 //
531 // Consider searching for the value 15. The probe interval [15, 15) is created,
532 // and [10, 20) is identified as the largest interval in the set <= the probe
533 // interval. This is the correct interval needed for the Contains() test, which
534 // will then return true.
535 //
536 // Now consider searching for the value 30. The probe interval [30, 30) is
537 // created, and again [10, 20] is identified as the largest interval <= the
538 // probe interval. This is again the correct interval needed for the Contains()
539 // test, which in this case returns false.
540 //
541 // Finally, consider searching for the value 10. The probe interval [10, 10) is
542 // created. Here the ordering relationship between [10, 10) and [10, 20) becomes
543 // vitally important. If [10, 10) were to come before [10, 20), then [0, 5)
544 // would be the largest interval <= the probe, leading to the wrong choice of
545 // interval for the Contains() test. Therefore [10, 10) needs to come after
546 // [10, 20). The simplest way to make this work in the general case is to order
547 // by ascending min() but descending max(). In this ordering, the empty interval
548 // is larger than any non-empty interval with the same min(). The comparator
549 // used by this library is careful to induce this ordering.
550 //
551 // Another detail involves the choice of which std::set method to use to try to
552 // find the candidate interval. The most appropriate entry point is
553 // set::upper_bound(), which finds the smallest interval which is > the probe
554 // interval. The semantics of upper_bound() are slightly different from what we
555 // want (namely, to find the largest interval which is <= the probe interval)
556 // but they are close enough; the interval found by upper_bound() will always be
557 // one step past the interval we are looking for (if it exists) or at begin()
558 // (if it does not). Getting to the proper interval is a simple matter of
559 // decrementing the iterator.
560 template <typename T>
Find(const T & value)561 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::Find(
562     const T& value) const {
563   value_type tmp(value, value);
564   const_iterator it = intervals_.upper_bound(tmp);
565   if (it == intervals_.begin())
566     return intervals_.end();
567   --it;
568   if (it->Contains(value))
569     return it;
570   else
571     return intervals_.end();
572 }
573 
574 // This method finds the interval that Contains() the interval "probe", if such
575 // an interval exists in the QuicIntervalSet. The way this is done is to locate
576 // the "candidate interval", the only interval that could *possibly* contain
577 // "probe", and test it using Contains(). The candidate interval is the largest
578 // interval that is <= the probe interval.
579 //
580 // The search for the candidate interval only works if the comparator used
581 // behaves in a certain way. In particular it needs to order first by ascending
582 // min(), and then by descending max(). The comparator used by this library is
583 // defined in exactly this way. To see why descending max() is required,
584 // consider the following example. Assume an QuicIntervalSet containing these
585 // intervals:
586 //
587 //   [0, 5)  [10, 20)  [50, 60)
588 //
589 // Consider searching for the probe [15, 17). [10, 20) is the largest interval
590 // in the set which is <= the probe interval. This is the correct interval
591 // needed for the Contains() test, which will then return true, because [10, 20)
592 // contains [15, 17).
593 //
594 // Now consider searching for the probe [30, 32). Again [10, 20] is the largest
595 // interval <= the probe interval. This is again the correct interval needed for
596 // the Contains() test, which in this case returns false, because [10, 20) does
597 // not contain [30, 32).
598 //
599 // Finally, consider searching for the probe [10, 12). Here the ordering
600 // relationship between [10, 12) and [10, 20) becomes vitally important. If
601 // [10, 12) were to come before [10, 20), then [0, 5) would be the largest
602 // interval <= the probe, leading to the wrong choice of interval for the
603 // Contains() test. Therefore [10, 12) needs to come after [10, 20). The
604 // simplest way to make this work in the general case is to order by ascending
605 // min() but descending max(). In this ordering, given two intervals with the
606 // same min(), the wider one goes before the narrower one. The comparator used
607 // by this library is careful to induce this ordering.
608 //
609 // Another detail involves the choice of which std::set method to use to try to
610 // find the candidate interval. The most appropriate entry point is
611 // set::upper_bound(), which finds the smallest interval which is > the probe
612 // interval. The semantics of upper_bound() are slightly different from what we
613 // want (namely, to find the largest interval which is <= the probe interval)
614 // but they are close enough; the interval found by upper_bound() will always be
615 // one step past the interval we are looking for (if it exists) or at begin()
616 // (if it does not). Getting to the proper interval is a simple matter of
617 // decrementing the iterator.
618 template <typename T>
Find(const value_type & probe)619 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::Find(
620     const value_type& probe) const {
621   const_iterator it = intervals_.upper_bound(probe);
622   if (it == intervals_.begin())
623     return intervals_.end();
624   --it;
625   if (it->Contains(probe))
626     return it;
627   else
628     return intervals_.end();
629 }
630 
631 template <typename T>
LowerBound(const T & value)632 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::LowerBound(
633     const T& value) const {
634   const_iterator it = intervals_.lower_bound(value_type(value, value));
635   if (it == intervals_.begin()) {
636     return it;
637   }
638 
639   // The previous intervals_.lower_bound() checking is essentially based on
640   // interval.min(), so we need to check whether the `value` is contained in
641   // the previous interval.
642   --it;
643   if (it->Contains(value)) {
644     return it;
645   } else {
646     return ++it;
647   }
648 }
649 
650 template <typename T>
UpperBound(const T & value)651 typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::UpperBound(
652     const T& value) const {
653   return intervals_.upper_bound(value_type(value, value));
654 }
655 
656 template <typename T>
IsDisjoint(const value_type & interval)657 bool QuicIntervalSet<T>::IsDisjoint(const value_type& interval) const {
658   if (interval.Empty())
659     return true;
660   value_type tmp(interval.min(), interval.min());
661   // Find the first interval with min() > interval.min()
662   const_iterator it = intervals_.upper_bound(tmp);
663   if (it != intervals_.end() && interval.max() > it->min())
664     return false;
665   if (it == intervals_.begin())
666     return true;
667   --it;
668   return it->max() <= interval.min();
669 }
670 
671 template <typename T>
Union(const QuicIntervalSet & other)672 void QuicIntervalSet<T>::Union(const QuicIntervalSet& other) {
673   intervals_.insert(other.begin(), other.end());
674   Compact(intervals_.begin(), intervals_.end());
675 }
676 
677 template <typename T>
678 typename QuicIntervalSet<T>::const_iterator
FindIntersectionCandidate(const QuicIntervalSet & other)679 QuicIntervalSet<T>::FindIntersectionCandidate(
680     const QuicIntervalSet& other) const {
681   return FindIntersectionCandidate(*other.intervals_.begin());
682 }
683 
684 template <typename T>
685 typename QuicIntervalSet<T>::const_iterator
FindIntersectionCandidate(const value_type & interval)686 QuicIntervalSet<T>::FindIntersectionCandidate(
687     const value_type& interval) const {
688   // Use upper_bound to efficiently find the first interval in intervals_
689   // where min() is greater than interval.min().  If the result
690   // isn't the beginning of intervals_ then move backwards one interval since
691   // the interval before it is the first candidate where max() may be
692   // greater than interval.min().
693   // In other words, no interval before that can possibly intersect with any
694   // of other.intervals_.
695   const_iterator mine = intervals_.upper_bound(interval);
696   if (mine != intervals_.begin()) {
697     --mine;
698   }
699   return mine;
700 }
701 
702 template <typename T>
703 template <typename X, typename Func>
FindNextIntersectingPairImpl(X * x,const QuicIntervalSet & y,const_iterator * mine,const_iterator * theirs,Func on_hole)704 bool QuicIntervalSet<T>::FindNextIntersectingPairImpl(X* x,
705                                                       const QuicIntervalSet& y,
706                                                       const_iterator* mine,
707                                                       const_iterator* theirs,
708                                                       Func on_hole) {
709   CHECK(x != nullptr);
710   if ((*mine == x->intervals_.end()) || (*theirs == y.intervals_.end())) {
711     return false;
712   }
713   while (!(**mine).Intersects(**theirs)) {
714     const_iterator erase_first = *mine;
715     // Skip over intervals in 'mine' that don't reach 'theirs'.
716     while (*mine != x->intervals_.end() && (**mine).max() <= (**theirs).min()) {
717       ++(*mine);
718     }
719     on_hole(x, erase_first, *mine);
720     // We're done if the end of intervals_ is reached.
721     if (*mine == x->intervals_.end()) {
722       return false;
723     }
724     // Skip over intervals 'theirs' that don't reach 'mine'.
725     while (*theirs != y.intervals_.end() &&
726            (**theirs).max() <= (**mine).min()) {
727       ++(*theirs);
728     }
729     // If the end of other.intervals_ is reached, we're done.
730     if (*theirs == y.intervals_.end()) {
731       on_hole(x, *mine, x->intervals_.end());
732       return false;
733     }
734   }
735   return true;
736 }
737 
738 template <typename T>
Intersection(const QuicIntervalSet & other)739 void QuicIntervalSet<T>::Intersection(const QuicIntervalSet& other) {
740   if (!SpanningInterval().Intersects(other.SpanningInterval())) {
741     intervals_.clear();
742     return;
743   }
744 
745   const_iterator mine = FindIntersectionCandidate(other);
746   // Remove any intervals that cannot possibly intersect with other.intervals_.
747   intervals_.erase(intervals_.begin(), mine);
748   const_iterator theirs = other.FindIntersectionCandidate(*this);
749 
750   while (FindNextIntersectingPairAndEraseHoles(other, &mine, &theirs)) {
751     // OK, *mine and *theirs intersect.  Now, we find the largest
752     // span of intervals in other (starting at theirs) - say [a..b]
753     // - that intersect *mine, and we replace *mine with (*mine
754     // intersect x) for all x in [a..b] Note that subsequent
755     // intervals in this can't intersect any intervals in [a..b) --
756     // they may only intersect b or subsequent intervals in other.
757     value_type i(*mine);
758     intervals_.erase(mine);
759     mine = intervals_.end();
760     value_type intersection;
761     while (theirs != other.intervals_.end() &&
762            i.Intersects(*theirs, &intersection)) {
763       std::pair<typename Set::iterator, bool> ins =
764           intervals_.insert(intersection);
765       DCHECK(ins.second);
766       mine = ins.first;
767       ++theirs;
768     }
769     DCHECK(mine != intervals_.end());
770     --theirs;
771     ++mine;
772   }
773   DCHECK(Valid());
774 }
775 
776 template <typename T>
Intersects(const QuicIntervalSet & other)777 bool QuicIntervalSet<T>::Intersects(const QuicIntervalSet& other) const {
778   if (!SpanningInterval().Intersects(other.SpanningInterval())) {
779     return false;
780   }
781 
782   const_iterator mine = FindIntersectionCandidate(other);
783   if (mine == intervals_.end()) {
784     return false;
785   }
786   const_iterator theirs = other.FindIntersectionCandidate(*mine);
787 
788   return FindNextIntersectingPair(other, &mine, &theirs);
789 }
790 
791 template <typename T>
Difference(const value_type & interval)792 void QuicIntervalSet<T>::Difference(const value_type& interval) {
793   if (!SpanningInterval().Intersects(interval)) {
794     return;
795   }
796   Difference(QuicIntervalSet<T>(interval));
797 }
798 
799 template <typename T>
Difference(const T & min,const T & max)800 void QuicIntervalSet<T>::Difference(const T& min, const T& max) {
801   Difference(value_type(min, max));
802 }
803 
804 template <typename T>
Difference(const QuicIntervalSet & other)805 void QuicIntervalSet<T>::Difference(const QuicIntervalSet& other) {
806   if (!SpanningInterval().Intersects(other.SpanningInterval())) {
807     return;
808   }
809 
810   const_iterator mine = FindIntersectionCandidate(other);
811   // If no interval in mine reaches the first interval of theirs then we're
812   // done.
813   if (mine == intervals_.end()) {
814     return;
815   }
816   const_iterator theirs = other.FindIntersectionCandidate(*this);
817 
818   while (FindNextIntersectingPair(other, &mine, &theirs)) {
819     // At this point *mine and *theirs overlap.  Remove mine from
820     // intervals_ and replace it with the possibly two intervals that are
821     // the difference between mine and theirs.
822     value_type i(*mine);
823     intervals_.erase(mine++);
824     value_type lo;
825     value_type hi;
826     i.Difference(*theirs, &lo, &hi);
827 
828     if (!lo.Empty()) {
829       // We have a low end.  This can't intersect anything else.
830       std::pair<typename Set::iterator, bool> ins = intervals_.insert(lo);
831       DCHECK(ins.second);
832     }
833 
834     if (!hi.Empty()) {
835       std::pair<typename Set::iterator, bool> ins = intervals_.insert(hi);
836       DCHECK(ins.second);
837       mine = ins.first;
838     }
839   }
840   DCHECK(Valid());
841 }
842 
843 template <typename T>
Complement(const T & min,const T & max)844 void QuicIntervalSet<T>::Complement(const T& min, const T& max) {
845   QuicIntervalSet<T> span(min, max);
846   span.Difference(*this);
847   intervals_.swap(span.intervals_);
848 }
849 
850 template <typename T>
ToString()851 std::string QuicIntervalSet<T>::ToString() const {
852   std::ostringstream os;
853   os << *this;
854   return os.str();
855 }
856 
857 // This method compacts the QuicIntervalSet, merging pairs of overlapping
858 // intervals into a single interval. In the steady state, the QuicIntervalSet
859 // does not contain any such pairs. However, the way the Union() and Add()
860 // methods work is to temporarily put the QuicIntervalSet into such a state and
861 // then to call Compact() to "fix it up" so that it is no longer in that state.
862 //
863 // Compact() needs the interval set to allow two intervals [a,b) and [a,c)
864 // (having the same min() but different max()) to briefly coexist in the set at
865 // the same time, and be adjacent to each other, so that they can be efficiently
866 // located and merged into a single interval. This state would be impossible
867 // with a comparator which only looked at min(), as such a comparator would
868 // consider such pairs equal. Fortunately, the comparator used by
869 // QuicIntervalSet does exactly what is needed, ordering first by ascending
870 // min(), then by descending max().
871 template <typename T>
Compact(const typename Set::iterator & begin,const typename Set::iterator & end)872 void QuicIntervalSet<T>::Compact(const typename Set::iterator& begin,
873                                  const typename Set::iterator& end) {
874   if (begin == end)
875     return;
876   typename Set::iterator next = begin;
877   typename Set::iterator prev = begin;
878   typename Set::iterator it = begin;
879   ++it;
880   ++next;
881   while (it != end) {
882     ++next;
883     if (prev->max() >= it->min()) {
884       // Overlapping / coalesced range; merge the two intervals.
885       T min = prev->min();
886       T max = std::max(prev->max(), it->max());
887       value_type i(min, max);
888       intervals_.erase(prev);
889       intervals_.erase(it);
890       std::pair<typename Set::iterator, bool> ins = intervals_.insert(i);
891       DCHECK(ins.second);
892       prev = ins.first;
893     } else {
894       prev = it;
895     }
896     it = next;
897   }
898 }
899 
900 template <typename T>
Valid()901 bool QuicIntervalSet<T>::Valid() const {
902   const_iterator prev = end();
903   for (const_iterator it = begin(); it != end(); ++it) {
904     // invalid or empty interval.
905     if (it->min() >= it->max())
906       return false;
907     // Not sorted, not disjoint, or adjacent.
908     if (prev != end() && prev->max() >= it->min())
909       return false;
910     prev = it;
911   }
912   return true;
913 }
914 
915 // This comparator orders intervals first by ascending min() and then by
916 // descending max(). Readers who are satisified with that explanation can stop
917 // reading here. The remainder of this comment is for the benefit of future
918 // maintainers of this library.
919 //
920 // The reason for this ordering is that this comparator has to serve two
921 // masters. First, it has to maintain the intervals in its internal set in the
922 // order that clients expect to see them. Clients see these intervals via the
923 // iterators provided by begin()/end() or as a result of invoking Get(). For
924 // this reason, the comparator orders intervals by ascending min().
925 //
926 // If client iteration were the only consideration, then ordering by ascending
927 // min() would be good enough. This is because the intervals in the
928 // QuicIntervalSet are non-empty, non-adjacent, and mutually disjoint; such
929 // intervals happen to always have disjoint min() values, so such a comparator
930 // would never even have to look at max() in order to work correctly for this
931 // class.
932 //
933 // However, in addition to ordering by ascending min(), this comparator also has
934 // a second responsibility: satisfying the special needs of this library's
935 // peculiar internal implementation. These needs require the comparator to order
936 // first by ascending min() and then by descending max(). The best way to
937 // understand why this is so is to check out the comments associated with the
938 // Find() and Compact() methods.
939 template <typename T>
operator()940 bool QuicIntervalSet<T>::IntervalLess::operator()(const value_type& a,
941                                                   const value_type& b) const {
942   return a.min() < b.min() || (a.min() == b.min() && a.max() > b.max());
943 }
944 
945 }  // namespace quic
946 
947 #endif  // QUICHE_QUIC_CORE_QUIC_INTERVAL_SET_H_
948