From 1e32ade79ced64597ef4148f16e0d8a329733c4e Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 11 Sep 2015 12:15:03 +0300 Subject: QIODevice: fix interleaving read() and write() in text mode under Windows Skip the correct number of bytes in the read buffer when expanding '\n' into "\r\n" upon writing. Change-Id: I5b01fc47c330dee5c83001abf0acd7d63d790b96 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qiodevice.cpp | 7 ++-- tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp | 41 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index c80c78bd3b..3b1cd196d2 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1289,6 +1289,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize) const char *startOfBlock = data; qint64 writtenSoFar = 0; + const qint64 savedPos = d->pos; forever { const char *endOfBlock = startOfBlock; @@ -1300,7 +1301,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize) qint64 ret = writeData(startOfBlock, blockSize); if (ret <= 0) { if (writtenSoFar && !sequential) - d->buffer.skip(writtenSoFar); + d->buffer.skip(d->pos - savedPos); return writtenSoFar ? writtenSoFar : ret; } if (!sequential) { @@ -1316,7 +1317,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize) qint64 ret = writeData("\r\n", 2); if (ret <= 0) { if (writtenSoFar && !sequential) - d->buffer.skip(writtenSoFar); + d->buffer.skip(d->pos - savedPos); return writtenSoFar ? writtenSoFar : ret; } if (!sequential) { @@ -1329,7 +1330,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize) } if (writtenSoFar && !sequential) - d->buffer.skip(writtenSoFar); + d->buffer.skip(d->pos - savedPos); return writtenSoFar; } #endif diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp index 565ca18899..334f5aba05 100644 --- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp +++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp @@ -59,6 +59,7 @@ private slots: void peekBug(); void readAllKeepPosition(); + void writeInTextMode(); }; void tst_QIODevice::initTestCase() @@ -628,5 +629,45 @@ void tst_QIODevice::readAllKeepPosition() QCOMPARE(resultArray, buffer.buffer()); } +class RandomAccessBuffer : public QIODevice +{ +public: + RandomAccessBuffer(const char *data) : QIODevice(), buf(data) { } + +protected: + qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE + { + maxSize = qMin(maxSize, qint64(buf.size() - pos())); + memcpy(data, buf.constData() + pos(), maxSize); + return maxSize; + } + qint64 writeData(const char *data, qint64 maxSize) Q_DECL_OVERRIDE + { + maxSize = qMin(maxSize, qint64(buf.size() - pos())); + memcpy(buf.data() + pos(), data, maxSize); + return maxSize; + } + +private: + QByteArray buf; +}; + +// Test write() on skipping correct number of bytes in read buffer +void tst_QIODevice::writeInTextMode() +{ + // Unlike other platforms, Windows implementation expands '\n' into + // "\r\n" sequence in write(). Ensure that write() properly works with + // a read buffer on random-access devices. +#ifndef Q_OS_WIN + QSKIP("This is a Windows-only test"); +#else + RandomAccessBuffer buffer("one\r\ntwo\r\nthree\r\n"); + buffer.open(QBuffer::ReadWrite | QBuffer::Text); + QCOMPARE(buffer.readLine(), QByteArray("one\n")); + QCOMPARE(buffer.write("two\n"), 4); + QCOMPARE(buffer.readLine(), QByteArray("three\n")); +#endif +} + QTEST_MAIN(tst_QIODevice) #include "tst_qiodevice.moc" -- cgit v1.2.3