LCOV - code coverage report
Current view: top level - dom/media - Intervals.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 281 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 118 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef INTERVALS_H
       8             : #define INTERVALS_H
       9             : 
      10             : #include <algorithm>
      11             : #include "mozilla/TypeTraits.h"
      12             : #include "nsTArray.h"
      13             : 
      14             : // Specialization for nsTArray CopyChooser.
      15             : namespace mozilla {
      16             : namespace media {
      17             : template<class T>
      18             : class IntervalSet;
      19             : } // namespace media
      20             : } // namespace mozilla
      21             : 
      22             : template<class E>
      23             : struct nsTArray_CopyChooser<mozilla::media::IntervalSet<E>>
      24             : {
      25             :   typedef nsTArray_CopyWithConstructors<mozilla::media::IntervalSet<E>> Type;
      26             : };
      27             : 
      28             : namespace mozilla {
      29             : namespace media {
      30             : 
      31             : /* Interval defines an interval between two points. Unlike a traditional
      32             :    interval [A,B] where A <= x <= B, the upper boundary B is exclusive: A <= x < B
      33             :    (e.g [A,B[ or [A,B) depending on where you're living)
      34             :    It provides basic interval arithmetic and fuzzy edges.
      35             :    The type T must provides a default constructor and +, -, <, <= and ==
      36             :    operators.
      37             :  */
      38             : template<typename T>
      39             : class Interval
      40             : {
      41             : public:
      42             :   typedef Interval<T> SelfType;
      43             : 
      44           0 :   Interval()
      45             :     : mStart(T())
      46             :     , mEnd(T())
      47           0 :     , mFuzz(T())
      48           0 :   { }
      49             : 
      50             :   template<typename StartArg, typename EndArg>
      51           0 :   Interval(StartArg&& aStart, EndArg&& aEnd)
      52           0 :     : mStart(Forward<StartArg>(aStart))
      53           0 :     , mEnd(Forward<EndArg>(aEnd))
      54           0 :     , mFuzz()
      55             :   {
      56           0 :     MOZ_ASSERT(aStart <= aEnd);
      57           0 :   }
      58             : 
      59             :   template<typename StartArg, typename EndArg, typename FuzzArg>
      60           0 :   Interval(StartArg&& aStart, EndArg&& aEnd, FuzzArg&& aFuzz)
      61           0 :     : mStart(Forward<StartArg>(aStart))
      62           0 :     , mEnd(Forward<EndArg>(aEnd))
      63           0 :     , mFuzz(Forward<FuzzArg>(aFuzz))
      64             :   {
      65           0 :     MOZ_ASSERT(aStart <= aEnd);
      66           0 :   }
      67             : 
      68           0 :   Interval(const SelfType& aOther)
      69           0 :     : mStart(aOther.mStart)
      70           0 :     , mEnd(aOther.mEnd)
      71           0 :     , mFuzz(aOther.mFuzz)
      72           0 :   { }
      73             : 
      74           0 :   Interval(SelfType&& aOther)
      75           0 :     : mStart(Move(aOther.mStart))
      76           0 :     , mEnd(Move(aOther.mEnd))
      77           0 :     , mFuzz(Move(aOther.mFuzz))
      78           0 :   { }
      79             : 
      80           0 :   SelfType& operator= (const SelfType& aOther)
      81             :   {
      82           0 :     mStart = aOther.mStart;
      83           0 :     mEnd = aOther.mEnd;
      84           0 :     mFuzz = aOther.mFuzz;
      85           0 :     return *this;
      86             :   }
      87             : 
      88           0 :   SelfType& operator= (SelfType&& aOther)
      89             :   {
      90           0 :     MOZ_ASSERT(&aOther != this, "self-moves are prohibited");
      91             :     this->~Interval();
      92           0 :     new(this) Interval(Move(aOther));
      93           0 :     return *this;
      94             :   }
      95             : 
      96             :   // Basic interval arithmetic operator definition.
      97             :   SelfType operator+ (const SelfType& aOther) const
      98             :   {
      99             :     return SelfType(mStart + aOther.mStart,
     100             :                     mEnd + aOther.mEnd,
     101             :                     mFuzz + aOther.mFuzz);
     102             :   }
     103             : 
     104           0 :   SelfType operator+ (const T& aVal) const
     105             :   {
     106           0 :     return SelfType(mStart + aVal, mEnd + aVal, mFuzz);
     107             :   }
     108             : 
     109             :   // Basic interval arithmetic operator definition.
     110             :   SelfType operator- (const SelfType& aOther) const
     111             :   {
     112             :     return SelfType(mStart - aOther.mEnd,
     113             :                     mEnd - aOther.mStart,
     114             :                     mFuzz + aOther.mFuzz);
     115             :   }
     116             : 
     117             :   SelfType operator- (const T& aVal) const
     118             :   {
     119             :     return SelfType(mStart - aVal, mEnd - aVal, mFuzz);
     120             :   }
     121             : 
     122           0 :   bool operator== (const SelfType& aOther) const
     123             :   {
     124           0 :     return mStart == aOther.mStart && mEnd == aOther.mEnd;
     125             :   }
     126             : 
     127             :   bool operator!= (const SelfType& aOther) const
     128             :   {
     129             :     return !(*this == aOther);
     130             :   }
     131             : 
     132           0 :   bool Contains(const T& aX) const
     133             :   {
     134           0 :     return mStart - mFuzz <= aX && aX < mEnd + mFuzz;
     135             :   }
     136             : 
     137           0 :   bool ContainsStrict(const T& aX) const
     138             :   {
     139           0 :     return mStart <= aX && aX < mEnd;
     140             :   }
     141             : 
     142           0 :   bool ContainsWithStrictEnd(const T& aX) const
     143             :   {
     144           0 :     return mStart - mFuzz <= aX && aX < mEnd;
     145             :   }
     146             : 
     147           0 :   bool Contains(const SelfType& aOther) const
     148             :   {
     149           0 :     return (mStart - mFuzz <= aOther.mStart + aOther.mFuzz)
     150           0 :            && (aOther.mEnd - aOther.mFuzz <= mEnd + mFuzz);
     151             :   }
     152             : 
     153           0 :   bool ContainsStrict(const SelfType& aOther) const
     154             :   {
     155           0 :     return mStart <= aOther.mStart && aOther.mEnd <= mEnd;
     156             :   }
     157             : 
     158           0 :   bool ContainsWithStrictEnd(const SelfType& aOther) const
     159             :   {
     160           0 :     return (mStart - mFuzz <= aOther.mStart + aOther.mFuzz)
     161           0 :            && aOther.mEnd <= mEnd;
     162             :   }
     163             : 
     164           0 :   bool Intersects(const SelfType& aOther) const
     165             :   {
     166           0 :     return (mStart - mFuzz < aOther.mEnd + aOther.mFuzz)
     167           0 :            && (aOther.mStart - aOther.mFuzz < mEnd + mFuzz);
     168             :   }
     169             : 
     170           0 :   bool IntersectsStrict(const SelfType& aOther) const
     171             :   {
     172           0 :     return mStart < aOther.mEnd && aOther.mStart < mEnd;
     173             :   }
     174             : 
     175             :   // Same as Intersects, but including the boundaries.
     176           0 :   bool Touches(const SelfType& aOther) const
     177             :   {
     178           0 :     return (mStart - mFuzz <= aOther.mEnd + aOther.mFuzz)
     179           0 :            && (aOther.mStart - aOther.mFuzz <= mEnd + mFuzz);
     180             :   }
     181             : 
     182             :   // Returns true if aOther is strictly to the right of this and contiguous.
     183             :   // This operation isn't commutative.
     184             :   bool Contiguous(const SelfType& aOther) const
     185             :   {
     186             :     return mEnd <= aOther.mStart && aOther.mStart - mEnd <= mFuzz + aOther.mFuzz;
     187             :   }
     188             : 
     189           0 :   bool RightOf(const SelfType& aOther) const
     190             :   {
     191           0 :     return aOther.mEnd - aOther.mFuzz <= mStart + mFuzz;
     192             :   }
     193             : 
     194           0 :   bool LeftOf(const SelfType& aOther) const
     195             :   {
     196           0 :     return mEnd - mFuzz <= aOther.mStart + aOther.mFuzz;
     197             :   }
     198             : 
     199           0 :   SelfType Span(const SelfType& aOther) const
     200             :   {
     201           0 :     if (IsEmpty()) {
     202           0 :       return aOther;
     203             :     }
     204           0 :     SelfType result(*this);
     205           0 :     if (aOther.mStart < mStart) {
     206           0 :       result.mStart = aOther.mStart;
     207             :     }
     208           0 :     if (mEnd < aOther.mEnd) {
     209           0 :       result.mEnd = aOther.mEnd;
     210             :     }
     211           0 :     if (mFuzz < aOther.mFuzz) {
     212           0 :       result.mFuzz = aOther.mFuzz;
     213             :     }
     214           0 :     return result;
     215             :   }
     216             : 
     217           0 :   SelfType Intersection(const SelfType& aOther) const
     218             :   {
     219           0 :     const T& s = std::max(mStart, aOther.mStart);
     220           0 :     const T& e = std::min(mEnd, aOther.mEnd);
     221           0 :     const T& f = std::max(mFuzz, aOther.mFuzz);
     222           0 :     if (s < e) {
     223           0 :       return SelfType(s, e, f);
     224             :     }
     225             :     // Return an empty interval.
     226           0 :     return SelfType();
     227             :   }
     228             : 
     229           0 :   T Length() const
     230             :   {
     231           0 :     return mEnd - mStart;
     232             :   }
     233             : 
     234           0 :   bool IsEmpty() const
     235             :   {
     236           0 :     return mStart == mEnd;
     237             :   }
     238             : 
     239           0 :   void SetFuzz(const T& aFuzz)
     240             :   {
     241           0 :     mFuzz = aFuzz;
     242           0 :   }
     243             : 
     244             :   // Returns true if the two intervals intersect with this being on the right
     245             :   // of aOther
     246           0 :   bool TouchesOnRight(const SelfType& aOther) const
     247             :   {
     248           0 :     return aOther.mStart <= mStart
     249           0 :            && (mStart - mFuzz <= aOther.mEnd + aOther.mFuzz)
     250           0 :            && (aOther.mStart - aOther.mFuzz <= mEnd + mFuzz);
     251             :   }
     252             : 
     253             :   T mStart;
     254             :   T mEnd;
     255             :   T mFuzz;
     256             : 
     257             : private:
     258             : };
     259             : 
     260             : // An IntervalSet in a collection of Intervals. The IntervalSet is always
     261             : // normalized.
     262             : template<typename T>
     263             : class IntervalSet
     264             : {
     265             : public:
     266             :   typedef IntervalSet<T> SelfType;
     267             :   typedef Interval<T> ElemType;
     268             :   typedef AutoTArray<ElemType,4> ContainerType;
     269             :   typedef typename ContainerType::index_type IndexType;
     270             : 
     271           0 :   IntervalSet()
     272           0 :   {
     273           0 :   }
     274           0 :   virtual ~IntervalSet()
     275             :   {
     276           0 :   }
     277             : 
     278           0 :   IntervalSet(const SelfType& aOther)
     279           0 :     : mIntervals(aOther.mIntervals)
     280             :   {
     281           0 :   }
     282             : 
     283           0 :   IntervalSet(SelfType&& aOther)
     284           0 :   {
     285           0 :     mIntervals.AppendElements(Move(aOther.mIntervals));
     286           0 :   }
     287             : 
     288             :   explicit IntervalSet(const ElemType& aOther)
     289             :   {
     290             :     if (!aOther.IsEmpty()) {
     291             :       mIntervals.AppendElement(aOther);
     292             :     }
     293             :   }
     294             : 
     295           0 :   explicit IntervalSet(ElemType&& aOther)
     296           0 :   {
     297           0 :     if (!aOther.IsEmpty()) {
     298           0 :       mIntervals.AppendElement(Move(aOther));
     299             :     }
     300           0 :   }
     301             : 
     302           0 :   bool operator== (const SelfType& aOther) const
     303             :   {
     304           0 :     return mIntervals == aOther.mIntervals;
     305             :   }
     306             : 
     307           0 :   bool operator!= (const SelfType& aOther) const
     308             :   {
     309           0 :     return mIntervals != aOther.mIntervals;
     310             :   }
     311             : 
     312           0 :   SelfType& operator= (const SelfType& aOther)
     313             :   {
     314           0 :     mIntervals = aOther.mIntervals;
     315           0 :     return *this;
     316             :   }
     317             : 
     318           0 :   SelfType& operator= (SelfType&& aOther)
     319             :   {
     320           0 :     MOZ_ASSERT(&aOther != this, "self-moves are prohibited");
     321           0 :     this->~IntervalSet();
     322           0 :     new(this) IntervalSet(Move(aOther));
     323           0 :     return *this;
     324             :   }
     325             : 
     326             :   SelfType& operator= (const ElemType& aInterval)
     327             :   {
     328             :     mIntervals.Clear();
     329             :     if (!aInterval.IsEmpty()) {
     330             :       mIntervals.AppendElement(aInterval);
     331             :     }
     332             :     return *this;
     333             :   }
     334             : 
     335             :   SelfType& operator= (ElemType&& aInterval)
     336             :   {
     337             :     mIntervals.Clear();
     338             :     if (!aInterval.IsEmpty()) {
     339             :       mIntervals.AppendElement(Move(aInterval));
     340             :     }
     341             :     return *this;
     342             :   }
     343             : 
     344           0 :   SelfType& Add(const SelfType& aIntervals)
     345             :   {
     346           0 :     mIntervals.AppendElements(aIntervals.mIntervals);
     347           0 :     Normalize();
     348           0 :     return *this;
     349             :   }
     350             : 
     351           0 :   SelfType& Add(const ElemType& aInterval)
     352             :   {
     353           0 :     if (aInterval.IsEmpty()) {
     354           0 :       return *this;
     355             :     }
     356           0 :     if (mIntervals.IsEmpty()) {
     357           0 :       mIntervals.AppendElement(aInterval);
     358           0 :       return *this;
     359             :     }
     360           0 :     ElemType& last = mIntervals.LastElement();
     361           0 :     if (aInterval.TouchesOnRight(last)) {
     362           0 :       last = last.Span(aInterval);
     363           0 :       return *this;
     364             :     }
     365             :     // Most of our actual usage is adding an interval that will be outside the
     366             :     // range. We can speed up normalization here.
     367           0 :     if (aInterval.RightOf(last)) {
     368           0 :       mIntervals.AppendElement(aInterval);
     369           0 :       return *this;
     370             :     }
     371             : 
     372           0 :     ContainerType normalized;
     373           0 :     ElemType current(aInterval);
     374           0 :     IndexType i = 0;
     375           0 :     for (; i < mIntervals.Length(); i++) {
     376           0 :       ElemType& interval = mIntervals[i];
     377           0 :       if (current.Touches(interval)) {
     378           0 :         current = current.Span(interval);
     379           0 :       } else if (current.LeftOf(interval)) {
     380           0 :         break;
     381             :       } else {
     382           0 :         normalized.AppendElement(Move(interval));
     383             :       }
     384             :     }
     385           0 :     normalized.AppendElement(Move(current));
     386           0 :     for (; i < mIntervals.Length(); i++) {
     387           0 :       normalized.AppendElement(Move(mIntervals[i]));
     388             :     }
     389           0 :     mIntervals.Clear();
     390           0 :     mIntervals.AppendElements(Move(normalized));
     391             : 
     392           0 :     return *this;
     393             :   }
     394             : 
     395           0 :   SelfType& operator+= (const SelfType& aIntervals)
     396             :   {
     397           0 :     Add(aIntervals);
     398           0 :     return *this;
     399             :   }
     400             : 
     401           0 :   SelfType& operator+= (const ElemType& aInterval)
     402             :   {
     403           0 :     Add(aInterval);
     404           0 :     return *this;
     405             :   }
     406             : 
     407             :   SelfType operator+ (const SelfType& aIntervals) const
     408             :   {
     409             :     SelfType intervals(*this);
     410             :     intervals.Add(aIntervals);
     411             :     return intervals;
     412             :   }
     413             : 
     414           0 :   SelfType operator+ (const ElemType& aInterval) const
     415             :   {
     416           0 :     SelfType intervals(*this);
     417           0 :     intervals.Add(aInterval);
     418           0 :     return intervals;
     419             :   }
     420             : 
     421             :   friend SelfType operator+ (const ElemType& aInterval,
     422             :                              const SelfType& aIntervals)
     423             :   {
     424             :     SelfType intervals;
     425             :     intervals.Add(aInterval);
     426             :     intervals.Add(aIntervals);
     427             :     return intervals;
     428             :   }
     429             : 
     430             :   // Excludes an interval from an IntervalSet.
     431             :   // This is done by inverting aInterval within the bounds of mIntervals
     432             :   // and then doing the intersection.
     433           0 :   SelfType& operator-= (const ElemType& aInterval)
     434             :   {
     435           0 :     if (aInterval.IsEmpty() || mIntervals.IsEmpty()) {
     436           0 :       return *this;
     437             :     }
     438           0 :     T firstEnd = std::max(mIntervals[0].mStart, aInterval.mStart);
     439           0 :     T secondStart = std::min(mIntervals.LastElement().mEnd, aInterval.mEnd);
     440           0 :     ElemType startInterval(mIntervals[0].mStart, firstEnd);
     441           0 :     ElemType endInterval(secondStart, mIntervals.LastElement().mEnd);
     442           0 :     SelfType intervals(Move(startInterval));
     443           0 :     intervals += Move(endInterval);
     444           0 :     return Intersection(intervals);
     445             :   }
     446             : 
     447           0 :   SelfType& operator-= (const SelfType& aIntervals)
     448             :   {
     449           0 :     for (const auto& interval : aIntervals.mIntervals) {
     450           0 :       *this -= interval;
     451             :     }
     452           0 :     return *this;
     453             :   }
     454             : 
     455             :   SelfType operator- (const SelfType& aInterval) const
     456             :   {
     457             :     SelfType intervals(*this);
     458             :     intervals -= aInterval;
     459             :     return intervals;
     460             :   }
     461             : 
     462             :   SelfType operator- (const ElemType& aInterval) const
     463             :   {
     464             :     SelfType intervals(*this);
     465             :     intervals -= aInterval;
     466             :     return intervals;
     467             :   }
     468             : 
     469             :   // Mutate this IntervalSet to be the union of this and aOther.
     470             :   SelfType& Union(const SelfType& aOther)
     471             :   {
     472             :     Add(aOther);
     473             :     return *this;
     474             :   }
     475             : 
     476             :   SelfType& Union(const ElemType& aInterval)
     477             :   {
     478             :     Add(aInterval);
     479             :     return *this;
     480             :   }
     481             : 
     482             :   // Mutate this TimeRange to be the intersection of this and aOther.
     483           0 :   SelfType& Intersection(const SelfType& aOther)
     484             :   {
     485           0 :     ContainerType intersection;
     486             : 
     487           0 :     const ContainerType& other = aOther.mIntervals;
     488           0 :     IndexType i = 0, j = 0;
     489           0 :     for (; i < mIntervals.Length() && j < other.Length();) {
     490           0 :       if (mIntervals[i].IntersectsStrict(other[j])) {
     491           0 :         intersection.AppendElement(mIntervals[i].Intersection(other[j]));
     492             :       }
     493           0 :       if (mIntervals[i].mEnd < other[j].mEnd) {
     494           0 :         i++;
     495             :       } else {
     496           0 :         j++;
     497             :       }
     498             :     }
     499           0 :     mIntervals.Clear();
     500           0 :     mIntervals.AppendElements(Move(intersection));
     501           0 :     return *this;
     502             :   }
     503             : 
     504             :   SelfType& Intersection(const ElemType& aInterval)
     505             :   {
     506             :     SelfType intervals(aInterval);
     507             :     return Intersection(intervals);
     508             :   }
     509             : 
     510           0 :   const ElemType& operator[] (IndexType aIndex) const
     511             :   {
     512           0 :     return mIntervals[aIndex];
     513             :   }
     514             : 
     515             :   // Returns the start boundary of the first interval. Or a default constructed
     516             :   // T if IntervalSet is empty (and aExists if provided will be set to false).
     517           0 :   T GetStart(bool* aExists = nullptr) const
     518             :   {
     519           0 :     bool exists = !mIntervals.IsEmpty();
     520             : 
     521           0 :     if (aExists) {
     522           0 :       *aExists = exists;
     523             :     }
     524             : 
     525           0 :     if (exists) {
     526           0 :       return mIntervals[0].mStart;
     527             :     } else {
     528           0 :       return T();
     529             :     }
     530             :   }
     531             : 
     532             :   // Returns the end boundary of the last interval. Or a default constructed T
     533             :   // if IntervalSet is empty (and aExists if provided will be set to false).
     534           0 :   T GetEnd(bool* aExists = nullptr) const
     535             :   {
     536           0 :     bool exists = !mIntervals.IsEmpty();
     537           0 :     if (aExists) {
     538           0 :       *aExists = exists;
     539             :     }
     540             : 
     541           0 :     if (exists) {
     542           0 :       return mIntervals.LastElement().mEnd;
     543             :     } else {
     544           0 :       return T();
     545             :     }
     546             :   }
     547             : 
     548           0 :   IndexType Length() const
     549             :   {
     550           0 :     return mIntervals.Length();
     551             :   }
     552             : 
     553           0 :   T Start(IndexType aIndex) const
     554             :   {
     555           0 :     return mIntervals[aIndex].mStart;
     556             :   }
     557             : 
     558             :   T Start(IndexType aIndex, bool& aExists) const
     559             :   {
     560             :     aExists = aIndex < mIntervals.Length();
     561             : 
     562             :     if (aExists) {
     563             :       return mIntervals[aIndex].mStart;
     564             :     } else {
     565             :       return T();
     566             :     }
     567             :   }
     568             : 
     569           0 :   T End(IndexType aIndex) const
     570             :   {
     571           0 :     return mIntervals[aIndex].mEnd;
     572             :   }
     573             : 
     574             :   T End(IndexType aIndex, bool& aExists) const
     575             :   {
     576             :     aExists = aIndex < mIntervals.Length();
     577             : 
     578             :     if (aExists) {
     579             :       return mIntervals[aIndex].mEnd;
     580             :     } else {
     581             :       return T();
     582             :     }
     583             :   }
     584             : 
     585           0 :   bool Contains(const ElemType& aInterval) const
     586             :   {
     587           0 :     for (const auto& interval : mIntervals) {
     588           0 :       if (interval.Contains(aInterval)) {
     589           0 :         return true;
     590             :       }
     591             :     }
     592           0 :     return false;
     593             :   }
     594             : 
     595           0 :   bool ContainsStrict(const ElemType& aInterval) const
     596             :   {
     597           0 :     for (const auto& interval : mIntervals) {
     598           0 :       if (interval.ContainsStrict(aInterval)) {
     599           0 :         return true;
     600             :       }
     601             :     }
     602           0 :     return false;
     603             :   }
     604             : 
     605             :   bool Contains(const T& aX) const
     606             :   {
     607             :     for (const auto& interval : mIntervals)
     608             :     {
     609             :       if (interval.Contains(aX)) {
     610             :         return true;
     611             :       }
     612             :     }
     613             :     return false;
     614             :   }
     615             : 
     616             :   bool ContainsStrict(const T& aX) const
     617             :   {
     618             :     for (const auto& interval : mIntervals) {
     619             :       if (interval.ContainsStrict(aX)) {
     620             :         return true;
     621             :       }
     622             :     }
     623             :     return false;
     624             :   }
     625             : 
     626           0 :   bool ContainsWithStrictEnd(const T& aX) const
     627             :   {
     628           0 :     for (const auto& interval : mIntervals) {
     629           0 :       if (interval.ContainsWithStrictEnd(aX)) {
     630           0 :         return true;
     631             :       }
     632             :     }
     633           0 :     return false;
     634             :   }
     635             : 
     636             :   // Shift all values by aOffset.
     637           0 :   SelfType& Shift(const T& aOffset)
     638             :   {
     639           0 :     for (auto& interval : mIntervals) {
     640           0 :       interval.mStart = interval.mStart + aOffset;
     641           0 :       interval.mEnd = interval.mEnd + aOffset;
     642             :     }
     643           0 :     return *this;
     644             :   }
     645             : 
     646           0 :   void SetFuzz(const T& aFuzz)
     647             :   {
     648           0 :     for (auto& interval : mIntervals) {
     649           0 :       interval.SetFuzz(aFuzz);
     650             :     }
     651           0 :     Normalize();
     652           0 :   }
     653             : 
     654             :   static const IndexType NoIndex = IndexType(-1);
     655             : 
     656           0 :   IndexType Find(const T& aValue) const
     657             :   {
     658           0 :     for (IndexType i = 0; i < mIntervals.Length(); i++) {
     659           0 :       if (mIntervals[i].Contains(aValue)) {
     660           0 :         return i;
     661             :       }
     662             :     }
     663           0 :     return NoIndex;
     664             :   }
     665             : 
     666             :   // Methods for range-based for loops.
     667           0 :   typename ContainerType::iterator begin()
     668             :   {
     669           0 :     return mIntervals.begin();
     670             :   }
     671             : 
     672           0 :   typename ContainerType::const_iterator begin() const
     673             :   {
     674           0 :     return mIntervals.begin();
     675             :   }
     676             : 
     677           0 :   typename ContainerType::iterator end()
     678             :   {
     679           0 :     return mIntervals.end();
     680             :   }
     681             : 
     682           0 :   typename ContainerType::const_iterator end() const
     683             :   {
     684           0 :     return mIntervals.end();
     685             :   }
     686             : 
     687             :   ElemType& LastInterval()
     688             :   {
     689             :     MOZ_ASSERT(!mIntervals.IsEmpty());
     690             :     return mIntervals.LastElement();
     691             :   }
     692             : 
     693           0 :   const ElemType& LastInterval() const
     694             :   {
     695           0 :     MOZ_ASSERT(!mIntervals.IsEmpty());
     696           0 :     return mIntervals.LastElement();
     697             :   }
     698             : 
     699           0 :   void Clear()
     700             :   {
     701           0 :     mIntervals.Clear();
     702           0 :   }
     703             : 
     704             : protected:
     705             :   ContainerType mIntervals;
     706             : 
     707             : private:
     708           0 :   void Normalize()
     709             :   {
     710           0 :     if (mIntervals.Length() >= 2) {
     711           0 :       ContainerType normalized;
     712             : 
     713           0 :       mIntervals.Sort(CompareIntervals());
     714             : 
     715             :       // This merges the intervals.
     716           0 :       ElemType current(mIntervals[0]);
     717           0 :       for (IndexType i = 1; i < mIntervals.Length(); i++) {
     718           0 :         ElemType& interval = mIntervals[i];
     719           0 :         if (current.Touches(interval)) {
     720           0 :           current = current.Span(interval);
     721             :         } else {
     722           0 :           normalized.AppendElement(Move(current));
     723           0 :           current = Move(interval);
     724             :         }
     725             :       }
     726           0 :       normalized.AppendElement(Move(current));
     727             : 
     728           0 :       mIntervals.Clear();
     729           0 :       mIntervals.AppendElements(Move(normalized));
     730             :     }
     731           0 :   }
     732             : 
     733             :   struct CompareIntervals
     734             :   {
     735           0 :     bool Equals(const ElemType& aT1, const ElemType& aT2) const
     736             :     {
     737           0 :       return aT1.mStart == aT2.mStart && aT1.mEnd == aT2.mEnd;
     738             :     }
     739             : 
     740           0 :     bool LessThan(const ElemType& aT1, const ElemType& aT2) const {
     741           0 :       return aT1.mStart - aT1.mFuzz < aT2.mStart + aT2.mFuzz;
     742             :     }
     743             :   };
     744             : };
     745             : 
     746             :   // clang doesn't allow for this to be defined inline of IntervalSet.
     747             : template<typename T>
     748             : IntervalSet<T> Union(const IntervalSet<T>& aIntervals1,
     749             :                      const IntervalSet<T>& aIntervals2)
     750             : {
     751             :   IntervalSet<T> intervals(aIntervals1);
     752             :   intervals.Union(aIntervals2);
     753             :   return intervals;
     754             : }
     755             : 
     756             : template<typename T>
     757           0 : IntervalSet<T> Intersection(const IntervalSet<T>& aIntervals1,
     758             :                             const IntervalSet<T>& aIntervals2)
     759             : {
     760           0 :   IntervalSet<T> intersection(aIntervals1);
     761           0 :   intersection.Intersection(aIntervals2);
     762           0 :   return intersection;
     763             : }
     764             : 
     765             : } // namespace media
     766             : } // namespace mozilla
     767             : 
     768             : #endif // INTERVALS_H

Generated by: LCOV version 1.13