QByteDataBuffer: add readPointer functionality using QByteArrayView

While it could be done before it's nice to not have a custom "local"
struct or the size in an out-parameter.

Change-Id: Ie910f7060b1dadf037312d45e922f8e2deafe3ec
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Mårten Nordheim 2020-07-30 13:55:15 +02:00
parent 0011a45102
commit 43f01ec2e5
2 changed files with 104 additions and 0 deletions

View File

@ -193,6 +193,55 @@ public:
return originalAmount;
}
/*!
\internal
Returns a view into the first QByteArray contained inside,
ignoring any already read data. Call advanceReadPointer()
to advance the view forward. When a QByteArray is exhausted
the view returned by this function will view into another
QByteArray if any. Returns a default constructed view if
no data is available.
\sa advanceReadPointer
*/
QByteArrayView readPointer() const
{
if (isEmpty())
return {};
return { buffers.first().constData() + qsizetype(firstPos),
buffers.first().size() - qsizetype(firstPos) };
}
/*!
\internal
Advances the read pointer by \a distance.
\sa readPointer
*/
void advanceReadPointer(qint64 distance)
{
qint64 newPos = firstPos + distance;
if (isEmpty()) {
newPos = 0;
} else if (auto size = buffers.first().size(); newPos >= size) {
while (newPos >= size) {
bufferCompleteSize -= (size - firstPos);
newPos -= size;
buffers.pop_front();
if (isEmpty()) {
size = 0;
newPos = 0;
break;
}
size = buffers.front().size();
}
bufferCompleteSize -= newPos;
} else {
bufferCompleteSize -= newPos - firstPos;
}
firstPos = newPos;
}
inline char getChar()
{
char c;

View File

@ -43,6 +43,7 @@ private Q_SLOTS:
void readCompleteBuffer();
void readPartialBuffer_data();
void readPartialBuffer();
void readPointer();
private:
void readBuffer(int size, int readSize);
};
@ -170,5 +171,59 @@ void tst_QByteDataBuffer::readPartialBuffer()
readBuffer(size, QIODEVICE_BUFFERSIZE);
}
void tst_QByteDataBuffer::readPointer()
{
QByteDataBuffer buffer;
auto view = buffer.readPointer();
QCOMPARE(view.size(), 0);
QCOMPARE(view, "");
buffer.append("Hello");
buffer.append("World");
qint64 initialSize = buffer.byteAmount();
view = buffer.readPointer();
QCOMPARE(initialSize, buffer.byteAmount());
QCOMPARE(view.size(), 5);
QCOMPARE(view, "Hello");
buffer.advanceReadPointer(2);
view = buffer.readPointer();
QCOMPARE(initialSize - 2, buffer.byteAmount());
QCOMPARE(view.size(), 3);
QCOMPARE(view, "llo");
buffer.advanceReadPointer(3);
view = buffer.readPointer();
QCOMPARE(initialSize - 5, buffer.byteAmount());
QCOMPARE(view.size(), 5);
QCOMPARE(view, "World");
buffer.advanceReadPointer(5);
view = buffer.readPointer();
QVERIFY(buffer.isEmpty());
QCOMPARE(view.size(), 0);
QCOMPARE(view, "");
// Advance past the current view's size
buffer.append("Hello");
buffer.append("World");
buffer.advanceReadPointer(6);
view = buffer.readPointer();
QCOMPARE(view, "orld");
QCOMPARE(buffer.byteAmount(), 4);
// Advance past the end of all contained data
buffer.advanceReadPointer(6);
view = buffer.readPointer();
QCOMPARE(view, "");
}
QTEST_MAIN(tst_QByteDataBuffer)
#include "tst_qbytedatabuffer.moc"