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.cpp
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
6#include <QtCore/qdatastream.h>
7
8QT_BEGIN_NAMESPACE
9
10bool operator==(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2)
11{
12 if (event1.timestamp() != event2.timestamp() || event1.typeIndex() != event2.typeIndex())
13 return false;
14
15 // This is not particularly efficient, but we also don't need to do this very often.
16 return event1.numbers<QVarLengthArray<qint64>>() == event2.numbers<QVarLengthArray<qint64>>();
17}
18
19bool operator!=(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2)
20{
21 return !(event1 == event2);
22}
23
24enum SerializationType {
25 OneByte = 0,
26 TwoByte = 1,
27 FourByte = 2,
28 EightByte = 3,
29 TypeMask = 0x3
30};
31
38
39template<typename Number>
40static inline void readNumbers(QDataStream &stream, Number *data, quint16 length)
41{
42 for (quint16 i = 0; i != length; ++i)
43 stream >> data[i];
44}
45
46template<typename Number>
47static inline Number readNumber(QDataStream &stream, qint8 type)
48{
49 switch (type) {
50 case OneByte: {
51 qint8 value;
52 stream >> value;
53 return static_cast<Number>(value);
54 }
55 case TwoByte: {
56 qint16 value;
57 stream >> value;
58 return static_cast<Number>(value);
59 }
60 case FourByte: {
61 qint32 value;
62 stream >> value;
63 return static_cast<Number>(value);
64 }
65 case EightByte: {
66 qint64 value;
67 stream >> value;
68 return static_cast<Number>(value);
69 }
70 default:
71 Q_UNREACHABLE_RETURN(0);
72 }
73}
74
75QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event)
76{
77 qint8 type;
78 stream >> type;
79
80 event.m_timestamp = readNumber<qint64>(stream, (type >> TimestampOffset) & TypeMask);
81 event.m_typeIndex = readNumber<qint32>(stream, (type >> TypeIndexOffset) & TypeMask);
82 event.m_dataLength = readNumber<quint16>(stream, (type >> DataLengthOffset) & TypeMask);
83
84 uint bytesPerNumber = 1 << ((type >> DataOffset) & TypeMask);
85
86 if (event.m_dataLength * bytesPerNumber > sizeof(event.m_data)) {
87 event.m_dataType = static_cast<QQmlProfilerEvent::Type>((bytesPerNumber * 8)
88 | QQmlProfilerEvent::External);
89 event.m_data.external = malloc(event.m_dataLength * bytesPerNumber);
90 } else {
91 event.m_dataType = static_cast<QQmlProfilerEvent::Type>(bytesPerNumber * 8);
92 }
93
94 switch (event.m_dataType) {
95 case QQmlProfilerEvent::Inline8Bit:
96 readNumbers<qint8>(stream, event.m_data.internal8bit, event.m_dataLength);
97 break;
98 case QQmlProfilerEvent::External8Bit:
99 readNumbers<qint8>(stream, static_cast<qint8 *>(event.m_data.external),
100 event.m_dataLength);
101 break;
102 case QQmlProfilerEvent::Inline16Bit:
103 readNumbers<qint16>(stream, event.m_data.internal16bit, event.m_dataLength);
104 break;
105 case QQmlProfilerEvent::External16Bit:
106 readNumbers<qint16>(stream, static_cast<qint16 *>(event.m_data.external),
107 event.m_dataLength);
108 break;
109 case QQmlProfilerEvent::Inline32Bit:
110 readNumbers<qint32>(stream, event.m_data.internal32bit, event.m_dataLength);
111 break;
112 case QQmlProfilerEvent::External32Bit:
113 readNumbers<qint32>(stream, static_cast<qint32 *>(event.m_data.external),
114 event.m_dataLength);
115 break;
116 case QQmlProfilerEvent::Inline64Bit:
117 readNumbers<qint64>(stream, event.m_data.internal64bit, event.m_dataLength);
118 break;
119 case QQmlProfilerEvent::External64Bit:
120 readNumbers<qint64>(stream, static_cast<qint64 *>(event.m_data.external),
121 event.m_dataLength);
122 break;
123 default:
124 Q_UNREACHABLE();
125 break;
126 }
127
128 return stream;
129}
130
131static inline qint8 minimumType(const QQmlProfilerEvent &event, quint16 length,
132 quint16 origBitsPerNumber)
133{
134 qint8 type = OneByte;
135 bool ok = true;
136 for (quint16 i = 0; i < length;) {
137 if ((1 << type) == origBitsPerNumber / 8)
138 return type;
139 switch (type) {
140 case OneByte:
141 ok = (event.number<qint8>(i) == event.number<qint64>(i));
142 break;
143 case TwoByte:
144 ok = (event.number<qint16>(i) == event.number<qint64>(i));
145 break;
146 case FourByte:
147 ok = (event.number<qint32>(i) == event.number<qint64>(i));
148 break;
149 default:
150 // EightByte isn't possible, as (1 << type) == origBitsPerNumber / 8 then.
151 Q_UNREACHABLE();
152 break;
153 }
154
155 if (ok)
156 ++i;
157 else
158 ++type;
159 }
160 return type;
161}
162
163template<typename Number>
164static inline qint8 minimumType(Number number)
165{
166 if (static_cast<qint8>(number) == number)
167 return OneByte;
168 if (static_cast<qint16>(number) == number)
169 return TwoByte;
170 if (static_cast<qint32>(number) == number)
171 return FourByte;
172 return EightByte;
173}
174
175template<typename Number>
176static inline void writeNumbers(QDataStream &stream, const QQmlProfilerEvent &event, quint16 length)
177{
178 for (quint16 i = 0; i != length; ++i)
179 stream << event.number<Number>(i);
180}
181
182template<typename Number>
183static inline void writeNumber(QDataStream &stream, Number number, qint8 type)
184{
185 switch (type) {
186 case OneByte:
187 stream << static_cast<qint8>(number);
188 break;
189 case TwoByte:
190 stream << static_cast<qint16>(number);
191 break;
192 case FourByte:
193 stream << static_cast<qint32>(number);
194 break;
195 case EightByte:
196 stream << static_cast<qint64>(number);
197 break;
198 default:
199 Q_UNREACHABLE();
200 break;
201 }
202}
203
204QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event)
205{
206 qint8 type = minimumType(event.m_timestamp); // << TimestampOffset;
207 type |= minimumType(event.m_typeIndex) << TypeIndexOffset;
208 type |= minimumType(event.m_dataLength) << DataLengthOffset;
209 type |= minimumType(event, event.m_dataLength, event.m_dataType) << DataOffset;
210 stream << type;
211
212 writeNumber(stream, event.m_timestamp, (type >> TimestampOffset) & TypeMask);
213 writeNumber(stream, event.m_typeIndex, (type >> TypeIndexOffset) & TypeMask);
214 writeNumber(stream, event.m_dataLength, (type >> DataLengthOffset) & TypeMask);
215
216 switch ((type >> DataOffset) & TypeMask) {
217 case OneByte:
218 writeNumbers<qint8>(stream, event, event.m_dataLength);
219 break;
220 case TwoByte:
221 writeNumbers<qint16>(stream, event, event.m_dataLength);
222 break;
223 case FourByte:
224 writeNumbers<qint32>(stream, event, event.m_dataLength);
225 break;
226 case EightByte:
227 writeNumbers<qint64>(stream, event, event.m_dataLength);
228 break;
229 default:
230 Q_UNREACHABLE();
231 break;
232 }
233
234 return stream;
235}
236
237QT_END_NAMESPACE
static Number readNumber(QDataStream &stream, qint8 type)
SerializationTypeOffset
@ DataOffset
@ TimestampOffset
@ DataLengthOffset
@ TypeIndexOffset
static qint8 minimumType(const QQmlProfilerEvent &event, quint16 length, quint16 origBitsPerNumber)
static void readNumbers(QDataStream &stream, Number *data, quint16 length)
static void writeNumbers(QDataStream &stream, const QQmlProfilerEvent &event, quint16 length)
static qint8 minimumType(Number number)
QDataStream & operator<<(QDataStream &stream, const QQmlProfilerEvent &event)
static void writeNumber(QDataStream &stream, Number number, qint8 type)
QDataStream & operator>>(QDataStream &stream, QQmlProfilerEvent &event)