summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qiodevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qiodevice.cpp')
-rw-r--r--src/corelib/io/qiodevice.cpp210
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;
}