18void QRingChunk::allocate(qsizetype alloc)
20 Q_ASSERT(alloc > 0 && size() == 0);
22 if (chunk.size() < alloc || isShared())
23 chunk = QByteArray(alloc, Qt::Uninitialized);
36QByteArray QRingChunk::toByteArray() &&
39 if (headOffset != 0 || tailOffset != chunk.size()) {
41 return chunk.sliced(head(), size());
43 chunk.resize(tailOffset);
44 chunk.remove(0, headOffset);
47 return std::move(chunk);
74void QRingBuffer::free(qint64 bytes)
76 Q_ASSERT(bytes <= bufferSize);
79 const qint64 chunkSize = buffers.constFirst().size();
81 if (buffers.size() == 1 || chunkSize > bytes) {
82 QRingChunk &chunk = buffers.first();
86 if (bufferSize == bytes) {
87 if (chunk.capacity() <= basicBlockSize && !chunk.isShared()) {
94 Q_ASSERT(bytes < QByteArray::maxSize());
101 bufferSize -= chunkSize;
103 buffers.removeFirst();
107char *QRingBuffer::reserve(qint64 bytes)
109 Q_ASSERT(bytes > 0 && bytes < QByteArray::maxSize());
111 const qsizetype chunkSize = qMax(qint64(basicBlockSize), bytes);
113 if (bufferSize == 0) {
114 if (buffers.isEmpty())
115 buffers.append(QRingChunk(chunkSize));
117 buffers.first().allocate(chunkSize);
119 const QRingChunk &chunk = buffers.constLast();
121 if (basicBlockSize == 0 || chunk.isShared() || bytes > chunk.available())
122 buffers.append(QRingChunk(chunkSize));
127 buffers.last().grow(bytes);
129 return buffers.last().data() + tail;
137char *QRingBuffer::reserveFront(qint64 bytes)
139 Q_ASSERT(bytes > 0 && bytes < QByteArray::maxSize());
141 const qsizetype chunkSize = qMax(qint64(basicBlockSize), bytes);
142 if (bufferSize == 0) {
143 if (buffers.isEmpty())
144 buffers.prepend(QRingChunk(chunkSize));
146 buffers.first().allocate(chunkSize);
147 buffers.first().grow(chunkSize);
148 buffers.first().advance(chunkSize - bytes);
150 const QRingChunk &chunk = buffers.constFirst();
152 if (basicBlockSize == 0 || chunk.isShared() || bytes > chunk.head()) {
153 buffers.prepend(QRingChunk(chunkSize));
154 buffers.first().grow(chunkSize);
155 buffers.first().advance(chunkSize - bytes);
157 buffers.first().advance(-bytes);
162 return buffers.first().data();
165void QRingBuffer::chop(qint64 bytes)
167 Q_ASSERT(bytes <= bufferSize);
170 const qsizetype chunkSize = buffers.constLast().size();
172 if (buffers.size() == 1 || chunkSize > bytes) {
173 QRingChunk &chunk = buffers.last();
177 if (bufferSize == bytes) {
178 if (chunk.capacity() <= basicBlockSize && !chunk.isShared()) {
185 Q_ASSERT(bytes < QByteArray::maxSize());
192 bufferSize -= chunkSize;
194 buffers.removeLast();
208qint64 QRingBuffer::indexOf(
char c, qint64 maxLength, qint64 pos)
const
210 Q_ASSERT(maxLength >= 0 && pos >= 0);
216 for (
const QRingChunk &chunk : buffers) {
217 const qint64 nextBlockIndex = qMin(index + chunk.size(), maxLength);
219 if (nextBlockIndex > 0) {
220 const char *ptr = chunk.data();
226 const char *findPtr =
reinterpret_cast<
const char *>(memchr(ptr, c,
227 nextBlockIndex - index));
229 return qint64(findPtr - ptr) + index + pos;
231 if (nextBlockIndex == maxLength)
234 index = nextBlockIndex;
239qint64 QRingBuffer::read(
char *data, qint64 maxLength)
241 const qint64 bytesToRead = qMin(size(), maxLength);
242 qint64 readSoFar = 0;
243 while (readSoFar < bytesToRead) {
244 const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
245 nextDataBlockSize());
247 memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
248 readSoFar += bytesToReadFromThisBlock;
249 free(bytesToReadFromThisBlock);
273qint64 QRingBuffer::peek(
char *data, qint64 maxLength, qint64 pos)
const
275 Q_ASSERT(maxLength >= 0 && pos >= 0);
277 qint64 readSoFar = 0;
278 for (
const QRingChunk &chunk : buffers) {
279 if (readSoFar == maxLength)
282 qint64 blockLength = chunk.size();
283 if (pos < blockLength) {
284 blockLength = qMin(blockLength - pos, maxLength - readSoFar);
285 memcpy(data + readSoFar, chunk.data() + pos, blockLength);
286 readSoFar += blockLength;