QIODevice: do not change the 'pos' member for sequential devices

Concept of 'current position' exists only for random-access devices.
As documented, for sequential devices QIODevice::pos() must always
return 0. Prevent a modification of the internal 'pos' member in
QIODevice::readAll() method to follow this rule.

Change-Id: Ida2ee6a629ccfc3068d62f95ab1064ada13fdda5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alex Trotsenko 2015-03-28 16:47:41 +02:00
parent 6dcbaa487d
commit f40cf77b0f
2 changed files with 48 additions and 2 deletions

View File

@ -972,6 +972,7 @@ QByteArray QIODevice::readAll()
QByteArray result;
qint64 readBytes = 0;
const bool sequential = d->isSequential();
// flush internal read buffer
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
@ -979,11 +980,12 @@ QByteArray QIODevice::readAll()
return QByteArray();
result = d->buffer.readAll();
readBytes = result.size();
d->pos += readBytes;
if (!sequential)
d->pos += readBytes;
}
qint64 theSize;
if (d->isSequential() || (theSize = size()) == 0) {
if (sequential || (theSize = size()) == 0) {
// Size is unknown, read incrementally.
qint64 readResult;
do {

View File

@ -58,6 +58,7 @@ private slots:
void readLine2();
void peekBug();
void readAllKeepPosition();
};
void tst_QIODevice::initTestCase()
@ -584,5 +585,48 @@ void tst_QIODevice::peekBug()
}
class SequentialReadBuffer : public QIODevice
{
public:
SequentialReadBuffer(const char *data) : QIODevice(), buf(data), offset(0) { }
bool isSequential() const Q_DECL_OVERRIDE { return true; }
const QByteArray &buffer() const { return buf; }
protected:
qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE
{
maxSize = qMin(maxSize, qint64(buf.size() - offset));
memcpy(data, buf.constData() + offset, maxSize);
offset += maxSize;
return maxSize;
}
qint64 writeData(const char * /* data */, qint64 /* maxSize */) Q_DECL_OVERRIDE
{
return -1;
}
private:
QByteArray buf;
int offset;
};
// Test readAll() on position change for sequential device
void tst_QIODevice::readAllKeepPosition()
{
SequentialReadBuffer buffer("Hello world!");
buffer.open(QIODevice::ReadOnly);
char c;
QVERIFY(buffer.getChar(&c));
QCOMPARE(buffer.pos(), qint64(0));
buffer.ungetChar(c);
QCOMPARE(buffer.pos(), qint64(0));
QByteArray resultArray = buffer.readAll();
QCOMPARE(buffer.pos(), qint64(0));
QCOMPARE(resultArray, buffer.buffer());
}
QTEST_MAIN(tst_QIODevice)
#include "tst_qiodevice.moc"