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
qqmlprofilerevent_p.h
Go to the documentation of this file.
1// Copyright (C) 2017 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
4
5#ifndef QQMLPROFILEREVENT_P_H
6#define QQMLPROFILEREVENT_P_H
7
9
10#include <QtCore/qstring.h>
11#include <QtCore/qbytearray.h>
12#include <QtCore/qvarlengtharray.h>
13#include <QtCore/qmetatype.h>
14
15#include <initializer_list>
16#include <limits>
17#include <type_traits>
18
19//
20// W A R N I N G
21// -------------
22//
23// This file is not part of the Qt API. It exists purely as an
24// implementation detail. This header file may change from version to
25// version without notice, or even be removed.
26//
27// We mean it.
28//
29
30QT_BEGIN_NAMESPACE
31
32struct QQmlProfilerEvent {
33 QQmlProfilerEvent() :
34 m_timestamp(-1), m_typeIndex(-1), m_dataType(Inline8Bit), m_dataLength(0)
35 {}
36
37 template<typename Number>
38 QQmlProfilerEvent(qint64 timestamp, int typeIndex, std::initializer_list<Number> list)
39 : m_timestamp(timestamp), m_typeIndex(typeIndex)
40 {
41 assignNumbers<std::initializer_list<Number>, Number>(list);
42 }
43
44 QQmlProfilerEvent(qint64 timestamp, int typeIndex, const QString &data)
45 : m_timestamp(timestamp), m_typeIndex(typeIndex)
46 {
47 assignNumbers<QByteArray, qint8>(data.toUtf8());
48 }
49
50 template<typename Number>
51 QQmlProfilerEvent(qint64 timestamp, int typeIndex, const QVector<Number> &data)
52 : m_timestamp(timestamp), m_typeIndex(typeIndex)
53 {
54 assignNumbers<QVector<Number>, Number>(data);
55 }
56
57 QQmlProfilerEvent(const QQmlProfilerEvent &other)
58 : m_timestamp(other.m_timestamp), m_typeIndex(other.m_typeIndex),
59 m_dataType(other.m_dataType), m_dataLength(other.m_dataLength)
60 {
61 assignData(other);
62 }
63
64 QQmlProfilerEvent(QQmlProfilerEvent &&other)
65 {
66 memcpy(static_cast<void *>(this), static_cast<const void *>(&other), sizeof(QQmlProfilerEvent));
67 other.m_dataType = Inline8Bit; // prevent dtor from deleting the pointer
68 }
69
70 QQmlProfilerEvent &operator=(const QQmlProfilerEvent &other)
71 {
72 if (this != &other) {
73 clearPointer();
74 m_timestamp = other.m_timestamp;
75 m_typeIndex = other.m_typeIndex;
76 m_dataType = other.m_dataType;
77 m_dataLength = other.m_dataLength;
78 assignData(other);
79 }
80 return *this;
81 }
82
83 QQmlProfilerEvent &operator=(QQmlProfilerEvent &&other)
84 {
85 if (this != &other) {
86 memcpy(static_cast<void *>(this), static_cast<const void *>(&other), sizeof(QQmlProfilerEvent));
87 other.m_dataType = Inline8Bit;
88 }
89 return *this;
90 }
91
92 ~QQmlProfilerEvent()
93 {
94 clearPointer();
95 }
96
97 qint64 timestamp() const { return m_timestamp; }
98 void setTimestamp(qint64 timestamp) { m_timestamp = timestamp; }
99
100 int typeIndex() const { return m_typeIndex; }
101 void setTypeIndex(int typeIndex) { m_typeIndex = typeIndex; }
102
103 template<typename Number>
104 Number number(int i) const
105 {
106 // Trailing zeroes can be omitted, for example for SceneGraph events
107 if (i >= m_dataLength)
108 return 0;
109 switch (m_dataType) {
110 case Inline8Bit:
111 return m_data.internal8bit[i];
112QT_WARNING_PUSH
113QT_WARNING_DISABLE_GCC("-Warray-bounds") // Mingw 5.3 gcc doesn't get the type/length logic.
114 case Inline16Bit:
115 return m_data.internal16bit[i];
116 case Inline32Bit:
117 return m_data.internal32bit[i];
118 case Inline64Bit:
119 return m_data.internal64bit[i];
120QT_WARNING_POP
121 case External8Bit:
122 return static_cast<const qint8 *>(m_data.external)[i];
123 case External16Bit:
124 return static_cast<const qint16 *>(m_data.external)[i];
125 case External32Bit:
126 return static_cast<const qint32 *>(m_data.external)[i];
127 case External64Bit:
128 return static_cast<const qint64 *>(m_data.external)[i];
129 default:
130 return 0;
131 }
132 }
133
134 template<typename Number>
135 void setNumber(int i, Number number)
136 {
137 QVarLengthArray<Number> nums = numbers<QVarLengthArray<Number>, Number>();
138 int prevSize = nums.size();
139 if (i >= prevSize) {
140 nums.resize(i + 1);
141 // Fill with zeroes. We don't want to accidentally prevent squeezing.
142 while (prevSize < i)
143 nums[prevSize++] = 0;
144 }
145 nums[i] = number;
146 setNumbers<QVarLengthArray<Number>, Number>(nums);
147 }
148
149 template<typename Container, typename Number>
150 void setNumbers(const Container &numbers)
151 {
152 clearPointer();
153 assignNumbers<Container, Number>(numbers);
154 }
155
156 template<typename Number>
157 void setNumbers(std::initializer_list<Number> numbers)
158 {
159 setNumbers<std::initializer_list<Number>, Number>(numbers);
160 }
161
162 template<typename Container, typename Number = qint64>
163 Container numbers() const
164 {
165 Container container;
166 for (int i = 0; i < m_dataLength; ++i)
167 container.append(number<Number>(i));
168 return container;
169 }
170
171 QString string() const
172 {
173 switch (m_dataType) {
174 case External8Bit:
175 return QString::fromUtf8(static_cast<const char *>(m_data.external), m_dataLength);
176 case Inline8Bit:
177 return QString::fromUtf8(m_data.internalChar, m_dataLength);
178 default:
179 Q_UNREACHABLE_RETURN(QString());
180 }
181 }
182
183 void setString(const QString &data)
184 {
185 clearPointer();
186 assignNumbers<QByteArray, char>(data.toUtf8());
187 }
188
189 Message rangeStage() const
190 {
191 Q_ASSERT(m_dataType == Inline8Bit);
192 return static_cast<Message>(m_data.internal8bit[0]);
193 }
194
195 void setRangeStage(Message stage)
196 {
197 clearPointer();
198 m_dataType = Inline8Bit;
199 m_dataLength = 1;
200 m_data.internal8bit[0] = stage;
201 }
202
203 bool isValid() const
204 {
205 return m_timestamp != -1;
206 }
207
208private:
209 enum Type: quint16 {
210 External = 1,
211 Inline8Bit = 8,
212 External8Bit = Inline8Bit | External,
213 Inline16Bit = 16,
214 External16Bit = Inline16Bit | External,
215 Inline32Bit = 32,
216 External32Bit = Inline32Bit | External,
217 Inline64Bit = 64,
218 External64Bit = Inline64Bit | External
219 };
220
221 qint64 m_timestamp;
222
223 static const int s_internalDataLength = 8;
224 union {
225 void *external;
226 char internalChar [s_internalDataLength];
227 qint8 internal8bit [s_internalDataLength];
228 qint16 internal16bit[s_internalDataLength / 2];
229 qint32 internal32bit[s_internalDataLength / 4];
230 qint64 internal64bit[s_internalDataLength / 8];
231 } m_data;
232
233 qint32 m_typeIndex;
234 Type m_dataType;
235 quint16 m_dataLength;
236
237 void assignData(const QQmlProfilerEvent &other)
238 {
239 if (m_dataType & External) {
240 uint length = m_dataLength * (other.m_dataType / 8);
241 m_data.external = malloc(length);
242 Q_CHECK_PTR(m_data.external);
243 memcpy(m_data.external, other.m_data.external, length);
244 } else {
245 memcpy(&m_data, &other.m_data, sizeof(m_data));
246 }
247 }
248
249 template<typename Big, typename Small>
250 bool squeezable(Big source)
251 {
252 return static_cast<Small>(source) == source;
253 }
254
255 template<typename Container, typename Number>
256 typename std::enable_if<(sizeof(Number) > 1), bool>::type
257 squeeze(const Container &numbers)
258 {
259 typedef typename QIntegerForSize<sizeof(Number) / 2>::Signed Small;
260 for (Number item : numbers) {
261 if (!squeezable<Number, Small>(item))
262 return false;
263 }
264 assignNumbers<Container, Small>(numbers);
265 return true;
266 }
267
268 template<typename Container, typename Number>
269 typename std::enable_if<(sizeof(Number) <= 1), bool>::type
270 squeeze(const Container &)
271 {
272 return false;
273 }
274
275 template<typename Container, typename Number>
276 void assignNumbers(const Container &numbers)
277 {
278 Number *data;
279 m_dataLength = squeezable<size_t, quint16>(static_cast<size_t>(numbers.size())) ?
280 static_cast<quint16>(numbers.size()) : std::numeric_limits<quint16>::max();
281 if (m_dataLength > sizeof(m_data) / sizeof(Number)) {
282 if (squeeze<Container, Number>(numbers))
283 return;
284 m_dataType = static_cast<Type>((sizeof(Number) * 8) | External);
285 m_data.external = malloc(m_dataLength * sizeof(Number));
286 Q_CHECK_PTR(m_data.external);
287 data = static_cast<Number *>(m_data.external);
288 } else {
289 m_dataType = static_cast<Type>(sizeof(Number) * 8);
290 data = static_cast<Number *>(m_dataType & External ? m_data.external : &m_data);
291 }
292 quint16 i = 0;
293 for (Number item : numbers) {
294 if (i >= m_dataLength)
295 break;
296 data[i++] = item;
297 }
298 }
299
300 void clearPointer()
301 {
302 if (m_dataType & External)
303 free(m_data.external);
304 }
305
306 friend QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event);
307 friend QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event);
308};
309
310bool operator==(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2);
311bool operator!=(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2);
312
313QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event);
314QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event);
315
317
318QT_END_NAMESPACE
319
320Q_DECLARE_METATYPE(QQmlProfilerEvent)
321
322#endif // QQMLPROFILEREVENT_P_H
void setFlushInterval(quint32 flushInterval)
quint64 recordedFeatures() const
void traceFinished(qint64 timestamp, const QList< int > &engineIds)
void setRequestedFeatures(quint64 features)
void recordedFeaturesChanged(quint64 features)
void traceStarted(qint64 timestamp, const QList< int > &engineIds)
virtual void messageReceived(const QByteArray &) override
void recordingChanged(bool arg)
QQmlProfilerClient(QQmlProfilerClientPrivate &dd)
void onStateChanged(State status)
void sendRecordingStatus(int engineId=-1)
Combined button and popup list for selecting options.
QDataStream & operator<<(QDataStream &stream, const QQmlProfilerEvent &event)
QDataStream & operator>>(QDataStream &stream, QQmlProfilerEvent &event)
Q_DECLARE_TYPEINFO(QQmlProfilerEvent, Q_RELOCATABLE_TYPE)
bool operator==(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2)
bool operator!=(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2)
QDataStream & operator<<(QDataStream &stream, const QQmlProfilerEventLocation &location)
size_t qHash(const QQmlProfilerEventLocation &location)
Q_DECLARE_TYPEINFO(QQmlProfilerEventLocation, Q_RELOCATABLE_TYPE)
bool operator!=(const QQmlProfilerEventLocation &location1, const QQmlProfilerEventLocation &location2)
bool operator==(const QQmlProfilerEventLocation &location1, const QQmlProfilerEventLocation &location2)
QDataStream & operator>>(QDataStream &stream, QQmlProfilerEventLocation &location)