diff options
author | Alex Trotsenko <alex1973tr@gmail.com> | 2021-07-21 14:44:13 +0300 |
---|---|---|
committer | Alex Trotsenko <alex1973tr@gmail.com> | 2021-08-01 20:20:46 +0300 |
commit | 3bc976c2bda1516066de1eeb706826d26b098952 (patch) | |
tree | bbee6cba66c1f37afde40ca8c662f824e177a294 | |
parent | 69c833dae91d004b48f815e0156d6caeb4cdb491 (diff) |
QIODevice: allow subclasses to enforce unbuffered mode
For subclasses that implement alternative buffering (such as
QLocalSocket), it would be useful to bypass the QIODevice's internal
buffer, even if the QIODeviceBase::Unbuffered flag is not set when
opened.
By setting the readBufferChunkSize member to 0 in their constructors,
these classes now unconditionally switch the base class to unbuffered
mode, while still reporting buffering with openMode() function.
Change-Id: I351bc57ac0ccb45c81f8c6be15f1745131aa26ba
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
-rw-r--r-- | src/corelib/io/qiodevice.cpp | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 75b03fe0fb..1837410ac3 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -703,8 +703,15 @@ void QIODevice::setCurrentReadChannel(int channel) void QIODevicePrivate::setReadChannelCount(int count) { if (count > readBuffers.size()) { + // If readBufferChunkSize is zero, we should bypass QIODevice's + // read buffers, even if the QIODeviceBase::Unbuffered flag is not + // set when opened. However, if a read transaction is started or + // ungetChar() is called, we still have to use the internal buffer. + // To support these cases, pass a default value to the QRingBuffer + // constructor. readBuffers.insert(readBuffers.end(), count - readBuffers.size(), - QRingBuffer(readBufferChunkSize)); + QRingBuffer(readBufferChunkSize != 0 ? readBufferChunkSize + : QIODEVICE_BUFFERSIZE)); } else { readBuffers.resize(count); } @@ -1068,7 +1075,7 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking) { Q_Q(QIODevice); - const bool buffered = (openMode & QIODevice::Unbuffered) == 0; + const bool buffered = (readBufferChunkSize != 0 && (openMode & QIODevice::Unbuffered) == 0); const bool sequential = isSequential(); const bool keepDataInBuffer = sequential ? peeking || transactionStarted @@ -1121,9 +1128,9 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking) } } else { // Do not read more than maxSize on unbuffered devices - const qint64 bytesToBuffer = (buffered || readBufferChunkSize < maxSize) - ? qint64(readBufferChunkSize) - : maxSize; + const qint64 bytesToBuffer = (!buffered && maxSize < buffer.chunkSize()) + ? maxSize + : qint64(buffer.chunkSize()); // Try to fill QIODevice buffer by single read readFromDevice = q->readData(buffer.reserve(bytesToBuffer), bytesToBuffer); deviceAtEof = (readFromDevice != bytesToBuffer); @@ -1266,7 +1273,7 @@ QByteArray QIODevice::readAll() qint64 readBytes = (d->isSequential() ? Q_INT64_C(0) : size()); if (readBytes == 0) { // Size is unknown, read incrementally. - qint64 readChunkSize = qMax(qint64(d->readBufferChunkSize), + qint64 readChunkSize = qMax(qint64(d->buffer.chunkSize()), d->isSequential() ? (d->buffer.size() - d->transactionPos) : d->buffer.size()); qint64 readResult; @@ -1279,7 +1286,7 @@ QByteArray QIODevice::readAll() readResult = d->read(result.data() + readBytes, readChunkSize); if (readResult > 0 || readBytes == 0) { readBytes += readResult; - readChunkSize = d->readBufferChunkSize; + readChunkSize = d->buffer.chunkSize(); } } while (readResult > 0); } else { @@ -1485,11 +1492,11 @@ QByteArray QIODevice::readLine(qint64 maxSize) qint64 readResult; do { - result.resize(int(qMin(maxSize, qint64(result.size() + d->readBufferChunkSize)))); + result.resize(int(qMin(maxSize, qint64(result.size() + d->buffer.chunkSize())))); readResult = d->readLine(result.data() + readBytes, result.size() - readBytes); if (readResult > 0 || readBytes == 0) readBytes += readResult; - } while (readResult == d->readBufferChunkSize + } while (readResult == d->buffer.chunkSize() && result[int(readBytes - 1)] != '\n'); } else { CHECK_LINEMAXLEN(readLine, result); |