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

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: use intptr_t 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 { 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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698