QRingBuffer: add packet mode

As a special case, setting the value of chunk size to zero forces
QRingBuffer to produce a separate QByteArray on each call which
appends the data. So, this enables a packet mode where portions of
data are stored independently from each other.

Change-Id: I2d0b331211901a289da7d4533e974f06830b5590
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alex Trotsenko 2016-07-12 16:14:11 +03:00
parent 3605fc653b
commit 3c6a7a96ef
2 changed files with 43 additions and 21 deletions

View File

@ -108,24 +108,25 @@ char *QRingBuffer::reserve(qint64 bytes)
if (bytes <= 0 || bytes >= MaxByteArraySize) if (bytes <= 0 || bytes >= MaxByteArraySize)
return 0; return 0;
if (buffers.isEmpty()) { if (bufferSize == 0) {
buffers.append(QByteArray()); if (buffers.isEmpty())
buffers.first().resize(qMax(basicBlockSize, int(bytes))); buffers.append(QByteArray(qMax(basicBlockSize, int(bytes)), Qt::Uninitialized));
else
buffers.first().resize(qMax(basicBlockSize, int(bytes)));
} else { } else {
const qint64 newSize = bytes + tail; const qint64 newSize = bytes + tail;
// if need buffer reallocation // if need a new buffer
if (newSize > buffers.constLast().size()) { if (basicBlockSize == 0 || (newSize > buffers.constLast().capacity()
if (newSize > buffers.constLast().capacity() && (tail >= basicBlockSize && (tail >= basicBlockSize || newSize >= MaxByteArraySize))) {
|| newSize >= MaxByteArraySize)) { // shrink this buffer to its current size
// shrink this buffer to its current size buffers.last().resize(tail);
buffers.last().resize(tail);
// create a new QByteArray // create a new QByteArray
buffers.append(QByteArray()); buffers.append(QByteArray(qMax(basicBlockSize, int(bytes)), Qt::Uninitialized));
++tailBuffer; ++tailBuffer;
tail = 0; tail = 0;
} } else if (newSize > buffers.constLast().size()) {
buffers.last().resize(qMax(basicBlockSize, tail + int(bytes))); buffers.last().resize(qMax(basicBlockSize, int(newSize)));
} }
} }
@ -146,10 +147,8 @@ char *QRingBuffer::reserveFront(qint64 bytes)
if (bytes <= 0 || bytes >= MaxByteArraySize) if (bytes <= 0 || bytes >= MaxByteArraySize)
return 0; return 0;
if (head < bytes) { if (head < bytes || basicBlockSize == 0) {
if (buffers.isEmpty()) { if (head > 0) {
buffers.append(QByteArray());
} else {
buffers.first().remove(0, head); buffers.first().remove(0, head);
if (tailBuffer == 0) if (tailBuffer == 0)
tail -= head; tail -= head;
@ -157,12 +156,15 @@ char *QRingBuffer::reserveFront(qint64 bytes)
head = qMax(basicBlockSize, int(bytes)); head = qMax(basicBlockSize, int(bytes));
if (bufferSize == 0) { if (bufferSize == 0) {
if (buffers.isEmpty())
buffers.prepend(QByteArray(head, Qt::Uninitialized));
else
buffers.first().resize(head);
tail = head; tail = head;
} else { } else {
buffers.prepend(QByteArray()); buffers.prepend(QByteArray(head, Qt::Uninitialized));
++tailBuffer; ++tailBuffer;
} }
buffers.first().resize(head);
} }
head -= int(bytes); head -= int(bytes);

View File

@ -45,6 +45,7 @@ private slots:
void sizeWhenReserved(); void sizeWhenReserved();
void free(); void free();
void reserveAndRead(); void reserveAndRead();
void reserveAndReadInPacketMode();
void reserveFrontAndRead(); void reserveFrontAndRead();
void chop(); void chop();
void ungetChar(); void ungetChar();
@ -243,6 +244,25 @@ void tst_QRingBuffer::reserveAndRead()
QCOMPARE(ringBuffer.size(), Q_INT64_C(0)); QCOMPARE(ringBuffer.size(), Q_INT64_C(0));
} }
void tst_QRingBuffer::reserveAndReadInPacketMode()
{
QRingBuffer ringBuffer(0);
// try to allocate 255 buffers
for (int i = 1; i < 256; ++i) {
char *ringPos = ringBuffer.reserve(i);
QVERIFY(ringPos);
}
// count and check the size of stored buffers
int buffersCount = 0;
while (!ringBuffer.isEmpty()) {
QByteArray ba = ringBuffer.read();
++buffersCount;
QCOMPARE(ba.size(), buffersCount);
}
QCOMPARE(buffersCount, 255);
}
void tst_QRingBuffer::reserveFrontAndRead() void tst_QRingBuffer::reserveFrontAndRead()
{ {
QRingBuffer ringBuffer; QRingBuffer ringBuffer;