nsresult SourceBufferResource::Seek(int32_t aWhence, int64_t aOffset) { SBR_DEBUG("Seek(aWhence=%d, aOffset=%lld)", aWhence, aOffset); ReentrantMonitorAutoEnter mon(mMonitor); int64_t newOffset = mOffset; switch (aWhence) { case nsISeekableStream::NS_SEEK_END: newOffset = GetLength() - aOffset; break; case nsISeekableStream::NS_SEEK_CUR: newOffset += aOffset; break; case nsISeekableStream::NS_SEEK_SET: newOffset = aOffset; break; } SBR_DEBUGV("newOffset=%lld GetOffset()=%llu GetLength()=%llu)", newOffset, mInputBuffer.GetOffset(), GetLength()); nsresult rv = SeekInternal(newOffset); mon.NotifyAll(); return rv; }
nsresult SourceBufferResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) { SBR_DEBUGV("Read(aBuffer=%p, aCount=%u, aBytes=%p)", aBuffer, aCount, aBytes); ReentrantMonitorAutoEnter mon(mMonitor); return ReadInternal(aBuffer, aCount, aBytes, /* aMayBlock = */ true); }
nsresult SourceBufferResource::ReadInternal(char* aBuffer, uint32_t aCount, uint32_t* aBytes, bool aMayBlock) { mMonitor.AssertCurrentThreadIn(); MOZ_ASSERT_IF(!aMayBlock, aBytes); // Cache the offset for the read in case mOffset changes while waiting on the // monitor below. It's basically impossible to implement these API semantics // sanely. :-( uint64_t readOffset = mOffset; while (aMayBlock && !mEnded && readOffset + aCount > static_cast<uint64_t>(GetLength())) { SBR_DEBUGV("waiting for data"); mMonitor.Wait(); // The callers of this function should have checked this, but it's // possible that we had an eviction while waiting on the monitor. if (readOffset < mInputBuffer.GetOffset()) { return NS_ERROR_FAILURE; } } uint32_t available = GetLength() - readOffset; uint32_t count = std::min(aCount, available); SBR_DEBUGV("readOffset=%llu GetLength()=%u available=%u count=%u mEnded=%d", readOffset, GetLength(), available, count, mEnded); if (available == 0) { SBR_DEBUGV("reached EOF"); *aBytes = 0; return NS_OK; } mInputBuffer.CopyData(readOffset, count, aBuffer); *aBytes = count; // From IRC: // <@cpearce>bholley: *this* is why there should only every be a ReadAt() and // no Read() on a Stream abstraction! there's no good answer, they all suck. mOffset = readOffset + count; return NS_OK; }