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

View File

@ -45,6 +45,7 @@ private slots:
void sizeWhenReserved();
void free();
void reserveAndRead();
void reserveAndReadInPacketMode();
void reserveFrontAndRead();
void chop();
void ungetChar();
@ -243,6 +244,25 @@ void tst_QRingBuffer::reserveAndRead()
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()
{
QRingBuffer ringBuffer;