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

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

Issue 1165903002: Multi reader/writer cache/buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: refactor 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
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_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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698