Chromium Code Reviews| Index: media/blink/rangemap.h |
| diff --git a/media/blink/rangemap.h b/media/blink/rangemap.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2b59d683102a9c0511fd5dee04236bc4a5e99d7e |
| --- /dev/null |
| +++ b/media/blink/rangemap.h |
| @@ -0,0 +1,215 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
|
DaleCurtis
2015/10/19 21:45:25
Is this just a std::map<x, Range> ?
https://code.
hubbe
2015/10/20 00:31:39
no
Comment added to explain this class.
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef MEDIA_BLINK_RANGEMAP_H_ |
| +#define MEDIA_BLINK_RANGEMAP_H_ |
| + |
| +#include <limits> |
| +#include <map> |
| + |
| +#include "base/logging.h" |
| + |
| +namespace media { |
| + |
| +template<typename T> |
| +struct Range { |
| +public: |
| + Range(const T& begin_, const T& end_) : begin(begin_), end(end_) {} |
| + T begin; |
| + T end; |
| +}; |
| + |
| +template<typename KeyType, typename ValueType> |
| +class RangeMapConstIterator { |
| +public: |
| + typedef std::map<KeyType, ValueType> MapType; |
| + RangeMapConstIterator() {} |
| + RangeMapConstIterator(const MapType* map, |
| + typename MapType::const_iterator first, |
| + typename MapType::const_iterator second) : |
| + map_(map), |
| + first_(first), |
| + second_(second) { |
| + } |
| + bool operator==(const RangeMapConstIterator& other) { |
| + return first_ == other.first_ && second_ == other.second_; |
| + } |
| + bool operator!=(const RangeMapConstIterator& other) { |
| + return first_ != other.first_ || second_ != other.second_; |
| + } |
| + KeyType range_begin() const { |
| + if (first_ == map_->end()) { |
| + return std::numeric_limits<KeyType>::min(); |
| + } else { |
| + return first_->first; |
| + } |
| + } |
| + KeyType range_end() const { |
| + if (second_ == map_->end()) { |
| + return std::numeric_limits<KeyType>::max(); |
| + } else { |
| + return second_->first; |
| + } |
| + } |
| + Range<KeyType> range() const { |
| + return Range<KeyType>(range_begin(), range_end()); |
| + } |
| + |
| + ValueType value() const { |
| + if (first_ == map_->end()) |
| + return 0; |
| + return first_->second; |
| + } |
| + void operator++() { |
| + first_ = second_; |
| + second_++; |
| + } |
| + void operator--() { |
| + second_ = first_; |
| + if (first_ == map_->begin()) { |
| + first_ = map_->end(); |
| + } else { |
| + first_--; |
| + } |
| + } |
| +private: |
| + const MapType* map_; |
| + typename MapType::const_iterator first_; |
| + typename MapType::const_iterator second_; |
| +}; |
| + |
| +template<typename KeyType, typename ValueType> |
| +class RangeMap { |
| + public: |
| + typedef std::map<KeyType, ValueType> MapType; |
| +typedef RangeMapConstIterator<KeyType, ValueType> const_iterator; |
| + |
| + ValueType operator[](KeyType k) const { |
| + typename MapType::const_iterator i = map_.upper_bound(k); |
| + if (i == map_.begin()) { |
| + return 0; |
| + } else { |
| + --i; |
| + return i->second; |
| + } |
| + } |
| + |
| + // Increase [from..to) by howmuch. |
| + void IncrementRange(KeyType from, KeyType to, ValueType howmuch) { |
| + DCHECK_GE(to, from); |
| + if (from == to || howmuch == 0) |
| + return; |
| + typename MapType::iterator a = MakeEntry(from); |
| + typename MapType::iterator b = MakeEntry(to); |
| + for (typename MapType::iterator i = a; i != b; ++i) { |
| + i->second += howmuch; |
| + } |
| + RemoveDuplicates(a); |
| + // b may be invalid |
| + RemoveDuplicates(map_.lower_bound(to)); |
| + } |
| + |
| + // Set [from..to) to howmuch. |
| + void SetRange(KeyType from, KeyType to, ValueType howmuch) { |
| + DCHECK_GE(to, from); |
| + if (from == to) |
| + return; |
| + typename MapType::iterator a = MakeEntry(from); |
| + typename MapType::iterator b = MakeEntry(to); |
| + a->second = howmuch; |
| + while (true) { |
| + typename MapType::iterator c = a; |
| + ++c; |
| + if (c == b) { |
| + break; |
| + } else { |
| + map_.erase(c); |
| + } |
| + } |
| + RemoveDuplicates(a); |
| + // b may be invalid |
| + RemoveDuplicates(map_.lower_bound(to)); |
| + } |
| + |
| + // Returns an iterator to the first range. |
| + // Note, there is always at least one range. |
| + const_iterator first_range() const { |
| + return const_iterator(&map(), map_.end(), map_.begin()); |
| + } |
| + |
| + // Returns an iterator to the last range. |
| + // Note, there is always at least one range. |
| + const_iterator last_range() const { |
| + if (map_.empty()) { |
| + return const_iterator(&map(), map_.end(), map_.end()); |
| + } |
| + typename MapType::const_iterator i = map_.end(); |
| + --i; |
| + return const_iterator(&map(), i, map_.end()); |
| + } |
| + |
| + // Returns an iterator to the range containing |k|. |
| + // Always returns a valid iterator. |
| + const_iterator find(KeyType k) const { |
| + if (map_.empty()) { |
| + return const_iterator(&map(), map_.end(), map_.end()); |
| + } |
| + typename MapType::const_iterator i = map_.upper_bound(k); |
| + typename MapType::const_iterator j = i; |
| + if (j == map_.begin()) { |
| + j = map_.end(); |
| + } else { |
| + --j; |
| + } |
| + return const_iterator(&map(), j, i); |
| + } |
| + |
| + const MapType& map() const { return map_; } |
| + |
| + private: |
| + typename MapType::iterator MakeEntry(KeyType k) { |
| + typename MapType::value_type tmp(k, 0); |
| + std::pair<typename MapType::iterator, bool> insert_result; |
| + insert_result = map_.insert(tmp); |
| + if (insert_result.second) { |
| + if (insert_result.first != map_.begin()) { |
| + typename MapType::iterator i = insert_result.first; |
| + --i; |
| + insert_result.first->second = i->second; |
| + } |
| + } |
| + return insert_result.first; |
| + } |
| + |
| + void RemoveDuplicates(typename MapType::iterator i) { |
| + if (i == map_.end()) |
| + return; |
| + if (i == map_.begin() && i->second == 0) { |
| + typename MapType::iterator j = i; |
| + ++i; |
| + map_.erase(j); |
| + if (i == map_.end()) |
| + return; |
| + } |
| + if (i != map_.begin()) { |
| + typename MapType::iterator j = i; |
| + --i; |
| + if (i ->second == j->second) { |
| + map_.erase(j); |
| + } |
| + } |
| + typename MapType::iterator j = i; |
| + ++j; |
| + if (j != map_.end() && i ->second == j->second) { |
| + map_.erase(j); |
| + } |
| + } |
| + |
| + MapType map_; |
| +}; |
| + |
| + |
| +} // namespace media |
| + |
| +#endif // MEDIA_BLINK_RANGEMAP_H_ |