| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 // An Interval<T> is a data structure used to represent a contiguous, mutable | |
| 6 // range over an ordered type T. Supported operations include testing a value to | |
| 7 // see whether it is included in the interval, comparing two intervals, and | |
| 8 // performing their union, intersection, and difference. For the purposes of | |
| 9 // this library, an "ordered type" is any type that induces a total order on its | |
| 10 // values via its less-than operator (operator<()). Examples of such types are | |
| 11 // basic arithmetic types like int and double as well as class types like | |
| 12 // string. | |
| 13 // | |
| 14 // An Interval<T> is represented using the usual C++ STL convention, namely as | |
| 15 // the half-open interval [min, max). A point p is considered to be contained in | |
| 16 // the interval iff p >= min && p < max. One consequence of this definition is | |
| 17 // that for any non-empty interval, min is contained in the interval but max is | |
| 18 // not. There is no canonical representation for the empty interval; rather, any | |
| 19 // interval where max <= min is regarded as empty. As a consequence, two empty | |
| 20 // intervals will still compare as equal despite possibly having different | |
| 21 // underlying min() or max() values. Also beware of the terminology used here: | |
| 22 // the library uses the terms "min" and "max" rather than "begin" and "end" as | |
| 23 // is conventional for the STL. | |
| 24 // | |
| 25 // T is required to be default- and copy-constructable, to have an assignment | |
| 26 // operator, and the full complement of comparison operators (<, <=, ==, !=, >=, | |
| 27 // >). A difference operator (operator-()) is required if Interval<T>::Length | |
| 28 // is used. | |
| 29 // | |
| 30 // For equality comparisons, Interval<T> supports an Equals() method and an | |
| 31 // operator==() which delegates to it. Two intervals are considered equal if | |
| 32 // either they are both empty or if their corresponding min and max fields | |
| 33 // compare equal. For ordered comparisons, Interval<T> also provides the | |
| 34 // comparator Interval<T>::Less and an operator<() which delegates to it. | |
| 35 // Unfortunately this comparator is currently buggy because its behavior is | |
| 36 // inconsistent with Equals(): two empty ranges with different representations | |
| 37 // may be regarded as equivalent by Equals() but regarded as different by | |
| 38 // the comparator. Bug 9240050 has been created to address this. | |
| 39 // | |
| 40 // This class is thread-compatible if T is thread-compatible. (See | |
| 41 // go/thread-compatible). | |
| 42 // | |
| 43 // Examples: | |
| 44 // Interval<int> r1(0, 100); // The interval [0, 100). | |
| 45 // EXPECT_TRUE(r1.Contains(0)); | |
| 46 // EXPECT_TRUE(r1.Contains(50)); | |
| 47 // EXPECT_FALSE(r1.Contains(100)); // 100 is just outside the interval. | |
| 48 // | |
| 49 // Interval<int> r2(50, 150); // The interval [50, 150). | |
| 50 // EXPECT_TRUE(r1.Intersects(r2)); | |
| 51 // EXPECT_FALSE(r1.Contains(r2)); | |
| 52 // EXPECT_TRUE(r1.IntersectWith(r2)); // Mutates r1. | |
| 53 // EXPECT_EQ(Interval<int>(50, 100), r1); // r1 is now [50, 100). | |
| 54 // | |
| 55 // Interval<int> r3(1000, 2000); // The interval [1000, 2000). | |
| 56 // EXPECT_TRUE(r1.IntersectWith(r3)); // Mutates r1. | |
| 57 // EXPECT_TRUE(r1.Empty()); // Now r1 is empty. | |
| 58 // EXPECT_FALSE(r1.Contains(r1.min())); // e.g. doesn't contain its own min. | |
| 59 | |
| 60 #ifndef NET_QUIC_INTERVAL_H_ | |
| 61 #define NET_QUIC_INTERVAL_H_ | |
| 62 | |
| 63 #include <stddef.h> | |
| 64 | |
| 65 #include <algorithm> | |
| 66 #include <functional> | |
| 67 #include <ostream> | |
| 68 #include <string> | |
| 69 #include <utility> | |
| 70 #include <vector> | |
| 71 | |
| 72 namespace net { | |
| 73 | |
| 74 template <typename T> | |
| 75 class Interval { | |
| 76 private: | |
| 77 // TODO(rtenneti): Implement after suupport for std::decay. | |
| 78 #if 0 | |
| 79 // Type trait for deriving the return type for Interval::Length. If | |
| 80 // operator-() is not defined for T, then the return type is void. This makes | |
| 81 // the signature for Length compile so that the class can be used for such T, | |
| 82 // but code that calls Length would still generate a compilation error. | |
| 83 template <typename U> | |
| 84 class DiffTypeOrVoid { | |
| 85 private: | |
| 86 template <typename V> | |
| 87 static auto f(const V* v) -> decltype(*v - *v); | |
| 88 template <typename V> | |
| 89 static void f(...); | |
| 90 | |
| 91 public: | |
| 92 using type = typename std::decay<decltype(f<U>(0))>::type; | |
| 93 }; | |
| 94 #endif | |
| 95 | |
| 96 public: | |
| 97 // Compatibility alias. | |
| 98 using Less = std::less<Interval>; | |
| 99 | |
| 100 // Construct an Interval representing an empty interval. | |
| 101 Interval() : min_(), max_() {} | |
| 102 | |
| 103 // Construct an Interval representing the interval [min, max). If min < max, | |
| 104 // the constructed object will represent the non-empty interval containing all | |
| 105 // values from min up to (but not including) max. On the other hand, if min >= | |
| 106 // max, the constructed object will represent the empty interval. | |
| 107 Interval(const T& min, const T& max) : min_(min), max_(max) {} | |
| 108 | |
| 109 const T& min() const { return min_; } | |
| 110 const T& max() const { return max_; } | |
| 111 void SetMin(const T& t) { min_ = t; } | |
| 112 void SetMax(const T& t) { max_ = t; } | |
| 113 | |
| 114 void Set(const T& min, const T& max) { | |
| 115 SetMin(min); | |
| 116 SetMax(max); | |
| 117 } | |
| 118 | |
| 119 void Clear() { *this = {}; } | |
| 120 void CopyFrom(const Interval& i) { *this = i; } | |
| 121 bool Equals(const Interval& i) const { return *this == i; } | |
| 122 bool Empty() const { return min() >= max(); } | |
| 123 | |
| 124 // Returns the length of this interval. The value returned is zero if | |
| 125 // IsEmpty() is true; otherwise the value returned is max() - min(). | |
| 126 const T Length() const { return (min_ >= max_ ? min_ : max_) - min_; } | |
| 127 | |
| 128 // Returns true iff t >= min() && t < max(). | |
| 129 bool Contains(const T& t) const { return min() <= t && max() > t; } | |
| 130 | |
| 131 // Returns true iff *this and i are non-empty, and *this includes i. "*this | |
| 132 // includes i" means that for all t, if i.Contains(t) then this->Contains(t). | |
| 133 // Note the unintuitive consequence of this definition: this method always | |
| 134 // returns false when i is the empty interval. | |
| 135 bool Contains(const Interval& i) const { | |
| 136 return !Empty() && !i.Empty() && min() <= i.min() && max() >= i.max(); | |
| 137 } | |
| 138 | |
| 139 // Returns true iff there exists some point t for which this->Contains(t) && | |
| 140 // i.Contains(t) evaluates to true, i.e. if the intersection is non-empty. | |
| 141 bool Intersects(const Interval& i) const { | |
| 142 return !Empty() && !i.Empty() && min() < i.max() && max() > i.min(); | |
| 143 } | |
| 144 | |
| 145 // Returns true iff there exists some point t for which this->Contains(t) && | |
| 146 // i.Contains(t) evaluates to true, i.e. if the intersection is non-empty. | |
| 147 // Furthermore, if the intersection is non-empty and the intersection pointer | |
| 148 // is not null, this method stores the calculated intersection in | |
| 149 // *intersection. | |
| 150 bool Intersects(const Interval& i, Interval* out) const; | |
| 151 | |
| 152 // Sets *this to be the intersection of itself with i. Returns true iff | |
| 153 // *this was modified. | |
| 154 bool IntersectWith(const Interval& i); | |
| 155 | |
| 156 // Calculates the smallest interval containing both *this i, and updates *this | |
| 157 // to represent that interval, and returns true iff *this was modified. | |
| 158 bool SpanningUnion(const Interval& i); | |
| 159 | |
| 160 // Determines the difference between two intervals by finding all points that | |
| 161 // are contained in *this but not in i, coalesces those points into the | |
| 162 // largest possible contiguous intervals, and appends those intervals to the | |
| 163 // *difference vector. Intuitively this can be thought of as "erasing" i from | |
| 164 // *this. This will either completely erase *this (leaving nothing behind), | |
| 165 // partially erase some of *this from the left or right side (leaving some | |
| 166 // residual behind), or erase a hole in the middle of *this (leaving behind an | |
| 167 // interval on either side). Therefore, 0, 1, or 2 intervals will be appended | |
| 168 // to *difference. The method returns true iff the intersection of *this and i | |
| 169 // is non-empty. The caller owns the vector and the Interval* pointers | |
| 170 // inside it. The difference vector is required to be non-null. | |
| 171 bool Difference(const Interval& i, std::vector<Interval*>* difference) const; | |
| 172 | |
| 173 // Determines the difference between two intervals as in | |
| 174 // Difference(Interval&, vector*), but stores the results directly in out | |
| 175 // parameters rather than dynamically allocating an Interval* and appending | |
| 176 // it to a vector. If two results are generated, the one with the smaller | |
| 177 // value of min() will be stored in *lo and the other in *hi. Otherwise (if | |
| 178 // fewer than two results are generated), unused arguments will be set to the | |
| 179 // empty interval (it is possible that *lo will be empty and *hi non-empty). | |
| 180 // The method returns true iff the intersection of *this and i is non-empty. | |
| 181 bool Difference(const Interval& i, Interval* lo, Interval* hi) const; | |
| 182 | |
| 183 friend bool operator==(const Interval& a, const Interval& b) { | |
| 184 bool ae = a.Empty(); | |
| 185 bool be = b.Empty(); | |
| 186 if (ae && be) | |
| 187 return true; // All empties are equal. | |
| 188 if (ae != be) | |
| 189 return false; // Empty cannot equal nonempty. | |
| 190 return a.min() == b.min() && a.max() == b.max(); | |
| 191 } | |
| 192 | |
| 193 friend bool operator!=(const Interval& a, const Interval& b) { | |
| 194 return !(a == b); | |
| 195 } | |
| 196 | |
| 197 // Defines a comparator which can be used to induce an order on Intervals, so | |
| 198 // that, for example, they can be stored in an ordered container such as | |
| 199 // std::set. The ordering is arbitrary, but does provide the guarantee that, | |
| 200 // for non-empty intervals X and Y, if X contains Y, then X <= Y. | |
| 201 // TODO(kosak): The current implementation of this comparator has a problem | |
| 202 // because the ordering it induces is inconsistent with that of Equals(). In | |
| 203 // particular, this comparator does not properly consider all empty intervals | |
| 204 // equivalent. Bug b/9240050 has been created to track this. | |
| 205 friend bool operator<(const Interval& a, const Interval& b) { | |
| 206 return a.min() < b.min() || (a.min() == b.min() && a.max() > b.max()); | |
| 207 } | |
| 208 | |
| 209 friend std::ostream& operator<<(std::ostream& out, const Interval& i) { | |
| 210 return out << "[" << i.min() << ", " << i.max() << ")"; | |
| 211 } | |
| 212 | |
| 213 private: | |
| 214 T min_; // Inclusive lower bound. | |
| 215 T max_; // Exclusive upper bound. | |
| 216 }; | |
| 217 | |
| 218 //============================================================================== | |
| 219 // Implementation details: Clients can stop reading here. | |
| 220 | |
| 221 template <typename T> | |
| 222 bool Interval<T>::Intersects(const Interval& i, Interval* out) const { | |
| 223 if (!Intersects(i)) | |
| 224 return false; | |
| 225 if (out != nullptr) { | |
| 226 *out = Interval(std::max(min(), i.min()), std::min(max(), i.max())); | |
| 227 } | |
| 228 return true; | |
| 229 } | |
| 230 | |
| 231 template <typename T> | |
| 232 bool Interval<T>::IntersectWith(const Interval& i) { | |
| 233 if (Empty()) | |
| 234 return false; | |
| 235 bool modified = false; | |
| 236 if (i.min() > min()) { | |
| 237 SetMin(i.min()); | |
| 238 modified = true; | |
| 239 } | |
| 240 if (i.max() < max()) { | |
| 241 SetMax(i.max()); | |
| 242 modified = true; | |
| 243 } | |
| 244 return modified; | |
| 245 } | |
| 246 | |
| 247 template <typename T> | |
| 248 bool Interval<T>::SpanningUnion(const Interval& i) { | |
| 249 if (i.Empty()) | |
| 250 return false; | |
| 251 if (Empty()) { | |
| 252 *this = i; | |
| 253 return true; | |
| 254 } | |
| 255 bool modified = false; | |
| 256 if (i.min() < min()) { | |
| 257 SetMin(i.min()); | |
| 258 modified = true; | |
| 259 } | |
| 260 if (i.max() > max()) { | |
| 261 SetMax(i.max()); | |
| 262 modified = true; | |
| 263 } | |
| 264 return modified; | |
| 265 } | |
| 266 | |
| 267 template <typename T> | |
| 268 bool Interval<T>::Difference(const Interval& i, | |
| 269 std::vector<Interval*>* difference) const { | |
| 270 if (Empty()) { | |
| 271 // <empty> - <i> = <empty> | |
| 272 return false; | |
| 273 } | |
| 274 if (i.Empty()) { | |
| 275 // <this> - <empty> = <this> | |
| 276 difference->push_back(new Interval(*this)); | |
| 277 return false; | |
| 278 } | |
| 279 if (min() < i.max() && min() >= i.min() && max() > i.max()) { | |
| 280 // [------ this ------) | |
| 281 // [------ i ------) | |
| 282 // [-- result ---) | |
| 283 difference->push_back(new Interval(i.max(), max())); | |
| 284 return true; | |
| 285 } | |
| 286 if (max() > i.min() && max() <= i.max() && min() < i.min()) { | |
| 287 // [------ this ------) | |
| 288 // [------ i ------) | |
| 289 // [- result -) | |
| 290 difference->push_back(new Interval(min(), i.min())); | |
| 291 return true; | |
| 292 } | |
| 293 if (min() < i.min() && max() > i.max()) { | |
| 294 // [------- this --------) | |
| 295 // [---- i ----) | |
| 296 // [ R1 ) [ R2 ) | |
| 297 // There are two results: R1 and R2. | |
| 298 difference->push_back(new Interval(min(), i.min())); | |
| 299 difference->push_back(new Interval(i.max(), max())); | |
| 300 return true; | |
| 301 } | |
| 302 if (min() >= i.min() && max() <= i.max()) { | |
| 303 // [--- this ---) | |
| 304 // [------ i --------) | |
| 305 // Intersection is <this>, so difference yields the empty interval. | |
| 306 // Nothing is appended to *difference. | |
| 307 return true; | |
| 308 } | |
| 309 // No intersection. Append <this>. | |
| 310 difference->push_back(new Interval(*this)); | |
| 311 return false; | |
| 312 } | |
| 313 | |
| 314 template <typename T> | |
| 315 bool Interval<T>::Difference(const Interval& i, | |
| 316 Interval* lo, | |
| 317 Interval* hi) const { | |
| 318 // Initialize *lo and *hi to empty | |
| 319 *lo = {}; | |
| 320 *hi = {}; | |
| 321 if (Empty()) | |
| 322 return false; | |
| 323 if (i.Empty()) { | |
| 324 *lo = *this; | |
| 325 return false; | |
| 326 } | |
| 327 if (min() < i.max() && min() >= i.min() && max() > i.max()) { | |
| 328 // [------ this ------) | |
| 329 // [------ i ------) | |
| 330 // [-- result ---) | |
| 331 *hi = Interval(i.max(), max()); | |
| 332 return true; | |
| 333 } | |
| 334 if (max() > i.min() && max() <= i.max() && min() < i.min()) { | |
| 335 // [------ this ------) | |
| 336 // [------ i ------) | |
| 337 // [- result -) | |
| 338 *lo = Interval(min(), i.min()); | |
| 339 return true; | |
| 340 } | |
| 341 if (min() < i.min() && max() > i.max()) { | |
| 342 // [------- this --------) | |
| 343 // [---- i ----) | |
| 344 // [ R1 ) [ R2 ) | |
| 345 // There are two results: R1 and R2. | |
| 346 *lo = Interval(min(), i.min()); | |
| 347 *hi = Interval(i.max(), max()); | |
| 348 return true; | |
| 349 } | |
| 350 if (min() >= i.min() && max() <= i.max()) { | |
| 351 // [--- this ---) | |
| 352 // [------ i --------) | |
| 353 // Intersection is <this>, so difference yields the empty interval. | |
| 354 return true; | |
| 355 } | |
| 356 *lo = *this; // No intersection. | |
| 357 return false; | |
| 358 } | |
| 359 | |
| 360 } // namespace net | |
| 361 | |
| 362 #endif // NET_QUIC_INTERVAL_H_ | |
| OLD | NEW |