// Copyright 2015 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_INTERVAL_MAP_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_INTERVAL_MAP_H_ #include <algorithm> #include <limits> #include <map> #include "base/check.h" #include "base/memory/raw_ptr.h" #include "base/not_fatal_until.h" #include "third_party/blink/renderer/platform/allow_discouraged_type.h" namespace blink { // An IntervalMap<KeyType, ValueType> maps every value of KeyType to // a ValueType, and incrementing, decrementing and setting ranges of values // has been optimized. The default state is to map all values in // KeyType to ValueType(). (Which is usually zero.) // // Set/Increment operations should generally take // O(log(N)) + O(M) time where N is the number of intervals in the map and // M is the number of modified intervals. // // Internally, IntervalMap<> uses an std::map, where the beginning of each // interval is stored along with the value for that interval. Adjacent intervals // which have the same value are automatically merged. For instance, if you did: // // IntervalMap<int, int> tmp; // tmp.IncrementInterval(2, 5, 2); // tmp.IncrementInterval(4, 6, 1); // // Then: // tmp[0] = 0 // tmp[1] = 0 // tmp[2] = 2 // tmp[3] = 2 // tmp[4] = 3 // tmp[5] = 1 // tmp[6] = 0 // // If you iterate over tmp, you get the following intervals: // -maxint .. 2 => 0 // 2 .. 4 => 2 // 4 .. 5 => 3 // 5 .. 6 => 1 // 6 .. maxint => 0 // // Internally, this would be stored in a map as: // -maxint:0, 2:2, 4:3, 5:1, 6:0 // // TODO(hubbe): Consider consolidating with media::Ranges. // Simple interval class. // Interval ends are always non-inclusive. // Please note that end <= begin is a valid (but empty) interval. template <typename T> struct Interval { … }; // The IntervalMapConstIterator points to an interval in an // IntervalMap where all values are the same. Calling ++/-- // goes to the next/previous interval, which is guaranteed to // have values different from the current interval. template <typename KeyType, typename ValueType, class Compare = std::less<KeyType>, class NumericLimits = std::numeric_limits<KeyType>> class IntervalMapConstIterator { public: typedef std::map<KeyType, ValueType, Compare> MapType; IntervalMapConstIterator() { … } IntervalMapConstIterator(const MapType* map, typename MapType::const_iterator iter) : … { … } bool operator==(const IntervalMapConstIterator& other) const { … } bool operator!=(const IntervalMapConstIterator& other) const { … } // Returns the beginning of the current interval. KeyType interval_begin() const { … } // Returns the end of the current interval, non-inclusive. KeyType interval_end() const { … } // Returns the current interval. Interval<KeyType> interval() const { … } // Returns the value associated with the current interval. ValueType value() const { … } // Needed to make the following construct work: // for (const auto& interval_value_pair : interval_map) std::pair<Interval<KeyType>, ValueType> operator*() const { … } // Go to the next interval. // The beginning of the next interval always matches the end of the current // interval. (But should always have a different value.) // Not allowed if we're already at map_->end(). void operator++() { … } // Go to the previous interval. // The end of the previous interval always matches the beginning of the // current interval. (But should always have a different value.) // Not allowed if we're already at map_->begin(). void operator--() { … } private: raw_ptr<const MapType> map_; // Pointer to the entry in the IntervalMap that specifies the // beginning of the current interval. typename MapType::const_iterator iter_; }; template <typename KeyType, typename ValueType, class Compare = std::less<KeyType>, class NumericLimits = std::numeric_limits<KeyType>> class IntervalMap { public: typedef std::map<KeyType, ValueType, Compare> MapType; typedef IntervalMapConstIterator<KeyType, ValueType, Compare, NumericLimits> const_iterator; IntervalMap() { … } // Returns the value at a particular point. // Defaults to ValueType(). ValueType operator[](const KeyType& k) const { … } // Increase [from..to) by |how_much|. void IncrementInterval(KeyType from, KeyType to, ValueType how_much) { … } // Set [from..to) to |how_much|. void SetInterval(KeyType from, KeyType to, ValueType how_much) { … } // Returns an iterator to the first interval. // Note, there is always at least one interval. const_iterator begin() const { … } // Returns an end marker iterator. const_iterator end() const { … } // Returns an iterator to the interval containing |k|. // Always returns a valid iterator. const_iterator find(KeyType k) const { … } bool empty() const { … } void clear() { … } private: const MapType& map() const { … } // 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) { … } // Remove duplicates before and after |i|. void RemoveDuplicates(typename MapType::iterator i) { … } MapType map_ ALLOW_DISCOURAGED_TYPE("HashMap lacks key sorting."); }; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_INTERVAL_MAP_H_