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;
|
||||
|
||||
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
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user