tor-browser

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

MediaSpan.h (4537B)


      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 #ifndef MediaSpan_h
      7 #define MediaSpan_h
      8 
      9 #include "MediaData.h"
     10 #include "mozilla/RefPtr.h"
     11 
     12 namespace mozilla {
     13 
     14 // A MediaSpan wraps a MediaByteBuffer and exposes a slice/span, or subregion,
     15 // of the buffer. This allows you to slice off a logical subregion without
     16 // needing to reallocate a new buffer to hold it. You can also append to a
     17 // MediaSpan without affecting other MediaSpans referencing the same buffer
     18 // (the MediaSpan receiving the append will allocate a new buffer to store its
     19 // result if necessary, to ensure other MediaSpans referencing its original
     20 // buffer are unaffected). Note there are no protections here that something
     21 // other than MediaSpans doesn't modify the underlying MediaByteBuffer while
     22 // a MediaSpan is alive.
     23 class MediaSpan {
     24 public:
     25  ~MediaSpan() = default;
     26 
     27  explicit MediaSpan(const MediaSpan& aOther) = default;
     28 
     29  MediaSpan(MediaSpan&& aOther) = default;
     30 
     31  explicit MediaSpan(const RefPtr<MediaByteBuffer>& aBuffer)
     32      : mBuffer(aBuffer), mStart(0), mLength(aBuffer ? aBuffer->Length() : 0) {
     33    MOZ_DIAGNOSTIC_ASSERT(mBuffer);
     34  }
     35 
     36  explicit MediaSpan(MediaByteBuffer* aBuffer)
     37      : mBuffer(aBuffer), mStart(0), mLength(aBuffer ? aBuffer->Length() : 0) {
     38    MOZ_DIAGNOSTIC_ASSERT(mBuffer);
     39  }
     40 
     41  MediaSpan& operator=(const MediaSpan& aOther) = default;
     42 
     43  static MediaSpan WithCopyOf(const RefPtr<MediaByteBuffer>& aBuffer) {
     44    RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer(aBuffer->Length());
     45    buffer->AppendElements(*aBuffer);
     46    return MediaSpan(buffer);
     47  }
     48 
     49  bool IsEmpty() const { return Length() == 0; }
     50 
     51  // Note: It's unsafe to store the pointer returned by this function, as an
     52  // append operation could cause the wrapped MediaByteBuffer to be
     53  // reallocated, invalidating pointers previously returned by this function.
     54  const uint8_t* Elements() const {
     55    MOZ_DIAGNOSTIC_ASSERT(mStart < mBuffer->Length());
     56    return mBuffer->Elements() + mStart;
     57  }
     58 
     59  size_t Length() const { return mLength; }
     60 
     61  uint8_t operator[](size_t aIndex) const {
     62    MOZ_DIAGNOSTIC_ASSERT(aIndex < Length());
     63    return (*mBuffer)[mStart + aIndex];
     64  }
     65 
     66  bool Append(const MediaSpan& aBuffer) { return Append(aBuffer.Buffer()); }
     67 
     68  bool Append(MediaByteBuffer* aBuffer) {
     69    if (!aBuffer) {
     70      return true;
     71    }
     72    if (mStart + mLength < mBuffer->Length()) {
     73      // This MediaSpan finishes before the end of its buffer. The buffer
     74      // could be shared with another MediaSpan. So we can't just append to
     75      // the underlying buffer without risking damaging other MediaSpans' data.
     76      // So we must reallocate a new buffer, copy our old data into it, and
     77      // append the new data into it.
     78      RefPtr<MediaByteBuffer> buffer =
     79          new MediaByteBuffer(mLength + aBuffer->Length());
     80      if (!buffer->AppendElements(Elements(), Length(), fallible) ||
     81          !buffer->AppendElements(*aBuffer, fallible)) {
     82        return false;
     83      }
     84      mBuffer = buffer;
     85      mLength += aBuffer->Length();
     86      return true;
     87    }
     88    if (!mBuffer->AppendElements(*aBuffer, fallible)) {
     89      return false;
     90    }
     91    mLength += aBuffer->Length();
     92    return true;
     93  }
     94 
     95  // Returns a new MediaSpan, spanning from the start of this span,
     96  // up until aEnd.
     97  MediaSpan To(size_t aEnd) const {
     98    MOZ_DIAGNOSTIC_ASSERT(aEnd <= Length());
     99    return MediaSpan(mBuffer, mStart, aEnd);
    100  }
    101 
    102  // Returns a new MediaSpan, spanning from aStart bytes offset from
    103  // the start of this span, until the end of this span.
    104  MediaSpan From(size_t aStart) const {
    105    MOZ_DIAGNOSTIC_ASSERT(aStart <= Length());
    106    return MediaSpan(mBuffer, mStart + aStart, Length() - aStart);
    107  }
    108 
    109  void RemoveFront(size_t aNumBytes) {
    110    MOZ_DIAGNOSTIC_ASSERT(aNumBytes <= Length());
    111    mStart += aNumBytes;
    112    mLength -= aNumBytes;
    113  }
    114 
    115  MediaByteBuffer* Buffer() const { return mBuffer; }
    116 
    117 private:
    118  MediaSpan(MediaByteBuffer* aBuffer, size_t aStart, size_t aLength)
    119      : mBuffer(aBuffer), mStart(aStart), mLength(aLength) {
    120    MOZ_DIAGNOSTIC_ASSERT(mStart + mLength <= mBuffer->Length());
    121  }
    122 
    123  RefPtr<MediaByteBuffer> mBuffer;
    124  size_t mStart = 0;
    125  size_t mLength = 0;
    126 };
    127 
    128 }  // namespace mozilla
    129 
    130 #endif  // MediaSpan_h