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