Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qringbuffer_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QRINGBUFFER_P_H
6#define QRINGBUFFER_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists for the convenience
13// of a number of Qt sources files. This header file may change from
14// version to version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/private/qglobal_p.h>
20#include <QtCore/qbytearray.h>
21#include <QtCore/qlist.h>
22
23QT_BEGIN_NAMESPACE
24
25#ifndef QRINGBUFFER_CHUNKSIZE
26#define QRINGBUFFER_CHUNKSIZE 4096
27#endif
28
29class QRingChunk
30{
31public:
32 // initialization and cleanup
33 QRingChunk() noexcept = default;
34 explicit inline QRingChunk(qsizetype alloc) :
35 chunk(alloc, Qt::Uninitialized), tailOffset(0)
36 {
37 }
38 explicit inline QRingChunk(const QByteArray &qba) noexcept :
39 chunk(qba), tailOffset(qba.size())
40 {
41 }
42 explicit QRingChunk(QByteArray &&qba) noexcept :
43 chunk(std::move(qba)), tailOffset(chunk.size())
44 {
45 }
46
47 inline void swap(QRingChunk &other) noexcept
48 {
49 chunk.swap(other.chunk);
50 qSwap(headOffset, other.headOffset);
51 qSwap(tailOffset, other.tailOffset);
52 }
53
54 // allocating and sharing
55 void allocate(qsizetype alloc);
56 inline bool isShared() const
57 {
58 return !chunk.isDetached();
59 }
60 Q_CORE_EXPORT void detach();
61 QByteArray toByteArray() &&;
62
63 // getters
64 inline qsizetype head() const
65 {
66 return headOffset;
67 }
68 inline qsizetype size() const
69 {
70 return tailOffset - headOffset;
71 }
72 inline qsizetype capacity() const
73 {
74 return chunk.size();
75 }
76 inline qsizetype available() const
77 {
78 return chunk.size() - tailOffset;
79 }
80 inline const char *data() const
81 {
82 return chunk.constData() + headOffset;
83 }
84 inline char *data()
85 {
86 if (isShared())
87 detach();
88 return chunk.data() + headOffset;
89 }
90
91 // array management
92 inline void advance(qsizetype offset)
93 {
94 Q_ASSERT(headOffset + offset >= 0);
95 Q_ASSERT(size() - offset > 0);
96
97 headOffset += offset;
98 }
99 inline void grow(qsizetype offset)
100 {
101 Q_ASSERT(size() + offset > 0);
102 Q_ASSERT(head() + size() + offset <= capacity());
103
104 tailOffset += offset;
105 }
106 inline void assign(const QByteArray &qba)
107 {
108 chunk = qba;
109 headOffset = 0;
110 tailOffset = qba.size();
111 }
112 void assign(QByteArray &&qba)
113 {
114 chunk = std::move(qba);
115 headOffset = 0;
116 tailOffset = chunk.size();
117 }
118 inline void reset()
119 {
120 headOffset = tailOffset = 0;
121 }
122 inline void clear()
123 {
124 *this = {};
125 }
126
127private:
128 QByteArray chunk;
129 qsizetype headOffset = 0;
130 qsizetype tailOffset = 0;
131};
132Q_DECLARE_SHARED(QRingChunk)
133
135{
137public:
140
141 QRingBuffer(QRingBuffer &&) noexcept = default;
142 QRingBuffer &operator=(QRingBuffer &&) noexcept = default;
143
144 inline void setChunkSize(int size) {
145 basicBlockSize = size;
146 }
147
148 inline int chunkSize() const {
149 return basicBlockSize;
150 }
151
152 inline qint64 nextDataBlockSize() const {
153 return bufferSize == 0 ? Q_INT64_C(0) : buffers.first().size();
154 }
155
156 inline const char *readPointer() const {
157 return bufferSize == 0 ? nullptr : buffers.first().data();
158 }
159
160 Q_CORE_EXPORT const char *readPointerAtPosition(qint64 pos, qint64 &length) const;
161 Q_CORE_EXPORT void free(qint64 bytes);
162 Q_CORE_EXPORT char *reserve(qint64 bytes);
163 Q_CORE_EXPORT char *reserveFront(qint64 bytes);
164
165 inline void truncate(qint64 pos) {
166 Q_ASSERT(pos >= 0 && pos <= size());
167
168 chop(size() - pos);
169 }
170
171 Q_CORE_EXPORT void chop(qint64 bytes);
172
173 inline bool isEmpty() const {
174 return bufferSize == 0;
175 }
176
177 inline int getChar() {
178 if (isEmpty())
179 return -1;
180 char c = *readPointer();
181 free(1);
182 return int(uchar(c));
183 }
184
185 inline void putChar(char c) {
186 char *ptr = reserve(1);
187 *ptr = c;
188 }
189
190 void ungetChar(char c)
191 {
192 char *ptr = reserveFront(1);
193 *ptr = c;
194 }
195
196
197 inline qint64 size() const {
198 return bufferSize;
199 }
200
201 Q_CORE_EXPORT void clear();
202 inline qint64 indexOf(char c) const { return indexOf(c, size()); }
203 Q_CORE_EXPORT qint64 indexOf(char c, qint64 maxLength, qint64 pos = 0) const;
205 Q_CORE_EXPORT QByteArray read();
207 Q_CORE_EXPORT void append(const char *data, qint64 size);
208 Q_CORE_EXPORT void append(const QByteArray &qba);
209 Q_CORE_EXPORT void append(QByteArray &&qba);
210
211 inline qint64 skip(qint64 length) {
212 qint64 bytesToSkip = qMin(length, bufferSize);
213
214 free(bytesToSkip);
215 return bytesToSkip;
216 }
217
220
221 inline bool canReadLine() const {
222 return indexOf('\n') >= 0;
223 }
224
225private:
226 QList<QRingChunk> buffers;
227 qint64 bufferSize;
228 int basicBlockSize;
229};
230
232
233QT_END_NAMESPACE
234
235#endif // QRINGBUFFER_P_H
bool isEmpty() const
Q_CORE_EXPORT void free(qint64 bytes)
qint64 size() const
QRingBuffer & operator=(QRingBuffer &&) noexcept=default
const char * readPointer() const
Q_CORE_EXPORT void append(const QByteArray &qba)
Q_CORE_EXPORT const char * readPointerAtPosition(qint64 pos, qint64 &length) const
qint64 skip(qint64 length)
Q_CORE_EXPORT void chop(qint64 bytes)
Q_CORE_EXPORT char * reserve(qint64 bytes)
bool canReadLine() const
void setChunkSize(int size)
void truncate(qint64 pos)
Q_CORE_EXPORT void append(const char *data, qint64 size)
Q_CORE_EXPORT char * reserveFront(qint64 bytes)
qint64 indexOf(char c) const
Q_CORE_EXPORT void clear()
qint64 nextDataBlockSize() const
int chunkSize() const
Q_CORE_EXPORT void append(QByteArray &&qba)
void ungetChar(char c)
void putChar(char c)
#define QRINGBUFFER_CHUNKSIZE
Q_DECLARE_TYPEINFO(QRingBuffer, Q_RELOCATABLE_TYPE)