From 853cba729bc2bbac254ee36be6d42241eb92fd21 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Mon, 23 Mar 2015 14:36:19 +0200 Subject: [PATCH] QRingBuffer: allow to peek bytes from any position Add an ordinary peek() function which also allows retrieving data from a specified position. We need this functionality in several places. Change-Id: Ia4a1b6fe1d7f76cb8f6f1ea34b3e4b89e05a2a68 Reviewed-by: Thiago Macieira --- src/corelib/tools/qringbuffer_p.h | 24 +++++++++++++++++ .../tools/qringbuffer/tst_qringbuffer.cpp | 26 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index 6f4ebcf420..9ca14d2987 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -293,6 +293,30 @@ public: return qba; } + // peek the bytes from a specified position + inline qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const + { + qint64 readSoFar = 0; + + if (pos >= 0) { + pos += head; + for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) { + qint64 blockLength = (i == tailBuffer ? tail : buffers[i].size()); + + if (pos < blockLength) { + blockLength = qMin(blockLength - pos, maxLength - readSoFar); + memcpy(data + readSoFar, buffers[i].constData() + pos, blockLength); + readSoFar += blockLength; + pos = 0; + } else { + pos -= blockLength; + } + } + } + + return readSoFar; + } + // append a new buffer to the end inline void append(const QByteArray &qba) { if (tail == 0) { diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp index 33e143fa7d..044fdbdee5 100644 --- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp +++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp @@ -52,6 +52,7 @@ private slots: void ungetChar(); void indexOf(); void appendAndRead(); + void peek(); void readLine(); }; @@ -280,6 +281,31 @@ void tst_QRingBuffer::appendAndRead() QVERIFY(ringBuffer.read() == ba3); } +void tst_QRingBuffer::peek() +{ + QRingBuffer ringBuffer; + QByteArray testBuffer; + // fill buffer with an arithmetic progression + for (int i = 1; i < 256; ++i) { + char *ringPos = ringBuffer.reserve(i); + QVERIFY(ringPos); + memset(ringPos, i, i); + testBuffer.append(ringPos, i); + } + + // check stored data + QByteArray resultBuffer; + int peekPosition = testBuffer.size(); + for (int i = 1; i < 256; ++i) { + QByteArray ba(i, 0); + peekPosition -= i; + qint64 thisPeek = ringBuffer.peek(ba.data(), i, peekPosition); + QCOMPARE(thisPeek, qint64(i)); + resultBuffer.prepend(ba); + } + QCOMPARE(testBuffer, resultBuffer); +} + void tst_QRingBuffer::readLine() { QRingBuffer ringBuffer;