xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_interval_set.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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