diff options
Diffstat (limited to 'src/qml/qml/ftw')
22 files changed, 1078 insertions, 1947 deletions
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri deleted file mode 100644 index eadba394b4..0000000000 --- a/src/qml/qml/ftw/ftw.pri +++ /dev/null @@ -1,26 +0,0 @@ -HEADERS += \ - $$PWD/qbitfield_p.h \ - $$PWD/qintrusivelist_p.h \ - $$PWD/qpodvector_p.h \ - $$PWD/qhashedstring_p.h \ - $$PWD/qprimefornumbits_p.h \ - $$PWD/qqmlrefcount_p.h \ - $$PWD/qfieldlist_p.h \ - $$PWD/qqmlthread_p.h \ - $$PWD/qfinitestack_p.h \ - $$PWD/qrecursionwatcher_p.h \ - $$PWD/qrecyclepool_p.h \ - $$PWD/qflagpointer_p.h \ - $$PWD/qlazilyallocated_p.h \ - $$PWD/qqmlnullablevalue_p.h \ - $$PWD/qstringhash_p.h \ - $$PWD/qlinkedstringhash_p.h - -SOURCES += \ - $$PWD/qintrusivelist.cpp \ - $$PWD/qhashedstring.cpp \ - $$PWD/qqmlthread.cpp - -# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri -# clock_gettime() is implemented in librt on these systems -qtConfig(clock-gettime):linux-*|hpux-*|solaris-*:LIBS_PRIVATE *= -lrt diff --git a/src/qml/qml/ftw/qbipointer_p.h b/src/qml/qml/ftw/qbipointer_p.h new file mode 100644 index 0000000000..1597b9e4fc --- /dev/null +++ b/src/qml/qml/ftw/qbipointer_p.h @@ -0,0 +1,203 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QBIPOINTER_P_H +#define QBIPOINTER_P_H + +// +// 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. +// + +#include <QtCore/private/qglobal_p.h> + +#include <QtCore/qhashfunctions.h> + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { +template <typename T> struct QFlagPointerAlignment +{ + enum : size_t { Value = Q_ALIGNOF(T) }; +}; +template <> struct QFlagPointerAlignment<void> +{ + enum : size_t { Value = ~size_t(0) }; +}; +} + +/*! + \internal + \class template<typename T1, typename T2> QBiPointer<T1, T2> + + \short QBiPointer can be thought of as a space-optimized std::variant<T1*, T2*> + with a nicer API to check the active pointer. Its other main feature is that + it only requires sizeof(void *) space. + + \note It can also store one additional flag for a user defined purpose. + */ +template<typename T, typename T2> +class QBiPointer { +public: + Q_NODISCARD_CTOR constexpr QBiPointer() noexcept = default; + ~QBiPointer() noexcept = default; + Q_NODISCARD_CTOR QBiPointer(const QBiPointer &o) noexcept = default; + Q_NODISCARD_CTOR QBiPointer(QBiPointer &&o) noexcept = default; + QBiPointer<T, T2> &operator=(const QBiPointer<T, T2> &o) noexcept = default; + QBiPointer<T, T2> &operator=(QBiPointer<T, T2> &&o) noexcept = default; + + void swap(QBiPointer &other) noexcept { std::swap(ptr_value, other.ptr_value); } + + Q_NODISCARD_CTOR inline QBiPointer(T *); + Q_NODISCARD_CTOR inline QBiPointer(T2 *); + + inline bool isNull() const; + inline bool isT1() const; + inline bool isT2() const; + + inline bool flag() const; + inline void setFlag(); + inline void clearFlag(); + inline void setFlagValue(bool); + + inline QBiPointer<T, T2> &operator=(T *); + inline QBiPointer<T, T2> &operator=(T2 *); + + friend inline bool operator==(QBiPointer<T, T2> ptr1, QBiPointer<T, T2> ptr2) + { + if (ptr1.isNull() && ptr2.isNull()) + return true; + if (ptr1.isT1() && ptr2.isT1()) + return ptr1.asT1() == ptr2.asT1(); + if (ptr1.isT2() && ptr2.isT2()) + return ptr1.asT2() == ptr2.asT2(); + return false; + } + friend inline bool operator!=(QBiPointer<T, T2> ptr1, QBiPointer<T, T2> ptr2) + { + return !(ptr1 == ptr2); + } + + friend void swap(QBiPointer &lhs, QBiPointer &rhs) noexcept { lhs.swap(rhs); } + + inline T *asT1() const; + inline T2 *asT2() const; + + friend size_t qHash(const QBiPointer<T, T2> &ptr, size_t seed = 0) + { + return qHash(ptr.isNull() ? quintptr(0) : ptr.ptr_value, seed); + } + +private: + quintptr ptr_value = 0; + + static const quintptr FlagBit = 0x1; + static const quintptr Flag2Bit = 0x2; + static const quintptr FlagsMask = FlagBit | Flag2Bit; +}; + +template <typename...Ts> // can't use commas in macros +Q_DECLARE_TYPEINFO_BODY(QBiPointer<Ts...>, Q_PRIMITIVE_TYPE); + +template<typename T, typename T2> +QBiPointer<T, T2>::QBiPointer(T *v) +: ptr_value(quintptr(v)) +{ + Q_STATIC_ASSERT_X(QtPrivate::QFlagPointerAlignment<T>::Value >= 4, + "Type T does not have sufficient alignment"); + Q_ASSERT((quintptr(v) & FlagsMask) == 0); +} + +template<typename T, typename T2> +QBiPointer<T, T2>::QBiPointer(T2 *v) +: ptr_value(quintptr(v) | Flag2Bit) +{ + Q_STATIC_ASSERT_X(QtPrivate::QFlagPointerAlignment<T2>::Value >= 4, + "Type T2 does not have sufficient alignment"); + Q_ASSERT((quintptr(v) & FlagsMask) == 0); +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::isNull() const +{ + return 0 == (ptr_value & (~FlagsMask)); +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::isT1() const +{ + return !(ptr_value & Flag2Bit); +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::isT2() const +{ + return ptr_value & Flag2Bit; +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::flag() const +{ + return ptr_value & FlagBit; +} + +template<typename T, typename T2> +void QBiPointer<T, T2>::setFlag() +{ + ptr_value |= FlagBit; +} + +template<typename T, typename T2> +void QBiPointer<T, T2>::clearFlag() +{ + ptr_value &= ~FlagBit; +} + +template<typename T, typename T2> +void QBiPointer<T, T2>::setFlagValue(bool v) +{ + if (v) setFlag(); + else clearFlag(); +} + +template<typename T, typename T2> +QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagBit); + return *this; +} + +template<typename T, typename T2> +QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T2 *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagBit) | Flag2Bit; + return *this; +} + +template<typename T, typename T2> +T *QBiPointer<T, T2>::asT1() const +{ + Q_ASSERT(isT1()); + return (T *)(ptr_value & ~FlagsMask); +} + +template<typename T, typename T2> +T2 *QBiPointer<T, T2>::asT2() const +{ + Q_ASSERT(isT2()); + return (T2 *)(ptr_value & ~FlagsMask); +} + +QT_END_NAMESPACE + +#endif // QBIPOINTER_P_H diff --git a/src/qml/qml/ftw/qbitfield_p.h b/src/qml/qml/ftw/qbitfield_p.h deleted file mode 100644 index 92017580d6..0000000000 --- a/src/qml/qml/ftw/qbitfield_p.h +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QBITFIELD_P_H -#define QBITFIELD_P_H - -// -// 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. -// - -#include <QtCore/qglobal.h> -#include <QtCore/qtypeinfo.h> - -QT_BEGIN_NAMESPACE - -class QBitField -{ -public: - inline QBitField(); - inline QBitField(const quint32 *, int bits); - inline QBitField(const QBitField &); - inline ~QBitField(); - - inline QBitField &operator=(const QBitField &); - - inline quint32 size() const; - inline QBitField united(const QBitField &); - inline bool testBit(int) const; - -private: - quint32 bits:31; - quint32 *ownData; - const quint32 *data; -}; - -QBitField::QBitField() -: bits(0), ownData(nullptr), data(nullptr) -{ -} - -QBitField::QBitField(const quint32 *bitData, int bitCount) -: bits((quint32)bitCount), ownData(nullptr), data(bitData) -{ -} - -QBitField::QBitField(const QBitField &other) -: bits(other.bits), ownData(other.ownData), data(other.data) -{ - if (ownData) - ++(*ownData); -} - -QBitField::~QBitField() -{ - if (ownData) - if(0 == --(*ownData)) delete [] ownData; -} - -QBitField &QBitField::operator=(const QBitField &other) -{ - if (other.data == data) - return *this; - - if (ownData) - if(0 == --(*ownData)) delete [] ownData; - - bits = other.bits; - ownData = other.ownData; - data = other.data; - - if (ownData) - ++(*ownData); - - return *this; -} - -inline quint32 QBitField::size() const -{ - return bits; -} - -QBitField QBitField::united(const QBitField &o) -{ - if (o.bits == 0) { - return *this; - } else if (bits == 0) { - return o; - } else { - int max = (bits > o.bits)?bits:o.bits; - int length = (max + 31) / 32; - QBitField rv; - rv.bits = max; - rv.ownData = new quint32[length + 1]; - *(rv.ownData) = 1; - quint32 *rvdata; - rv.data = rvdata = rv.ownData + 1; - if (bits > o.bits) { - ::memcpy(rvdata, data, length * sizeof(quint32)); - for (quint32 ii = 0; ii < (o.bits + quint32(31)) / 32; ++ii) - (rvdata)[ii] |= o.data[ii]; - } else { - ::memcpy(rvdata, o.data, length * sizeof(quint32)); - for (quint32 ii = 0; ii < (bits + quint32(31)) / 32; ++ii) - (rvdata)[ii] |= data[ii]; - } - return rv; - } -} - -bool QBitField::testBit(int b) const -{ - Q_ASSERT(b >= 0); - if ((quint32)b < bits) { - return data[b / 32] & (1 << (b % 32)); - } else { - return false; - } -} - -Q_DECLARE_TYPEINFO(QBitField, Q_MOVABLE_TYPE); - -QT_END_NAMESPACE - -#endif // QBITFIELD_P_H diff --git a/src/qml/qml/ftw/qdoubleendedlist_p.h b/src/qml/qml/ftw/qdoubleendedlist_p.h new file mode 100644 index 0000000000..0a4d9f75d3 --- /dev/null +++ b/src/qml/qml/ftw/qdoubleendedlist_p.h @@ -0,0 +1,256 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QDOUBLEENDEDLIST_P_H +#define QDOUBLEENDEDLIST_P_H + +// +// 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. +// + +#include <QtCore/private/qglobal_p.h> + +QT_BEGIN_NAMESPACE + +class QInheritedListNode +{ +public: + ~QInheritedListNode() { remove(); } + bool isInList() const + { + Q_ASSERT((m_prev && m_next) || (!m_prev && !m_next)); + return m_prev != nullptr; + } + +private: + template<class N> + friend class QDoubleEndedList; + + void remove() + { + Q_ASSERT((m_prev && m_next) || (!m_prev && !m_next)); + if (!m_prev) + return; + + m_prev->m_next = m_next; + m_next->m_prev = m_prev; + m_prev = nullptr; + m_next = nullptr; + } + + QInheritedListNode *m_next = nullptr; + QInheritedListNode *m_prev = nullptr; +}; + +template<class N> +class QDoubleEndedList +{ +public: + QDoubleEndedList() + { + m_head.m_next = &m_head; + m_head.m_prev = &m_head; + assertHeadConsistent(); + } + + ~QDoubleEndedList() + { + assertHeadConsistent(); + while (!isEmpty()) + m_head.m_next->remove(); + assertHeadConsistent(); + } + + bool isEmpty() const + { + assertHeadConsistent(); + return m_head.m_next == &m_head; + } + + void prepend(N *n) + { + assertHeadConsistent(); + QInheritedListNode *nnode = n; + nnode->remove(); + + nnode->m_next = m_head.m_next ? m_head.m_next : &m_head; + nnode->m_next->m_prev = nnode; + + m_head.m_next = nnode; + nnode->m_prev = &m_head; + assertHeadConsistent(); + } + + void append(N *n) + { + assertHeadConsistent(); + QInheritedListNode *nnode = n; + nnode->remove(); + + nnode->m_prev = m_head.m_prev ? m_head.m_prev : &m_head; + nnode->m_prev->m_next = nnode; + + m_head.m_prev = nnode; + nnode->m_next = &m_head; + assertHeadConsistent(); + } + + void remove(N *n) { + Q_ASSERT(contains(n)); + QInheritedListNode *nnode = n; + nnode->remove(); + assertHeadConsistent(); + } + + bool contains(const N *n) const + { + assertHeadConsistent(); + for (const QInheritedListNode *nnode = m_head.m_next; + nnode != &m_head; nnode = nnode->m_next) { + if (nnode == n) + return true; + } + + return false; + } + + template<typename T, typename Node> + class base_iterator { + public: + T *operator*() const { return QDoubleEndedList<N>::nodeToN(m_node); } + T *operator->() const { return QDoubleEndedList<N>::nodeToN(m_node); } + + bool operator==(const base_iterator &other) const { return other.m_node == m_node; } + bool operator!=(const base_iterator &other) const { return other.m_node != m_node; } + + base_iterator &operator++() + { + m_node = m_node->m_next; + return *this; + } + + base_iterator operator++(int) + { + const base_iterator self(m_node); + m_node = m_node->m_next; + return self; + } + + private: + friend class QDoubleEndedList<N>; + + base_iterator(Node *node) : m_node(node) + { + Q_ASSERT(m_node != nullptr); + } + + Node *m_node = nullptr; + }; + + using iterator = base_iterator<N, QInheritedListNode>; + using const_iterator = base_iterator<const N, const QInheritedListNode>; + + const N *first() const { return checkedNodeToN(m_head.m_next); } + N *first() { return checkedNodeToN(m_head.m_next); } + + const N *last() const { return checkedNodeToN(m_head.m_prev); } + N *last() { return checkedNodeToN(m_head.m_prev); } + + const N *next(const N *current) const + { + Q_ASSERT(contains(current)); + const QInheritedListNode *nnode = current; + return checkedNodeToN(nnode->m_next); + } + + N *next(N *current) + { + Q_ASSERT(contains(current)); + const QInheritedListNode *nnode = current; + return checkedNodeToN(nnode->m_next); + } + + const N *prev(const N *current) const + { + Q_ASSERT(contains(current)); + const QInheritedListNode *nnode = current; + return checkedNodeToN(nnode->m_prev); + } + + N *prev(N *current) + { + Q_ASSERT(contains(current)); + const QInheritedListNode *nnode = current; + return checkedNodeToN(nnode->m_prev); + } + + iterator begin() + { + assertHeadConsistent(); + return iterator(m_head.m_next); + } + + iterator end() + { + assertHeadConsistent(); + return iterator(&m_head); + } + + const_iterator begin() const + { + assertHeadConsistent(); + return const_iterator(m_head.m_next); + } + + const_iterator end() const + { + assertHeadConsistent(); + return const_iterator(&m_head); + } + + qsizetype count() const + { + assertHeadConsistent(); + qsizetype result = 0; + for (const auto *node = m_head.m_next; node != &m_head; node = node->m_next) + ++result; + return result; + } + +private: + static N *nodeToN(QInheritedListNode *node) + { + return static_cast<N *>(node); + } + + static const N *nodeToN(const QInheritedListNode *node) + { + return static_cast<const N *>(node); + } + + N *checkedNodeToN(QInheritedListNode *node) const + { + assertHeadConsistent(); + return (!node || node == &m_head) ? nullptr : nodeToN(node); + } + + void assertHeadConsistent() const + { + Q_ASSERT(m_head.m_next != nullptr); + Q_ASSERT(m_head.m_prev != nullptr); + Q_ASSERT(m_head.m_next != &m_head || m_head.m_prev == &m_head); + } + + QInheritedListNode m_head; +}; + +QT_END_NAMESPACE + +#endif // QDOUBLEENDEDLIST_P_H diff --git a/src/qml/qml/ftw/qfieldlist_p.h b/src/qml/qml/ftw/qfieldlist_p.h index 2bf07fb20d..b4c6a55f1a 100644 --- a/src/qml/qml/ftw/qfieldlist_p.h +++ b/src/qml/qml/ftw/qfieldlist_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QFIELDLIST_P_H #define QFIELDLIST_P_H @@ -51,12 +15,12 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> +#include <QtCore/qtaggedpointer.h> -#include <private/qflagpointer_p.h> // QForwardFieldList is a super simple linked list that can only prepend -template<class N, N *N::*nextMember> +template<class N, N *N::*nextMember, typename Tag = QtPrivate::TagInfo<N>> class QForwardFieldList { public: @@ -65,6 +29,8 @@ public: inline N *takeFirst(); inline void prepend(N *); + template <typename OtherTag> + inline void copyAndClearPrepend(QForwardFieldList<N, nextMember, OtherTag> &); inline bool isEmpty() const; inline bool isOne() const; @@ -72,17 +38,10 @@ public: static inline N *next(N *v); - inline bool flag() const; - inline void setFlag(); - inline void clearFlag(); - inline void setFlagValue(bool); - - inline bool flag2() const; - inline void setFlag2(); - inline void clearFlag2(); - inline void setFlag2Value(bool); + inline Tag tag() const; + inline void setTag(Tag t); private: - QFlagPointer<N> _first; + QTaggedPointer<N, Tag> _first; }; // QFieldList is a simple linked list, that can append and prepend and also @@ -108,8 +67,10 @@ public: inline void insertAfter(N *, QFieldList<N, nextMember> &); inline void copyAndClear(QFieldList<N, nextMember> &); - inline void copyAndClearAppend(QForwardFieldList<N, nextMember> &); - inline void copyAndClearPrepend(QForwardFieldList<N, nextMember> &); + template <typename Tag> + inline void copyAndClearAppend(QForwardFieldList<N, nextMember, Tag> &); + template <typename Tag> + inline void copyAndClearPrepend(QForwardFieldList<N, nextMember, Tag> &); static inline N *next(N *v); @@ -124,21 +85,21 @@ private: quint32 _count:31; }; -template<class N, N *N::*nextMember> -QForwardFieldList<N, nextMember>::QForwardFieldList() +template<class N, N *N::*nextMember, typename Tag> +QForwardFieldList<N, nextMember, Tag>::QForwardFieldList() { } -template<class N, N *N::*nextMember> -N *QForwardFieldList<N, nextMember>::first() const +template<class N, N *N::*nextMember, typename Tag> +N *QForwardFieldList<N, nextMember, Tag>::first() const { - return *_first; + return _first.data(); } -template<class N, N *N::*nextMember> -N *QForwardFieldList<N, nextMember>::takeFirst() +template<class N, N *N::*nextMember, typename Tag> +N *QForwardFieldList<N, nextMember, Tag>::takeFirst() { - N *value = *_first; + N *value = _first.data(); if (value) { _first = next(value); value->*nextMember = nullptr; @@ -146,85 +107,57 @@ N *QForwardFieldList<N, nextMember>::takeFirst() return value; } -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::prepend(N *v) +template<class N, N *N::*nextMember, typename Tag> +void QForwardFieldList<N, nextMember, Tag>::prepend(N *v) { Q_ASSERT(v->*nextMember == nullptr); - v->*nextMember = *_first; + v->*nextMember = _first.data(); _first = v; } -template<class N, N *N::*nextMember> -bool QForwardFieldList<N, nextMember>::isEmpty() const +template<class N, N *N::*nextMember, typename Tag> +template <typename OtherTag> +void QForwardFieldList<N, nextMember, Tag>::copyAndClearPrepend(QForwardFieldList<N, nextMember, OtherTag> &o) { - return _first.isNull(); -} - -template<class N, N *N::*nextMember> -bool QForwardFieldList<N, nextMember>::isOne() const -{ - return *_first && _first->*nextMember == 0; -} - -template<class N, N *N::*nextMember> -bool QForwardFieldList<N, nextMember>::isMany() const -{ - return *_first && _first->*nextMember != 0; -} - -template<class N, N *N::*nextMember> -N *QForwardFieldList<N, nextMember>::next(N *v) -{ - Q_ASSERT(v); - return v->*nextMember; -} - -template<class N, N *N::*nextMember> -bool QForwardFieldList<N, nextMember>::flag() const -{ - return _first.flag(); -} - -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::setFlag() -{ - _first.setFlag(); + _first = nullptr; + while (N *n = o.takeFirst()) prepend(n); } -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::clearFlag() +template<class N, N *N::*nextMember, typename Tag> +bool QForwardFieldList<N, nextMember, Tag>::isEmpty() const { - _first.clearFlag(); + return _first.isNull(); } -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::setFlagValue(bool v) +template<class N, N *N::*nextMember, typename Tag> +bool QForwardFieldList<N, nextMember, Tag>::isOne() const { - _first.setFlagValue(v); + return _first.data() && _first->*nextMember == 0; } -template<class N, N *N::*nextMember> -bool QForwardFieldList<N, nextMember>::flag2() const +template<class N, N *N::*nextMember, typename Tag> +bool QForwardFieldList<N, nextMember, Tag>::isMany() const { - return _first.flag2(); + return _first.data() && _first->*nextMember != 0; } -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::setFlag2() +template<class N, N *N::*nextMember, typename Tag> +N *QForwardFieldList<N, nextMember, Tag>::next(N *v) { - _first.setFlag2(); + Q_ASSERT(v); + return v->*nextMember; } -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::clearFlag2() +template<class N, N *N::*nextMember, typename Tag> +Tag QForwardFieldList<N, nextMember, Tag>::tag() const { - _first.clearFlag2(); + return _first.tag(); } -template<class N, N *N::*nextMember> -void QForwardFieldList<N, nextMember>::setFlag2Value(bool v) +template<class N, N *N::*nextMember, typename Tag> +void QForwardFieldList<N, nextMember, Tag>::setTag(Tag t) { - _first.setFlag2Value(v); + _first.setTag(t); } template<class N, N *N::*nextMember> @@ -380,7 +313,8 @@ void QFieldList<N, nextMember>::copyAndClear(QFieldList<N, nextMember> &o) } template<class N, N *N::*nextMember> -void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember> &o) +template <typename Tag> +void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember, Tag> &o) { _first = 0; _last = 0; @@ -389,7 +323,8 @@ void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMemb } template<class N, N *N::*nextMember> -void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember> &o) +template <typename Tag> +void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember, Tag> &o) { _first = nullptr; _last = nullptr; diff --git a/src/qml/qml/ftw/qfinitestack_p.h b/src/qml/qml/ftw/qfinitestack_p.h index 9a74199137..3e206e205f 100644 --- a/src/qml/qml/ftw/qfinitestack_p.h +++ b/src/qml/qml/ftw/qfinitestack_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QFINITESTACK_P_H #define QFINITESTACK_P_H @@ -51,7 +15,7 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/ftw/qflagpointer_p.h b/src/qml/qml/ftw/qflagpointer_p.h deleted file mode 100644 index 71b41cd30b..0000000000 --- a/src/qml/qml/ftw/qflagpointer_p.h +++ /dev/null @@ -1,350 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QFLAGPOINTER_P_H -#define QFLAGPOINTER_P_H - -// -// 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. -// - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -template<typename T> -class QFlagPointer { -public: - inline QFlagPointer(); - inline QFlagPointer(T *); - inline QFlagPointer(const QFlagPointer<T> &o); - - inline bool isNull() const; - - inline bool flag() const; - inline void setFlag(); - inline void clearFlag(); - inline void setFlagValue(bool); - - inline bool flag2() const; - inline void setFlag2(); - inline void clearFlag2(); - inline void setFlag2Value(bool); - - inline QFlagPointer<T> &operator=(const QFlagPointer &o); - inline QFlagPointer<T> &operator=(T *); - - inline T *operator->() const; - inline T *operator*() const; - - inline T *data() const; - - inline explicit operator bool() const; - -private: - quintptr ptr_value = 0; - - static const quintptr FlagBit = 0x1; - static const quintptr Flag2Bit = 0x2; - static const quintptr FlagsMask = FlagBit | Flag2Bit; -}; - -template<typename T, typename T2> -class QBiPointer { -public: - inline QBiPointer(); - inline QBiPointer(T *); - inline QBiPointer(T2 *); - inline QBiPointer(const QBiPointer<T, T2> &o); - - inline bool isNull() const; - inline bool isT1() const; - inline bool isT2() const; - - inline bool flag() const; - inline void setFlag(); - inline void clearFlag(); - inline void setFlagValue(bool); - - inline QBiPointer<T, T2> &operator=(const QBiPointer<T, T2> &o); - inline QBiPointer<T, T2> &operator=(T *); - inline QBiPointer<T, T2> &operator=(T2 *); - - inline T *asT1() const; - inline T2 *asT2() const; - -private: - quintptr ptr_value = 0; - - static const quintptr FlagBit = 0x1; - static const quintptr Flag2Bit = 0x2; - static const quintptr FlagsMask = FlagBit | Flag2Bit; -}; - -template<typename T> -QFlagPointer<T>::QFlagPointer() -{ -} - -template<typename T> -QFlagPointer<T>::QFlagPointer(T *v) -: ptr_value(quintptr(v)) -{ - Q_ASSERT((ptr_value & FlagsMask) == 0); -} - -template<typename T> -QFlagPointer<T>::QFlagPointer(const QFlagPointer<T> &o) -: ptr_value(o.ptr_value) -{ -} - -template<typename T> -bool QFlagPointer<T>::isNull() const -{ - return 0 == (ptr_value & (~FlagsMask)); -} - -template<typename T> -bool QFlagPointer<T>::flag() const -{ - return ptr_value & FlagBit; -} - -template<typename T> -void QFlagPointer<T>::setFlag() -{ - ptr_value |= FlagBit; -} - -template<typename T> -void QFlagPointer<T>::clearFlag() -{ - ptr_value &= ~FlagBit; -} - -template<typename T> -void QFlagPointer<T>::setFlagValue(bool v) -{ - if (v) setFlag(); - else clearFlag(); -} - -template<typename T> -bool QFlagPointer<T>::flag2() const -{ - return ptr_value & Flag2Bit; -} - -template<typename T> -void QFlagPointer<T>::setFlag2() -{ - ptr_value|= Flag2Bit; -} - -template<typename T> -void QFlagPointer<T>::clearFlag2() -{ - ptr_value &= ~Flag2Bit; -} - -template<typename T> -void QFlagPointer<T>::setFlag2Value(bool v) -{ - if (v) setFlag2(); - else clearFlag2(); -} - -template<typename T> -QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o) -{ - ptr_value = o.ptr_value; - return *this; -} - -template<typename T> -QFlagPointer<T> &QFlagPointer<T>::operator=(T *o) -{ - Q_ASSERT((quintptr(o) & FlagsMask) == 0); - - ptr_value = quintptr(o) | (ptr_value & FlagsMask); - return *this; -} - -template<typename T> -T *QFlagPointer<T>::operator->() const -{ - return (T *)(ptr_value & ~FlagsMask); -} - -template<typename T> -T *QFlagPointer<T>::operator*() const -{ - return (T *)(ptr_value & ~FlagsMask); -} - -template<typename T> -T *QFlagPointer<T>::data() const -{ - return (T *)(ptr_value & ~FlagsMask); -} - -template<typename T> -QFlagPointer<T>::operator bool() const -{ - return data() != nullptr; -} - -template<typename T, typename T2> -QBiPointer<T, T2>::QBiPointer() -{ -} - -template<typename T, typename T2> -QBiPointer<T, T2>::QBiPointer(T *v) -: ptr_value(quintptr(v)) -{ - Q_ASSERT((quintptr(v) & FlagsMask) == 0); -} - -template<typename T, typename T2> -QBiPointer<T, T2>::QBiPointer(T2 *v) -: ptr_value(quintptr(v) | Flag2Bit) -{ - Q_ASSERT((quintptr(v) & FlagsMask) == 0); -} - -template<typename T, typename T2> -QBiPointer<T, T2>::QBiPointer(const QBiPointer<T, T2> &o) -: ptr_value(o.ptr_value) -{ -} - -template<typename T, typename T2> -bool QBiPointer<T, T2>::isNull() const -{ - return 0 == (ptr_value & (~FlagsMask)); -} - -template<typename T, typename T2> -bool QBiPointer<T, T2>::isT1() const -{ - return !(ptr_value & Flag2Bit); -} - -template<typename T, typename T2> -bool QBiPointer<T, T2>::isT2() const -{ - return ptr_value & Flag2Bit; -} - -template<typename T, typename T2> -bool QBiPointer<T, T2>::flag() const -{ - return ptr_value & FlagBit; -} - -template<typename T, typename T2> -void QBiPointer<T, T2>::setFlag() -{ - ptr_value |= FlagBit; -} - -template<typename T, typename T2> -void QBiPointer<T, T2>::clearFlag() -{ - ptr_value &= ~FlagBit; -} - -template<typename T, typename T2> -void QBiPointer<T, T2>::setFlagValue(bool v) -{ - if (v) setFlag(); - else clearFlag(); -} - -template<typename T, typename T2> -QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(const QBiPointer<T, T2> &o) -{ - ptr_value = o.ptr_value; - return *this; -} - -template<typename T, typename T2> -QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T *o) -{ - Q_ASSERT((quintptr(o) & FlagsMask) == 0); - - ptr_value = quintptr(o) | (ptr_value & FlagBit); - return *this; -} - -template<typename T, typename T2> -QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T2 *o) -{ - Q_ASSERT((quintptr(o) & FlagsMask) == 0); - - ptr_value = quintptr(o) | (ptr_value & FlagBit) | Flag2Bit; - return *this; -} - -template<typename T, typename T2> -T *QBiPointer<T, T2>::asT1() const -{ - Q_ASSERT(isT1()); - return (T *)(ptr_value & ~FlagsMask); -} - -template<typename T, typename T2> -T2 *QBiPointer<T, T2>::asT2() const -{ - Q_ASSERT(isT2()); - return (T2 *)(ptr_value & ~FlagsMask); -} - -QT_END_NAMESPACE - -#endif // QFLAGPOINTER_P_H diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp index 7a8fdd0a14..b963bc7984 100644 --- a/src/qml/qml/ftw/qhashedstring.cpp +++ b/src/qml/qml/ftw/qhashedstring.cpp @@ -1,100 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhashedstring_p.h" QT_BEGIN_NAMESPACE -// Copy of QString's qMemCompare -bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length) -{ - Q_ASSERT(lhs && rhs); - const quint16 *a = (const quint16 *)lhs; - const quint16 *b = (const quint16 *)rhs; - - if (a == b || !length) - return true; - - union { - const quint16 *w; - const quint32 *d; - quintptr value; - } sa, sb; - sa.w = a; - sb.w = b; - - // check alignment - if ((sa.value & 2) == (sb.value & 2)) { - // both addresses have the same alignment - if (sa.value & 2) { - // both addresses are not aligned to 4-bytes boundaries - // compare the first character - if (*sa.w != *sb.w) - return false; - --length; - ++sa.w; - ++sb.w; - - // now both addresses are 4-bytes aligned - } - - // both addresses are 4-bytes aligned - // do a fast 32-bit comparison - const quint32 *e = sa.d + (length >> 1); - for ( ; sa.d != e; ++sa.d, ++sb.d) { - if (*sa.d != *sb.d) - return false; - } - - // do we have a tail? - return (length & 1) ? *sa.w == *sb.w : true; - } else { - // one of the addresses isn't 4-byte aligned but the other is - const quint16 *e = sa.w + length; - for ( ; sa.w != e; ++sa.w, ++sb.w) { - if (*sa.w != *sb.w) - return false; - } - } - return true; -} - QHashedStringRef QHashedStringRef::mid(int offset, int length) const { Q_ASSERT(offset < m_length); @@ -102,37 +12,41 @@ QHashedStringRef QHashedStringRef::mid(int offset, int length) const (length == -1 || (offset + length) > m_length)?(m_length - offset):length); } -bool QHashedStringRef::endsWith(const QString &s) const +QVector<QHashedStringRef> QHashedStringRef::split(const QChar sep) const { - return s.length() < m_length && - QHashedString::compare(s.constData(), m_data + m_length - s.length(), s.length()); + QVector<QHashedStringRef> ret; + auto curLength = 0; + auto curOffset = m_data; + for (int offset = 0; offset < m_length; ++offset) { + if (*(m_data + offset) == sep) { + ret.push_back({curOffset, curLength}); + curOffset = m_data + offset + 1; + curLength = 0; + } else { + ++curLength; + } + } + if (curLength > 0) + ret.push_back({curOffset, curLength}); + return ret; } -bool QHashedStringRef::startsWith(const QString &s) const +bool QHashedStringRef::endsWith(const QString &s) const { - return s.length() < m_length && - QHashedString::compare(s.constData(), m_data, s.length()); + QStringView view {m_data, m_length}; + return view.endsWith(s); } -static int findChar(const QChar *str, int len, QChar ch, int from) +bool QHashedStringRef::startsWith(const QString &s) const { - const ushort *s = (const ushort *)str; - ushort c = ch.unicode(); - if (from < 0) - from = qMax(from + len, 0); - if (from < len) { - const ushort *n = s + from - 1; - const ushort *e = s + len; - while (++n != e) - if (*n == c) - return n - s; - } - return -1; + QStringView view {m_data, m_length}; + return view.startsWith(s); } int QHashedStringRef::indexOf(const QChar &c, int from) const { - return findChar(m_data, m_length, c, from); + QStringView view {m_data, m_length}; + return view.indexOf(c, from); } QString QHashedStringRef::toString() const diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index b9f3f81219..78ce738f3b 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHASHEDSTRING_P_H #define QHASHEDSTRING_P_H @@ -55,8 +19,6 @@ #include <QtCore/qstring.h> #include <private/qv4string_p.h> -#include <private/qflagpointer_p.h> - #if defined(Q_OS_QNX) #include <stdlib.h> #endif @@ -64,7 +26,7 @@ QT_BEGIN_NAMESPACE class QHashedStringRef; -class Q_QML_PRIVATE_EXPORT QHashedString : public QString +class Q_QML_EXPORT QHashedString : public QString { public: inline QHashedString(); @@ -79,7 +41,6 @@ public: inline quint32 hash() const; inline quint32 existingHash() const; - static bool compare(const QChar *lhs, const QChar *rhs, int length); static inline bool compare(const QChar *lhs, const char *rhs, int length); static inline bool compare(const char *lhs, const char *rhs, int length); @@ -95,12 +56,12 @@ private: }; class QHashedCStringRef; -class Q_QML_PRIVATE_EXPORT QHashedStringRef +class Q_QML_EXPORT QHashedStringRef { public: inline QHashedStringRef(); inline QHashedStringRef(const QString &); - inline QHashedStringRef(const QStringRef &); + inline QHashedStringRef(QStringView); inline QHashedStringRef(const QChar *, int); inline QHashedStringRef(const QChar *, int, quint32); inline QHashedStringRef(const QHashedString &); @@ -125,6 +86,7 @@ public: bool endsWith(const QString &) const; int indexOf(const QChar &, int from=0) const; QHashedStringRef mid(int, int) const; + QVector<QHashedStringRef> split(const QChar sep) const; inline bool isEmpty() const; inline int length() const; @@ -144,7 +106,7 @@ private: mutable quint32 m_hash = 0; }; -class Q_AUTOTEST_EXPORT QHashedCStringRef +class QHashedCStringRef { public: inline QHashedCStringRef(); @@ -157,7 +119,7 @@ public: inline const char *constData() const; inline int length() const; - QString toUtf16() const; + Q_AUTOTEST_EXPORT QString toUtf16() const; inline int utf16length() const; inline void writeUtf16(QChar *) const; inline void writeUtf16(quint16 *) const; @@ -171,12 +133,12 @@ private: mutable quint32 m_hash = 0; }; -inline uint qHash(const QHashedString &string) +inline size_t qHash(const QHashedString &string) { return uint(string.hash()); } -inline uint qHash(const QHashedStringRef &string) +inline size_t qHash(const QHashedStringRef &string) { return uint(string.hash()); } @@ -216,9 +178,10 @@ bool QHashedString::operator==(const QHashedString &string) const bool QHashedString::operator==(const QHashedStringRef &string) const { - return length() == string.m_length && - (string.m_hash == m_hash || !string.m_hash || !m_hash) && - QHashedString::compare(constData(), string.m_data, string.m_length); + if (m_hash && string.m_hash && m_hash != string.m_hash) + return false; + QStringView otherView {string.m_data, string.m_length}; + return static_cast<const QString &>(*this) == otherView; } quint32 QHashedString::hash() const @@ -236,14 +199,18 @@ QHashedStringRef::QHashedStringRef() { } +// QHashedStringRef is meant for identifiers, property names, etc. +// Those should alsways be smaller than std::numeric_limits<int>::max()) QHashedStringRef::QHashedStringRef(const QString &str) -: m_data(str.constData()), m_length(str.length()), m_hash(0) +: m_data(str.constData()), m_length(int(str.size())), m_hash(0) { + Q_ASSERT(str.size() <= std::numeric_limits<int>::max()); } -QHashedStringRef::QHashedStringRef(const QStringRef &str) -: m_data(str.constData()), m_length(str.length()), m_hash(0) +QHashedStringRef::QHashedStringRef(QStringView str) +: m_data(str.constData()), m_length(int(str.size())), m_hash(0) { + Q_ASSERT(str.size() <= std::numeric_limits<int>::max()); } QHashedStringRef::QHashedStringRef(const QChar *data, int length) @@ -257,8 +224,9 @@ QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash) } QHashedStringRef::QHashedStringRef(const QHashedString &string) -: m_data(string.constData()), m_length(string.length()), m_hash(string.m_hash) +: m_data(string.constData()), m_length(int(string.size())), m_hash(string.m_hash) { + Q_ASSERT(string.size() <= std::numeric_limits<int>::max()); } QHashedStringRef::QHashedStringRef(const QHashedStringRef &string) @@ -276,22 +244,26 @@ QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o) bool QHashedStringRef::operator==(const QString &string) const { - return m_length == string.length() && - QHashedString::compare(string.constData(), m_data, m_length); + QStringView view {m_data, m_length}; + return view == string; } bool QHashedStringRef::operator==(const QHashedString &string) const { - return m_length == string.length() && - (m_hash == string.m_hash || !m_hash || !string.m_hash) && - QHashedString::compare(string.constData(), m_data, m_length); + if (m_hash && string.m_hash && m_hash != string.m_hash) + return false; + QStringView view {m_data, m_length}; + QStringView otherView {string.constData(), string.size()}; + return view == otherView; } bool QHashedStringRef::operator==(const QHashedStringRef &string) const { - return m_length == string.m_length && - (m_hash == string.m_hash || !m_hash || !string.m_hash) && - QHashedString::compare(string.m_data, m_data, m_length); + if (m_hash && string.m_hash && m_hash != string.m_hash) + return false; + QStringView view {m_data, m_length}; + QStringView otherView {string.m_data, string.m_length}; + return view == otherView; } bool QHashedStringRef::operator==(const QHashedCStringRef &string) const @@ -303,29 +275,22 @@ bool QHashedStringRef::operator==(const QHashedCStringRef &string) const bool QHashedStringRef::operator!=(const QString &string) const { - return m_length != string.length() || - !QHashedString::compare(string.constData(), m_data, m_length); + return !(*this == string); } bool QHashedStringRef::operator!=(const QHashedString &string) const { - return m_length != string.length() || - (m_hash != string.m_hash && m_hash && string.m_hash) || - !QHashedString::compare(string.constData(), m_data, m_length); + return !(*this == string); } bool QHashedStringRef::operator!=(const QHashedStringRef &string) const { - return m_length != string.m_length || - (m_hash != string.m_hash && m_hash && string.m_hash) || - QHashedString::compare(string.m_data, m_data, m_length); + return !(*this == string); } bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const { - return m_length != string.m_length || - (m_hash != string.m_hash && m_hash && string.m_hash) || - QHashedString::compare(m_data, string.m_data, m_length); + return !(*this == string); } QChar *QHashedStringRef::data() @@ -451,6 +416,7 @@ bool QHashedString::compare(const char *lhs, const char *rhs, int length) return 0 == ::memcmp(lhs, rhs, length); } + quint32 QHashedString::stringHash(const QChar *data, int length) { return QV4::String::createHashValue(data, length, nullptr); @@ -463,7 +429,12 @@ quint32 QHashedString::stringHash(const char *data, int length) void QHashedString::computeHash() const { - m_hash = stringHash(constData(), length()); + m_hash = stringHash(constData(), int(size())); +} + +namespace QtPrivate { +inline QString asString(const QHashedCStringRef &ref) { return ref.toUtf16(); } +inline QString asString(const QHashedStringRef &ref) { return ref.toString(); } } QT_END_NAMESPACE diff --git a/src/qml/qml/ftw/qintrusivelist.cpp b/src/qml/qml/ftw/qintrusivelist.cpp index 2ebaffb375..a0a1ddb470 100644 --- a/src/qml/qml/ftw/qintrusivelist.cpp +++ b/src/qml/qml/ftw/qintrusivelist.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qintrusivelist_p.h" diff --git a/src/qml/qml/ftw/qintrusivelist_p.h b/src/qml/qml/ftw/qintrusivelist_p.h index 8992be9f93..1170370fae 100644 --- a/src/qml/qml/ftw/qintrusivelist_p.h +++ b/src/qml/qml/ftw/qintrusivelist_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QINTRUSIVELIST_P_H #define QINTRUSIVELIST_P_H @@ -51,220 +15,144 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> QT_BEGIN_NAMESPACE -class QIntrusiveListNode; -template<class N, QIntrusiveListNode N::*member> -class QIntrusiveList +class QIntrusiveListNode { public: - inline QIntrusiveList(); - inline ~QIntrusiveList(); - - inline bool isEmpty() const; - inline void insert(N *n); - inline void remove(N *n); - inline bool contains(N *) const; - - class iterator { - public: - inline iterator(); - inline iterator(N *value); - - inline N *operator*() const; - inline N *operator->() const; - inline bool operator==(const iterator &other) const; - inline bool operator!=(const iterator &other) const; - inline iterator &operator++(); - - inline iterator &erase(); - - private: - N *_value; - }; - typedef iterator Iterator; - - inline N *first() const; - static inline N *next(N *current); + ~QIntrusiveListNode() { remove(); } + + void remove() + { + if (_prev) *_prev = _next; + if (_next) _next->_prev = _prev; + _prev = nullptr; + _next = nullptr; + } - inline iterator begin(); - inline iterator end(); + bool isInList() const { return _prev != nullptr; } private: - static inline N *nodeToN(QIntrusiveListNode *node); - - QIntrusiveListNode *__first = nullptr; -}; - -class QIntrusiveListNode -{ -public: - inline QIntrusiveListNode(); - inline ~QIntrusiveListNode(); - - inline void remove(); - inline bool isInList() const; + template<class N, QIntrusiveListNode N::*member> + friend class QIntrusiveList; QIntrusiveListNode *_next = nullptr; QIntrusiveListNode**_prev = nullptr; }; template<class N, QIntrusiveListNode N::*member> -QIntrusiveList<N, member>::iterator::iterator() -: _value(nullptr) -{ -} - -template<class N, QIntrusiveListNode N::*member> -QIntrusiveList<N, member>::iterator::iterator(N *value) -: _value(value) -{ -} - -template<class N, QIntrusiveListNode N::*member> -N *QIntrusiveList<N, member>::iterator::operator*() const -{ - return _value; -} - -template<class N, QIntrusiveListNode N::*member> -N *QIntrusiveList<N, member>::iterator::operator->() const -{ - return _value; -} - -template<class N, QIntrusiveListNode N::*member> -bool QIntrusiveList<N, member>::iterator::operator==(const iterator &other) const -{ - return other._value == _value; -} - -template<class N, QIntrusiveListNode N::*member> -bool QIntrusiveList<N, member>::iterator::operator!=(const iterator &other) const -{ - return other._value != _value; -} - -template<class N, QIntrusiveListNode N::*member> -typename QIntrusiveList<N, member>::iterator &QIntrusiveList<N, member>::iterator::operator++() -{ - _value = QIntrusiveList<N, member>::next(_value); - return *this; -} - -template<class N, QIntrusiveListNode N::*member> -typename QIntrusiveList<N, member>::iterator &QIntrusiveList<N, member>::iterator::erase() +class QIntrusiveList { - N *old = _value; - _value = QIntrusiveList<N, member>::next(_value); - (old->*member).remove(); - return *this; -} +private: + template<typename O> + class iterator_impl { + public: + iterator_impl() = default; + iterator_impl(O value) : _value(value) {} + + O operator*() const { return _value; } + O operator->() const { return _value; } + bool operator==(const iterator_impl &other) const { return other._value == _value; } + bool operator!=(const iterator_impl &other) const { return other._value != _value; } + iterator_impl &operator++() + { + _value = QIntrusiveList<N, member>::next(_value); + return *this; + } + + protected: + O _value = nullptr; + }; -template<class N, QIntrusiveListNode N::*member> -QIntrusiveList<N, member>::QIntrusiveList() +public: + class iterator : public iterator_impl<N *> + { + public: + iterator() = default; + iterator(N *value) : iterator_impl<N *>(value) {} + + iterator &erase() + { + N *old = this->_value; + this->_value = QIntrusiveList<N, member>::next(this->_value); + (old->*member).remove(); + return *this; + } + }; -{ -} + using const_iterator = iterator_impl<const N *>; -template<class N, QIntrusiveListNode N::*member> -QIntrusiveList<N, member>::~QIntrusiveList() -{ - while (__first) __first->remove(); -} + using Iterator = iterator; + using ConstIterator = const_iterator; -template<class N, QIntrusiveListNode N::*member> -bool QIntrusiveList<N, member>::isEmpty() const -{ - return __first == nullptr; -} + ~QIntrusiveList() { while (__first) __first->remove(); } -template<class N, QIntrusiveListNode N::*member> -void QIntrusiveList<N, member>::insert(N *n) -{ - QIntrusiveListNode *nnode = &(n->*member); - nnode->remove(); + bool isEmpty() const { return __first == nullptr; } - nnode->_next = __first; - if (nnode->_next) nnode->_next->_prev = &nnode->_next; - __first = nnode; - nnode->_prev = &__first; -} + void insert(N *n) + { + QIntrusiveListNode *nnode = &(n->*member); + nnode->remove(); -template<class N, QIntrusiveListNode N::*member> -void QIntrusiveList<N, member>::remove(N *n) -{ - QIntrusiveListNode *nnode = &(n->*member); - nnode->remove(); -} + nnode->_next = __first; + if (nnode->_next) nnode->_next->_prev = &nnode->_next; + __first = nnode; + nnode->_prev = &__first; + } -template<class N, QIntrusiveListNode N::*member> -bool QIntrusiveList<N, member>::contains(N *n) const -{ - QIntrusiveListNode *nnode = __first; - while (nnode) { - if (nodeToN(nnode) == n) - return true; - nnode = nnode->_next; + void remove(N *n) + { + QIntrusiveListNode *nnode = &(n->*member); + nnode->remove(); } - return false; -} -template<class N, QIntrusiveListNode N::*member> -N *QIntrusiveList<N, member>::first() const -{ - return __first?nodeToN(__first):nullptr; -} + bool contains(const N *n) const + { + QIntrusiveListNode *nnode = __first; + while (nnode) { + if (nodeToN(nnode) == n) + return true; + nnode = nnode->_next; + } + return false; + } -template<class N, QIntrusiveListNode N::*member> -N *QIntrusiveList<N, member>::next(N *current) -{ - QIntrusiveListNode *nextnode = (current->*member)._next; - N *nextstruct = nextnode?nodeToN(nextnode):nullptr; - return nextstruct; -} + const N *first() const { return __first ? nodeToN(__first) : nullptr; } + N *first() { return __first ? nodeToN(__first) : nullptr; } -template<class N, QIntrusiveListNode N::*member> -typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::begin() -{ - return __first?iterator(nodeToN(__first)):iterator(); -} + template<typename O> + static O next(O current) + { + QIntrusiveListNode *nextnode = (current->*member)._next; + return nextnode ? nodeToN(nextnode) : nullptr; + } -template<class N, QIntrusiveListNode N::*member> -typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::end() -{ - return iterator(); -} + iterator begin() { return __first ? iterator(nodeToN(__first)) : iterator(); } + iterator end() { return iterator(); } -template<class N, QIntrusiveListNode N::*member> -N *QIntrusiveList<N, member>::nodeToN(QIntrusiveListNode *node) -{ - return (N *)((char *)node - ((char *)&(((N *)nullptr)->*member) - (char *)nullptr)); -} + const_iterator begin() const + { + return __first ? const_iterator(nodeToN(__first)) : const_iterator(); + } -QIntrusiveListNode::QIntrusiveListNode() -{ -} + const_iterator end() const { return const_iterator(); } -QIntrusiveListNode::~QIntrusiveListNode() -{ - remove(); -} +private: -void QIntrusiveListNode::remove() -{ - if (_prev) *_prev = _next; - if (_next) _next->_prev = _prev; - _prev = nullptr; - _next = nullptr; -} + static N *nodeToN(QIntrusiveListNode *node) + { + QT_WARNING_PUSH +#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 1300 + QT_WARNING_DISABLE_CLANG("-Wnull-pointer-subtraction") +#endif + return (N *)((char *)node - ((char *)&(((N *)nullptr)->*member) - (char *)nullptr)); + QT_WARNING_POP + } -bool QIntrusiveListNode::isInList() const -{ - return _prev != nullptr; -} + QIntrusiveListNode *__first = nullptr; +}; QT_END_NAMESPACE diff --git a/src/qml/qml/ftw/qlazilyallocated_p.h b/src/qml/qml/ftw/qlazilyallocated_p.h index 9073e41558..81f6ab7e89 100644 --- a/src/qml/qml/ftw/qlazilyallocated_p.h +++ b/src/qml/qml/ftw/qlazilyallocated_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QLAZILYALLOCATED_P_H #define QLAZILYALLOCATED_P_H @@ -51,13 +15,12 @@ // We mean it. // -#include <QtCore/qglobal.h> - -#include <private/qflagpointer_p.h> +#include <QtCore/private/qglobal_p.h> +#include <QtCore/qtaggedpointer.h> QT_BEGIN_NAMESPACE -template<typename T> +template<typename T, typename Tag = typename QtPrivate::TagInfo<T>::TagType> class QLazilyAllocated { public: inline QLazilyAllocated(); @@ -70,73 +33,59 @@ public: inline T &value(); inline const T &value() const; - inline bool flag() const; - inline void setFlag(); - inline void clearFlag(); - inline void setFlagValue(bool); + inline Tag tag() const; + inline void setTag(Tag t); private: - mutable QFlagPointer<T> d; + mutable QTaggedPointer<T, Tag> d; }; -template<typename T> -QLazilyAllocated<T>::QLazilyAllocated() +template<typename T, typename Tag> +QLazilyAllocated<T, Tag>::QLazilyAllocated() { } -template<typename T> -QLazilyAllocated<T>::~QLazilyAllocated() +template<typename T, typename Tag> +QLazilyAllocated<T, Tag>::~QLazilyAllocated() { - delete *d; + delete d.data(); } -template<typename T> -bool QLazilyAllocated<T>::isAllocated() const +template<typename T, typename Tag> +bool QLazilyAllocated<T, Tag>::isAllocated() const { return !d.isNull(); } -template<typename T> -T &QLazilyAllocated<T>::value() +template<typename T, typename Tag> +T &QLazilyAllocated<T, Tag>::value() { if (d.isNull()) d = new T; - return *(*d); + return *d; } -template<typename T> -const T &QLazilyAllocated<T>::value() const +template<typename T, typename Tag> +const T &QLazilyAllocated<T, Tag>::value() const { if (d.isNull()) d = new T; - return *(*d); -} - -template<typename T> -T *QLazilyAllocated<T>::operator->() const -{ return *d; } -template<typename T> -bool QLazilyAllocated<T>::flag() const -{ - return d.flag(); -} - -template<typename T> -void QLazilyAllocated<T>::setFlag() +template<typename T, typename Tag> +T *QLazilyAllocated<T, Tag>::operator->() const { - d.setFlag(); + return d.data(); } -template<typename T> -void QLazilyAllocated<T>::clearFlag() +template<typename T, typename Tag> +Tag QLazilyAllocated<T, Tag>::tag() const { - d.clearFlag(); + return d.tag(); } -template<typename T> -void QLazilyAllocated<T>::setFlagValue(bool v) +template<typename T, typename Tag> +void QLazilyAllocated<T, Tag>::setTag(Tag t) { - d.setFlagValue(v); + d.setTag(t); } QT_END_NAMESPACE diff --git a/src/qml/qml/ftw/qlinkedstringhash_p.h b/src/qml/qml/ftw/qlinkedstringhash_p.h index 67ced7fbbf..a2309db717 100644 --- a/src/qml/qml/ftw/qlinkedstringhash_p.h +++ b/src/qml/qml/ftw/qlinkedstringhash_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QLINKEDSTRINGHASH_P_H #define QLINKEDSTRINGHASH_P_H @@ -223,7 +187,7 @@ public: { if (auto *node = iter.node()) { QHashedString key(node->key()); - while ((node = static_cast<typename QLinkedStringHash<T>::Node *>(*node->next))) { + while ((node = static_cast<typename QLinkedStringHash<T>::Node *>(node->next.data()))) { if (node->equals(key)) return QLinkedStringHash<T>::iterator(node); } diff --git a/src/qml/qml/ftw/qpodvector_p.h b/src/qml/qml/ftw/qpodvector_p.h index b2fb481793..6508071105 100644 --- a/src/qml/qml/ftw/qpodvector_p.h +++ b/src/qml/qml/ftw/qpodvector_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QPODVECTOR_P_H #define QPODVECTOR_P_H @@ -51,7 +15,7 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> #include <QDebug> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/ftw/qprimefornumbits_p.h b/src/qml/qml/ftw/qprimefornumbits_p.h index 6e9acbf7fd..82c9ea023e 100644 --- a/src/qml/qml/ftw/qprimefornumbits_p.h +++ b/src/qml/qml/ftw/qprimefornumbits_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QPRIMEFORNUMBITS_P_H #define QPRIMEFORNUMBITS_P_H diff --git a/src/qml/qml/ftw/qqmlnullablevalue_p.h b/src/qml/qml/ftw/qqmlnullablevalue_p.h index 5b3d2fc456..62899e4644 100644 --- a/src/qml/qml/ftw/qqmlnullablevalue_p.h +++ b/src/qml/qml/ftw/qqmlnullablevalue_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QQMLNULLABLEVALUE_P_H #define QQMLNULLABLEVALUE_P_H @@ -51,27 +15,76 @@ // We mean it. // +#include <QtCore/private/qglobal_p.h> + QT_BEGIN_NAMESPACE template<typename T> struct QQmlNullableValue { - QQmlNullableValue() - : value(T()) {} + QQmlNullableValue() = default; + QQmlNullableValue(const QQmlNullableValue<T> &o) - : isNull(o.isNull), value(o.value) {} + : m_value(o.m_value) + , m_isNull(o.m_isNull) + {} + + QQmlNullableValue(QQmlNullableValue<T> &&o) noexcept + : m_value(std::move(o.m_value)) + , m_isNull(std::exchange(o.m_isNull, true)) + {} + QQmlNullableValue(const T &t) - : isNull(false), value(t) {} - QQmlNullableValue<T> &operator=(const T &t) - { isNull = false; value = t; return *this; } + : m_value(t) + , m_isNull(false) + {} + + QQmlNullableValue(T &&t) noexcept + : m_value(std::move(t)) + , m_isNull(false) + {} + QQmlNullableValue<T> &operator=(const QQmlNullableValue<T> &o) - { isNull = o.isNull; value = o.value; return *this; } - operator T() const { return value; } + { + if (&o != this) { + m_value = o.m_value; + m_isNull = o.m_isNull; + } + return *this; + } + + QQmlNullableValue<T> &operator=(QQmlNullableValue<T> &&o) noexcept + { + if (&o != this) { + m_value = std::move(o.m_value); + m_isNull = std::exchange(o.m_isNull, true); + } + return *this; + } + + QQmlNullableValue<T> &operator=(const T &t) + { + m_value = t; + m_isNull = false; + return *this; + } + + QQmlNullableValue<T> &operator=(T &&t) noexcept + { + m_value = std::move(t); + m_isNull = false; + return *this; + } + + const T &value() const { return m_value; } + operator T() const { return m_value; } + + void invalidate() { m_isNull = true; } + bool isValid() const { return !m_isNull; } - void invalidate() { isNull = true; } - bool isValid() const { return !isNull; } - bool isNull = true; - T value; +private: + T m_value = T(); + bool m_isNull = true; }; QT_END_NAMESPACE diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h index b4f8acad49..e7616915eb 100644 --- a/src/qml/qml/ftw/qqmlrefcount_p.h +++ b/src/qml/qml/ftw/qqmlrefcount_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QQMLREFCOUNT_P_H #define QQMLREFCOUNT_P_H @@ -57,23 +21,34 @@ QT_BEGIN_NAMESPACE +template <typename T> +class QQmlRefCounted; -class Q_QML_PRIVATE_EXPORT QQmlRefCount +class QQmlRefCount { Q_DISABLE_COPY_MOVE(QQmlRefCount) public: inline QQmlRefCount(); inline void addref() const; - inline void release() const; inline int count() const; -protected: - inline virtual ~QQmlRefCount(); +private: + inline ~QQmlRefCount(); + template <typename T> friend class QQmlRefCounted; private: mutable QAtomicInt refCount; }; +template <typename T> +class QQmlRefCounted : public QQmlRefCount +{ +public: + inline void release() const; +protected: + inline ~QQmlRefCounted(); +}; + template<class T> class QQmlRefPointer { @@ -82,14 +57,16 @@ public: AddRef, Adopt }; - inline QQmlRefPointer(); - inline QQmlRefPointer(T *, Mode m = AddRef); - inline QQmlRefPointer(const QQmlRefPointer<T> &); - inline QQmlRefPointer(QQmlRefPointer<T> &&); + Q_NODISCARD_CTOR inline QQmlRefPointer() noexcept; + Q_NODISCARD_CTOR inline QQmlRefPointer(T *, Mode m = AddRef); + Q_NODISCARD_CTOR inline QQmlRefPointer(const QQmlRefPointer &); + Q_NODISCARD_CTOR inline QQmlRefPointer(QQmlRefPointer &&) noexcept; inline ~QQmlRefPointer(); + void swap(QQmlRefPointer &other) noexcept { qt_ptr_swap(o, other.o); } + inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o); - inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o); + inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o) noexcept; inline bool isNull() const { return !o; } @@ -102,10 +79,54 @@ public: inline T* take() { T *res = o; o = nullptr; return res; } + friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept + { + return a.o == b.o; + } + + friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept + { + return !(a == b); + } + + friend size_t qHash(const QQmlRefPointer &v, size_t seed = 0) noexcept + { + return qHash(v.o, seed); + } + + void reset(T *t = nullptr) + { + if (t == o) + return; + if (o) + o->release(); + if (t) + t->addref(); + o = t; + } + private: T *o; }; +namespace QQml { +/*! + \internal + Creates a QQmlRefPointer which takes ownership of a newly constructed T. + T must derive from QQmlRefCounted<T> (as we rely on an initial refcount of _1_). + T will be constructed by forwarding \a args to its constructor. + */ +template <typename T, typename ...Args> +QQmlRefPointer<T> makeRefPointer(Args&&... args) +{ + static_assert(std::is_base_of_v<QQmlRefCount, T>); + return QQmlRefPointer<T>(new T(std::forward<Args>(args)...), QQmlRefPointer<T>::Adopt); +} +} + +template <typename T> +Q_DECLARE_TYPEINFO_BODY(QQmlRefPointer<T>, Q_RELOCATABLE_TYPE); + QQmlRefCount::QQmlRefCount() : refCount(1) { @@ -122,11 +143,22 @@ void QQmlRefCount::addref() const refCount.ref(); } -void QQmlRefCount::release() const +template <typename T> +void QQmlRefCounted<T>::release() const { + static_assert(std::is_base_of_v<QQmlRefCounted, T>, + "QQmlRefCounted<T> must be a base of T (CRTP)"); Q_ASSERT(refCount.loadRelaxed() > 0); if (!refCount.deref()) - delete this; + delete static_cast<const T *>(this); +} + +template <typename T> +QQmlRefCounted<T>::~QQmlRefCounted() +{ + static_assert(std::is_final_v<T> || std::has_virtual_destructor_v<T>, + "T must either be marked final or have a virtual dtor, " + "lest release() runs into UB."); } int QQmlRefCount::count() const @@ -135,7 +167,7 @@ int QQmlRefCount::count() const } template<class T> -QQmlRefPointer<T>::QQmlRefPointer() +QQmlRefPointer<T>::QQmlRefPointer() noexcept : o(nullptr) { } @@ -156,7 +188,7 @@ QQmlRefPointer<T>::QQmlRefPointer(const QQmlRefPointer<T> &other) } template <class T> -QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other) +QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other) noexcept : o(other.take()) { } @@ -170,17 +202,21 @@ QQmlRefPointer<T>::~QQmlRefPointer() template<class T> QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other) { - if (other.o) other.o->addref(); - if (o) o->release(); + if (o == other.o) + return *this; + if (other.o) + other.o->addref(); + if (o) + o->release(); o = other.o; return *this; } template <class T> -QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other) +QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other) noexcept { QQmlRefPointer<T> m(std::move(other)); - qSwap(o, m.o); + swap(m); return *this; } diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp index e961ed3d0d..57f91b6b4d 100644 --- a/src/qml/qml/ftw/qqmlthread.cpp +++ b/src/qml/qml/ftw/qqmlthread.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qqmlthread_p.h" @@ -47,6 +11,8 @@ #include <QtCore/qwaitcondition.h> #include <QtCore/qcoreapplication.h> +#include <QtCore/private/qthread_p.h> + QT_BEGIN_NAMESPACE class QQmlThreadPrivate : public QThread @@ -55,19 +21,16 @@ public: QQmlThreadPrivate(QQmlThread *); QQmlThread *q; - void run() override; - inline QMutex &mutex() { return _mutex; } inline void lock() { _mutex.lock(); } inline void unlock() { _mutex.unlock(); } inline void wait() { _wait.wait(&_mutex); } inline void wakeOne() { _wait.wakeOne(); } - inline void wakeAll() { _wait.wakeAll(); } - quint32 m_threadProcessing:1; // Set when the thread is processing messages - quint32 m_mainProcessing:1; // Set when the main thread is processing messages - quint32 m_shutdown:1; // Set by main thread to request a shutdown - quint32 m_mainThreadWaiting:1; // Set by main thread if it is waiting for the message queue to empty + bool m_threadProcessing; // Set when the thread is processing messages + bool m_mainProcessing; // Set when the main thread is processing messages + bool m_shutdown; // Set by main thread to request a shutdown + bool m_mainThreadWaiting; // Set by main thread if it is waiting for the message queue to empty typedef QFieldList<QQmlThread::Message, &QQmlThread::Message::next> MessageList; MessageList threadList; @@ -131,6 +94,9 @@ QQmlThreadPrivate::QQmlThreadPrivate(QQmlThread *q) m_mainThreadWaiting(false), mainSync(nullptr), m_mainObject(this) { setObjectName(QStringLiteral("QQmlThread")); + // This size is aligned with the recursion depth limits in the parser/codegen. In case of + // absurd content we want to hit the recursion checks instead of running out of stack. + setStackSize(8 * 1024 * 1024); } bool QQmlThreadPrivate::event(QEvent *e) @@ -140,19 +106,6 @@ bool QQmlThreadPrivate::event(QEvent *e) return QThread::event(e); } -void QQmlThreadPrivate::run() -{ - lock(); - - wakeOne(); - - unlock(); - - q->startupThread(); - exec(); - q->shutdownThread(); -} - void QQmlThreadPrivate::mainEvent() { lock(); @@ -185,13 +138,7 @@ void QQmlThreadPrivate::threadEvent() lock(); for (;;) { - if (m_shutdown) { - quit(); - wakeOne(); - unlock(); - - return; - } else if (!threadList.isEmpty()) { + if (!threadList.isEmpty()) { m_threadProcessing = true; QQmlThread::Message *message = threadList.first(); @@ -203,6 +150,12 @@ void QQmlThreadPrivate::threadEvent() lock(); delete threadList.takeFirst(); + } else if (m_shutdown) { + quit(); + wakeOne(); + unlock(); + + return; } else { wakeOne(); @@ -225,12 +178,13 @@ QQmlThread::~QQmlThread() delete d; } +/*! + \internal + Starts the actual worker thread. + */ void QQmlThread::startup() { - d->lock(); d->start(); - d->wait(); - d->unlock(); d->moveToThread(d); } @@ -239,28 +193,19 @@ void QQmlThread::shutdown() d->lock(); Q_ASSERT(!d->m_shutdown); - for (;;) { - if (d->mainSync || !d->mainList.isEmpty()) { - d->unlock(); - d->mainEvent(); - d->lock(); - } else if (!d->threadList.isEmpty()) { - d->wait(); - } else { - break; - } - } - d->m_shutdown = true; - if (QCoreApplication::closingDown()) { + + if (QCoreApplication::closingDown()) d->quit(); - } else { + else d->triggerThreadEvent(); - d->wait(); - } d->unlock(); d->QThread::wait(); + + // Discard all remaining messages. + // We don't need the lock anymore because the thread is dead. + discardMessages(); } bool QQmlThread::isShutdown() const @@ -288,11 +233,6 @@ void QQmlThread::wakeOne() d->wakeOne(); } -void QQmlThread::wakeAll() -{ - d->wakeAll(); -} - void QQmlThread::wait() { d->wait(); @@ -300,7 +240,7 @@ void QQmlThread::wait() bool QQmlThread::isThisThread() const { - return QThread::currentThread() == d; + return QThread::currentThreadId() == static_cast<QThreadPrivate *>(QObjectPrivate::get(d))->threadData.loadRelaxed()->threadId.loadRelaxed(); } QThread *QQmlThread::thread() const @@ -308,16 +248,6 @@ QThread *QQmlThread::thread() const return const_cast<QThread *>(static_cast<const QThread *>(d)); } -// Called when the thread starts. Do startup stuff in here. -void QQmlThread::startupThread() -{ -} - -// Called when the thread shuts down. Do cleanup in here. -void QQmlThread::shutdownThread() -{ -} - void QQmlThread::internalCallMethodInThread(Message *message) { #if !QT_CONFIG(thread) @@ -355,6 +285,13 @@ void QQmlThread::internalCallMethodInThread(Message *message) d->unlock(); } +/*! + \internal + \note This method needs to run in the worker/QQmlThread + + This runs \a message in the main thread, and blocks the + worker thread until the call has completed + */ void QQmlThread::internalCallMethodInMain(Message *message) { #if !QT_CONFIG(thread) @@ -418,12 +355,22 @@ void QQmlThread::internalPostMethodToMain(Message *message) d->unlock(); } +/*! + \internal + \note This method must be called in the main thread + \warning This method requires that the lock is held! + + A call to this method will either: + - run a message requested to run synchronously on the main thread if there is one + (and return afterrwards), + - wait for the worker thread to notify it if the worker thread has pending work, + - or simply return if neither of the conditions above hold + */ void QQmlThread::waitForNextMessage() { #if QT_CONFIG(thread) Q_ASSERT(!isThisThread()); #endif - d->lock(); Q_ASSERT(d->m_mainThreadWaiting == false); d->m_mainThreadWaiting = true; @@ -443,8 +390,24 @@ void QQmlThread::waitForNextMessage() } d->m_mainThreadWaiting = false; - d->unlock(); } +/*! + \internal + \note This method must be called in the main thread + \warning This method requires that the lock is held! + + Clear all pending events, for either thread. +*/ +void QQmlThread::discardMessages() +{ + Q_ASSERT(!isThisThread()); + if (Message *mainSync = std::exchange(d->mainSync, nullptr)) + delete mainSync; + while (!d->mainList.isEmpty()) + delete d->mainList.takeFirst(); + while (!d->threadList.isEmpty()) + delete d->threadList.takeFirst(); +} QT_END_NAMESPACE diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h index b5c580fe8b..35f586f7e7 100644 --- a/src/qml/qml/ftw/qqmlthread_p.h +++ b/src/qml/qml/ftw/qqmlthread_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QQMLTHREAD_P_H #define QQMLTHREAD_P_H @@ -76,51 +40,31 @@ public: void lock(); void unlock(); void wakeOne(); - void wakeAll(); void wait(); QThread *thread() const; bool isThisThread() const; // Synchronously invoke a method in the thread - template<class O> - inline void callMethodInThread(void (O::*Member)()); - template<typename T, class V, class O> - inline void callMethodInThread(void (O::*Member)(V), const T &); - template<typename T, typename T2, class V, class V2, class O> - inline void callMethodInThread(void (O::*Member)(V, V2), const T &, const T2 &); + template<typename Method, typename ...Args> + void callMethodInThread(Method &&method, Args &&...args); // Synchronously invoke a method in the main thread. If the main thread is // blocked in a callMethodInThread() call, the call is made from within that // call. - template<class O> - inline void callMethodInMain(void (O::*Member)()); - template<typename T, class V, class O> - inline void callMethodInMain(void (O::*Member)(V), const T &); - template<typename T, typename T2, class V, class V2, class O> - inline void callMethodInMain(void (O::*Member)(V, V2), const T &, const T2 &); + template<typename Method, typename ...Args> + void callMethodInMain(Method &&method, Args &&...args); // Asynchronously invoke a method in the thread. - template<class O> - inline void postMethodToThread(void (O::*Member)()); - template<typename T, class V, class O> - inline void postMethodToThread(void (O::*Member)(V), const T &); - template<typename T, typename T2, class V, class V2, class O> - inline void postMethodToThread(void (O::*Member)(V, V2), const T &, const T2 &); + template<typename Method, typename ...Args> + void postMethodToThread(Method &&method, Args &&...args); // Asynchronously invoke a method in the main thread. - template<class O> - inline void postMethodToMain(void (O::*Member)()); - template<typename T, class V, class O> - inline void postMethodToMain(void (O::*Member)(V), const T &); - template<typename T, typename T2, class V, class V2, class O> - inline void postMethodToMain(void (O::*Member)(V, V2), const T &, const T2 &); + template<typename Method, typename ...Args> + void postMethodToMain(Method &&method, Args &&...args); void waitForNextMessage(); - -protected: - virtual void startupThread(); - virtual void shutdownThread(); + void discardMessages(); private: friend class QQmlThreadPrivate; @@ -131,6 +75,8 @@ private: Message *next; virtual void call(QQmlThread *) = 0; }; + template<typename Method, typename ...Args> + Message *createMessageFromMethod(Method &&method, Args &&...args); void internalCallMethodInThread(Message *); void internalCallMethodInMain(Message *); void internalPostMethodToThread(Message *); @@ -138,184 +84,58 @@ private: QQmlThreadPrivate *d; }; -template<class O> -void QQmlThread::callMethodInThread(void (O::*Member)()) -{ - struct I : public Message { - void (O::*Member)(); - I(void (O::*Member)()) : Member(Member) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(); - } - }; - internalCallMethodInThread(new I(Member)); -} - -template<typename T, class V, class O> -void QQmlThread::callMethodInThread(void (O::*Member)(V), const T &arg) -{ - struct I : public Message { - void (O::*Member)(V); - T arg; - I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg); - } - }; - internalCallMethodInThread(new I(Member, arg)); -} - -template<typename T, typename T2, class V, class V2, class O> -void QQmlThread::callMethodInThread(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) -{ - struct I : public Message { - void (O::*Member)(V, V2); - T arg; - T2 arg2; - I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg, arg2); - } - }; - internalCallMethodInThread(new I(Member, arg, arg2)); -} - -template<class O> -void QQmlThread::callMethodInMain(void (O::*Member)()) -{ - struct I : public Message { - void (O::*Member)(); - I(void (O::*Member)()) : Member(Member) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(); - } - }; - internalCallMethodInMain(new I(Member)); -} +namespace QtPrivate { +template <typename> struct member_function_traits; -template<typename T, class V, class O> -void QQmlThread::callMethodInMain(void (O::*Member)(V), const T &arg) +template <typename Return, typename Object, typename... Args> +struct member_function_traits<Return (Object::*)(Args...)> { - struct I : public Message { - void (O::*Member)(V); - T arg; - I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg); - } - }; - internalCallMethodInMain(new I(Member, arg)); + using class_type = Object; +}; } -template<typename T, typename T2, class V, class V2, class O> -void QQmlThread::callMethodInMain(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) +template<typename Method, typename ...Args> +QQmlThread::Message *QQmlThread::createMessageFromMethod(Method &&method, Args &&...args) { struct I : public Message { - void (O::*Member)(V, V2); - T arg; - T2 arg2; - I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {} + Method m; + std::tuple<std::decay_t<Args>...> arguments; + I(Method &&method, Args&& ...args) : m(std::forward<Method>(method)), arguments(std::forward<Args>(args)...) {} void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg, arg2); + using class_type = typename QtPrivate::member_function_traits<Method>::class_type; + class_type *me = static_cast<class_type *>(thread); + std::apply(m, std::tuple_cat(std::make_tuple(me), arguments)); } }; - internalCallMethodInMain(new I(Member, arg, arg2)); + return new I(std::forward<Method>(method), std::forward<Args>(args)...); } -template<class O> -void QQmlThread::postMethodToThread(void (O::*Member)()) +template<typename Method, typename ...Args> +void QQmlThread::callMethodInMain(Method &&method, Args&& ...args) { - struct I : public Message { - void (O::*Member)(); - I(void (O::*Member)()) : Member(Member) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(); - } - }; - internalPostMethodToThread(new I(Member)); + Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...); + internalCallMethodInMain(m); } -template<typename T, class V, class O> -void QQmlThread::postMethodToThread(void (O::*Member)(V), const T &arg) +template<typename Method, typename ...Args> +void QQmlThread::callMethodInThread(Method &&method, Args&& ...args) { - struct I : public Message { - void (O::*Member)(V); - T arg; - I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg); - } - }; - internalPostMethodToThread(new I(Member, arg)); + Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...); + internalCallMethodInThread(m); } -template<typename T, typename T2, class V, class V2, class O> -void QQmlThread::postMethodToThread(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) +template<typename Method, typename ...Args> +void QQmlThread::postMethodToThread(Method &&method, Args&& ...args) { - struct I : public Message { - void (O::*Member)(V, V2); - T arg; - T2 arg2; - I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg, arg2); - } - }; - internalPostMethodToThread(new I(Member, arg, arg2)); + Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...); + internalPostMethodToThread(m); } -template<class O> -void QQmlThread::postMethodToMain(void (O::*Member)()) +template<typename Method, typename ...Args> +void QQmlThread::postMethodToMain(Method &&method, Args&& ...args) { - struct I : public Message { - void (O::*Member)(); - I(void (O::*Member)()) : Member(Member) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(); - } - }; - internalPostMethodToMain(new I(Member)); -} - -template<typename T, class V, class O> -void QQmlThread::postMethodToMain(void (O::*Member)(V), const T &arg) -{ - struct I : public Message { - void (O::*Member)(V); - T arg; - I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg); - } - }; - internalPostMethodToMain(new I(Member, arg)); -} - -template<typename T, typename T2, class V, class V2, class O> -void QQmlThread::postMethodToMain(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) -{ - struct I : public Message { - void (O::*Member)(V, V2); - T arg; - T2 arg2; - I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {} - void call(QQmlThread *thread) override { - O *me = static_cast<O *>(thread); - (me->*Member)(arg, arg2); - } - }; - internalPostMethodToMain(new I(Member, arg, arg2)); + Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...); + internalPostMethodToMain(m); } QT_END_NAMESPACE diff --git a/src/qml/qml/ftw/qrecursionwatcher_p.h b/src/qml/qml/ftw/qrecursionwatcher_p.h index 56b714f922..668695877e 100644 --- a/src/qml/qml/ftw/qrecursionwatcher_p.h +++ b/src/qml/qml/ftw/qrecursionwatcher_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QRECURSIONWATCHER_P_H #define QRECURSIONWATCHER_P_H @@ -51,7 +15,7 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/ftw/qrecyclepool_p.h b/src/qml/qml/ftw/qrecyclepool_p.h index 39f4f88512..6661c88631 100644 --- a/src/qml/qml/ftw/qrecyclepool_p.h +++ b/src/qml/qml/ftw/qrecyclepool_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QRECYCLEPOOL_P_H #define QRECYCLEPOOL_P_H @@ -51,6 +15,10 @@ // We mean it. // +#include <QtCore/private/qglobal_p.h> + +#include <QtCore/q20memory.h> + QT_BEGIN_NAMESPACE #define QRECYCLEPOOLCOOKIE 0x33218ADF @@ -101,11 +69,8 @@ public: inline QRecyclePool(); inline ~QRecyclePool(); - inline T *New(); - template<typename T1> - inline T *New(const T1 &); - template<typename T1> - inline T *New(T1 &); + template<typename...Args> + [[nodiscard]] inline T *New(Args&&...args); static inline void Delete(T *); @@ -127,29 +92,10 @@ QRecyclePool<T, Step>::~QRecyclePool() } template<typename T, int Step> -T *QRecyclePool<T, Step>::New() -{ - T *rv = d->allocate(); - new (rv) T; - return rv; -} - -template<typename T, int Step> -template<typename T1> -T *QRecyclePool<T, Step>::New(const T1 &a) +template<typename...Args> +T *QRecyclePool<T, Step>::New(Args&&...args) { - T *rv = d->allocate(); - new (rv) T(a); - return rv; -} - -template<typename T, int Step> -template<typename T1> -T *QRecyclePool<T, Step>::New(T1 &a) -{ - T *rv = d->allocate(); - new (rv) T(a); - return rv; + return q20::construct_at(d->allocate(), std::forward<Args>(args)...); } template<typename T, int Step> diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h index f9435b4919..c431a4d6b3 100644 --- a/src/qml/qml/ftw/qstringhash_p.h +++ b/src/qml/qml/ftw/qstringhash_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSTRINGHASH_P_H #define QSTRINGHASH_P_H @@ -54,25 +18,34 @@ #include <private/qhashedstring_p.h> #include <private/qprimefornumbits_p.h> -#include <QtCore/qglobal.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qstring.h> +#include <QtCore/qtaggedpointer.h> QT_BEGIN_NAMESPACE +static inline QString::DataPointer &mutableStringData(const QHashedString &key) +{ + return const_cast<QHashedString &>(key).data_ptr(); +} + class QStringHashData; class QStringHashNode { public: QStringHashNode() - : ckey(nullptr) { } QStringHashNode(const QHashedString &key) - : length(key.length()), hash(key.hash()), symbolId(0) + : length(int(key.size())), hash(key.hash()), symbolId(0) + , arrayData(mutableStringData(key).d_ptr()) + , strData(mutableStringData(key).data()) { - strData = const_cast<QHashedString &>(key).data_ptr(); + Q_ASSERT(key.size() <= std::numeric_limits<int>::max()); + if (arrayData) + arrayData->ref(); setQString(true); - strData->ref.ref(); } QStringHashNode(const QHashedCStringRef &key) @@ -81,49 +54,63 @@ public: } QStringHashNode(const QStringHashNode &o) - : length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey) + : length(o.length), hash(o.hash), symbolId(o.symbolId), arrayData(o.arrayData) { setQString(o.isQString()); - if (isQString()) { strData->ref.ref(); } + if (isQString()) { + strData = o.strData; + if (arrayData) + arrayData->ref(); + } else { + ckey = o.ckey; + } } ~QStringHashNode() { - if (isQString()) { if (!strData->ref.deref()) free(strData); } + if (isQString() && arrayData && !arrayData->deref()) + QTypedArrayData<char16_t>::deallocate(arrayData); } - QFlagPointer<QStringHashNode> next; + enum Tag { + NodeIsCString, + NodeIsQString + }; + + QTaggedPointer<QStringHashNode, Tag> next; qint32 length = 0; quint32 hash = 0; quint32 symbolId = 0; + QTypedArrayData<char16_t> *arrayData = nullptr; union { - const char *ckey; - QStringData *strData; + const char *ckey = nullptr; + char16_t *strData; }; inline QHashedString key() const { - if (isQString()) - return QHashedString(QString((QChar *)strData->data(), length), hash); + if (isQString()) { + if (arrayData) + arrayData->ref(); + return QHashedString(QString(QStringPrivate(arrayData, strData, length)), hash); + } return QHashedString(QString::fromLatin1(ckey, length), hash); } - bool isQString() const { return next.flag(); } - void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); } + bool isQString() const { return next.tag() == NodeIsQString; } + void setQString(bool v) { if (v) next.setTag(NodeIsQString); else next.setTag(NodeIsCString); } - inline char *cStrData() const { return (char *)ckey; } - inline quint16 *utf16Data() const { return (quint16 *)strData->data(); } + inline qsizetype size() const { return length; } + inline const char *cStrData() const { return ckey; } + inline const char16_t *utf16Data() const { return strData; } inline bool equals(const QV4::Value &string) const { QString s = string.toQStringNoThrow(); if (isQString()) { - QStringDataPtr dd; - dd.ptr = strData; - strData->ref.ref(); - return QString(dd) == s; + return QStringView(utf16Data(), length) == s; } else { return QLatin1String(cStrData(), length) == s; } @@ -133,10 +120,7 @@ public: if (length != string->d()->length() || hash != string->hashValue()) return false; if (isQString()) { - QStringDataPtr dd; - dd.ptr = strData; - strData->ref.ref(); - return QString(dd) == string->toQString(); + return QStringView(utf16Data(), length) == string->toQString(); } else { return QLatin1String(cStrData(), length) == string->toQString(); } @@ -145,7 +129,7 @@ public: inline bool equals(const QHashedStringRef &string) const { return length == string.length() && hash == string.hash() && - (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length): + (isQString()? string == QStringView {utf16Data(), length}: QHashedString::compare(string.constData(), cStrData(), length)); } @@ -237,7 +221,7 @@ template<typename T> struct HashedForm {}; template<> struct HashedForm<QString> { typedef QHashedString Type; }; -template<> struct HashedForm<QStringRef> { typedef QHashedStringRef Type; }; +template<> struct HashedForm<QStringView> { typedef QHashedStringRef Type; }; template<> struct HashedForm<QHashedString> { typedef const QHashedString &Type; }; template<> struct HashedForm<QV4::String *> { typedef const QV4::String *Type; }; template<> struct HashedForm<const QV4::String *> { typedef const QV4::String *Type; }; @@ -249,13 +233,21 @@ class QStringHashBase { public: static HashedForm<QString>::Type hashedString(const QString &s) { return QHashedString(s);} - static HashedForm<QStringRef>::Type hashedString(const QStringRef &s) { return QHashedStringRef(s.constData(), s.size());} + static HashedForm<QStringView>::Type hashedString(QStringView s) + { + Q_ASSERT(s.size() <= std::numeric_limits<int>::max()); + return QHashedStringRef(s.constData(), int(s.size())); + } static HashedForm<QHashedString>::Type hashedString(const QHashedString &s) { return s; } static HashedForm<QV4::String *>::Type hashedString(QV4::String *s) { return s; } static HashedForm<const QV4::String *>::Type hashedString(const QV4::String *s) { return s; } static HashedForm<QHashedStringRef>::Type hashedString(const QHashedStringRef &s) { return s; } - static HashedForm<QLatin1String>::Type hashedString(const QLatin1String &s) { return QHashedCStringRef(s.data(), s.size()); } + static HashedForm<QLatin1StringView>::Type hashedString(QLatin1StringView s) + { + Q_ASSERT(s.size() <= std::numeric_limits<int>::max()); + return QHashedCStringRef(s.data(), int(s.size())); + } static HashedForm<QHashedCStringRef>::Type hashedString(const QHashedCStringRef &s) { return s; } static const QString &toQString(const QString &s) { return s; } @@ -508,10 +500,12 @@ int QStringHash<T>::numBuckets() const template<class T> void QStringHash<T>::initializeNode(Node *node, const QHashedString &key) { - node->length = key.length(); + node->length = key.size(); node->hash = key.hash(); - node->strData = const_cast<QHashedString &>(key).data_ptr(); - node->strData->ref.ref(); + node->arrayData = mutableStringData(key).d_ptr(); + node->strData = mutableStringData(key).data(); + if (node->arrayData) + node->arrayData->ref(); node->setQString(true); } @@ -547,10 +541,12 @@ typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o) Node *rv = nodePool->nodes + nodePool->used++; rv->length = o.length; rv->hash = o.hash; + rv->arrayData = o.arrayData; if (o.isQString()) { rv->strData = o.strData; - rv->strData->ref.ref(); rv->setQString(true); + if (rv->arrayData) + rv->arrayData->ref(); } else { rv->ckey = o.ckey; } @@ -700,7 +696,7 @@ typename QStringHash<T>::Node *QStringHash<T>::findNode(const K &key) const typename HashedForm<K>::Type hashedKey(hashedString(key)); while (node && !node->equals(hashedKey)) - node = (*node->next); + node = node->next.data(); return (Node *)node; } |