Make QBuffer::bytesAvailable() work

We don't need to keep an internal QBuffer position, we can just use the
one from QIODevice::pos(). It will keep track of goings ahead and
backwards for us, plus it will make the default bytesAvailable() work
out-of-the-box too.

This error was reported on IRC.

Change-Id: I8559e8ee56edaa01ca8732c1f1012082ebe3a3f2
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
This commit is contained in:
Thiago Macieira 2013-04-11 15:56:17 -07:00 committed by The Qt Project
parent fb1649d30b
commit b4ce49287f
2 changed files with 26 additions and 16 deletions

View File

@ -61,7 +61,6 @@ public:
QByteArray *buf; QByteArray *buf;
QByteArray defaultBuf; QByteArray defaultBuf;
int ioIndex;
virtual qint64 peek(char *data, qint64 maxSize); virtual qint64 peek(char *data, qint64 maxSize);
virtual QByteArray peek(qint64 maxSize); virtual QByteArray peek(qint64 maxSize);
@ -157,14 +156,12 @@ QBuffer::QBuffer()
{ {
Q_D(QBuffer); Q_D(QBuffer);
d->buf = &d->defaultBuf; d->buf = &d->defaultBuf;
d->ioIndex = 0;
} }
QBuffer::QBuffer(QByteArray *buf) QBuffer::QBuffer(QByteArray *buf)
: QIODevice(*new QBufferPrivate) : QIODevice(*new QBufferPrivate)
{ {
Q_D(QBuffer); Q_D(QBuffer);
d->buf = buf ? buf : &d->defaultBuf; d->buf = buf ? buf : &d->defaultBuf;
d->ioIndex = 0;
d->defaultBuf.clear(); d->defaultBuf.clear();
} }
#else #else
@ -180,7 +177,6 @@ QBuffer::QBuffer(QObject *parent)
{ {
Q_D(QBuffer); Q_D(QBuffer);
d->buf = &d->defaultBuf; d->buf = &d->defaultBuf;
d->ioIndex = 0;
} }
/*! /*!
@ -206,7 +202,6 @@ QBuffer::QBuffer(QByteArray *byteArray, QObject *parent)
Q_D(QBuffer); Q_D(QBuffer);
d->buf = byteArray ? byteArray : &d->defaultBuf; d->buf = byteArray ? byteArray : &d->defaultBuf;
d->defaultBuf.clear(); d->defaultBuf.clear();
d->ioIndex = 0;
} }
#endif #endif
@ -253,7 +248,6 @@ void QBuffer::setBuffer(QByteArray *byteArray)
d->buf = &d->defaultBuf; d->buf = &d->defaultBuf;
} }
d->defaultBuf.clear(); d->defaultBuf.clear();
d->ioIndex = 0;
} }
/*! /*!
@ -312,7 +306,6 @@ void QBuffer::setData(const QByteArray &data)
return; return;
} }
*d->buf = data; *d->buf = data;
d->ioIndex = 0;
} }
/*! /*!
@ -340,7 +333,6 @@ bool QBuffer::open(OpenMode flags)
if ((flags & Truncate) == Truncate) if ((flags & Truncate) == Truncate)
d->buf->resize(0); d->buf->resize(0);
d->ioIndex = (flags & Append) == Append ? d->buf->size() : 0;
return QIODevice::open(flags); return QIODevice::open(flags);
} }
@ -390,7 +382,6 @@ bool QBuffer::seek(qint64 pos)
qWarning("QBuffer::seek: Invalid pos: %d", int(pos)); qWarning("QBuffer::seek: Invalid pos: %d", int(pos));
return false; return false;
} }
d->ioIndex = int(pos);
return QIODevice::seek(pos); return QIODevice::seek(pos);
} }
@ -420,10 +411,9 @@ bool QBuffer::canReadLine() const
qint64 QBuffer::readData(char *data, qint64 len) qint64 QBuffer::readData(char *data, qint64 len)
{ {
Q_D(QBuffer); Q_D(QBuffer);
if ((len = qMin(len, qint64(d->buf->size()) - d->ioIndex)) <= 0) if ((len = qMin(len, qint64(d->buf->size()) - pos())) <= 0)
return qint64(0); return qint64(0);
memcpy(data, d->buf->constData() + d->ioIndex, len); memcpy(data, d->buf->constData() + pos(), len);
d->ioIndex += int(len);
return len; return len;
} }
@ -433,7 +423,7 @@ qint64 QBuffer::readData(char *data, qint64 len)
qint64 QBuffer::writeData(const char *data, qint64 len) qint64 QBuffer::writeData(const char *data, qint64 len)
{ {
Q_D(QBuffer); Q_D(QBuffer);
int extraBytes = d->ioIndex + len - d->buf->size(); int extraBytes = pos() + len - d->buf->size();
if (extraBytes > 0) { // overflow if (extraBytes > 0) { // overflow
int newSize = d->buf->size() + extraBytes; int newSize = d->buf->size() + extraBytes;
d->buf->resize(newSize); d->buf->resize(newSize);
@ -443,8 +433,7 @@ qint64 QBuffer::writeData(const char *data, qint64 len)
} }
} }
memcpy(d->buf->data() + d->ioIndex, (uchar *)data, int(len)); memcpy(d->buf->data() + pos(), (uchar *)data, int(len));
d->ioIndex += int(len);
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
d->writtenSinceLastEmit += len; d->writtenSinceLastEmit += len;

View File

@ -149,20 +149,25 @@ void tst_QBuffer::readBlock()
const int arraySize = 10; const int arraySize = 10;
char a[arraySize]; char a[arraySize];
QBuffer b; QBuffer b;
QCOMPARE(b.bytesAvailable(), (qint64) 0); // no data
QCOMPARE(b.read(a, arraySize), (qint64) -1); // not opened QCOMPARE(b.read(a, arraySize), (qint64) -1); // not opened
QVERIFY(b.atEnd()); QVERIFY(b.atEnd());
QByteArray ba; QByteArray ba;
ba.resize(arraySize); ba.resize(arraySize);
b.setBuffer(&ba); b.setBuffer(&ba);
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
b.open(QIODevice::WriteOnly); b.open(QIODevice::WriteOnly);
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device"); QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
QCOMPARE(b.read(a, arraySize), (qint64) -1); // no read access QCOMPARE(b.read(a, arraySize), (qint64) -1); // no read access
b.close(); b.close();
b.open(QIODevice::ReadOnly); b.open(QIODevice::ReadOnly);
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
QCOMPARE(b.read(a, arraySize), (qint64) arraySize); QCOMPARE(b.read(a, arraySize), (qint64) arraySize);
QVERIFY(b.atEnd()); QVERIFY(b.atEnd());
QCOMPARE(b.bytesAvailable(), (qint64) 0);
// up to 3.0.x reading beyond the end was an error while ok // up to 3.0.x reading beyond the end was an error while ok
// this has been made consistent with other QIODevice sub classes in 3.1 // this has been made consistent with other QIODevice sub classes in 3.1
@ -172,10 +177,13 @@ void tst_QBuffer::readBlock()
// read in two chunks // read in two chunks
b.close(); b.close();
b.open(QIODevice::ReadOnly); b.open(QIODevice::ReadOnly);
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
QCOMPARE(b.read(a, arraySize/2), (qint64) arraySize/2); QCOMPARE(b.read(a, arraySize/2), (qint64) arraySize/2);
QCOMPARE(b.bytesAvailable(), (qint64) arraySize/2);
QCOMPARE(b.read(a + arraySize/2, arraySize - arraySize/2), QCOMPARE(b.read(a + arraySize/2, arraySize - arraySize/2),
(qint64)(arraySize - arraySize/2)); (qint64)(arraySize - arraySize/2));
QVERIFY(b.atEnd()); QVERIFY(b.atEnd());
QCOMPARE(b.bytesAvailable(), (qint64) 0);
} }
void tst_QBuffer::readBlockPastEnd() void tst_QBuffer::readBlockPastEnd()
@ -319,9 +327,12 @@ void tst_QBuffer::seekTest()
buf.open(QIODevice::ReadWrite); buf.open(QIODevice::ReadWrite);
QCOMPARE(buf.pos(), qint64(0)); QCOMPARE(buf.pos(), qint64(0));
QCOMPARE(buf.bytesAvailable(), qint64(0));
QByteArray data = str.toLatin1(); QByteArray data = str.toLatin1();
QCOMPARE(buf.write( data.constData(), data.size() ), qint64(data.size())); QCOMPARE(buf.write( data.constData(), data.size() ), qint64(data.size()));
QCOMPARE(buf.bytesAvailable(), qint64(0)); // we're at the end
QCOMPARE(buf.size(), qint64(data.size()));
QTest::ignoreMessage(QtWarningMsg, "QBuffer::seek: Invalid pos: -1"); QTest::ignoreMessage(QtWarningMsg, "QBuffer::seek: Invalid pos: -1");
DO_INVALID_SEEK(-1); DO_INVALID_SEEK(-1);
@ -336,6 +347,7 @@ void tst_QBuffer::seekTest()
{ {
char c = 'a'; char c = 'a';
QVERIFY(buf.seek(qint64(str.size()))); QVERIFY(buf.seek(qint64(str.size())));
QCOMPARE(buf.bytesAvailable(), qint64(0));
QCOMPARE(buf.read(&c, qint64(1)), qint64(0)); QCOMPARE(buf.read(&c, qint64(1)), qint64(0));
QCOMPARE(c, 'a'); QCOMPARE(c, 'a');
QCOMPARE(buf.write(&c, qint64(1)), qint64(1)); QCOMPARE(buf.write(&c, qint64(1)), qint64(1));
@ -347,6 +359,7 @@ void tst_QBuffer::seekTest()
const int offset = 1; // any positive integer will do const int offset = 1; // any positive integer will do
const qint64 pos = buf.size() + offset; const qint64 pos = buf.size() + offset;
QVERIFY(buf.seek(pos)); QVERIFY(buf.seek(pos));
QCOMPARE(buf.bytesAvailable(), qint64(0));
QCOMPARE(buf.pos(), pos); QCOMPARE(buf.pos(), pos);
QVERIFY(!buf.getChar(&c)); QVERIFY(!buf.getChar(&c));
QVERIFY(buf.seek(pos - 1)); QVERIFY(buf.seek(pos - 1));
@ -533,7 +546,11 @@ void tst_QBuffer::readLineBoundaries()
lineByLine.append(buffer.readLine()); lineByLine.append(buffer.readLine());
buffer.seek(0); buffer.seek(0);
QCOMPARE(lineByLine, buffer.readAll()); QCOMPARE(buffer.bytesAvailable(), lineByLine.size());
QByteArray all = buffer.readAll();
QCOMPARE(all.size(), lineByLine.size());
QCOMPARE(all, lineByLine);
} }
// Test that any character in a buffer can be read and pushed back. // Test that any character in a buffer can be read and pushed back.
@ -548,7 +565,9 @@ void tst_QBuffer::getAndUngetChar()
// Take a copy of the data held in the buffer // Take a copy of the data held in the buffer
buffer.seek(0); buffer.seek(0);
QCOMPARE(buffer.bytesAvailable(), buffer.size());
QByteArray data = buffer.readAll(); QByteArray data = buffer.readAll();
QCOMPARE(buffer.bytesAvailable(), qint64(0));
// Get and unget each character in order // Get and unget each character in order
for (qint64 i = 0; i < buffer.size(); ++i) { for (qint64 i = 0; i < buffer.size(); ++i) {
@ -570,7 +589,9 @@ void tst_QBuffer::getAndUngetChar()
// Verify that the state of the buffer still matches the original data. // Verify that the state of the buffer still matches the original data.
buffer.seek(0); buffer.seek(0);
QCOMPARE(buffer.bytesAvailable(), data.size());
QCOMPARE(buffer.readAll(), data); QCOMPARE(buffer.readAll(), data);
QCOMPARE(buffer.bytesAvailable(), qint64(0));
} }
void tst_QBuffer::writeAfterQByteArrayResize() void tst_QBuffer::writeAfterQByteArrayResize()