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 #ifndef MEDIA_BLINK_RANGEMAP_H_ |
| 6 #define MEDIA_BLINK_RANGEMAP_H_ |
| 7 |
| 8 #include <limits> |
| 9 #include <map> |
| 10 |
| 11 #include "base/logging.h" |
| 12 |
| 13 namespace media { |
| 14 |
| 15 // A RangeMap<KeyType, ValueType> is similar to a std::map<KeyType, ValueType>, |
| 16 // where incrementing, decrementing and setting ranges of values has been |
| 17 // optimized. Internally, a RangeMap<> keeps a list KeyType ranges and the |
| 18 // associated ValueType. Set/Increment operations should generally take |
| 19 // O(log(N)) + O(M) time where N is the number of ranges in the map and |
| 20 // M is the number of modified ranges. Adjacent ranges which have the same |
| 21 // value are automatically merged |
| 22 // |
| 23 // Internally, RangeMap<> uses an std::map, where the beginning of each range |
| 24 // is stored along with the value for that range. |
| 25 |
| 26 // Simple range class. |
| 27 // Range ends are always non-inclusive. |
| 28 template<typename T> |
| 29 struct Range { |
| 30 public: |
| 31 Range(const T& begin_, const T& end_) : begin(begin_), end(end_) {} |
| 32 T begin; |
| 33 T end; |
| 34 |
| 35 Range Intersect(const Range& other) const { |
| 36 return Range(std::max(begin, other.begin), std::min<T>(end, other.end)); |
| 37 } |
| 38 |
| 39 bool Empty() const { |
| 40 return begin >= end; |
| 41 } |
| 42 }; |
| 43 |
| 44 template<typename KeyType, |
| 45 typename ValueType, |
| 46 class Compare = std::less<KeyType>, |
| 47 class Minmax = std::numeric_limits<KeyType> > |
| 48 class RangeMapConstIterator { |
| 49 public: |
| 50 typedef std::map<KeyType, ValueType, Compare> MapType; |
| 51 RangeMapConstIterator() {} |
| 52 RangeMapConstIterator(const MapType* map, |
| 53 typename MapType::const_iterator first, |
| 54 typename MapType::const_iterator second) : |
| 55 map_(map), |
| 56 first_(first), |
| 57 second_(second) { |
| 58 } |
| 59 |
| 60 bool operator==(const RangeMapConstIterator& other) { |
| 61 return first_ == other.first_ && second_ == other.second_; |
| 62 } |
| 63 |
| 64 bool operator!=(const RangeMapConstIterator& other) { |
| 65 return first_ != other.first_ || second_ != other.second_; |
| 66 } |
| 67 |
| 68 // Returns the beginning of the current range. |
| 69 KeyType range_begin() const { |
| 70 if (first_ == map_->end()) { |
| 71 return Minmax::min(); |
| 72 } else { |
| 73 return first_->first; |
| 74 } |
| 75 } |
| 76 |
| 77 // Returns the end of the current range, non-inclusive. |
| 78 KeyType range_end() const { |
| 79 if (second_ == map_->end()) { |
| 80 return Minmax::max(); |
| 81 } else { |
| 82 return second_->first; |
| 83 } |
| 84 } |
| 85 |
| 86 // Returns the current range. |
| 87 Range<KeyType> range() const { |
| 88 return Range<KeyType>(range_begin(), range_end()); |
| 89 } |
| 90 |
| 91 // Returns the value associated with the current range. |
| 92 ValueType value() const { |
| 93 if (first_ == map_->end()) |
| 94 return 0; |
| 95 return first_->second; |
| 96 } |
| 97 |
| 98 // Needed to make the following construct work: |
| 99 // for (const auto& range_value_pair : rangemap) |
| 100 // Note however that this will skip the "end" range, which |
| 101 // is usually ok since it generally has the default value. |
| 102 std::pair<Range<KeyType>, ValueType> operator*() const { |
| 103 return std::make_pair(range(), value()); |
| 104 } |
| 105 |
| 106 // Go to the next range. |
| 107 // The beginning of the next range always matches the end of the current |
| 108 // range. |
| 109 void operator++() { |
| 110 first_ = second_; |
| 111 second_++; |
| 112 } |
| 113 |
| 114 // Go to the previous range. |
| 115 void operator--() { |
| 116 second_ = first_; |
| 117 if (first_ == map_->begin()) { |
| 118 first_ = map_->end(); |
| 119 } else { |
| 120 first_--; |
| 121 } |
| 122 } |
| 123 private: |
| 124 const MapType* map_; |
| 125 typename MapType::const_iterator first_; |
| 126 typename MapType::const_iterator second_; |
| 127 }; |
| 128 |
| 129 template<typename KeyType, |
| 130 typename ValueType, |
| 131 class Compare = std::less<KeyType>, |
| 132 class Minmax = std::numeric_limits<KeyType> > |
| 133 class RangeMap { |
| 134 public: |
| 135 typedef std::map<KeyType, ValueType, Compare> MapType; |
| 136 typedef RangeMapConstIterator<KeyType, ValueType, Compare, Minmax> |
| 137 const_iterator; |
| 138 |
| 139 // Returns the value at a particular point. |
| 140 // Defaults to ValueType(). |
| 141 ValueType operator[](KeyType k) const { |
| 142 typename MapType::const_iterator i = map_.upper_bound(k); |
| 143 if (i == map_.begin()) { |
| 144 return 0; |
| 145 } else { |
| 146 --i; |
| 147 return i->second; |
| 148 } |
| 149 } |
| 150 |
| 151 // Increase [from..to) by |how_much|. |
| 152 void IncrementRange(KeyType from, KeyType to, ValueType how_much) { |
| 153 DCHECK_GE(to, from); |
| 154 if (from == to || how_much == 0) |
| 155 return; |
| 156 typename MapType::iterator a = MakeEntry(from); |
| 157 typename MapType::iterator b = MakeEntry(to); |
| 158 for (typename MapType::iterator i = a; i != b; ++i) { |
| 159 i->second += how_much; |
| 160 } |
| 161 RemoveDuplicates(a); |
| 162 // b may be invalid |
| 163 RemoveDuplicates(map_.lower_bound(to)); |
| 164 } |
| 165 |
| 166 // Set [from..to) to |how_much|. |
| 167 void SetRange(KeyType from, KeyType to, ValueType how_much) { |
| 168 DCHECK_GE(to, from); |
| 169 if (from == to) |
| 170 return; |
| 171 typename MapType::iterator a = MakeEntry(from); |
| 172 typename MapType::iterator b = MakeEntry(to); |
| 173 a->second = how_much; |
| 174 while (true) { |
| 175 typename MapType::iterator c = a; |
| 176 ++c; |
| 177 if (c == b) { |
| 178 break; |
| 179 } else { |
| 180 map_.erase(c); |
| 181 } |
| 182 } |
| 183 RemoveDuplicates(a); |
| 184 // b may be invalid |
| 185 RemoveDuplicates(map_.lower_bound(to)); |
| 186 } |
| 187 |
| 188 // Returns an iterator to the first range. |
| 189 // Note, there is always at least one range. |
| 190 const_iterator begin() const { |
| 191 return const_iterator(&map(), map_.end(), map_.begin()); |
| 192 } |
| 193 |
| 194 // Returns an iterator to the last range. |
| 195 // Note that this works slightly different than most containers |
| 196 // as end() returns a valid, but mostly uninteresting iterator. |
| 197 // For example, if you have you do: |
| 198 // RangeMap<int, int> tmp; |
| 199 // tmp.IncrementRange(-5, 5, 1); |
| 200 // Then end will return the range [6, maxint) with a value of 0. |
| 201 const_iterator end() const { |
| 202 if (map_.empty()) { |
| 203 return const_iterator(&map(), map_.end(), map_.end()); |
| 204 } |
| 205 typename MapType::const_iterator i = map_.end(); |
| 206 --i; |
| 207 return const_iterator(&map(), i, map_.end()); |
| 208 } |
| 209 |
| 210 // Returns an iterator to the range containing |k|. |
| 211 // Always returns a valid iterator. |
| 212 const_iterator find(KeyType k) const { |
| 213 if (map_.empty()) { |
| 214 return const_iterator(&map(), map_.end(), map_.end()); |
| 215 } |
| 216 typename MapType::const_iterator i = map_.upper_bound(k); |
| 217 typename MapType::const_iterator j = i; |
| 218 if (j == map_.begin()) { |
| 219 j = map_.end(); |
| 220 } else { |
| 221 --j; |
| 222 } |
| 223 return const_iterator(&map(), j, i); |
| 224 } |
| 225 |
| 226 private: |
| 227 const MapType& map() const { return map_; } |
| 228 |
| 229 // Make an entry in map_ with the key |k| and return it's iterator. |
| 230 // If such an entry already exists, just re-use it. |
| 231 // If a new entry is created, it's value will be set to the same |
| 232 // as the preceeding entry, or ValueType() if no preceeding entry exists. |
| 233 // After calling this function, we'll need to call RemoveDuplicates() |
| 234 // to clean up any duplicates that we made. |
| 235 typename MapType::iterator MakeEntry(KeyType k) { |
| 236 typename MapType::value_type tmp(k, 0); |
| 237 std::pair<typename MapType::iterator, bool> insert_result; |
| 238 insert_result = map_.insert(tmp); |
| 239 if (insert_result.second) { |
| 240 if (insert_result.first != map_.begin()) { |
| 241 typename MapType::iterator i = insert_result.first; |
| 242 --i; |
| 243 insert_result.first->second = i->second; |
| 244 } |
| 245 } |
| 246 return insert_result.first; |
| 247 } |
| 248 |
| 249 // Remove duplicates before and after |i|. |
| 250 void RemoveDuplicates(typename MapType::iterator i) { |
| 251 if (i == map_.end()) |
| 252 return; |
| 253 if (i == map_.begin() && i->second == 0) { |
| 254 typename MapType::iterator j = i; |
| 255 ++i; |
| 256 map_.erase(j); |
| 257 if (i == map_.end()) |
| 258 return; |
| 259 } |
| 260 if (i != map_.begin()) { |
| 261 typename MapType::iterator j = i; |
| 262 --i; |
| 263 if (i->second == j->second) { |
| 264 map_.erase(j); |
| 265 } |
| 266 } |
| 267 typename MapType::iterator j = i; |
| 268 ++j; |
| 269 if (j != map_.end() && i ->second == j->second) { |
| 270 map_.erase(j); |
| 271 } |
| 272 } |
| 273 |
| 274 MapType map_; |
| 275 }; |
| 276 |
| 277 |
| 278 } // namespace media |
| 279 |
| 280 #endif // MEDIA_BLINK_RANGEMAP_H_ |
OLD | NEW |