Bug 1636823 - nsMultiplexInputStream should not be blocking and nsIAsyncInputStream at the same time - part 4 - support Seek(END) correctly, r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D77100
This commit is contained in:
Andrea Marchesini 2020-05-28 05:48:52 +00:00
Родитель 8c01ca65b0
Коммит acd3fa5467
1 изменённых файлов: 41 добавлений и 56 удалений

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

@ -701,76 +701,61 @@ nsMultiplexInputStream::Seek(int32_t aWhence, int64_t aOffset) {
if (aOffset > 0) {
return NS_ERROR_INVALID_ARG;
}
int64_t remaining = aOffset;
for (uint32_t i = mStreams.Length() - 1; i != (uint32_t)-1; --i) {
int32_t i;
for (i = mStreams.Length() - 1; i >= 0; --i) {
nsCOMPtr<nsISeekableStream> stream = mStreams[i].mSeekableStream;
// See if all remaining streams should be seeked to end
if (remaining == 0) {
if (i >= oldCurrentStream) {
uint64_t avail;
rv = AvailableMaybeSeek(mStreams[i], &avail);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stream->Seek(NS_SEEK_END, 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mStreams[i].mCurrentPos += avail;
} else {
break;
}
uint64_t avail;
rv = AvailableMaybeSeek(mStreams[i], &avail);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Get position in current stream
int64_t streamPos;
if (i < oldCurrentStream) {
streamPos = 0;
} else {
streamPos = mStreams[i].mCurrentPos;
}
int64_t streamLength = avail + mStreams[i].mCurrentPos;
// See if we have enough data in the current stream.
if (DeprecatedAbs(remaining) < streamPos) {
// The seek(END) can be completed in the current stream.
if (streamLength >= DeprecatedAbs(remaining)) {
rv = stream->Seek(NS_SEEK_END, remaining);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// remaining is negative.
mStreams[i].mCurrentPos = streamPos + remaining;
mStreams[i].mCurrentPos = streamLength + remaining;
mCurrentStream = i;
mStartedReadingCurrent = true;
remaining = 0;
} else if (DeprecatedAbs(remaining) > streamPos) {
if (i > oldCurrentStream ||
(i == oldCurrentStream && !oldStartedReadingCurrent)) {
// We're already at start so no need to seek this stream
remaining += streamPos;
} else {
int64_t diff =
XPCOM_MIN((int64_t)streamPos, DeprecatedAbs(remaining));
int64_t newPos = streamPos + diff;
rv = stream->Seek(NS_SEEK_END, -newPos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mCurrentStream = i;
mStartedReadingCurrent = true;
mStreams[i].mCurrentPos += diff;
remaining += newPos;
}
} else {
NS_ASSERTION(remaining == streamPos, "Huh?");
remaining = 0;
break;
}
// We are at the beginning of this stream.
rv = stream->Seek(NS_SEEK_SET, 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
remaining += streamLength;
mStreams[i].mCurrentPos = 0;
}
// Any other stream must be set to the end.
for (--i; i >= 0; --i) {
nsCOMPtr<nsISeekableStream> stream = mStreams[i].mSeekableStream;
uint64_t avail;
rv = AvailableMaybeSeek(mStreams[i], &avail);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
int64_t streamLength = avail + mStreams[i].mCurrentPos;
rv = stream->Seek(NS_SEEK_END, 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mStreams[i].mCurrentPos = streamLength;
}
return NS_OK;