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
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.
uint8_t* buffer = mChannelData.AppendElements(aCount, fallible);
size_t oldLength = mChannelData.Length();
char* buffer =
reinterpret_cast<char*>(mChannelData.AppendElements(aCount, fallible));
if (!buffer) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ASSERTION((mChannelData.Length() == (aOffset + aCount)),
"stream length mismatch w/write buffer");
MOZ_ASSERT(mChannelData.Length() == (aOffset + aCount),
"stream length mismatch w/write buffer");
// Read() may not return aCount on a single call, so loop until we've
// accumulated all the data OnDataAvailable has promised.
nsresult rv;
uint32_t odaBytesReadTotal = 0;
do {
uint32_t bytesRead = 0;
while (bytesRead < aCount) {
uint32_t bytesReadByCall = 0;
rv = aInputStream->Read((char*)(buffer + odaBytesReadTotal), aCount,
&bytesReadByCall);
odaBytesReadTotal += bytesReadByCall;
} while (aCount < odaBytesReadTotal && NS_SUCCEEDED(rv));
return rv;
nsresult rv = aInputStream->Read(buffer + bytesRead, aCount - bytesRead,
&bytesReadByCall);
bytesRead += bytesReadByCall;
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) {