diff options
Diffstat (limited to 'src/corelib/tools/qringbuffer.cpp')
-rw-r--r-- | src/corelib/tools/qringbuffer.cpp | 89 |
1 files changed, 60 insertions, 29 deletions
diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp index 85cfdaf129..e9b655c01e 100644 --- a/src/corelib/tools/qringbuffer.cpp +++ b/src/corelib/tools/qringbuffer.cpp @@ -65,6 +65,8 @@ const char *QRingBuffer::readPointerAtPosition(qint64 pos, qint64 &length) const void QRingBuffer::free(qint64 bytes) { + Q_ASSERT(bytes <= bufferSize); + while (bytes > 0) { const qint64 blockSize = buffers.first().size() - head; @@ -100,20 +102,25 @@ char *QRingBuffer::reserve(qint64 bytes) if (bytes <= 0 || bytes >= MaxByteArraySize) return 0; - const qint64 newSize = bytes + tail; - // if need buffer reallocation - if (newSize > buffers.last().size()) { - if (newSize > buffers.last().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; + if (buffers.isEmpty()) { + buffers.append(QByteArray()); + buffers.first().resize(qMax(basicBlockSize, int(bytes))); + } else { + const qint64 newSize = bytes + tail; + // if need buffer reallocation + if (newSize > buffers.last().size()) { + if (newSize > buffers.last().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))); } - buffers.last().resize(qMax(basicBlockSize, tail + int(bytes))); } char *writePtr = buffers.last().data() + tail; @@ -134,9 +141,13 @@ char *QRingBuffer::reserveFront(qint64 bytes) return 0; if (head < bytes) { - buffers.first().remove(0, head); - if (tailBuffer == 0) - tail -= head; + if (buffers.isEmpty()) { + buffers.append(QByteArray()); + } else { + buffers.first().remove(0, head); + if (tailBuffer == 0) + tail -= head; + } head = qMax(basicBlockSize, int(bytes)); if (bufferSize == 0) { @@ -155,6 +166,8 @@ char *QRingBuffer::reserveFront(qint64 bytes) void QRingBuffer::chop(qint64 bytes) { + Q_ASSERT(bytes <= bufferSize); + while (bytes > 0) { if (tailBuffer == 0 || tail > bytes) { // keep a single block around if it does not exceed @@ -185,6 +198,9 @@ void QRingBuffer::chop(qint64 bytes) void QRingBuffer::clear() { + if (buffers.isEmpty()) + return; + buffers.erase(buffers.begin() + 1, buffers.end()); buffers.first().clear(); @@ -193,20 +209,32 @@ void QRingBuffer::clear() bufferSize = 0; } -qint64 QRingBuffer::indexOf(char c, qint64 maxLength) const +qint64 QRingBuffer::indexOf(char c, qint64 maxLength, qint64 pos) const { - qint64 index = 0; - qint64 j = head; - for (int i = 0; index < maxLength && i < buffers.size(); ++i) { - const char *ptr = buffers[i].constData() + j; - j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength); - - while (index < j) { - if (*ptr++ == c) - return index; - ++index; + if (maxLength <= 0 || pos < 0) + return -1; + + qint64 index = -(pos + head); + for (int i = 0; i < buffers.size(); ++i) { + const qint64 nextBlockIndex = qMin(index + (i == tailBuffer ? tail : buffers[i].size()), + maxLength); + + if (nextBlockIndex > 0) { + const char *ptr = buffers[i].constData(); + if (index < 0) { + ptr -= index; + index = 0; + } + + const char *findPtr = reinterpret_cast<const char *>(memchr(ptr, c, + nextBlockIndex - index)); + if (findPtr) + return qint64(findPtr - ptr) + index + pos; + + if (nextBlockIndex == maxLength) + return -1; } - j = 0; + index = nextBlockIndex; } return -1; } @@ -288,7 +316,10 @@ qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const void QRingBuffer::append(const QByteArray &qba) { if (tail == 0) { - buffers.last() = qba; + if (buffers.isEmpty()) + buffers.append(qba); + else + buffers.last() = qba; } else { buffers.last().resize(tail); buffers.append(qba); |