summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qiodevice.cpp83
-rw-r--r--src/corelib/io/qiodevice_p.h2
-rw-r--r--tests/benchmarks/corelib/io/qiodevice/main.cpp32
3 files changed, 72 insertions, 45 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 8cef993cf4..41a4d7a1ba 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -1047,26 +1047,29 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
/*!
\internal
*/
-qint64 QIODevicePrivate::read(char *data, qint64 maxSize)
+qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking)
{
Q_Q(QIODevice);
const bool buffered = (openMode & QIODevice::Unbuffered) == 0;
const bool sequential = isSequential();
- const bool keepDataInBuffer = sequential && transactionStarted;
+ const bool keepDataInBuffer = sequential
+ ? peeking || transactionStarted
+ : peeking && buffered;
+ const qint64 savedPos = pos;
qint64 readSoFar = 0;
bool madeBufferReadsOnly = true;
bool deviceAtEof = false;
char *readPtr = data;
+ qint64 bufferPos = (sequential && transactionStarted) ? transactionPos : Q_INT64_C(0);
forever {
// Try reading from the buffer.
qint64 bufferReadChunkSize = keepDataInBuffer
- ? buffer.peek(data, maxSize, transactionPos)
+ ? buffer.peek(data, maxSize, bufferPos)
: buffer.read(data, maxSize);
if (bufferReadChunkSize > 0) {
- if (keepDataInBuffer)
- transactionPos += bufferReadChunkSize;
- else if (!sequential)
+ bufferPos += bufferReadChunkSize;
+ if (!sequential)
pos += bufferReadChunkSize;
#if defined QIODEVICE_DEBUG
printf("%p \treading %lld bytes from buffer into position %lld\n", q,
@@ -1160,6 +1163,16 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize)
break;
}
+ // Restore positions after reading
+ if (keepDataInBuffer) {
+ if (peeking)
+ pos = savedPos; // does nothing on sequential devices
+ else
+ transactionPos = bufferPos;
+ } else if (peeking) {
+ seekBuffer(savedPos); // unbuffered random-access device
+ }
+
if (madeBufferReadsOnly && isBufferEmpty())
q->readData(data, 0);
@@ -1773,27 +1786,7 @@ bool QIODevicePrivate::putCharHelper(char c)
*/
qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
{
- Q_Q(QIODevice);
-
- if (transactionStarted) {
- const qint64 savedTransactionPos = transactionPos;
- const qint64 savedPos = pos;
-
- qint64 readBytes = q->read(data, maxSize);
-
- // Restore initial position
- if (isSequential())
- transactionPos = savedTransactionPos;
- else
- seekBuffer(savedPos);
- return readBytes;
- }
-
- q->startTransaction();
- qint64 readBytes = q->read(data, maxSize);
- q->rollbackTransaction();
-
- return readBytes;
+ return read(data, maxSize, true);
}
/*!
@@ -1801,26 +1794,17 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevicePrivate::peek(qint64 maxSize)
{
- Q_Q(QIODevice);
+ QByteArray result(maxSize, Qt::Uninitialized);
- if (transactionStarted) {
- const qint64 savedTransactionPos = transactionPos;
- const qint64 savedPos = pos;
+ const qint64 readBytes = read(result.data(), maxSize, true);
- QByteArray result = q->read(maxSize);
-
- // Restore initial position
- if (isSequential())
- transactionPos = savedTransactionPos;
+ if (readBytes < maxSize) {
+ if (readBytes <= 0)
+ result.clear();
else
- seekBuffer(savedPos);
- return result;
+ result.resize(readBytes);
}
- q->startTransaction();
- QByteArray result = q->read(maxSize);
- q->rollbackTransaction();
-
return result;
}
@@ -1858,7 +1842,12 @@ bool QIODevice::getChar(char *c)
*/
qint64 QIODevice::peek(char *data, qint64 maxSize)
{
- return d_func()->peek(data, maxSize);
+ Q_D(QIODevice);
+
+ CHECK_MAXLEN(peek, qint64(-1));
+ CHECK_READABLE(peek, qint64(-1));
+
+ return d->peek(data, maxSize);
}
/*!
@@ -1880,7 +1869,13 @@ qint64 QIODevice::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevice::peek(qint64 maxSize)
{
- return d_func()->peek(maxSize);
+ Q_D(QIODevice);
+
+ CHECK_MAXLEN(peek, QByteArray());
+ CHECK_MAXBYTEARRAYSIZE(peek);
+ CHECK_READABLE(peek, QByteArray());
+
+ return d->peek(maxSize);
}
/*!
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index 0e424b6831..71a326dd53 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -171,7 +171,7 @@ public:
void setReadChannelCount(int count);
void setWriteChannelCount(int count);
- qint64 read(char *data, qint64 maxSize);
+ qint64 read(char *data, qint64 maxSize, bool peeking = false);
virtual qint64 peek(char *data, qint64 maxSize);
virtual QByteArray peek(qint64 maxSize);
diff --git a/tests/benchmarks/corelib/io/qiodevice/main.cpp b/tests/benchmarks/corelib/io/qiodevice/main.cpp
index b106a9fd3d..de4660a253 100644
--- a/tests/benchmarks/corelib/io/qiodevice/main.cpp
+++ b/tests/benchmarks/corelib/io/qiodevice/main.cpp
@@ -39,6 +39,8 @@ class tst_qiodevice : public QObject
private slots:
void read_old();
void read_old_data() { read_data(); }
+ void peekAndRead();
+ void peekAndRead_data() { read_data(); }
//void read_new();
//void read_new_data() { read_data(); }
private:
@@ -86,6 +88,36 @@ void tst_qiodevice::read_old()
}
}
+void tst_qiodevice::peekAndRead()
+{
+ QFETCH(qint64, size);
+
+ QString name = "tmp" + QString::number(size);
+
+ {
+ QFile file(name);
+ file.open(QIODevice::WriteOnly);
+ file.seek(size);
+ file.write("x", 1);
+ file.close();
+ }
+
+ QBENCHMARK {
+ QFile file(name);
+ file.open(QIODevice::ReadOnly);
+
+ QByteArray ba(size / 1024, Qt::Uninitialized);
+ while (!file.atEnd()) {
+ file.peek(ba.data(), ba.size());
+ file.read(ba.data(), ba.size());
+ }
+ }
+
+ {
+ QFile file(name);
+ file.remove();
+ }
+}
QTEST_MAIN(tst_qiodevice)