diff options
Diffstat (limited to 'src/corelib/io/qiodevice.cpp')
-rw-r--r-- | src/corelib/io/qiodevice.cpp | 210 |
1 files changed, 86 insertions, 124 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 72ec6ff403..388c623bcb 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -117,8 +117,7 @@ void debugBinaryString(const char *data, qint64 maxlen) */ QIODevicePrivate::QIODevicePrivate() : openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE), - pos(0), devicePos(0), seqDumpPos(0) - , pPos(&pos), pDevicePos(&devicePos) + pos(0), devicePos(0) , baseReadLineDataCalled(false) , firstRead(true) , accessMode(Unset) @@ -566,7 +565,6 @@ void QIODevice::close() d->openMode = NotOpen; d->errorString.clear(); d->pos = 0; - d->seqDumpPos = 0; d->buffer.clear(); d->firstRead = true; } @@ -733,12 +731,6 @@ qint64 QIODevice::bytesToWrite() const return qint64(0); } -#ifdef Q_CC_RVCT -// arm mode makes the 64-bit integer operations much faster in RVCT 2.2 -#pragma push -#pragma arm -#endif - /*! Reads at most \a maxSize bytes from the device into \a data, and returns the number of bytes read. If an error occurs, such as when @@ -761,11 +753,14 @@ qint64 QIODevice::read(char *data, qint64 maxSize) this, data, int(maxSize), int(d->pos), int(d->buffer.size())); #endif + const bool sequential = d->isSequential(); + // Short circuit for getChar() if (maxSize == 1) { int chint; while ((chint = d->buffer.getChar()) != -1) { - ++(*d->pPos); + if (!sequential) + ++d->pos; char c = char(uchar(chint)); if (c == '\r' && (d->openMode & Text)) @@ -783,27 +778,21 @@ qint64 QIODevice::read(char *data, qint64 maxSize) CHECK_MAXLEN(read, qint64(-1)); qint64 readSoFar = 0; - bool moreToRead = true; - do { + bool madeBufferReadsOnly = true; + bool deviceAtEof = false; + char *readPtr = data; + forever { // Try reading from the buffer. - qint64 lastReadChunkSize = d->buffer.read(data, maxSize); - if (lastReadChunkSize > 0) { - *d->pPos += lastReadChunkSize; - readSoFar += lastReadChunkSize; - // fast exit when satisfied by buffer - if (lastReadChunkSize == maxSize && !(d->openMode & Text)) { - if (d->buffer.isEmpty()) { - d->buffer.clear(); - readData(data, 0); - } - return readSoFar; - } - - data += lastReadChunkSize; - maxSize -= lastReadChunkSize; + qint64 bufferReadChunkSize = d->buffer.read(data, maxSize); + if (bufferReadChunkSize > 0) { + if (!sequential) + d->pos += bufferReadChunkSize; + readSoFar += bufferReadChunkSize; + data += bufferReadChunkSize; + maxSize -= bufferReadChunkSize; #if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from buffer into position %d\n", this, lastReadChunkSize, - int(readSoFar) - lastReadChunkSize); + printf("%p \treading %d bytes from buffer into position %d\n", this, + bufferReadChunkSize, int(readSoFar) - bufferReadChunkSize); #endif } else { if (d->firstRead) { @@ -811,105 +800,88 @@ qint64 QIODevice::read(char *data, qint64 maxSize) // for fast pos updates. CHECK_READABLE(read, qint64(-1)); d->firstRead = false; - if (d->isSequential()) { - d->pPos = &d->seqDumpPos; - d->pDevicePos = &d->seqDumpPos; - } } + } - if (!maxSize) - return readSoFar; - - if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) { - // In buffered mode, we try to fill up the QIODevice buffer before - // we do anything else. - // buffer is empty at this point, try to fill it - const int bytesToBuffer = QIODEVICE_BUFFERSIZE; - char *writePointer = d->buffer.reserve(bytesToBuffer); - - // Make sure the device is positioned correctly. - if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos)) - return readSoFar ? readSoFar : qint64(-1); - qint64 readFromDevice = readData(writePointer, bytesToBuffer); - d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice))); - - if (readFromDevice > 0) { - *d->pDevicePos += readFromDevice; + if (maxSize > 0 && !deviceAtEof) { + qint64 readFromDevice = 0; + // Make sure the device is positioned correctly. + if (sequential || d->pos == d->devicePos || seek(d->pos)) { + madeBufferReadsOnly = false; // fix readData attempt + if (maxSize >= QIODEVICE_BUFFERSIZE || (d->openMode & Unbuffered)) { + // Read big chunk directly to output buffer + readFromDevice = readData(data, maxSize); + deviceAtEof = (readFromDevice != maxSize); #if defined QIODEVICE_DEBUG - printf("%p \treading %d from device into buffer\n", this, int(readFromDevice)); + printf("%p \treading %d bytes from device (total %d)\n", this, + int(readFromDevice), int(readSoFar)); #endif - - if (!d->buffer.isEmpty()) { - lastReadChunkSize = d->buffer.read(data, maxSize); - readSoFar += lastReadChunkSize; - data += lastReadChunkSize; - maxSize -= lastReadChunkSize; - *d->pPos += lastReadChunkSize; + if (readFromDevice > 0) { + readSoFar += readFromDevice; + data += readFromDevice; + maxSize -= readFromDevice; + if (!sequential) { + d->pos += readFromDevice; + d->devicePos += readFromDevice; + } + } + } else { + const int bytesToBuffer = QIODEVICE_BUFFERSIZE; + // Try to fill QIODevice buffer by single read + readFromDevice = readData(d->buffer.reserve(bytesToBuffer), bytesToBuffer); + deviceAtEof = (readFromDevice != bytesToBuffer); + d->buffer.chop(bytesToBuffer - qMax(0, int(readFromDevice))); + if (readFromDevice > 0) { + if (!sequential) + d->devicePos += readFromDevice; #if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from buffer at position %d\n", this, - lastReadChunkSize, int(readSoFar)); + printf("%p \treading %d from device into buffer\n", this, + int(readFromDevice)); #endif + continue; } } + } else { + readFromDevice = -1; } - } - // If we need more, try reading from the device. - if (maxSize > 0) { - // Make sure the device is positioned correctly. - if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos)) - return readSoFar ? readSoFar : qint64(-1); - qint64 readFromDevice = readData(data, maxSize); -#if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from device (total %d)\n", this, int(readFromDevice), int(readSoFar)); -#endif - if (readFromDevice == -1 && readSoFar == 0) { + if (readFromDevice < 0 && readSoFar == 0) { // error and we haven't read anything: return immediately - return -1; - } - if (readFromDevice > 0) { - lastReadChunkSize += int(readFromDevice); - readSoFar += readFromDevice; - data += readFromDevice; - maxSize -= readFromDevice; - *d->pPos += readFromDevice; - *d->pDevicePos += readFromDevice; + return qint64(-1); } } - // Best attempt has been made to read data, don't try again except for text mode adjustment below - moreToRead = false; - if (readSoFar && d->openMode & Text) { - char *readPtr = data - lastReadChunkSize; + if ((d->openMode & Text) && readPtr < data) { const char *endPtr = data; - if (readPtr < endPtr) { - // optimization to avoid initial self-assignment - while (*readPtr != '\r') { - if (++readPtr == endPtr) - return readSoFar; - } + // optimization to avoid initial self-assignment + while (*readPtr != '\r') { + if (++readPtr == endPtr) + break; + } - char *writePtr = readPtr; + char *writePtr = readPtr; - while (readPtr < endPtr) { - char ch = *readPtr++; - if (ch != '\r') - *writePtr++ = ch; - else { - --readSoFar; - --data; - ++maxSize; - } + while (readPtr < endPtr) { + char ch = *readPtr++; + if (ch != '\r') + *writePtr++ = ch; + else { + --readSoFar; + --data; + ++maxSize; } - - // Make sure we get more data if there is room for more. This - // is very important for when someone seeks to the start of a - // '\r\n' and reads one character - they should get the '\n'. - moreToRead = (readPtr != writePtr); } + + // Make sure we get more data if there is room for more. This + // is very important for when someone seeks to the start of a + // '\r\n' and reads one character - they should get the '\n'. + readPtr = data; + continue; } - } while (moreToRead); + + break; + } #if defined QIODEVICE_DEBUG printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this, @@ -917,16 +889,14 @@ qint64 QIODevice::read(char *data, qint64 maxSize) debugBinaryString(data - readSoFar, readSoFar); #endif - if (d->buffer.isEmpty()) + if (madeBufferReadsOnly && d->buffer.isEmpty()) { + d->buffer.clear(); readData(data, 0); + } return readSoFar; } -#ifdef Q_CC_RVCT -#pragma pop -#endif - /*! \overload @@ -1039,12 +1009,6 @@ QByteArray QIODevice::readAll() return result; } -#ifdef Q_CC_RVCT -// arm mode makes the 64-bit integer operations much faster in RVCT 2.2 -#pragma push -#pragma arm -#endif - /*! This function reads a line of ASCII characters from the device, up to a maximum of \a maxSize - 1 bytes, stores the characters in \a @@ -1264,10 +1228,6 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize) return readSoFar; } -#ifdef Q_CC_RVCT -#pragma pop -#endif - /*! Returns \c true if a complete line of data can be read from the device; otherwise returns \c false. @@ -1455,7 +1415,8 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize) return readBytes; buffer.ungetBlock(data, readBytes); - *pPos -= readBytes; + if (!isSequential()) + pos -= readBytes; return readBytes; } @@ -1470,7 +1431,8 @@ QByteArray QIODevicePrivate::peek(qint64 maxSize) return result; buffer.ungetBlock(result.constData(), result.size()); - *pPos -= result.size(); + if (!isSequential()) + pos -= result.size(); return result; } |