michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsTemporaryFileInputStream.h" michael@0: #include "nsStreamUtils.h" michael@0: #include michael@0: michael@0: NS_IMPL_ISUPPORTS(nsTemporaryFileInputStream, nsIInputStream) michael@0: michael@0: nsTemporaryFileInputStream::nsTemporaryFileInputStream(FileDescOwner* aFileDescOwner, uint64_t aStartPos, uint64_t aEndPos) michael@0: : mFileDescOwner(aFileDescOwner), michael@0: mStartPos(aStartPos), michael@0: mEndPos(aEndPos), michael@0: mClosed(false) michael@0: { michael@0: NS_ASSERTION(aStartPos <= aEndPos, "StartPos should less equal than EndPos!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsTemporaryFileInputStream::Close() michael@0: { michael@0: mClosed = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsTemporaryFileInputStream::Available(uint64_t * bytesAvailable) michael@0: { michael@0: if (mClosed) michael@0: return NS_BASE_STREAM_CLOSED; michael@0: michael@0: NS_ASSERTION(mStartPos <= mEndPos, "StartPos should less equal than EndPos!"); michael@0: michael@0: *bytesAvailable = mEndPos - mStartPos; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsTemporaryFileInputStream::Read(char* buffer, uint32_t count, uint32_t* bytesRead) michael@0: { michael@0: return ReadSegments(NS_CopySegmentToBuffer, buffer, count, bytesRead); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsTemporaryFileInputStream::ReadSegments(nsWriteSegmentFun writer, michael@0: void * closure, michael@0: uint32_t count, michael@0: uint32_t * result) michael@0: { michael@0: NS_ASSERTION(result, "null ptr"); michael@0: NS_ASSERTION(mStartPos <= mEndPos, "bad stream state"); michael@0: *result = 0; michael@0: michael@0: if (mClosed) { michael@0: return NS_BASE_STREAM_CLOSED; michael@0: } michael@0: michael@0: mozilla::MutexAutoLock lock(mFileDescOwner->FileMutex()); michael@0: PR_Seek64(mFileDescOwner->mFD, mStartPos, PR_SEEK_SET); michael@0: michael@0: count = std::min(count, uint32_t(mEndPos - mStartPos)); michael@0: uint32_t remainBufCount = count; michael@0: michael@0: char buf[4096]; michael@0: while (remainBufCount > 0) { michael@0: uint32_t bufCount = std::min(remainBufCount, (uint32_t)sizeof(buf)); michael@0: int32_t read_result = PR_Read(mFileDescOwner->mFD, buf, bufCount); michael@0: if (read_result < 0) { michael@0: return NS_ErrorAccordingToNSPR(); michael@0: } michael@0: uint32_t write_result = 0; michael@0: nsresult rv = writer(this, closure, buf, michael@0: count - remainBufCount, bufCount, &write_result); michael@0: remainBufCount -= bufCount; michael@0: if (NS_SUCCEEDED(rv)) { michael@0: NS_ASSERTION(write_result <= bufCount, michael@0: "writer should not write more than we asked it to write"); michael@0: } michael@0: mStartPos += bufCount; michael@0: } michael@0: *result = count; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsTemporaryFileInputStream::IsNonBlocking(bool * nonBlocking) michael@0: { michael@0: *nonBlocking = false; michael@0: return NS_OK; michael@0: } michael@0: