Simplify QIODevice::readAll()
The previous implementation performed reading in two steps: - flush the internal buffer - request the rest of the data by calling the read() function It would resize the result buffer separately at each step, even if its total size was known in advance. This is important for random-access devices, which may have big chunks of cached data. Also, possible failures during the second step would cause a loss of result data from the first stage. This patch eliminates the initial flush, which improves performance and prevents data loss. Change-Id: I3da4c24ee33dca6afc4ba519d078b86068de43b9 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
parent
657e8ffb9e
commit
5c0ff27d9b
@ -992,40 +992,31 @@ QByteArray QIODevice::readAll()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QByteArray result;
|
QByteArray result;
|
||||||
qint64 readBytes = 0;
|
qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size());
|
||||||
const bool sequential = d->isSequential();
|
if (readBytes == 0) {
|
||||||
|
|
||||||
// flush internal read buffer
|
|
||||||
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
|
|
||||||
if (d->buffer.size() >= MaxByteArraySize)
|
|
||||||
return QByteArray();
|
|
||||||
result = d->buffer.readAll();
|
|
||||||
readBytes = result.size();
|
|
||||||
if (!sequential)
|
|
||||||
d->pos += readBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 theSize;
|
|
||||||
if (sequential || (theSize = size()) == 0) {
|
|
||||||
// Size is unknown, read incrementally.
|
// Size is unknown, read incrementally.
|
||||||
|
qint64 readChunkSize = qMax(d->buffer.size(), QIODEVICE_BUFFERSIZE);
|
||||||
qint64 readResult;
|
qint64 readResult;
|
||||||
do {
|
do {
|
||||||
if (readBytes + QIODEVICE_BUFFERSIZE >= MaxByteArraySize) {
|
if (readBytes + readChunkSize >= MaxByteArraySize) {
|
||||||
// If resize would fail, don't read more, return what we have.
|
// If resize would fail, don't read more, return what we have.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result.resize(readBytes + QIODEVICE_BUFFERSIZE);
|
result.resize(readBytes + readChunkSize);
|
||||||
readResult = read(result.data() + readBytes, QIODEVICE_BUFFERSIZE);
|
readResult = read(result.data() + readBytes, readChunkSize);
|
||||||
if (readResult > 0 || readBytes == 0)
|
if (readResult > 0 || readBytes == 0) {
|
||||||
readBytes += readResult;
|
readBytes += readResult;
|
||||||
|
readChunkSize = QIODEVICE_BUFFERSIZE;
|
||||||
|
}
|
||||||
} while (readResult > 0);
|
} while (readResult > 0);
|
||||||
} else {
|
} else {
|
||||||
// Read it all in one go.
|
// Read it all in one go.
|
||||||
// If resize fails, don't read anything.
|
// If resize fails, don't read anything.
|
||||||
if (readBytes + theSize - d->pos >= MaxByteArraySize)
|
readBytes -= d->pos;
|
||||||
|
if (readBytes >= MaxByteArraySize)
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
result.resize(int(readBytes + theSize - d->pos));
|
result.resize(readBytes);
|
||||||
readBytes += read(result.data() + readBytes, result.size() - readBytes);
|
readBytes = read(result.data(), readBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readBytes <= 0)
|
if (readBytes <= 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user