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_RANGE_MAP_H_ | |
6 #define MEDIA_BLINK_RANGE_MAP_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>, | |
xhwang
2015/11/11 01:05:06
This comment really confused me. There's a fundame
hubbe
2015/11/11 01:29:23
Sure, but I had never heard of a step function bef
xhwang
2015/11/11 07:46:22
Agreed step function isn't super self explanatory.
| |
16 // where incrementing, decrementing and setting ranges of values has been | |
17 // optimized. The default state for a rangemap is to map all values in | |
18 // KeyType to ValueType(). | |
19 // | |
20 // Set/Increment operations should generally take | |
21 // O(log(N)) + O(M) time where N is the number of ranges in the map and | |
22 // M is the number of modified ranges. | |
23 // | |
24 // Internally, RangeMap<> uses an std::map, where the beginning of each range | |
25 // is stored along with the value for that range. Adjacent ranges which have the | |
26 // same value are automatically merged. For instance, if you did: | |
27 // | |
28 // RangeMap<int, int> tmp; | |
29 // tmp.IncrementRange(2, 5, 2); | |
30 // tmp.IncrementRange(4, 6, 1); | |
31 // | |
32 // Then: | |
33 // tmp[0] = 0 | |
34 // tmp[1] = 0 | |
35 // tmp[2] = 2 | |
36 // tmp[3] = 2 | |
37 // tmp[4] = 3 | |
38 // tmp[5] = 1 | |
39 // tmp[6] = 0 | |
40 // | |
41 // If you iterate over tmp, you get the following ranges: | |
42 // -maxint .. 2 => 0 | |
43 // 2 .. 4 => 2 | |
44 // 4 .. 5 => 3 | |
45 // 5 .. 6 => 1 | |
46 // 6 .. maxint => 0 | |
47 // | |
48 // Internally, this would be stored in a map as: | |
49 // 2:2, 4:3, 5:1, 6:0 | |
50 // | |
51 // TODO(hubbe): Consider consolidating with media::Ranges. | |
52 | |
53 // Simple range class. | |
54 // Range ends are always non-inclusive. | |
55 // Please note that end <= begin is a valid (but empty) range. | |
56 template <typename T> | |
57 struct Range { | |
58 public: | |
59 Range(const T& begin_, const T& end_) : begin(begin_), end(end_) {} | |
xhwang
2015/11/11 01:05:06
I don't think we use |begin_| for non-member varia
hubbe
2015/11/11 01:29:23
I'm pretty sure that results in an "variable used
xhwang
2015/11/11 07:46:22
It should work: http://stackoverflow.com/questions
hubbe
2015/11/12 06:57:43
Done.
| |
60 | |
61 // May return empty ranges (begin >= end). | |
62 Range Intersect(const Range& other) const { | |
63 return Range(std::max(begin, other.begin), std::min(end, other.end)); | |
64 } | |
65 | |
66 bool Empty() const { return begin >= end; } | |
67 | |
68 T begin; | |
69 T end; | |
70 }; | |
71 | |
72 template <typename KeyType, | |
73 typename ValueType, | |
74 class Compare = std::less<KeyType>, | |
75 class Minmax = std::numeric_limits<KeyType>> | |
xhwang
2015/11/11 01:05:06
Minmax can be confusing given we have std::minmax.
hubbe
2015/11/11 01:29:23
I choose you, NumericLimits.
| |
76 class RangeMapConstIterator { | |
77 public: | |
78 typedef std::map<KeyType, ValueType, Compare> MapType; | |
79 RangeMapConstIterator() {} | |
80 RangeMapConstIterator(const MapType* map, | |
81 typename MapType::const_iterator first, | |
82 typename MapType::const_iterator second) | |
83 : map_(map), first_(first), second_(second) {} | |
84 | |
85 bool operator==(const RangeMapConstIterator& other) const { | |
86 return first_ == other.first_ && second_ == other.second_; | |
87 } | |
88 | |
89 bool operator!=(const RangeMapConstIterator& other) const { | |
90 return first_ != other.first_ || second_ != other.second_; | |
91 } | |
92 | |
93 // Returns the beginning of the current range. | |
94 KeyType range_begin() const { | |
95 if (first_ == map_->end()) { | |
96 return Minmax::min(); | |
97 } else { | |
98 return first_->first; | |
99 } | |
100 } | |
101 | |
102 // Returns the end of the current range, non-inclusive. | |
103 KeyType range_end() const { | |
104 if (second_ == map_->end()) { | |
105 return Minmax::max(); | |
106 } else { | |
107 return second_->first; | |
108 } | |
109 } | |
110 | |
111 // Returns the current range. | |
112 Range<KeyType> range() const { | |
113 return Range<KeyType>(range_begin(), range_end()); | |
114 } | |
115 | |
116 // Returns the value associated with the current range. | |
117 ValueType value() const { | |
118 if (first_ == map_->end()) | |
119 return 0; | |
120 return first_->second; | |
121 } | |
122 | |
123 // Needed to make the following construct work: | |
124 // for (const auto& range_value_pair : rangemap) | |
125 // Note however that this will skip the "end" range, which | |
126 // is usually ok since it generally has the default value. | |
127 std::pair<Range<KeyType>, ValueType> operator*() const { | |
128 return std::make_pair(range(), value()); | |
129 } | |
130 | |
131 // Go to the next range. | |
132 // The beginning of the next range always matches the end of the current | |
133 // range. (But should always have a different value.) | |
134 void operator++() { | |
xhwang
2015/11/11 01:05:06
Add a note that the range could be empty after thi
hubbe
2015/11/11 01:29:23
That shouldn't happen.
(Unless you're doing someth
| |
135 first_ = second_; | |
136 second_++; | |
137 } | |
138 | |
139 // Go to the previous range. | |
140 void operator--() { | |
xhwang
2015/11/11 01:05:06
ditto
hubbe
2015/11/11 01:29:23
See comment above.
| |
141 second_ = first_; | |
142 if (first_ == map_->begin()) { | |
143 first_ = map_->end(); | |
144 } else { | |
145 first_--; | |
146 } | |
147 } | |
148 | |
149 private: | |
150 const MapType* map_; | |
151 | |
152 // Pointer to the entry in the RangeMap that specifies the | |
153 // beginning of the current range. (Or map_->end() if we are | |
154 // currently at the first range.) | |
155 typename MapType::const_iterator first_; | |
156 | |
157 // Pointer to the entry in the RangeMap that specifies the | |
158 // end of the current range (non-inclusive) Or, it will | |
159 // point to map_->end() if we are currently at the last range. | |
160 // Note that if there are no entries in map_, both first_ and | |
161 // second_ will point to map_->end(). | |
xhwang
2015/11/11 01:05:06
This could also happen when we are at the first r
hubbe
2015/11/11 01:29:23
Calling operator-- on the first range is not valid
| |
162 typename MapType::const_iterator second_; | |
163 }; | |
164 | |
165 template <typename KeyType, | |
166 typename ValueType, | |
167 class Compare = std::less<KeyType>, | |
168 class Minmax = std::numeric_limits<KeyType>> | |
xhwang
2015/11/11 01:05:06
ditto
hubbe
2015/11/11 01:29:23
Done.
| |
169 class RangeMap { | |
170 public: | |
171 typedef std::map<KeyType, ValueType, Compare> MapType; | |
172 typedef RangeMapConstIterator<KeyType, ValueType, Compare, Minmax> | |
173 const_iterator; | |
174 | |
175 // Returns the value at a particular point. | |
176 // Defaults to ValueType(). | |
177 ValueType operator[](const KeyType& k) const { | |
178 typename MapType::const_iterator i = map_.upper_bound(k); | |
179 if (i == map_.begin()) { | |
180 return 0; | |
181 } else { | |
182 --i; | |
183 return i->second; | |
184 } | |
185 } | |
186 | |
187 // Increase [from..to) by |how_much|. | |
188 void IncrementRange(KeyType from, KeyType to, ValueType how_much) { | |
189 DCHECK_GE(to, from); | |
190 if (from == to || how_much == 0) | |
xhwang
2015/11/11 01:05:06
Why do we allow |from == to|?
hubbe
2015/11/11 01:29:23
No reason I suppose, I don't think I use that beha
| |
191 return; | |
192 typename MapType::iterator a = MakeEntry(from); | |
193 typename MapType::iterator b = MakeEntry(to); | |
194 for (typename MapType::iterator i = a; i != b; ++i) { | |
195 i->second += how_much; | |
196 } | |
197 RemoveDuplicates(a); | |
198 // b may be invalid | |
199 RemoveDuplicates(map_.lower_bound(to)); | |
200 } | |
201 | |
202 // Set [from..to) to |how_much|. | |
203 void SetRange(KeyType from, KeyType to, ValueType how_much) { | |
204 DCHECK_GE(to, from); | |
205 if (from == to) | |
xhwang
2015/11/11 01:05:06
Why do we allow this?
hubbe
2015/11/11 01:29:23
See comment above.
| |
206 return; | |
207 typename MapType::iterator a = MakeEntry(from); | |
208 typename MapType::iterator b = MakeEntry(to); | |
209 a->second = how_much; | |
210 while (true) { | |
211 typename MapType::iterator c = a; | |
212 ++c; | |
213 if (c == b) { | |
214 break; | |
215 } else { | |
216 map_.erase(c); | |
217 } | |
218 } | |
219 RemoveDuplicates(a); | |
220 // b may be invalid | |
221 RemoveDuplicates(map_.lower_bound(to)); | |
222 } | |
223 | |
224 // Returns an iterator to the first range. | |
225 // Note, there is always at least one range. | |
226 const_iterator begin() const { | |
227 return const_iterator(&map(), map_.end(), map_.begin()); | |
228 } | |
229 | |
230 // Returns an iterator to the last range. | |
231 // Note that this works slightly different than most containers | |
232 // as end() returns a valid, but mostly uninteresting iterator. | |
233 // For example, if you have you do: | |
234 // RangeMap<int, int> tmp; | |
235 // tmp.IncrementRange(-5, 5, 1); | |
236 // Then end will return the range [6, maxint) with a value of 0. | |
237 const_iterator end() const { | |
238 if (map_.empty()) { | |
239 return const_iterator(&map(), map_.end(), map_.end()); | |
240 } | |
241 typename MapType::const_iterator i = map_.end(); | |
242 --i; | |
243 return const_iterator(&map(), i, map_.end()); | |
244 } | |
245 | |
246 // Returns an iterator to the range containing |k|. | |
247 // Always returns a valid iterator. | |
248 const_iterator find(KeyType k) const { | |
249 if (map_.empty()) { | |
250 return const_iterator(&map(), map_.end(), map_.end()); | |
251 } | |
252 typename MapType::const_iterator i = map_.upper_bound(k); | |
253 typename MapType::const_iterator j = i; | |
254 if (j == map_.begin()) { | |
255 j = map_.end(); | |
256 } else { | |
257 --j; | |
258 } | |
259 return const_iterator(&map(), j, i); | |
260 } | |
261 | |
262 private: | |
263 const MapType& map() const { return map_; } | |
264 | |
265 // Make an entry in map_ with the key |k| and return it's iterator. | |
266 // If such an entry already exists, just re-use it. | |
267 // If a new entry is created, it's value will be set to the same | |
268 // as the preceeding entry, or ValueType() if no preceeding entry exists. | |
269 // After calling this function, we'll need to call RemoveDuplicates() | |
270 // to clean up any duplicates that we made. | |
271 typename MapType::iterator MakeEntry(KeyType k) { | |
272 typename MapType::value_type tmp(k, 0); | |
273 std::pair<typename MapType::iterator, bool> insert_result; | |
274 insert_result = map_.insert(tmp); | |
275 if (insert_result.second) { | |
276 if (insert_result.first != map_.begin()) { | |
277 typename MapType::iterator i = insert_result.first; | |
278 --i; | |
279 insert_result.first->second = i->second; | |
280 } | |
281 } | |
282 return insert_result.first; | |
283 } | |
284 | |
285 // Remove duplicates before and after |i|. | |
286 void RemoveDuplicates(typename MapType::iterator i) { | |
287 if (i == map_.end()) | |
288 return; | |
289 if (i == map_.begin() && i->second == 0) { | |
290 typename MapType::iterator j = i; | |
291 ++i; | |
292 map_.erase(j); | |
293 if (i == map_.end()) | |
294 return; | |
295 } | |
296 if (i != map_.begin()) { | |
297 typename MapType::iterator j = i; | |
298 --i; | |
299 if (i->second == j->second) { | |
300 map_.erase(j); | |
301 } | |
302 } | |
303 typename MapType::iterator j = i; | |
304 ++j; | |
305 if (j != map_.end() && i->second == j->second) { | |
306 map_.erase(j); | |
307 } | |
308 } | |
309 | |
310 MapType map_; | |
311 }; | |
312 | |
313 } // namespace media | |
314 | |
315 #endif // MEDIA_BLINK_RANGE_MAP_H_ | |
OLD | NEW |