Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qbuffer.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 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:critical reason:data-parser
4
5
#
include
"qbuffer.h"
6
#
include
<
QtCore
/
qmetaobject
.
h
>
7
#
include
"private/qiodevice_p.h"
8
9
#
include
<
limits
>
10
11
QT_BEGIN_NAMESPACE
12
13
/** QBufferPrivate **/
14
class
QBufferPrivate :
public
QIODevicePrivate
15
{
16
Q_DECLARE_PUBLIC(QBuffer)
17
18
public
:
19
QBufferPrivate() =
default
;
20
21
QByteArray *buf =
nullptr
;
22
QByteArray defaultBuf;
23
24
qint64 peek(
char
*data, qint64 maxSize) override;
25
QByteArray peek(qint64 maxSize) override;
26
27
#
ifndef
QT_NO_QOBJECT
28
qint64 writtenSinceLastEmit = 0;
29
int
signalConnectionCount = 0;
30
bool
signalsEmitted =
false
;
31
#
endif
32
};
33
34
qint64 QBufferPrivate::peek(
char
*data, qint64 maxSize)
35
{
36
qint64 readBytes = qMin(maxSize,
static_cast
<qint64>(buf->size()) - pos);
37
memcpy(data, buf->constData() + pos, readBytes);
38
return
readBytes;
39
}
40
41
QByteArray QBufferPrivate::peek(qint64 maxSize)
42
{
43
qint64 readBytes = qMin(maxSize,
static_cast
<qint64>(buf->size()) - pos);
44
if
(pos == 0 && maxSize >= buf->size())
45
return
*buf;
46
return
QByteArray(buf->constData() + pos, readBytes);
47
}
48
49
/*!
50
\class QBuffer
51
\inmodule QtCore
52
\reentrant
53
\brief The QBuffer class provides a QIODevice interface for a QByteArray.
54
55
\ingroup io
56
57
QBuffer allows you to access a QByteArray using the QIODevice
58
interface. The QByteArray is treated just as a standard random-accessed
59
file. Example:
60
61
\snippet buffer/buffer.cpp 0
62
63
By default, an internal QByteArray buffer is created for you when
64
you create a QBuffer. You can access this buffer directly by
65
calling buffer(). You can also use QBuffer with an existing
66
QByteArray by calling setBuffer(), or by passing your array to
67
QBuffer's constructor.
68
69
Call open() to open the buffer. Then call write() or
70
putChar() to write to the buffer, and read(), readLine(),
71
readAll(), or getChar() to read from it. size() returns the
72
current size of the buffer, and you can seek to arbitrary
73
positions in the buffer by calling seek(). When you are done with
74
accessing the buffer, call close().
75
76
The following code snippet shows how to write data to a
77
QByteArray using QDataStream and QBuffer:
78
79
\snippet buffer/buffer.cpp 1
80
81
Effectively, we convert the application's QPalette into a byte
82
array. Here's how to read the data from the QByteArray:
83
84
\snippet buffer/buffer.cpp 2
85
86
QTextStream and QDataStream also provide convenience constructors
87
that take a QByteArray and that create a QBuffer behind the
88
scenes.
89
90
QBuffer emits readyRead() when new data has arrived in the
91
buffer. By connecting to this signal, you can use QBuffer to
92
store temporary data before processing it. QBuffer also emits
93
bytesWritten() every time new data has been written to the buffer.
94
95
\sa QFile, QDataStream, QTextStream, QByteArray
96
*/
97
98
#
ifdef
QT_NO_QOBJECT
99
QBuffer::QBuffer()
100
: QIODevice(*
new
QBufferPrivate)
101
{
102
Q_D(QBuffer);
103
d->buf = &d->defaultBuf;
104
}
105
QBuffer::QBuffer(QByteArray *buf)
106
: QIODevice(*
new
QBufferPrivate)
107
{
108
Q_D(QBuffer);
109
d->buf = buf ? buf : &d->defaultBuf;
110
d->defaultBuf.clear();
111
}
112
#
else
113
/*!
114
Constructs an empty buffer with the given \a parent. You can call
115
setData() to fill the buffer with data, or you can open it in
116
write mode and use write().
117
118
\sa open()
119
*/
120
QBuffer::QBuffer(QObject *parent)
121
: QIODevice(*
new
QBufferPrivate, parent)
122
{
123
Q_D(QBuffer);
124
d->buf = &d->defaultBuf;
125
}
126
127
/*!
128
Constructs a QBuffer that uses the QByteArray pointed to by \a
129
byteArray as its internal buffer, and with the given \a parent.
130
The caller is responsible for ensuring that \a byteArray remains
131
valid until the QBuffer is destroyed, or until setBuffer() is
132
called to change the buffer. QBuffer doesn't take ownership of
133
the QByteArray.
134
135
If you open the buffer in write-only mode or read-write mode and
136
write something into the QBuffer, \a byteArray will be modified.
137
138
Example:
139
140
\snippet buffer/buffer.cpp 3
141
142
\sa open(), setBuffer(), setData()
143
*/
144
QBuffer::QBuffer(QByteArray *byteArray, QObject *parent)
145
: QIODevice(*
new
QBufferPrivate, parent)
146
{
147
Q_D(QBuffer);
148
d->buf = byteArray ? byteArray : &d->defaultBuf;
149
d->defaultBuf.clear();
150
}
151
#
endif
152
153
/*!
154
Destroys the buffer.
155
*/
156
157
QBuffer::~QBuffer()
158
{
159
}
160
161
/*!
162
Makes QBuffer use the QByteArray pointed to by \a
163
byteArray as its internal buffer. The caller is responsible for
164
ensuring that \a byteArray remains valid until the QBuffer is
165
destroyed, or until setBuffer() is called to change the buffer.
166
QBuffer doesn't take ownership of the QByteArray.
167
168
Does nothing if isOpen() is true.
169
170
If you open the buffer in write-only mode or read-write mode and
171
write something into the QBuffer, \a byteArray will be modified.
172
173
Example:
174
175
\snippet buffer/buffer.cpp 4
176
177
If \a byteArray is \nullptr, the buffer creates its own internal
178
QByteArray to work on. This byte array is initially empty.
179
180
\sa buffer(), setData(), open()
181
*/
182
183
void
QBuffer::setBuffer(QByteArray *byteArray)
184
{
185
Q_D(QBuffer);
186
if
(isOpen()) {
187
qWarning(
"QBuffer::setBuffer: Buffer is open"
);
188
return
;
189
}
190
if
(byteArray) {
191
d->buf = byteArray;
192
}
else
{
193
d->buf = &d->defaultBuf;
194
}
195
d->defaultBuf.clear();
196
}
197
198
/*!
199
Returns a reference to the QBuffer's internal buffer. You can use
200
it to modify the QByteArray behind the QBuffer's back.
201
202
\sa setBuffer(), data()
203
*/
204
205
QByteArray &QBuffer::buffer()
206
{
207
Q_D(QBuffer);
208
return
*d->buf;
209
}
210
211
/*!
212
\overload
213
214
This is the same as data().
215
*/
216
217
const
QByteArray &QBuffer::buffer()
const
218
{
219
Q_D(
const
QBuffer);
220
return
*d->buf;
221
}
222
223
224
/*!
225
Returns the data contained in the buffer.
226
227
This is the same as buffer().
228
229
\sa setData(), setBuffer()
230
*/
231
232
const
QByteArray &QBuffer::data()
const
233
{
234
Q_D(
const
QBuffer);
235
return
*d->buf;
236
}
237
238
/*!
239
Sets the contents of the internal buffer to be \a data. This is
240
the same as assigning \a data to buffer().
241
242
Does nothing if isOpen() is true.
243
244
\sa setBuffer()
245
*/
246
void
QBuffer::setData(
const
QByteArray &data)
247
{
248
Q_D(QBuffer);
249
if
(isOpen()) {
250
qWarning(
"QBuffer::setData: Buffer is open"
);
251
return
;
252
}
253
*d->buf = data;
254
}
255
256
/*!
257
\overload
258
259
Sets the contents of the internal buffer to be the first \a size
260
bytes of \a data.
261
262
\note In Qt versions prior to 6.5, this function took the length as
263
an \c{int} parameter, potentially truncating sizes.
264
*/
265
void
QBuffer::setData(
const
char
*data, qsizetype size)
266
{
267
Q_D(QBuffer);
268
if
(isOpen()) {
269
qWarning(
"QBuffer::setData: Buffer is open"
);
270
return
;
271
}
272
d->buf->assign(data, data + size);
273
}
274
275
/*!
276
Opens the buffer using \a mode flags, returning \c true if successful;
277
otherwise returns \c false.
278
279
The flags for \a mode must include \l QIODeviceBase::ReadOnly,
280
\l WriteOnly, or \l ReadWrite. If not, an error is printed and
281
the method fails. In any other case, it succeeds.
282
283
Unlike \l QFile::open(), opening a QBuffer with \l WriteOnly
284
does not truncate it. However, \l pos() is set to \c{0}.
285
Use \l Append or \l Truncate to change either behavior.
286
*/
287
bool
QBuffer::open(OpenMode mode)
288
{
289
Q_D(QBuffer);
290
291
if
((mode & (Append | Truncate)) != 0)
292
mode |= WriteOnly;
293
if
((mode & (ReadOnly | WriteOnly)) == 0) {
294
qWarning(
"QBuffer::open: Buffer access not specified"
);
295
return
false
;
296
}
297
298
if
((mode & Truncate) == Truncate)
299
d->buf->resize(0);
300
301
return
QIODevice::open(mode | QIODevice::Unbuffered);
302
}
303
304
/*!
305
\reimp
306
*/
307
void
QBuffer::close()
308
{
309
QIODevice::close();
310
}
311
312
/*!
313
\reimp
314
*/
315
qint64 QBuffer::pos()
const
316
{
317
return
QIODevice::pos();
318
}
319
320
/*!
321
\reimp
322
*/
323
qint64 QBuffer::size()
const
324
{
325
Q_D(
const
QBuffer);
326
return
qint64(d->buf->size());
327
}
328
329
/*!
330
\reimp
331
*/
332
bool
QBuffer::seek(qint64 pos)
333
{
334
Q_D(QBuffer);
335
const
auto
oldBufSize = d->buf->size();
336
constexpr
qint64 MaxSeekPos = (std::numeric_limits<
decltype
(oldBufSize)>::max)();
337
if
(pos <= MaxSeekPos && pos > oldBufSize && isWritable()) {
338
QT_TRY {
339
d->buf->resize(qsizetype(pos),
'\0'
);
340
} QT_CATCH(
const
std::bad_alloc &) {}
// swallow, failure case is handled below
341
if
(d->buf->size() != pos) {
342
qWarning(
"QBuffer::seek: Unable to fill gap"
);
343
return
false
;
344
}
345
}
346
if
(pos > d->buf->size() || pos < 0) {
347
qWarning(
"QBuffer::seek: Invalid pos: %lld"
, pos);
348
return
false
;
349
}
350
return
QIODevice::seek(pos);
351
}
352
353
/*!
354
\reimp
355
*/
356
bool
QBuffer::atEnd()
const
357
{
358
return
QIODevice::atEnd();
359
}
360
361
/*!
362
\reimp
363
*/
364
bool
QBuffer::canReadLine()
const
365
{
366
Q_D(
const
QBuffer);
367
if
(!isOpen())
368
return
false
;
369
370
return
d->buf->indexOf(
'\n'
,
int
(pos())) != -1 || QIODevice::canReadLine();
371
}
372
373
/*!
374
\reimp
375
*/
376
qint64 QBuffer::readData(
char
*data, qint64 len)
377
{
378
Q_D(QBuffer);
379
if
((len = qMin(len, qint64(d->buf->size()) - pos())) <= 0)
380
return
qint64(0);
381
memcpy(data, d->buf->constData() + pos(), len);
382
return
len;
383
}
384
385
/*!
386
\reimp
387
*/
388
qint64 QBuffer::writeData(
const
char
*data, qint64 len)
389
{
390
Q_D(QBuffer);
391
const
quint64 required = quint64(pos()) + quint64(len);
// cannot overflow (pos() ≥ 0, len ≥ 0)
392
393
if
(required > quint64(d->buf->size())) {
// capacity exceeded
394
// The following must hold, since qsizetype covers half the virtual address space:
395
Q_ASSERT(required <= quint64((std::numeric_limits<qsizetype>::max)()));
396
d->buf->resize(qsizetype(required));
397
if
(quint64(d->buf->size()) != required) {
// could not resize
398
qWarning(
"QBuffer::writeData: Memory allocation error"
);
399
return
-1;
400
}
401
}
402
403
memcpy(d->buf->data() + pos(), data, size_t(len));
404
405
#
ifndef
QT_NO_QOBJECT
406
d->writtenSinceLastEmit += len;
407
if
(d->signalConnectionCount && !d->signalsEmitted && !signalsBlocked()) {
408
d->signalsEmitted =
true
;
409
QMetaObject::invokeMethod(
this
, [](QBuffer *q) {
410
auto
d = q->d_func();
411
emit q->bytesWritten(d->writtenSinceLastEmit);
412
d->writtenSinceLastEmit = 0;
413
emit q->readyRead();
414
d->signalsEmitted =
false
;
415
}, Qt::QueuedConnection,
this
);
416
}
417
#
endif
418
return
len;
419
}
420
421
#
ifndef
QT_NO_QOBJECT
422
static
bool
is_tracked_signal
(
const
QMetaMethod &signal)
423
{
424
// dynamic initialization: minimize the number of guard variables:
425
static
const
struct
{
426
QMetaMethod readyReadSignal = QMetaMethod::fromSignal(&QBuffer::readyRead);
427
QMetaMethod bytesWrittenSignal = QMetaMethod::fromSignal(&QBuffer::bytesWritten);
428
} sigs;
429
return
signal == sigs.readyReadSignal || signal == sigs.bytesWrittenSignal;
430
}
431
/*!
432
\reimp
433
\internal
434
*/
435
void
QBuffer::connectNotify(
const
QMetaMethod &signal)
436
{
437
if
(is_tracked_signal(signal))
438
d_func()->signalConnectionCount++;
439
}
440
441
/*!
442
\reimp
443
\internal
444
*/
445
void
QBuffer::disconnectNotify(
const
QMetaMethod &signal)
446
{
447
if
(signal.isValid()) {
448
if
(is_tracked_signal(signal))
449
d_func()->signalConnectionCount--;
450
}
else
{
451
d_func()->signalConnectionCount = 0;
452
}
453
}
454
#
endif
455
456
QT_END_NAMESPACE
457
458
#
ifndef
QT_NO_QOBJECT
459
#
include
"moc_qbuffer.cpp"
460
#
endif
is_tracked_signal
static bool is_tracked_signal(const QMetaMethod &signal)
Definition
qbuffer.cpp:422
qtbase
src
corelib
io
qbuffer.cpp
Generated on
for Qt by
1.18.0