Bug 1815987 - Rewrite data-read loop in OnDataAvailable r=yjuglaret

The read-loop in OnDataAvailable is needlessly baroque and uses a very
strange dialect of Hungarian notation. Factor out the zero-element case
for simplicity (of explication, if nothing else), and add justificatory
comments as appropriate.

Differential Revision: https://phabricator.services.mozilla.com/D171001
This commit is contained in:
Ray Kraesig 2023-03-14 19:54:26 +00:00
Родитель 65ff891284
Коммит 68184463ff
1 изменённых файлов: 35 добавлений и 11 удалений

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

@ -125,25 +125,49 @@ nsDataObj::CStream::OnDataAvailable(
uint64_t aOffset, // offset within the stream uint64_t aOffset, // offset within the stream
uint32_t aCount) // bytes available on this call uint32_t aCount) // bytes available on this call
{ {
// If we've been asked to read zero bytes, call `Read` once, just to ensure
// any side-effects take place, and return immediately.
if (aCount == 0) {
char buffer[1] = {0};
uint32_t bytesReadByCall = 0;
nsresult rv = aInputStream->Read(buffer, 0, &bytesReadByCall);
MOZ_ASSERT(bytesReadByCall == 0);
return rv;
}
// Extend the write buffer for the incoming data. // Extend the write buffer for the incoming data.
uint8_t* buffer = mChannelData.AppendElements(aCount, fallible); size_t oldLength = mChannelData.Length();
char* buffer =
reinterpret_cast<char*>(mChannelData.AppendElements(aCount, fallible));
if (!buffer) { if (!buffer) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
NS_ASSERTION((mChannelData.Length() == (aOffset + aCount)), MOZ_ASSERT(mChannelData.Length() == (aOffset + aCount),
"stream length mismatch w/write buffer"); "stream length mismatch w/write buffer");
// Read() may not return aCount on a single call, so loop until we've // Read() may not return aCount on a single call, so loop until we've
// accumulated all the data OnDataAvailable has promised. // accumulated all the data OnDataAvailable has promised.
nsresult rv; uint32_t bytesRead = 0;
uint32_t odaBytesReadTotal = 0; while (bytesRead < aCount) {
do {
uint32_t bytesReadByCall = 0; uint32_t bytesReadByCall = 0;
rv = aInputStream->Read((char*)(buffer + odaBytesReadTotal), aCount, nsresult rv = aInputStream->Read(buffer + bytesRead, aCount - bytesRead,
&bytesReadByCall); &bytesReadByCall);
odaBytesReadTotal += bytesReadByCall; bytesRead += bytesReadByCall;
} while (aCount < odaBytesReadTotal && NS_SUCCEEDED(rv));
return rv; if (bytesReadByCall == 0) {
// A `bytesReadByCall` of zero indicates EOF without failure... but we
// were promised `aCount` elements and haven't gotten them. Return a
// generic failure.
rv = NS_ERROR_FAILURE;
}
if (NS_FAILED(rv)) {
// Drop any trailing uninitialized elements before erroring out.
mChannelData.RemoveElementsAt(oldLength + bytesRead, aCount - bytesRead);
return rv;
}
}
return NS_OK;
} }
NS_IMETHODIMP nsDataObj::CStream::OnStartRequest(nsIRequest* aRequest) { NS_IMETHODIMP nsDataObj::CStream::OnStartRequest(nsIRequest* aRequest) {