| Index: media/blink/rangemap.h
|
| diff --git a/media/blink/rangemap.h b/media/blink/rangemap.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..afd2b7cc698d7636b2b6b371f8f37d86944d3988
|
| --- /dev/null
|
| +++ b/media/blink/rangemap.h
|
| @@ -0,0 +1,280 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// 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 {
|
| +
|
| +// A RangeMap<KeyType, ValueType> is similar to a std::map<KeyType, ValueType>,
|
| +// where incrementing, decrementing and setting ranges of values has been
|
| +// optimized. Internally, a RangeMap<> keeps a list KeyType ranges and the
|
| +// associated ValueType. Set/Increment operations should generally take
|
| +// O(log(N)) + O(M) time where N is the number of ranges in the map and
|
| +// M is the number of modified ranges. Adjacent ranges which have the same
|
| +// value are automatically merged
|
| +//
|
| +// Internally, RangeMap<> uses an std::map, where the beginning of each range
|
| +// is stored along with the value for that range.
|
| +
|
| +// Simple range class.
|
| +// Range ends are always non-inclusive.
|
| +template<typename T>
|
| +struct Range {
|
| +public:
|
| + Range(const T& begin_, const T& end_) : begin(begin_), end(end_) {}
|
| + T begin;
|
| + T end;
|
| +
|
| + Range Intersect(const Range& other) const {
|
| + return Range(std::max(begin, other.begin), std::min<T>(end, other.end));
|
| + }
|
| +
|
| + bool Empty() const {
|
| + return begin >= end;
|
| + }
|
| +};
|
| +
|
| +template<typename KeyType,
|
| + typename ValueType,
|
| + class Compare = std::less<KeyType>,
|
| + class Minmax = std::numeric_limits<KeyType> >
|
| +class RangeMapConstIterator {
|
| +public:
|
| + typedef std::map<KeyType, ValueType, Compare> 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_;
|
| + }
|
| +
|
| + // Returns the beginning of the current range.
|
| + KeyType range_begin() const {
|
| + if (first_ == map_->end()) {
|
| + return Minmax::min();
|
| + } else {
|
| + return first_->first;
|
| + }
|
| + }
|
| +
|
| + // Returns the end of the current range, non-inclusive.
|
| + KeyType range_end() const {
|
| + if (second_ == map_->end()) {
|
| + return Minmax::max();
|
| + } else {
|
| + return second_->first;
|
| + }
|
| + }
|
| +
|
| + // Returns the current range.
|
| + Range<KeyType> range() const {
|
| + return Range<KeyType>(range_begin(), range_end());
|
| + }
|
| +
|
| + // Returns the value associated with the current range.
|
| + ValueType value() const {
|
| + if (first_ == map_->end())
|
| + return 0;
|
| + return first_->second;
|
| + }
|
| +
|
| + // Needed to make the following construct work:
|
| + // for (const auto& range_value_pair : rangemap)
|
| + // Note however that this will skip the "end" range, which
|
| + // is usually ok since it generally has the default value.
|
| + std::pair<Range<KeyType>, ValueType> operator*() const {
|
| + return std::make_pair(range(), value());
|
| + }
|
| +
|
| + // Go to the next range.
|
| + // The beginning of the next range always matches the end of the current
|
| + // range.
|
| + void operator++() {
|
| + first_ = second_;
|
| + second_++;
|
| + }
|
| +
|
| + // Go to the previous range.
|
| + 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 Compare = std::less<KeyType>,
|
| + class Minmax = std::numeric_limits<KeyType> >
|
| +class RangeMap {
|
| + public:
|
| + typedef std::map<KeyType, ValueType, Compare> MapType;
|
| + typedef RangeMapConstIterator<KeyType, ValueType, Compare, Minmax>
|
| + const_iterator;
|
| +
|
| + // Returns the value at a particular point.
|
| + // Defaults to ValueType().
|
| + 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 |how_much|.
|
| + void IncrementRange(KeyType from, KeyType to, ValueType how_much) {
|
| + DCHECK_GE(to, from);
|
| + if (from == to || how_much == 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 += how_much;
|
| + }
|
| + RemoveDuplicates(a);
|
| + // b may be invalid
|
| + RemoveDuplicates(map_.lower_bound(to));
|
| + }
|
| +
|
| + // Set [from..to) to |how_much|.
|
| + void SetRange(KeyType from, KeyType to, ValueType how_much) {
|
| + DCHECK_GE(to, from);
|
| + if (from == to)
|
| + return;
|
| + typename MapType::iterator a = MakeEntry(from);
|
| + typename MapType::iterator b = MakeEntry(to);
|
| + a->second = how_much;
|
| + 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 begin() const {
|
| + return const_iterator(&map(), map_.end(), map_.begin());
|
| + }
|
| +
|
| + // Returns an iterator to the last range.
|
| + // Note that this works slightly different than most containers
|
| + // as end() returns a valid, but mostly uninteresting iterator.
|
| + // For example, if you have you do:
|
| + // RangeMap<int, int> tmp;
|
| + // tmp.IncrementRange(-5, 5, 1);
|
| + // Then end will return the range [6, maxint) with a value of 0.
|
| + const_iterator end() 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);
|
| + }
|
| +
|
| + private:
|
| + const MapType& map() const { return map_; }
|
| +
|
| + // Make an entry in map_ with the key |k| and return it's iterator.
|
| + // If such an entry already exists, just re-use it.
|
| + // If a new entry is created, it's value will be set to the same
|
| + // as the preceeding entry, or ValueType() if no preceeding entry exists.
|
| + // After calling this function, we'll need to call RemoveDuplicates()
|
| + // to clean up any duplicates that we made.
|
| + 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;
|
| + }
|
| +
|
| + // Remove duplicates before and after |i|.
|
| + 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_
|
|
|