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