tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TimeRanges.cpp (5149B)


      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 #include "mozilla/dom/TimeRanges.h"
      8 
      9 #include "TimeUnits.h"
     10 #include "mozilla/dom/HTMLMediaElement.h"
     11 #include "mozilla/dom/TimeRangesBinding.h"
     12 #include "nsError.h"
     13 
     14 namespace mozilla::dom {
     15 
     16 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TimeRanges, mParent)
     17 NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeRanges)
     18 NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeRanges)
     19 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeRanges)
     20  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     21  NS_INTERFACE_MAP_ENTRY(nsISupports)
     22 NS_INTERFACE_MAP_END
     23 
     24 TimeRanges::TimeRanges() : mParent(nullptr) {}
     25 
     26 TimeRanges::TimeRanges(nsISupports* aParent) : mParent(aParent) {}
     27 
     28 TimeRanges::TimeRanges(nsISupports* aParent,
     29                       const media::TimeIntervals& aTimeIntervals)
     30    : TimeRanges(aParent) {
     31  if (aTimeIntervals.IsInvalid()) {
     32    return;
     33  }
     34  for (const media::TimeInterval& interval : aTimeIntervals) {
     35    Add(interval.mStart.ToSeconds(), interval.mEnd.ToSeconds());
     36  }
     37 }
     38 
     39 TimeRanges::TimeRanges(nsISupports* aParent,
     40                       const media::TimeRanges& aTimeRanges)
     41    : TimeRanges(aParent) {
     42  if (aTimeRanges.IsInvalid()) {
     43    return;
     44  }
     45  for (const media::TimeRange& interval : aTimeRanges) {
     46    Add(interval.mStart, interval.mEnd);
     47  }
     48 }
     49 
     50 TimeRanges::TimeRanges(const media::TimeIntervals& aTimeIntervals)
     51    : TimeRanges(nullptr, aTimeIntervals) {}
     52 
     53 TimeRanges::TimeRanges(const media::TimeRanges& aTimeRanges)
     54    : TimeRanges(nullptr, aTimeRanges) {}
     55 
     56 media::TimeIntervals TimeRanges::ToTimeIntervals() const {
     57  media::TimeIntervals t;
     58  for (uint32_t i = 0; i < Length(); i++) {
     59    t += media::TimeInterval(media::TimeUnit::FromSeconds(Start(i)),
     60                             media::TimeUnit::FromSeconds(End(i)));
     61  }
     62  return t;
     63 }
     64 
     65 TimeRanges::~TimeRanges() = default;
     66 
     67 double TimeRanges::Start(uint32_t aIndex, ErrorResult& aRv) const {
     68  if (aIndex >= mRanges.Length()) {
     69    aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
     70    return 0;
     71  }
     72 
     73  return Start(aIndex);
     74 }
     75 
     76 double TimeRanges::End(uint32_t aIndex, ErrorResult& aRv) const {
     77  if (aIndex >= mRanges.Length()) {
     78    aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
     79    return 0;
     80  }
     81 
     82  return End(aIndex);
     83 }
     84 
     85 void TimeRanges::Add(double aStart, double aEnd) {
     86  if (aStart > aEnd) {
     87    NS_WARNING("Can't add a range if the end is older that the start.");
     88    return;
     89  }
     90  mRanges.AppendElement(TimeRange(aStart, aEnd));
     91 }
     92 
     93 double TimeRanges::GetStartTime() {
     94  if (mRanges.IsEmpty()) {
     95    return -1.0;
     96  }
     97  return mRanges[0].mStart;
     98 }
     99 
    100 double TimeRanges::GetEndTime() {
    101  if (mRanges.IsEmpty()) {
    102    return -1.0;
    103  }
    104  return mRanges[mRanges.Length() - 1].mEnd;
    105 }
    106 
    107 void TimeRanges::Normalize(double aTolerance) {
    108  if (mRanges.Length() >= 2) {
    109    AutoTArray<TimeRange, 4> normalized;
    110 
    111    mRanges.Sort(CompareTimeRanges());
    112 
    113    // This merges the intervals.
    114    TimeRange current(mRanges[0]);
    115    for (uint32_t i = 1; i < mRanges.Length(); i++) {
    116      if (current.mStart <= mRanges[i].mStart &&
    117          current.mEnd >= mRanges[i].mEnd) {
    118        continue;
    119      }
    120      if (current.mEnd + aTolerance >= mRanges[i].mStart) {
    121        current.mEnd = mRanges[i].mEnd;
    122      } else {
    123        normalized.AppendElement(current);
    124        current = mRanges[i];
    125      }
    126    }
    127 
    128    normalized.AppendElement(current);
    129 
    130    mRanges = std::move(normalized);
    131  }
    132 }
    133 
    134 void TimeRanges::Union(const TimeRanges* aOtherRanges, double aTolerance) {
    135  mRanges.AppendElements(aOtherRanges->mRanges);
    136  Normalize(aTolerance);
    137 }
    138 
    139 void TimeRanges::Intersection(const TimeRanges* aOtherRanges) {
    140  AutoTArray<TimeRange, 4> intersection;
    141 
    142  const nsTArray<TimeRange>& otherRanges = aOtherRanges->mRanges;
    143  for (index_type i = 0, j = 0;
    144       i < mRanges.Length() && j < otherRanges.Length();) {
    145    double start = std::max(mRanges[i].mStart, otherRanges[j].mStart);
    146    double end = std::min(mRanges[i].mEnd, otherRanges[j].mEnd);
    147    if (start < end) {
    148      intersection.AppendElement(TimeRange(start, end));
    149    }
    150    if (mRanges[i].mEnd < otherRanges[j].mEnd) {
    151      i += 1;
    152    } else {
    153      j += 1;
    154    }
    155  }
    156 
    157  mRanges = std::move(intersection);
    158 }
    159 
    160 TimeRanges::index_type TimeRanges::Find(double aTime,
    161                                        double aTolerance /* = 0 */) {
    162  for (index_type i = 0; i < mRanges.Length(); ++i) {
    163    if (aTime < mRanges[i].mEnd && (aTime + aTolerance) >= mRanges[i].mStart) {
    164      return i;
    165    }
    166  }
    167  return NoIndex;
    168 }
    169 
    170 JSObject* TimeRanges::WrapObject(JSContext* aCx,
    171                                 JS::Handle<JSObject*> aGivenProto) {
    172  return TimeRanges_Binding::Wrap(aCx, this, aGivenProto);
    173 }
    174 
    175 nsISupports* TimeRanges::GetParentObject() const { return mParent; }
    176 
    177 void TimeRanges::Shift(double aOffset) {
    178  for (index_type i = 0; i < mRanges.Length(); ++i) {
    179    mRanges[i].mStart += aOffset;
    180    mRanges[i].mEnd += aOffset;
    181  }
    182 }
    183 
    184 }  // namespace mozilla::dom