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>
This commit is contained in:
parent
33486e0ae7
commit
1e32ade79c
@ -1289,6 +1289,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize)
|
|||||||
const char *startOfBlock = data;
|
const char *startOfBlock = data;
|
||||||
|
|
||||||
qint64 writtenSoFar = 0;
|
qint64 writtenSoFar = 0;
|
||||||
|
const qint64 savedPos = d->pos;
|
||||||
|
|
||||||
forever {
|
forever {
|
||||||
const char *endOfBlock = startOfBlock;
|
const char *endOfBlock = startOfBlock;
|
||||||
@ -1300,7 +1301,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize)
|
|||||||
qint64 ret = writeData(startOfBlock, blockSize);
|
qint64 ret = writeData(startOfBlock, blockSize);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (writtenSoFar && !sequential)
|
if (writtenSoFar && !sequential)
|
||||||
d->buffer.skip(writtenSoFar);
|
d->buffer.skip(d->pos - savedPos);
|
||||||
return writtenSoFar ? writtenSoFar : ret;
|
return writtenSoFar ? writtenSoFar : ret;
|
||||||
}
|
}
|
||||||
if (!sequential) {
|
if (!sequential) {
|
||||||
@ -1316,7 +1317,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize)
|
|||||||
qint64 ret = writeData("\r\n", 2);
|
qint64 ret = writeData("\r\n", 2);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (writtenSoFar && !sequential)
|
if (writtenSoFar && !sequential)
|
||||||
d->buffer.skip(writtenSoFar);
|
d->buffer.skip(d->pos - savedPos);
|
||||||
return writtenSoFar ? writtenSoFar : ret;
|
return writtenSoFar ? writtenSoFar : ret;
|
||||||
}
|
}
|
||||||
if (!sequential) {
|
if (!sequential) {
|
||||||
@ -1329,7 +1330,7 @@ qint64 QIODevice::write(const char *data, qint64 maxSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (writtenSoFar && !sequential)
|
if (writtenSoFar && !sequential)
|
||||||
d->buffer.skip(writtenSoFar);
|
d->buffer.skip(d->pos - savedPos);
|
||||||
return writtenSoFar;
|
return writtenSoFar;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,6 +59,7 @@ private slots:
|
|||||||
|
|
||||||
void peekBug();
|
void peekBug();
|
||||||
void readAllKeepPosition();
|
void readAllKeepPosition();
|
||||||
|
void writeInTextMode();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QIODevice::initTestCase()
|
void tst_QIODevice::initTestCase()
|
||||||
@ -628,5 +629,45 @@ void tst_QIODevice::readAllKeepPosition()
|
|||||||
QCOMPARE(resultArray, buffer.buffer());
|
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)
|
QTEST_MAIN(tst_QIODevice)
|
||||||
#include "tst_qiodevice.moc"
|
#include "tst_qiodevice.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user