Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: media/blink/interval_map.h

Issue 1422523007: RangeMap: A int->int mapping with fast range operations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lru
Patch Set: comments addressed Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/blink/BUILD.gn ('k') | media/blink/interval_map_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_INTERVAL_MAP_H_
6 #define MEDIA_BLINK_INTERVAL_MAP_H_
7
8 #include <limits>
9 #include <map>
10
11 #include "base/logging.h"
12
13 namespace media {
14
15 // An IntervalMap<KeyType, ValueType> maps every value of KeyType to
16 // a ValueType, and incrementing, decrementing and setting ranges of values
17 // has been optimized. The default state is to map all values in
18 // KeyType to ValueType(). (Which is usually zero.)
19 //
20 // Set/Increment operations should generally take
21 // O(log(N)) + O(M) time where N is the number of intervals in the map and
22 // M is the number of modified intervals.
23 //
24 // Internally, IntervalMap<> uses an std::map, where the beginning of each
25 // interval is stored along with the value for that interval. Adjacent intervals
26 // which have the same value are automatically merged. For instance, if you did:
27 //
28 // IntervalMap<int, int> tmp;
29 // tmp.IncrementInterval(2, 5, 2);
30 // tmp.IncrementInterval(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 intervals:
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 // -maxint:0, 2:2, 4:3, 5:1, 6:0
50 //
51 // TODO(hubbe): Consider consolidating with media::Ranges.
52
53 // Simple interval class.
54 // Interval ends are always non-inclusive.
55 // Please note that end <= begin is a valid (but empty) interval.
56 template <typename T>
57 struct Interval {
58 public:
59 Interval(const T& begin, const T& end) : begin(begin), end(end) {}
60
61 // May return empty intervals (begin >= end).
62 Interval Intersect(const Interval& other) const {
63 return Interval(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 // The IntervalMapConstIterator points to an interval in an
73 // IntervalMap where all values are the same. Calling ++/--
74 // goes to the next/previous interval, which is guaranteed to
75 // have values different from the current interval.
76 template <typename KeyType,
77 typename ValueType,
78 class Compare = std::less<KeyType>,
79 class NumericLimits = std::numeric_limits<KeyType>>
80 class IntervalMapConstIterator {
81 public:
82 typedef std::map<KeyType, ValueType, Compare> MapType;
83 IntervalMapConstIterator() {}
84 IntervalMapConstIterator(const MapType* map,
85 typename MapType::const_iterator iter)
86 : map_(map), iter_(iter) {}
87
88 bool operator==(const IntervalMapConstIterator& other) const {
89 return iter_ == other.iter_;
90 }
91
92 bool operator!=(const IntervalMapConstIterator& other) const {
93 return iter_ != other.iter_;
94 }
95
96 // Returns the beginning of the current interval.
97 KeyType interval_begin() const {
98 DCHECK(iter_ != map_->end());
99 return iter_->first;
100 }
101
102 // Returns the end of the current interval, non-inclusive.
103 KeyType interval_end() const {
104 DCHECK(iter_ != map_->end());
105 typename MapType::const_iterator next = iter_;
106 ++next;
107 if (next == map_->end()) {
108 return NumericLimits::max();
109 } else {
110 return next->first;
111 }
112 }
113
114 // Returns the current interval.
115 Interval<KeyType> interval() const {
116 return Interval<KeyType>(interval_begin(), interval_end());
117 }
118
119 // Returns the value associated with the current interval.
120 ValueType value() const {
121 DCHECK(iter_ != map_->end());
122 return iter_->second;
123 }
124
125 // Needed to make the following construct work:
126 // for (const auto& interval_value_pair : interval_map)
127 // Note however that this will skip the "end" interval, which
128 // is usually ok since it generally has the default value.
129 std::pair<Interval<KeyType>, ValueType> operator*() const {
130 return std::make_pair(interval(), value());
131 }
132
133 // Go to the next interval.
134 // The beginning of the next interval always matches the end of the current
135 // interval. (But should always have a different value.)
136 // Not allowed if we're already at map_->end().
137 void operator++() {
138 DCHECK(iter_ != map_->end());
139 ++iter_;
140 }
141
142 // Go to the previous interval.
143 // The end of the previous interval always matches the beginning of the
144 // current interval. (But should always have a different value.)
145 // Not allowed if we're already at map_->begin().
146 void operator--() {
147 DCHECK(iter_ != map_->begin());
148 --iter_;
149 }
150
151 private:
152 const MapType* map_;
153
154 // Pointer to the entry in the IntervalMap that specifies the
155 // beginning of the current interval.
156 typename MapType::const_iterator iter_;
157 };
158
159 template <typename KeyType,
160 typename ValueType,
161 class Compare = std::less<KeyType>,
162 class NumericLimits = std::numeric_limits<KeyType>>
163 class IntervalMap {
164 public:
165 typedef std::map<KeyType, ValueType, Compare> MapType;
166 typedef IntervalMapConstIterator<KeyType, ValueType, Compare, NumericLimits>
167 const_iterator;
168 IntervalMap() {
169 // Adding an explicit entry for the default interval is not strictly needed,
170 // but simplifies the code a lot.
171 map_[NumericLimits::min()] = ValueType();
172 }
173
174 // Returns the value at a particular point.
175 // Defaults to ValueType().
176 ValueType operator[](const KeyType& k) const {
177 typename MapType::const_iterator i = map_.upper_bound(k);
178 DCHECK(i != map_.begin());
179 --i;
180 return i->second;
181 }
182
183 // Increase [from..to) by |how_much|.
184 void IncrementInterval(KeyType from, KeyType to, ValueType how_much) {
185 DCHECK_GT(to, from);
186 if (how_much == 0)
187 return;
188 typename MapType::iterator a = MakeEntry(from);
189 typename MapType::iterator b = MakeEntry(to);
190 for (typename MapType::iterator i = a; i != b; ++i) {
191 i->second += how_much;
192 }
193 RemoveDuplicates(a);
194 // b may be invalid
195 RemoveDuplicates(map_.lower_bound(to));
196 }
197
198 // Set [from..to) to |how_much|.
199 void SetInterval(KeyType from, KeyType to, ValueType how_much) {
200 DCHECK_GT(to, from);
201 typename MapType::iterator a = MakeEntry(from);
202 typename MapType::iterator b = MakeEntry(to);
203 a->second = how_much;
204 while (true) {
205 typename MapType::iterator c = a;
206 ++c;
207 if (c == b) {
208 break;
209 } else {
210 map_.erase(c);
211 }
212 }
213 RemoveDuplicates(a);
214 // b may be invalid
215 RemoveDuplicates(map_.lower_bound(to));
216 }
217
218 // Returns an iterator to the first interval.
219 // Note, there is always at least one interval.
220 const_iterator begin() const { return const_iterator(&map(), map_.begin()); }
221
222 // Returns an end marker iterator.
223 const_iterator end() const { return const_iterator(&map(), map_.end()); }
224
225 // Returns an iterator to the interval containing |k|.
226 // Always returns a valid iterator.
227 const_iterator find(KeyType k) const {
228 typename MapType::const_iterator iter = map_.upper_bound(k);
229 DCHECK(iter != map_.begin());
230 --iter;
231 return const_iterator(&map(), iter);
232 }
233
234 bool empty() const { return map().size() == 1; }
235 void clear() {
236 map_.clear();
237 map_[NumericLimits::min()] = ValueType();
238 }
239
240 private:
241 const MapType& map() const { return map_; }
242
243 // Make an entry in map_ with the key |k| and return it's iterator.
244 // If such an entry already exists, just re-use it.
245 // If a new entry is created, it's value will be set to the same
246 // as the preceeding entry, or ValueType() if no preceeding entry exists.
247 // After calling this function, we'll need to call RemoveDuplicates()
248 // to clean up any duplicates that we made.
249 typename MapType::iterator MakeEntry(KeyType k) {
250 typename MapType::value_type tmp(k, 0);
251 std::pair<typename MapType::iterator, bool> insert_result;
252 insert_result = map_.insert(tmp);
253 if (insert_result.second) {
254 if (insert_result.first != map_.begin()) {
255 typename MapType::iterator i = insert_result.first;
256 --i;
257 insert_result.first->second = i->second;
258 }
259 }
260 return insert_result.first;
261 }
262
263 // Remove duplicates before and after |i|.
264 void RemoveDuplicates(typename MapType::iterator i) {
265 if (i == map_.end())
266 return;
267
268 typename MapType::iterator first = i;
269 typename MapType::iterator second = i;
270 if (i != map_.begin()) {
271 --first;
272 if (first->second == second->second) {
273 map_.erase(second);
274 second = first;
275 } else {
276 first = second;
277 }
278 }
279 ++second;
280 if (second != map_.end() && first->second == second->second) {
281 map_.erase(second);
282 }
283 }
284
285 MapType map_;
286 };
287
288 } // namespace media
289
290 #endif // MEDIA_BLINK_INTERVAL_MAP_H_
OLDNEW
« no previous file with comments | « media/blink/BUILD.gn ('k') | media/blink/interval_map_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698