summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2015-09-11 12:15:03 +0300
committerAlex Trotsenko <alex1973tr@gmail.com>2015-10-27 18:24:34 +0000
commit1e32ade79ced64597ef4148f16e0d8a329733c4e (patch)
tree443c995629abb8db88a9d53b00af365f72df218b
parent33486e0ae7d40045029f9e24bebdf7a6829f756c (diff)
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 <oswald.buddenhagen@theqtcompany.com>
-rw-r--r--src/corelib/io/qiodevice.cpp7
-rw-r--r--tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp41
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"