blob: 2d44f2b9fab68d1102e874c2ee94aaf172924670 [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
vasilvv872e7a32019-03-12 16:42:44 -070060#include <string>
61
QUICHE teama6ef0a62019-03-07 20:34:33 -050062#include "net/third_party/quiche/src/quic/core/quic_interval.h"
63#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050064
65namespace quic {
66
67template <typename T>
dschinazie2116422019-10-29 11:54:26 -070068class QUIC_NO_EXPORT QuicIntervalSet {
QUICHE teama6ef0a62019-03-07 20:34:33 -050069 public:
70 typedef QuicInterval<T> value_type;
71
72 private:
dschinazie2116422019-10-29 11:54:26 -070073 struct QUIC_NO_EXPORT IntervalLess {
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 bool operator()(const value_type& a, const value_type& b) const;
75 };
wub4f59d712019-11-05 06:48:55 -080076 // TODO(wub): Switch to absl::btree_set when it is available in Chromium.
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 typedef std::set<value_type, IntervalLess> Set;
78
79 public:
80 typedef typename Set::const_iterator const_iterator;
81 typedef typename Set::const_reverse_iterator const_reverse_iterator;
82
83 // Instantiates an empty 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.
89 explicit QuicIntervalSet(const value_type& interval) { Add(interval); }
90
91 // Instantiates an QuicIntervalSet containing the half-open interval [min,
92 // max).
93 QuicIntervalSet(const T& min, const T& max) { Add(min, max); }
94
95 QuicIntervalSet(std::initializer_list<value_type> il) { assign(il); }
96
97 // Clears this QuicIntervalSet.
98 void Clear() { intervals_.clear(); }
99
100 // Returns the number of disjoint intervals contained in this QuicIntervalSet.
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.
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().
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|.
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
wub4f59d712019-11-05 06:48:55 -0800156 // Remove the first interval.
157 // REQUIRES: !Empty()
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.
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
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 // Returns true if this QuicIntervalSet is 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&).
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().
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.
318 const_iterator begin() const { return intervals_.begin(); }
319
320 // QuicIntervalSet's end() iterator.
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().
325 const_reverse_iterator rbegin() const { return intervals_.rbegin(); }
326
327 const_reverse_iterator rend() const { return intervals_.rend(); }
328
329 template <typename Iter>
330 void assign(Iter first, Iter last) {
331 Clear();
332 for (; first != last; ++first)
333 Add(*first);
334 }
335
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.
vasilvvc48c8712019-03-11 13:38:16 -0700346 std::string ToString() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500347
348 QuicIntervalSet& operator=(std::initializer_list<value_type> il) {
349 assign(il.begin(), il.end());
350 return *this;
351 }
352
QUICHE teama6ef0a62019-03-07 20:34:33 -0500353 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.
dschinazie2116422019-10-29 11:54:26 -0700364 struct QUIC_NO_EXPORT NonemptyIntervalEq {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500365 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.
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.
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
426template <typename T>
427auto 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
QUICHE teama6ef0a62019-03-07 20:34:33 -0500438//==============================================================================
439// Implementation details: Clients can stop reading here.
440
441template <typename T>
442typename 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
452template <typename T>
453void 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
475template <typename T>
476bool 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
486template <typename T>
487bool 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
496template <typename T>
497bool 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.
560template <typename T>
561typename 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.
618template <typename T>
619typename 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
631template <typename T>
632typename 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
650template <typename T>
651typename QuicIntervalSet<T>::const_iterator QuicIntervalSet<T>::UpperBound(
652 const T& value) const {
653 return intervals_.upper_bound(value_type(value, value));
654}
655
656template <typename T>
657bool 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
671template <typename T>
672void QuicIntervalSet<T>::Union(const QuicIntervalSet& other) {
673 intervals_.insert(other.begin(), other.end());
674 Compact(intervals_.begin(), intervals_.end());
675}
676
677template <typename T>
678typename QuicIntervalSet<T>::const_iterator
679QuicIntervalSet<T>::FindIntersectionCandidate(
680 const QuicIntervalSet& other) const {
681 return FindIntersectionCandidate(*other.intervals_.begin());
682}
683
684template <typename T>
685typename QuicIntervalSet<T>::const_iterator
686QuicIntervalSet<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
702template <typename T>
703template <typename X, typename Func>
704bool 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
738template <typename T>
739void 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
776template <typename T>
777bool 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
791template <typename T>
792void QuicIntervalSet<T>::Difference(const value_type& interval) {
793 if (!SpanningInterval().Intersects(interval)) {
794 return;
795 }
796 Difference(QuicIntervalSet<T>(interval));
797}
798
799template <typename T>
800void QuicIntervalSet<T>::Difference(const T& min, const T& max) {
801 Difference(value_type(min, max));
802}
803
804template <typename T>
805void 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
843template <typename T>
844void 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
850template <typename T>
vasilvvc48c8712019-03-11 13:38:16 -0700851std::string QuicIntervalSet<T>::ToString() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500852 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().
871template <typename T>
872void 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
900template <typename T>
901bool 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
QUICHE teama6ef0a62019-03-07 20:34:33 -0500915// 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.
939template <typename T>
940bool 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_