aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldebug/qqmlprofilerevent_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldebug/qqmlprofilerevent_p.h')
-rw-r--r--src/qmldebug/qqmlprofilerevent_p.h355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/qmldebug/qqmlprofilerevent_p.h b/src/qmldebug/qqmlprofilerevent_p.h
new file mode 100644
index 0000000000..93562302e9
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerevent_p.h
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROFILEREVENT_P_H
+#define QQMLPROFILEREVENT_P_H
+
+#include <private/qqmlprofilerdefinitions_p.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qmetatype.h>
+
+#include <initializer_list>
+#include <type_traits>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlProfilerEvent : public QQmlProfilerDefinitions {
+ QQmlProfilerEvent() :
+ m_timestamp(-1), m_typeIndex(-1), m_dataType(Inline8Bit), m_dataLength(0)
+ {}
+
+ template<typename Number>
+ QQmlProfilerEvent(qint64 timestamp, int typeIndex, std::initializer_list<Number> list)
+ : m_timestamp(timestamp), m_typeIndex(typeIndex)
+ {
+ assignNumbers<std::initializer_list<Number>, Number>(list);
+ }
+
+ QQmlProfilerEvent(qint64 timestamp, int typeIndex, const QString &data)
+ : m_timestamp(timestamp), m_typeIndex(typeIndex)
+ {
+ assignNumbers<QByteArray, qint8>(data.toUtf8());
+ }
+
+ template<typename Number>
+ QQmlProfilerEvent(qint64 timestamp, int typeIndex, const QVector<Number> &data)
+ : m_timestamp(timestamp), m_typeIndex(typeIndex)
+ {
+ assignNumbers<QVector<Number>, Number>(data);
+ }
+
+ QQmlProfilerEvent(const QQmlProfilerEvent &other)
+ : m_timestamp(other.m_timestamp), m_typeIndex(other.m_typeIndex),
+ m_dataType(other.m_dataType), m_dataLength(other.m_dataLength)
+ {
+ assignData(other);
+ }
+
+ QQmlProfilerEvent(QQmlProfilerEvent &&other)
+ {
+ memcpy(this, &other, sizeof(QQmlProfilerEvent));
+ other.m_dataType = Inline8Bit; // prevent dtor from deleting the pointer
+ }
+
+ QQmlProfilerEvent &operator=(const QQmlProfilerEvent &other)
+ {
+ if (this != &other) {
+ clearPointer();
+ m_timestamp = other.m_timestamp;
+ m_typeIndex = other.m_typeIndex;
+ m_dataType = other.m_dataType;
+ m_dataLength = other.m_dataLength;
+ assignData(other);
+ }
+ return *this;
+ }
+
+ QQmlProfilerEvent &operator=(QQmlProfilerEvent &&other)
+ {
+ if (this != &other) {
+ memcpy(this, &other, sizeof(QQmlProfilerEvent));
+ other.m_dataType = Inline8Bit;
+ }
+ return *this;
+ }
+
+ ~QQmlProfilerEvent()
+ {
+ clearPointer();
+ }
+
+ qint64 timestamp() const { return m_timestamp; }
+ void setTimestamp(qint64 timestamp) { m_timestamp = timestamp; }
+
+ int typeIndex() const { return m_typeIndex; }
+ void setTypeIndex(int typeIndex) { m_typeIndex = typeIndex; }
+
+ template<typename Number>
+ Number number(int i) const
+ {
+ // Trailing zeroes can be omitted, for example for SceneGraph events
+ if (i >= m_dataLength)
+ return 0;
+ switch (m_dataType) {
+ case Inline8Bit:
+ return m_data.internal8bit[i];
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Warray-bounds") // Mingw 5.3 gcc doesn't get the type/length logic.
+ case Inline16Bit:
+ return m_data.internal16bit[i];
+ case Inline32Bit:
+ return m_data.internal32bit[i];
+ case Inline64Bit:
+ return m_data.internal64bit[i];
+QT_WARNING_POP
+ case External8Bit:
+ return static_cast<const qint8 *>(m_data.external)[i];
+ case External16Bit:
+ return static_cast<const qint16 *>(m_data.external)[i];
+ case External32Bit:
+ return static_cast<const qint32 *>(m_data.external)[i];
+ case External64Bit:
+ return static_cast<const qint64 *>(m_data.external)[i];
+ default:
+ return 0;
+ }
+ }
+
+ template<typename Number>
+ void setNumber(int i, Number number)
+ {
+ QVarLengthArray<Number> nums = numbers<QVarLengthArray<Number>, Number>();
+ int prevSize = nums.size();
+ if (i >= prevSize) {
+ nums.resize(i + 1);
+ // Fill with zeroes. We don't want to accidentally prevent squeezing.
+ while (prevSize < i)
+ nums[prevSize++] = 0;
+ }
+ nums[i] = number;
+ setNumbers<QVarLengthArray<Number>, Number>(nums);
+ }
+
+ template<typename Container, typename Number>
+ void setNumbers(const Container &numbers)
+ {
+ clearPointer();
+ assignNumbers<Container, Number>(numbers);
+ }
+
+ template<typename Number>
+ void setNumbers(std::initializer_list<Number> numbers)
+ {
+ setNumbers<std::initializer_list<Number>, Number>(numbers);
+ }
+
+ template<typename Container, typename Number = qint64>
+ Container numbers() const
+ {
+ Container container;
+ for (int i = 0; i < m_dataLength; ++i)
+ container.append(number<Number>(i));
+ return container;
+ }
+
+ QString string() const
+ {
+ switch (m_dataType) {
+ case External8Bit:
+ return QString::fromUtf8(static_cast<const char *>(m_data.external), m_dataLength);
+ case Inline8Bit:
+ return QString::fromUtf8(m_data.internalChar, m_dataLength);
+ default:
+ Q_UNREACHABLE();
+ return QString();
+ }
+ }
+
+ void setString(const QString &data)
+ {
+ clearPointer();
+ assignNumbers<QByteArray, char>(data.toUtf8());
+ }
+
+ Message rangeStage() const
+ {
+ Q_ASSERT(m_dataType == Inline8Bit);
+ return static_cast<Message>(m_data.internal8bit[0]);
+ }
+
+ void setRangeStage(Message stage)
+ {
+ clearPointer();
+ m_dataType = Inline8Bit;
+ m_dataLength = 1;
+ m_data.internal8bit[0] = stage;
+ }
+
+ bool isValid() const
+ {
+ return m_timestamp != -1;
+ }
+
+private:
+ enum Type: quint16 {
+ External = 1,
+ Inline8Bit = 8,
+ External8Bit = Inline8Bit | External,
+ Inline16Bit = 16,
+ External16Bit = Inline16Bit | External,
+ Inline32Bit = 32,
+ External32Bit = Inline32Bit | External,
+ Inline64Bit = 64,
+ External64Bit = Inline64Bit | External
+ };
+
+ qint64 m_timestamp;
+
+ static const int s_internalDataLength = 8;
+ union {
+ void *external;
+ char internalChar [s_internalDataLength];
+ qint8 internal8bit [s_internalDataLength];
+ qint16 internal16bit[s_internalDataLength / 2];
+ qint32 internal32bit[s_internalDataLength / 4];
+ qint64 internal64bit[s_internalDataLength / 8];
+ } m_data;
+
+ qint32 m_typeIndex;
+ Type m_dataType;
+ quint16 m_dataLength;
+
+ void assignData(const QQmlProfilerEvent &other)
+ {
+ if (m_dataType & External) {
+ uint length = m_dataLength * (other.m_dataType / 8);
+ m_data.external = malloc(length);
+ memcpy(m_data.external, other.m_data.external, length);
+ } else {
+ memcpy(&m_data, &other.m_data, sizeof(m_data));
+ }
+ }
+
+ template<typename Big, typename Small>
+ bool squeezable(Big source)
+ {
+ return static_cast<Small>(source) == source;
+ }
+
+ template<typename Container, typename Number>
+ typename std::enable_if<(sizeof(Number) > 1), bool>::type
+ squeeze(const Container &numbers)
+ {
+ typedef typename QIntegerForSize<sizeof(Number) / 2>::Signed Small;
+ foreach (Number item, numbers) {
+ if (!squeezable<Number, Small>(item))
+ return false;
+ }
+ assignNumbers<Container, Small>(numbers);
+ return true;
+ }
+
+ template<typename Container, typename Number>
+ typename std::enable_if<(sizeof(Number) <= 1), bool>::type
+ squeeze(const Container &)
+ {
+ return false;
+ }
+
+ template<typename Container, typename Number>
+ void assignNumbers(const Container &numbers)
+ {
+ Number *data;
+ m_dataLength = squeezable<size_t, quint16>(static_cast<size_t>(numbers.size())) ?
+ static_cast<quint16>(numbers.size()) : std::numeric_limits<quint16>::max();
+ if (m_dataLength > sizeof(m_data) / sizeof(Number)) {
+ if (squeeze<Container, Number>(numbers))
+ return;
+ m_dataType = static_cast<Type>((sizeof(Number) * 8) | External);
+ m_data.external = malloc(m_dataLength * sizeof(Number));
+ data = static_cast<Number *>(m_data.external);
+ } else {
+ m_dataType = static_cast<Type>(sizeof(Number) * 8);
+ data = static_cast<Number *>(m_dataType & External ? m_data.external : &m_data);
+ }
+ quint16 i = 0;
+ for (Number item : numbers) {
+ if (i >= m_dataLength)
+ break;
+ data[i++] = item;
+ }
+ }
+
+ void clearPointer()
+ {
+ if (m_dataType & External)
+ free(m_data.external);
+ }
+
+ friend QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event);
+ friend QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event);
+};
+
+bool operator==(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2);
+bool operator!=(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2);
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event);
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event);
+
+Q_DECLARE_TYPEINFO(QQmlProfilerEvent, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQmlProfilerEvent)
+
+#endif // QQMLPROFILEREVENT_P_H