Make fastload handle short reads from its underlying buffered stream. Bug

387588, r+sr=biesi
This commit is contained in:
bzbarsky@mit.edu 2007-07-17 18:54:55 -07:00
Родитель 39ee949499
Коммит 564a303215
3 изменённых файлов: 71 добавлений и 12 удалений

Просмотреть файл

@ -315,7 +315,30 @@ NS_IMETHODIMP
nsBinaryInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
{
NS_ENSURE_STATE(mInputStream);
return mInputStream->Read(aBuffer, aCount, aNumRead);
// mInputStream might give us short reads, so deal with that.
PRUint32 totalRead = 0;
PRUint32 bytesRead;
do {
nsresult rv = mInputStream->Read(aBuffer, aCount, &bytesRead);
if (rv == NS_BASE_STREAM_WOULD_BLOCK && totalRead != 0) {
// We already read some data. Return it.
break;
}
if (NS_FAILED(rv)) {
return rv;
}
totalRead += bytesRead;
aBuffer += bytesRead;
aCount -= bytesRead;
} while (aCount != 0 && bytesRead != 0);
*aNumRead = totalRead;
return NS_OK;
}
@ -328,6 +351,8 @@ struct ReadSegmentsClosure {
nsIInputStream* mRealInputStream;
void* mRealClosure;
nsWriteSegmentFun mRealWriter;
nsresult mRealResult;
PRUint32 mBytesRead; // to properly implement aToOffset
};
// the thunking function
@ -342,10 +367,17 @@ ReadSegmentForwardingThunk(nsIInputStream* aStream,
ReadSegmentsClosure* thunkClosure =
reinterpret_cast<ReadSegmentsClosure*>(aClosure);
return thunkClosure->mRealWriter(thunkClosure->mRealInputStream,
thunkClosure->mRealClosure,
aFromSegment, aToOffset,
aCount, aWriteCount);
NS_ASSERTION(NS_SUCCEEDED(thunkClosure->mRealResult),
"How did this get to be a failure status?");
thunkClosure->mRealResult =
thunkClosure->mRealWriter(thunkClosure->mRealInputStream,
thunkClosure->mRealClosure,
aFromSegment,
thunkClosure->mBytesRead + aToOffset,
aCount, aWriteCount);
return thunkClosure->mRealResult;
}
@ -354,9 +386,32 @@ nsBinaryInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUi
{
NS_ENSURE_STATE(mInputStream);
ReadSegmentsClosure thunkClosure = { this, closure, writer };
ReadSegmentsClosure thunkClosure = { this, closure, writer, NS_OK, 0 };
return mInputStream->ReadSegments(ReadSegmentForwardingThunk, &thunkClosure, count, _retval);
// mInputStream might give us short reads, so deal with that.
PRUint32 bytesRead;
do {
nsresult rv = mInputStream->ReadSegments(ReadSegmentForwardingThunk,
&thunkClosure,
count, &bytesRead);
if (rv == NS_BASE_STREAM_WOULD_BLOCK && thunkClosure.mBytesRead != 0) {
// We already read some data. Return it.
break;
}
if (NS_FAILED(rv)) {
return rv;
}
thunkClosure.mBytesRead += bytesRead;
count -= bytesRead;
} while (count != 0 && bytesRead != 0 &&
NS_SUCCEEDED(thunkClosure.mRealResult));
*_retval = thunkClosure.mBytesRead;
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -579,7 +579,7 @@ nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead)
}
}
rv = mInputStream->Read(aBuffer, aCount, aBytesRead);
rv = nsBinaryInputStream::Read(aBuffer, aCount, aBytesRead);
if (NS_SUCCEEDED(rv) && entry) {
NS_ASSERTION(entry->mBytesLeft >= *aBytesRead, "demux Read underflow!");

Просмотреть файл

@ -48,10 +48,14 @@ interface nsIInputStream;
*
* @param aInStream stream being read
* @param aClosure opaque parameter passed to ReadSegments
* @param aFromSegment pointer to memory owned by the input stream
* @param aToOffset amount already read (since ReadSegments was called)
* @param aCount length of fromSegment
* @param aWriteCount number of bytes read
* @param aFromSegment pointer to memory owned by the input stream. This is
* where the writer function should start consuming data.
* @param aToOffset amount of data already consumed by this writer during this
* ReadSegments call. This is also the sum of the aWriteCount
* returns from this writer over the previous invocations of
* the writer by this ReadSegments call.
* @param aCount Number of bytes available to be read starting at aFromSegment
* @param [out] aWriteCount number of bytes read by this writer function call
*
* Implementers should return the following:
*