diff options
Diffstat (limited to 'src/corelib')
100 files changed, 1537 insertions, 1789 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 9d7a256191..e37f9a0271 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -152,6 +152,7 @@ #include <QtCore/qthreadstorage.h> #include <QtCore/qcoreevent.h> #include <QtCore/qpointer.h> +#include <QtCore/qscopedvaluerollback.h> #define DEFAULT_TIMER_INTERVAL 16 #define PAUSE_TIMER_COARSE_THRESHOLD 2000 @@ -315,14 +316,13 @@ void QUnifiedTimer::updateAnimationTimers(qint64 currentTick) //* it might happen in some cases that the delta is negative because the animation driver // advances faster than time.elapsed() if (delta > 0) { - insideTick = true; + QScopedValueRollback<bool> guard(insideTick, true); if (profilerCallback) profilerCallback(delta); for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.count(); ++currentAnimationIdx) { QAbstractAnimationTimer *animation = animationTimers.at(currentAnimationIdx); animation->updateAnimationsTime(delta); } - insideTick = false; currentAnimationIdx = 0; } } @@ -361,10 +361,11 @@ void QUnifiedTimer::localRestart() void QUnifiedTimer::restart() { - insideRestart = true; - for (int i = 0; i < animationTimers.count(); ++i) - animationTimers.at(i)->restartAnimationTimer(); - insideRestart = false; + { + QScopedValueRollback<bool> guard(insideRestart, true); + for (int i = 0; i < animationTimers.count(); ++i) + animationTimers.at(i)->restartAnimationTimer(); + } localRestart(); } @@ -599,14 +600,13 @@ void QAnimationTimer::updateAnimationsTime(qint64 delta) //it might happen in some cases that the time doesn't change because events are delayed //when the CPU load is high if (delta) { - insideTick = true; + QScopedValueRollback<bool> guard(insideTick, true); for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) { QAbstractAnimation *animation = animations.at(currentAnimationIdx); int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta); animation->setCurrentTime(elapsed); } - insideTick = false; currentAnimationIdx = 0; } } diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 3b6e8d6cc4..037d3be74f 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -78,7 +78,7 @@ public: hasRegisteredTimer(false), isPause(false), isGroup(false), - group(0) + group(nullptr) { } diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h index ff759d11fd..215734b656 100644 --- a/src/corelib/animation/qanimationgroup_p.h +++ b/src/corelib/animation/qanimationgroup_p.h @@ -76,7 +76,7 @@ public: void disconnectUncontrolledAnimation(QAbstractAnimation *anim) { //0 for the signal here because we might be called from the animation destructor - QObject::disconnect(anim, 0, q_func(), SLOT(_q_uncontrolledAnimationFinished())); + QObject::disconnect(anim, nullptr, q_func(), SLOT(_q_uncontrolledAnimationFinished())); } void connectUncontrolledAnimation(QAbstractAnimation *anim) diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h index 479762f573..cbd3ce287d 100644 --- a/src/corelib/animation/qpropertyanimation_p.h +++ b/src/corelib/animation/qpropertyanimation_p.h @@ -64,7 +64,7 @@ class QPropertyAnimationPrivate : public QVariantAnimationPrivate Q_DECLARE_PUBLIC(QPropertyAnimation) public: QPropertyAnimationPrivate() - : targetValue(0), propertyType(0), propertyIndex(-1) + : targetValue(nullptr), propertyType(0), propertyIndex(-1) { } diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h index 88dac4f566..c082d6b524 100644 --- a/src/corelib/animation/qsequentialanimationgroup_p.h +++ b/src/corelib/animation/qsequentialanimationgroup_p.h @@ -63,7 +63,7 @@ class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate Q_DECLARE_PUBLIC(QSequentialAnimationGroup) public: QSequentialAnimationGroupPrivate() - : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0) + : currentAnimation(nullptr), currentAnimationIndex(-1), lastLoop(0) { } diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h index 0e449d994c..7fcf6df984 100644 --- a/src/corelib/codecs/qtextcodec_p.h +++ b/src/corelib/codecs/qtextcodec_p.h @@ -98,7 +98,7 @@ public: struct ConverterState { ConverterState(ConversionFlags f = DefaultConversion) - : flags(f), remainingChars(0), invalidChars(0), d(0) { state_data[0] = state_data[1] = state_data[2] = 0; } + : flags(f), remainingChars(0), invalidChars(0), d(nullptr) { state_data[0] = state_data[1] = state_data[2] = 0; } ~ConverterState() { } ConversionFlags flags; int remainingChars; diff --git a/src/corelib/configure.json b/src/corelib/configure.json index b7eefb58c8..a6091d4825 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -12,7 +12,7 @@ "inotify": "boolean", "journald": "boolean", "mimetype-database": "boolean", - "pcre": { "type": "enum", "values": [ "qt", "system" ] }, + "pcre": { "type": "enum", "values": [ "no", "qt", "system" ] }, "posix-ipc": { "type": "boolean", "name": "ipc_posix" }, "pps": { "type": "boolean", "name": "qqnx_pps" }, "slog2": "boolean", @@ -684,15 +684,18 @@ "condition": "features.mimetype", "output": [ "privateFeature" ] }, + "pcre2": { + "label": "PCRE2", + "disable": "input.pcre == 'no' || input.pcre == 'system'", + "enable": "input.pcre == 'qt'", + "output": [ "privateConfig" ] + }, "system-pcre2": { - "label": "Using system PCRE2", - "disable": "input.pcre == 'qt'", + "label": " Using system PCRE2", + "disable": "input.pcre == 'no' || input.pcre == 'qt'", "enable": "input.pcre == 'system'", "condition": "libs.pcre2", - "output": [ - "privateFeature", - { "type": "privateConfig", "negative": true, "name": "pcre2" } - ] + "output": [ "privateFeature" ] }, "poll_ppoll": { "label": "Native ppoll()", @@ -771,6 +774,7 @@ "label": "QRegularExpression", "purpose": "Provides an API to Perl-compatible regular expressions.", "section": "Kernel", + "condition": "features.system-pcre2 || features.pcre2", "output": [ "publicFeature", "feature" ] }, "sharedmemory": { @@ -1071,6 +1075,7 @@ Please apply the patch corresponding to your Standard Library vendor, found in "args": "qqnx_pps", "condition": "config.qnx" }, + "pcre2", "system-pcre2" ] } diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 4b758532e6..dc43e56836 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -68,8 +68,6 @@ integrity { QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtCore.dynlist -contains(DEFINES,QT_EVAL):include(eval.pri) - HOST_BINS = $$[QT_HOST_BINS] host_bins.name = host_bins host_bins.variable = HOST_BINS diff --git a/src/corelib/eval.pri b/src/corelib/eval.pri deleted file mode 100644 index efda56b16a..0000000000 --- a/src/corelib/eval.pri +++ /dev/null @@ -1,4 +0,0 @@ -SOURCES += \ - $$QT_SOURCE_TREE/src/corelib/kernel/qtcore_eval.cpp -INCLUDEPATH += \ - $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 029357ff43..428c674307 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -12,7 +12,6 @@ HEADERS += \ global/qendian_p.h \ global/qnumeric_p.h \ global/qnumeric.h \ - global/qfloat16_p.h \ global/qfloat16.h \ global/qglobalstatic.h \ global/qlibraryinfo.h \ diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index fd608efe55..110d7c4d7c 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "qfloat16_p.h" +#include "qfloat16.h" #include "private/qsimd_p.h" QT_BEGIN_NAMESPACE @@ -65,28 +65,31 @@ QT_BEGIN_NAMESPACE */ /*! - Returns true if the \c qfloat16 \a {f} is equivalent to infinity. + \fn bool qIsInf(qfloat16 f) \relates <QFloat16> + Returns true if the \c qfloat16 \a {f} is equivalent to infinity. + \sa qIsInf */ -Q_REQUIRED_RESULT bool qIsInf(qfloat16 f) Q_DECL_NOTHROW { return qt_is_inf(f); } /*! - Returns true if the \c qfloat16 \a {f} is not a number (NaN). + \fn bool qIsNaN(qfloat16 f) \relates <QFloat16> + Returns true if the \c qfloat16 \a {f} is not a number (NaN). + \sa qIsNaN */ -Q_REQUIRED_RESULT bool qIsNaN(qfloat16 f) Q_DECL_NOTHROW { return qt_is_nan(f); } /*! - Returns true if the \c qfloat16 \a {f} is a finite number. + \fn bool qIsFinite(qfloat16 f) \relates <QFloat16> + Returns true if the \c qfloat16 \a {f} is a finite number. + \sa qIsFinite */ -Q_REQUIRED_RESULT bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW { return qt_is_finite(f); } /*! \fn int qRound(qfloat16 value) \relates <QFloat16> diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 42cb1357f1..e823d0298b 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -67,10 +67,14 @@ QT_BEGIN_NAMESPACE class qfloat16 { public: - Q_DECL_CONSTEXPR inline qfloat16() Q_DECL_NOTHROW : b16(0) { } + constexpr inline qfloat16() Q_DECL_NOTHROW : b16(0) {} inline qfloat16(float f) Q_DECL_NOTHROW; inline operator float() const Q_DECL_NOTHROW; + // Support for qIs{Inf,NaN,Finite}: + bool isInf() const Q_DECL_NOTHROW { return ((b16 >> 8) & 0x7e) == 0x7c; } + bool isNaN() const Q_DECL_NOTHROW { return ((b16 >> 8) & 0x7e) == 0x7e; } + bool isFinite() const Q_DECL_NOTHROW { return ((b16 >> 8) & 0x7c) != 0x7c; } private: quint16 b16; @@ -89,9 +93,11 @@ Q_DECLARE_TYPEINFO(qfloat16, Q_PRIMITIVE_TYPE); Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *, const float *, qsizetype length) Q_DECL_NOTHROW; Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length) Q_DECL_NOTHROW; -Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsInf(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h -Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsNaN(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h -Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h +// Complement qnumeric.h: +Q_REQUIRED_RESULT inline bool qIsInf(qfloat16 f) Q_DECL_NOTHROW { return f.isInf(); } +Q_REQUIRED_RESULT inline bool qIsNaN(qfloat16 f) Q_DECL_NOTHROW { return f.isNaN(); } +Q_REQUIRED_RESULT inline bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW { return f.isFinite(); } +// Q_REQUIRED_RESULT quint32 qFloatDistance(qfloat16 a, qfloat16 b); // The remainder of these utility functions complement qglobal.h Q_REQUIRED_RESULT inline int qRound(qfloat16 d) Q_DECL_NOTHROW diff --git a/src/corelib/global/qfloat16_p.h b/src/corelib/global/qfloat16_p.h deleted file mode 100644 index f3fc96e119..0000000000 --- a/src/corelib/global/qfloat16_p.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 by Southwest Research Institute (R) -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore 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 QFLOAT16_P_H -#define QFLOAT16_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/qfloat16.h> -#include <QtCore/qsysinfo.h> - -QT_BEGIN_NAMESPACE - -static inline bool qt_is_inf(qfloat16 d) Q_DECL_NOTHROW -{ - bool is_inf; - uchar *ch = (uchar *)&d; - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - is_inf = (ch[0] & 0x7c) == 0x7c && (ch[0] & 0x02) == 0; - else - is_inf = (ch[1] & 0x7c) == 0x7c && (ch[1] & 0x02) == 0; - return is_inf; -} - -static inline bool qt_is_nan(qfloat16 d) Q_DECL_NOTHROW -{ - bool is_nan; - uchar *ch = (uchar *)&d; - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - is_nan = (ch[0] & 0x7c) == 0x7c && (ch[0] & 0x02) != 0; - else - is_nan = (ch[1] & 0x7c) == 0x7c && (ch[1] & 0x02) != 0; - return is_nan; -} - -static inline bool qt_is_finite(qfloat16 d) Q_DECL_NOTHROW -{ - bool is_finite; - uchar *ch = (uchar *)&d; - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - is_finite = (ch[0] & 0x7c) != 0x7c; - else - is_finite = (ch[1] & 0x7c) != 0x7c; - return is_finite; -} - - -QT_END_NAMESPACE - -#endif // QFLOAT16_P_H diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h index 555bdf04c1..93d71cee57 100644 --- a/src/corelib/global/qglobalstatic.h +++ b/src/corelib/global/qglobalstatic.h @@ -131,8 +131,8 @@ struct QGlobalStatic bool isDestroyed() const { return guard.load() <= QtGlobalStatic::Destroyed; } bool exists() const { return guard.load() == QtGlobalStatic::Initialized; } - operator Type *() { if (isDestroyed()) return 0; return innerFunction(); } - Type *operator()() { if (isDestroyed()) return 0; return innerFunction(); } + operator Type *() { if (isDestroyed()) return nullptr; return innerFunction(); } + Type *operator()() { if (isDestroyed()) return nullptr; return innerFunction(); } Type *operator->() { Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed"); diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp index bbddb1cbf1..020dee3710 100644 --- a/src/corelib/global/qhooks.cpp +++ b/src/corelib/global/qhooks.cpp @@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = { // The required sizes and offsets are tested in tests/auto/other/toolsupport. // When this fails and the change was intentional, adjust the test and // adjust this value here. - 16 + 17 }; Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0])); diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 4119012d85..88cc5b0b01 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -717,11 +717,6 @@ void qt_core_boilerplate() QT_PREPEND_NAMESPACE(qDumpCPUFeatures)(); -#ifdef QT_EVAL - extern void qt_core_eval_init(QCoreApplicationPrivate::Type); - qt_core_eval_init(QCoreApplicationPrivate::Tty); -#endif - exit(0); } diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index fc2b052edf..e6ba62f530 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE /*! Returns \c true if the double \a {d} is equivalent to infinity. \relates <QtGlobal> + \sa qInf() */ Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); } @@ -64,6 +65,7 @@ Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); } /*! Returns \c true if the float \a {f} is equivalent to infinity. \relates <QtGlobal> + \sa qInf() */ Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); } @@ -88,15 +90,36 @@ Q_CORE_EXPORT double qSNaN() { return qt_snan(); } /*! Returns the bit pattern of a quiet NaN as a double. \relates <QtGlobal> + \sa qIsNaN() */ Q_CORE_EXPORT double qQNaN() { return qt_qnan(); } /*! Returns the bit pattern for an infinite number as a double. \relates <QtGlobal> + \sa qIsInf() */ Q_CORE_EXPORT double qInf() { return qt_inf(); } +/*! + \relates <QtGlobal> + Classifies a floating-point value. + + The return values are defined in \c{<cmath>}: returns one of the following, + determined by the floating-point class of \a val: + \list + \li FP_NAN not a number + \li FP_INFINITE infinities (positive or negative) + \li FP_NORMAL finite with a full mantissa + \li FP_SUBNORMAL finite with a reduced mantissa + \endlist +*/ +Q_CORE_EXPORT int qFpClassify(double val) { return qt_fpclassify(val); } + +/*! + \overload +*/ +Q_CORE_EXPORT int qFpClassify(float val) { return qt_fpclassify(val); } /*! diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 535a96aaec..6a0c64712f 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -48,9 +48,11 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d); +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(double val); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f); +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN(); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN(); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf(); diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 4a225b2599..56e670c477 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -85,9 +85,11 @@ namespace qnumeric_std_wrapper { Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); } Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); } Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); } +Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(double d) { using namespace std; return fpclassify(d); } Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); } Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); } Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); } +Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(float f) { using namespace std; return fpclassify(f); } } QT_END_NAMESPACE // These macros from math.h conflict with the real functions in the std namespace. @@ -95,6 +97,7 @@ QT_END_NAMESPACE # undef isnan # undef isinf # undef isfinite +# undef fpclassify # endif // defined(isnan) #endif @@ -106,16 +109,20 @@ namespace qnumeric_std_wrapper { Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); } Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); } Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); } +Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return math_h_fpclassify(d); } Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); } Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); } Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); } +Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return math_h_fpclassify(f); } #else Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); } Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); } Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); } +Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return std::fpclassify(d); } Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); } Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); } Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); } +Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return std::fpclassify(f); } #endif } @@ -157,6 +164,11 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d) return qnumeric_std_wrapper::isfinite(d); } +Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(double d) +{ + return qnumeric_std_wrapper::fpclassify(d); +} + Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f) { return qnumeric_std_wrapper::isinf(f); @@ -172,6 +184,11 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f) return qnumeric_std_wrapper::isfinite(f); } +Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(float f) +{ + return qnumeric_std_wrapper::fpclassify(f); +} + #ifndef Q_CLANG_QDOC namespace { /*! diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 6195c324e7..90df8653a7 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -930,7 +930,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn quint32 QRandomGenerator::bounded(int highest) + \fn int QRandomGenerator::bounded(int highest) \overload Generates one random 32-bit quantity in the range between 0 (inclusive) and @@ -957,7 +957,6 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel \snippet code/src_corelib_global_qrandom.cpp 14 - Note that this function cannot be used to obtain values in the full 32-bit range of quint32. Instead, use generate(). @@ -965,7 +964,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn quint32 QRandomGenerator::bounded(int lowest, int highest) + \fn int QRandomGenerator::bounded(int lowest, int highest) \overload Generates one random 32-bit quantity in the range between \a lowest diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h index 3d04a7311d..56d1f9a318 100644 --- a/src/corelib/global/qtrace_p.h +++ b/src/corelib/global/qtrace_p.h @@ -114,10 +114,12 @@ QT_BEGIN_NAMESPACE #if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) +# define Q_HAS_TRACEPOINTS 1 # define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__) # define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__) # define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled() #else +# define Q_HAS_TRACEPOINTS 0 # define Q_TRACE(x, ...) # define Q_UNCONDITIONAL_TRACE(x, ...) # define Q_TRACE_ENABLED(x) false diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index 4a7fe7bff5..c88b66c7ce 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -193,7 +193,7 @@ public: uchar *address; }; - virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0); + virtual bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr); virtual bool supportsExtension(Extension extension) const; // Factory diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h index e4b28f4519..36f440812f 100644 --- a/src/corelib/io/qfileinfo_p.h +++ b/src/corelib/io/qfileinfo_p.h @@ -80,7 +80,7 @@ public: }; inline QFileInfoPrivate() - : QSharedData(), fileEngine(0), + : QSharedData(), fileEngine(nullptr), cachedFlags(0), isDefaultConstructed(true), cache_enabled(true), fileFlags(0), fileSize(0) diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h index 09ec2d6a10..e44837747c 100644 --- a/src/corelib/io/qfilesystemengine_p.h +++ b/src/corelib/io/qfilesystemengine_p.h @@ -130,7 +130,7 @@ public: static bool removeFile(const QFileSystemEntry &entry, QSystemError &error); static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, - QFileSystemMetaData *data = 0); + QFileSystemMetaData *data = nullptr); // unused, therefore not implemented static bool setFileTime(const QFileSystemEntry &entry, const QDateTime &newDate, diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index 4d2a5acb9b..81f4b3ba13 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -76,7 +76,7 @@ class Q_AUTOTEST_EXPORT QFileSystemMetaData { public: QFileSystemMetaData() - : knownFlagsMask(0), + : knownFlagsMask(nullptr), size_(-1) { } @@ -184,7 +184,7 @@ public: void clear() { - knownFlagsMask = 0; + knownFlagsMask = nullptr; } void clearFlags(MetaDataFlags flags = AllMetaDataFlags) diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 66985f8982..7f4f9d345b 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -108,7 +108,11 @@ public: // Call from QFileSystemWatcher::addPaths() to set up notifications on drives void addPath(const QString &path); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool nativeEventFilter(const QByteArray &, void *messageIn, qintptr *) override; +#else bool nativeEventFilter(const QByteArray &, void *messageIn, long *) override; +#endif signals: void driveAdded(); @@ -255,7 +259,11 @@ inline void QWindowsRemovableDriveListener::handleDbtDriveArrivalRemoval(const M } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, qintptr *) +#else bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, long *) +#endif { const MSG *msg = reinterpret_cast<const MSG *>(messageIn); if (msg->message == WM_DEVICECHANGE) { diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 6b091a8eef..0f416f4886 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -115,7 +115,7 @@ public: virtual bool isUnnamedFile() const { return false; } - bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) override; + bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr) override; bool supportsExtension(Extension extension) const override; //FS only!! diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index d5d67d86f3..c7635cc7b4 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -42,6 +42,7 @@ #include <qdebug.h> #include <qdir.h> +#include <qscopedvaluerollback.h> #if defined(Q_OS_WIN) #include <qtimer.h> #endif @@ -1062,9 +1063,8 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel) if (currentReadChannel == channelIdx) { didRead = true; if (!emittedReadyRead) { - emittedReadyRead = true; + QScopedValueRollback<bool> guard(emittedReadyRead, true); emit q->readyRead(); - emittedReadyRead = false; } } emit q->channelReadyRead(int(channelIdx)); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index aa7ecbe91d..1bc63240fe 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -247,7 +247,7 @@ public: // if you add "= 4" here, increase the number of bits below }; - Channel() : process(0), notifier(0), type(Normal), closed(false), append(false) + Channel() : process(nullptr), notifier(nullptr), type(Normal), closed(false), append(false) { pipe[0] = INVALID_Q_PIPE; pipe[1] = INVALID_Q_PIPE; diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h index 7451de8809..fedf95bb33 100644 --- a/src/corelib/io/qresource_p.h +++ b/src/corelib/io/qresource_p.h @@ -108,7 +108,7 @@ public: Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override; Iterator *endEntryList() override; - bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) override; + bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr) override; bool supportsExtension(Extension extension) const override; }; diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h index 1b9237e58a..e75de32e03 100644 --- a/src/corelib/io/qurl_p.h +++ b/src/corelib/io/qurl_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE // in qurlrecode.cpp extern Q_AUTOTEST_EXPORT int qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end, - QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications = 0); + QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications = nullptr); // in qurlidna.cpp enum AceLeadingDot { AllowLeadingDot, ForbidLeadingDot }; diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 15c9f52cf3..1f03ac5d5a 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -40,6 +40,7 @@ #include "qwindowspipereader_p.h" #include "qiodevice_p.h" #include <qelapsedtimer.h> +#include <qscopedvaluerollback.h> QT_BEGIN_NAMESPACE @@ -301,9 +302,8 @@ void QWindowsPipeReader::emitPendingReadyRead() { if (readyReadPending) { readyReadPending = false; - inReadyRead = true; + QScopedValueRollback<bool> guard(inReadyRead, true); emit readyRead(); - inReadyRead = false; } } diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 92e8b6db52..32536f495b 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -39,6 +39,7 @@ #include "qwindowspipewriter_p.h" #include "qiodevice_p.h" +#include <qscopedvaluerollback.h> QT_BEGIN_NAMESPACE @@ -111,9 +112,8 @@ void QWindowsPipeWriter::emitPendingBytesWrittenValue() emit canWrite(); if (!inBytesWritten) { - inBytesWritten = true; + QScopedValueRollback<bool> guard(inBytesWritten, true); emit bytesWritten(bytes); - inBytesWritten = false; } } } diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h index e6085eca94..92a440a125 100644 --- a/src/corelib/itemmodels/qabstractitemmodel_p.h +++ b/src/corelib/itemmodels/qabstractitemmodel_p.h @@ -98,7 +98,7 @@ public: void itemsMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation); bool allowMove(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation); - inline QModelIndex createIndex(int row, int column, void *data = 0) const { + inline QModelIndex createIndex(int row, int column, void *data = nullptr) const { return q_func()->createIndex(row, column, data); } diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h index f7bd5cc691..a95687c970 100644 --- a/src/corelib/itemmodels/qabstractproxymodel_p.h +++ b/src/corelib/itemmodels/qabstractproxymodel_p.h @@ -62,7 +62,7 @@ class Q_CORE_EXPORT QAbstractProxyModelPrivate : public QAbstractItemModelPrivat { Q_DECLARE_PUBLIC(QAbstractProxyModel) public: - QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(0) {} + QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(nullptr) {} QAbstractItemModel *model; virtual void _q_sourceModelDestroyed(); void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, diff --git a/src/corelib/itemmodels/qitemselectionmodel_p.h b/src/corelib/itemmodels/qitemselectionmodel_p.h index e12a0c2928..ba85f22be3 100644 --- a/src/corelib/itemmodels/qitemselectionmodel_p.h +++ b/src/corelib/itemmodels/qitemselectionmodel_p.h @@ -62,7 +62,7 @@ class QItemSelectionModelPrivate: public QObjectPrivate Q_DECLARE_PUBLIC(QItemSelectionModel) public: QItemSelectionModelPrivate() - : model(0), + : model(nullptr), currentCommand(QItemSelectionModel::NoUpdate), tableSelected(false), tableColCount(0), tableRowCount(0) {} diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 3f7bf3cd47..789bcb7927 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -7,7 +7,7 @@ HEADERS += \ kernel/qdeadlinetimer.h \ kernel/qdeadlinetimer_p.h \ kernel/qelapsedtimer.h \ - kernel/qeventloop.h\ + kernel/qeventloop.h \ kernel/qpointer.h \ kernel/qcorecmdlineargs_p.h \ kernel/qcoreapplication.h \ diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index 8e1b560874..0ecfc7a8c7 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -470,7 +470,11 @@ void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilte \sa installNativeEventFilter(), QAbstractNativeEventFilter::nativeEventFilter() \since 5.0 */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result) +#else bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result) +#endif { Q_D(QAbstractEventDispatcher); if (!d->eventFilters.isEmpty()) { diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index bd8da5c35d..4ef9c068df 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -110,7 +110,11 @@ public: void installNativeEventFilter(QAbstractNativeEventFilter *filterObj); void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result); +#else bool filterNativeEvent(const QByteArray &eventType, void *message, long *result); +#endif #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED bool filterEvent(void *message) { return filterNativeEvent("", message, nullptr); } diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp index dcbb92f044..eaadea4c12 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.cpp +++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp @@ -74,6 +74,7 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter() eventDispatcher->removeNativeEventFilter(this); } +// ### fixme Qt 6: result will be qintptr * /*! \fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) diff --git a/src/corelib/kernel/qabstractnativeeventfilter.h b/src/corelib/kernel/qabstractnativeeventfilter.h index d7baa42513..a468bffd61 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.h +++ b/src/corelib/kernel/qabstractnativeeventfilter.h @@ -52,7 +52,11 @@ public: QAbstractNativeEventFilter(); virtual ~QAbstractNativeEventFilter(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) = 0; +#else virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0; +#endif private: Q_DISABLE_COPY(QAbstractNativeEventFilter) diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 5a2a29a327..32ef6408c2 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -171,7 +171,7 @@ inline void qt_ignore_sigpipe() struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); + ::sigaction(SIGPIPE, &noaction, nullptr); atom.store(1); } } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c06af79cc7..5da33a5aae 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -256,15 +256,6 @@ void QCoreApplicationPrivate::processCommandLineArguments() // Support for introspection -#ifndef QT_NO_QOBJECT -QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 }; - -void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set) -{ - qt_signal_spy_callback_set = callback_set; -} -#endif - extern "C" void Q_CORE_EXPORT qt_startup_hook() { } @@ -866,11 +857,6 @@ void QCoreApplicationPrivate::init() eventDispatcherReady(); #endif -#ifdef QT_EVAL - extern void qt_core_eval_init(QCoreApplicationPrivate::Type); - qt_core_eval_init(application_type); -#endif - processCommandLineArguments(); qt_call_pre_routines(); diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index b3479414ab..14ca3efd7f 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -149,7 +149,7 @@ public: QString cachedApplicationDirPath; static QString *cachedApplicationFilePath; static void setApplicationFilePath(const QString &path); - static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; } + static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = nullptr; } #ifndef QT_NO_QOBJECT void execCleanup(); diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 88ff316ee5..313825d0a7 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -66,8 +66,8 @@ class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher Q_DECLARE_PRIVATE(QEventDispatcherGlib) public: - explicit QEventDispatcherGlib(QObject *parent = 0); - explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = 0); + explicit QEventDispatcherGlib(QObject *parent = nullptr); + explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = nullptr); ~QEventDispatcherGlib(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; @@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatche { public: - QEventDispatcherGlibPrivate(GMainContext *context = 0); + QEventDispatcherGlibPrivate(GMainContext *context = nullptr); GMainContext *mainContext; GPostEventSource *postEventSource; GSocketNotifierSource *socketNotifierSource; diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 0fd068b074..8cfa4bbdf7 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher Q_DECLARE_PRIVATE(QEventDispatcherUNIX) public: - explicit QEventDispatcherUNIX(QObject *parent = 0); + explicit QEventDispatcherUNIX(QObject *parent = nullptr); ~QEventDispatcherUNIX(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; @@ -123,7 +123,7 @@ public: void flush() override; protected: - QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0); + QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = nullptr); }; class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate @@ -152,9 +152,9 @@ public: inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW { - notifiers[0] = 0; - notifiers[1] = 0; - notifiers[2] = 0; + notifiers[0] = nullptr; + notifiers[1] = nullptr; + notifiers[2] = nullptr; } inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 685d765adb..84378454ca 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -136,7 +136,11 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA msg.wParam = wp; msg.lParam = lp; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + qintptr result; +#else long result; +#endif if (!dispatcher) { if (message == WM_TIMER) KillTimer(hwnd, wp); diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h index ad258acfcd..8c7900767b 100644 --- a/src/corelib/kernel/qmetaobject_moc_p.h +++ b/src/corelib/kernel/qmetaobject_moc_p.h @@ -138,7 +138,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc { "struct ", 7 }, { "class ", 6 }, { "enum ", 5 }, - { 0, 0 } + { nullptr, 0 } }; int i = 0; do { @@ -146,7 +146,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc t += optional[i].len; break; } - } while (optional[++i].keyword != 0); + } while (optional[++i].keyword != nullptr); } bool star = false; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 522bd78e42..0cd9da2eac 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -54,6 +54,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qobjectdefs.h> +#include <QtCore/qmutex.h> #ifndef QT_NO_QOBJECT #include <private/qobject_p.h> // For QObjectPrivate::Connection #endif @@ -168,7 +169,6 @@ Q_DECLARE_TYPEINFO(QArgumentType, Q_MOVABLE_TYPE); typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray; class QMetaMethodPrivate; -class QMutex; struct QMetaObjectPrivate { @@ -226,15 +226,15 @@ struct QMetaObjectPrivate static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index_relative, - const QMetaObject *rmeta = 0, - int type = 0, int *types = 0); + const QMetaObject *rmeta = nullptr, + int type = 0, int *types = nullptr); static bool disconnect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index, void **slot, DisconnectType = DisconnectAll); - static inline bool disconnectHelper(QObjectPrivate::Connection *c, + static inline bool disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex, const QObject *receiver, int method_index, void **slot, - QMutex *senderMutex, DisconnectType = DisconnectAll); + QBasicMutex *senderMutex, DisconnectType = DisconnectAll); #endif }; diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index 6100835bad..6d43be7811 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -173,7 +173,7 @@ public: void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value); QMetaObject *toMetaObject() const; - QByteArray toRelocatableData(bool * = 0) const; + QByteArray toRelocatableData(bool * = nullptr) const; static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &); #ifndef QT_NO_DATASTREAM @@ -196,7 +196,7 @@ private: class Q_CORE_EXPORT QMetaMethodBuilder { public: - QMetaMethodBuilder() : _mobj(0), _index(0) {} + QMetaMethodBuilder() : _mobj(nullptr), _index(0) {} int index() const; @@ -238,7 +238,7 @@ private: class Q_CORE_EXPORT QMetaPropertyBuilder { public: - QMetaPropertyBuilder() : _mobj(0), _index(0) {} + QMetaPropertyBuilder() : _mobj(nullptr), _index(0) {} int index() const { return _index; } @@ -294,7 +294,7 @@ private: class Q_CORE_EXPORT QMetaEnumBuilder { public: - QMetaEnumBuilder() : _mobj(0), _index(0) {} + QMetaEnumBuilder() : _mobj(nullptr), _index(0) {} int index() const { return _index; } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 15955e1665..45e88a2082 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ @@ -77,6 +77,12 @@ QT_BEGIN_NAMESPACE static int DIRECT_CONNECTION_ONLY = 0; +Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr); + +void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set) +{ + qt_signal_spy_callback_set.store(callback_set); +} QDynamicMetaObjectData::~QDynamicMetaObjectData() { @@ -146,10 +152,9 @@ static QBasicMutex _q_ObjectMutexPool[131]; * \internal * mutex to be locked when accessing the connectionlists or the senders list */ -static inline QMutex *signalSlotLock(const QObject *o) +static inline QBasicMutex *signalSlotLock(const QObject *o) { - return static_cast<QMutex *>(&_q_ObjectMutexPool[ - uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]); + return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]; } #if QT_VERSION < 0x60000 @@ -160,39 +165,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) {} #endif -struct QConnectionSenderSwitcher { - QObject *receiver; - QObjectPrivate::Sender *previousSender; - QObjectPrivate::Sender currentSender; - bool switched; - - inline QConnectionSenderSwitcher() : switched(false) {} - - inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id) - { - switchSender(receiver, sender, signal_absolute_id); - } - - inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id) - { - this->receiver = receiver; - currentSender.sender = sender; - currentSender.signal = signal_absolute_id; - currentSender.ref = 1; - previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); - switched = true; - } - - inline ~QConnectionSenderSwitcher() - { - if (switched) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - } -private: - Q_DISABLE_COPY(QConnectionSenderSwitcher) -}; - - void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; @@ -209,7 +181,7 @@ QMetaObject *QObjectData::dynamicMetaObject() const } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0) + : threadData(0), currentChildBeingDeleted(0) { #ifdef QT_BUILD_INTERNAL // Don't check the version parameter in internal builds. @@ -232,7 +204,6 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals[0] = connectedSignals[1] = 0; metaObject = 0; isWindow = false; deleteLaterCalled = false; @@ -285,59 +256,22 @@ static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int } } -/* - This vector contains the all connections from an object. - - Each object may have one vector containing the lists of - connections for a given signal. The index in the vector correspond - to the signal index. The signal index is the one returned by - QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal). - Negative index means connections to all signals. - - This vector is protected by the object mutex (signalSlotMutexes()) - - Each Connection is also part of a 'senders' linked list. The mutex - of the receiver must be locked when touching the pointers of this - linked list. -*/ -class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList> -{ -public: - bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse - bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet - int inUse; //number of functions that are currently accessing this object or its connections - QObjectPrivate::ConnectionList allsignals; - - QObjectConnectionListVector() - : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0) - { } - - QObjectPrivate::ConnectionList &operator[](int at) - { - if (at < 0) - return allsignals; - return QVector<QObjectPrivate::ConnectionList>::operator[](at); - } -}; - // Used by QAccessibleWidget bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const { Q_Q(const QObject); int signal_index = signalIndex(signal); - if (signal_index < 0) + ConnectionData *cd = connections.load(); + if (signal_index < 0 || !cd) return false; - QMutexLocker locker(signalSlotLock(q)); - if (connectionLists) { - if (signal_index < connectionLists->count()) { - const QObjectPrivate::Connection *c = - connectionLists->at(signal_index).first; - - while (c) { - if (c->receiver == receiver) - return true; - c = c->nextConnectionList; - } + QBasicMutexLocker locker(signalSlotLock(q)); + if (signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); + + while (c) { + if (c->receiver.load() == receiver) + return true; + c = c->nextConnectionList.load(); } } return false; @@ -346,21 +280,19 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const // Used by QAccessibleWidget QObjectList QObjectPrivate::receiverList(const char *signal) const { - Q_Q(const QObject); QObjectList returnValue; int signal_index = signalIndex(signal); - if (signal_index < 0) + ConnectionData *cd = connections.load(); + if (signal_index < 0 || !cd) return returnValue; - QMutexLocker locker(signalSlotLock(q)); - if (connectionLists) { - if (signal_index < connectionLists->count()) { - const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first; - - while (c) { - if (c->receiver) - returnValue << c->receiver; - c = c->nextConnectionList; - } + if (signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); + + while (c) { + QObject *r = c->receiver.load(); + if (r) + returnValue << r; + c = c->nextConnectionList.load(); } } return returnValue; @@ -370,9 +302,12 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const QObjectList QObjectPrivate::senderList() const { QObjectList returnValue; - QMutexLocker locker(signalSlotLock(q_func())); - for (Connection *c = senders; c; c = c->next) - returnValue << c->sender; + ConnectionData *cd = connections.load(); + if (cd) { + QBasicMutexLocker locker(signalSlotLock(q_func())); + for (Connection *c = cd->senders; c; c = c->next) + returnValue << c->sender; + } return returnValue; } @@ -389,79 +324,187 @@ QObjectList QObjectPrivate::senderList() const void QObjectPrivate::addConnection(int signal, Connection *c) { Q_ASSERT(c->sender == q_ptr); - if (!connectionLists) - connectionLists = new QObjectConnectionListVector(); - if (signal >= connectionLists->count()) - connectionLists->resize(signal + 1); - - ConnectionList &connectionList = (*connectionLists)[signal]; - if (connectionList.last) { - connectionList.last->nextConnectionList = c; + ensureConnectionData(); + ConnectionData *cd = connections.load(); + cd->resizeSignalVector(signal + 1); + + ConnectionList &connectionList = cd->connectionsForSignal(signal); + if (connectionList.last.load()) { + Q_ASSERT(connectionList.last.load()->receiver.load()); + connectionList.last.load()->nextConnectionList.store(c); } else { - connectionList.first = c; + connectionList.first.store(c); } - connectionList.last = c; + c->id = ++cd->currentConnectionId; + c->prevConnectionList = connectionList.last.load(); + connectionList.last.store(c); - cleanConnectionLists(); + QObjectPrivate *rd = QObjectPrivate::get(c->receiver.load()); + rd->ensureConnectionData(); - c->prev = &(QObjectPrivate::get(c->receiver)->senders); + c->prev = &(rd->connections.load()->senders); c->next = *c->prev; *c->prev = c; if (c->next) c->next->prev = &c->next; +} + +void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c) +{ + Q_ASSERT(c->receiver.load()); + ConnectionList &connections = signalVector.load()->at(c->signal_index); + c->receiver.store(nullptr); + QThreadData *td = c->receiverThreadData.load(); + if (td) + td->deref(); + c->receiverThreadData.store(nullptr); - if (signal < 0) { - connectedSignals[0] = connectedSignals[1] = ~0; - } else if (signal < (int)sizeof(connectedSignals) * 8) { - connectedSignals[signal >> 5] |= (1 << (signal & 0x1f)); +#ifndef QT_NO_DEBUG + bool found = false; + for (Connection *cc = connections.first.load(); cc; cc = cc->nextConnectionList.load()) { + if (cc == c) { + found = true; + break; + } } + Q_ASSERT(found); +#endif + + // remove from the senders linked list + *c->prev = c->next; + if (c->next) + c->next->prev = c->prev; + c->prev = nullptr; + + if (connections.first.load() == c) + connections.first.store(c->nextConnectionList.load()); + if (connections.last.load() == c) + connections.last.store(c->prevConnectionList); + Q_ASSERT(signalVector.load()->at(c->signal_index).first.load() != c); + Q_ASSERT(signalVector.load()->at(c->signal_index).last.load() != c); + + // keep c->nextConnectionList intact, as it might still get accessed by activate + Connection *n = c->nextConnectionList.load(); + if (n) + n->prevConnectionList = c->prevConnectionList; + if (c->prevConnectionList) + c->prevConnectionList->nextConnectionList.store(n); + c->prevConnectionList = nullptr; + + Q_ASSERT(c != orphaned.load()); + // add c to orphanedConnections + c->nextInOrphanList = orphaned.load(); + orphaned.store(c); + +#ifndef QT_NO_DEBUG + found = false; + for (Connection *cc = connections.first.load(); cc; cc = cc->nextConnectionList.load()) { + if (cc == c) { + found = true; + break; + } + } + Q_ASSERT(!found); +#endif + } -void QObjectPrivate::cleanConnectionLists() +void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender) { - if (connectionLists->dirty && !connectionLists->inUse) { - // remove broken connections - bool allConnected = false; - for (int signal = -1; signal < connectionLists->count(); ++signal) { - QObjectPrivate::ConnectionList &connectionList = - (*connectionLists)[signal]; - - // Set to the last entry in the connection list that was *not* - // deleted. This is needed to update the list's last pointer - // at the end of the cleanup. - QObjectPrivate::Connection *last = 0; - - QObjectPrivate::Connection **prev = &connectionList.first; - QObjectPrivate::Connection *c = *prev; - bool connected = false; // whether the signal is still connected somewhere - while (c) { - if (c->receiver) { - last = c; - prev = &c->nextConnectionList; - c = *prev; - connected = true; - } else { - QObjectPrivate::Connection *next = c->nextConnectionList; - *prev = next; - c->deref(); - c = next; - } - } + ConnectionOrSignalVector *c = nullptr; + { + QBasicMutexLocker l(signalSlotLock(sender)); + if (ref > 1) + return; - // Correct the connection list's last pointer. - // As conectionList.last could equal last, this could be a noop - connectionList.last = last; + // Since ref == 1, no activate() is in process since we locked the mutex. That implies, + // that nothing can reference the orphaned connection objects anymore and they can + // be safely deleted + c = orphaned.load(); + orphaned.store(nullptr); + } + deleteOrphaned(c); +} - if (!allConnected && !connected && signal >= 0 - && size_t(signal) < sizeof(connectedSignals) * 8) { - // This signal is no longer connected - connectedSignals[signal >> 5] &= ~(1 << (signal & 0x1f)); - } else if (signal == -1) { - allConnected = connected; - } +void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o) +{ + while (o) { + QObjectPrivate::ConnectionOrSignalVector *next = nullptr; + if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(o)) { + next = v->nextInOrphanList; + free(v); + } else { + QObjectPrivate::Connection *c = static_cast<Connection *>(o); + next = c->nextInOrphanList; + Q_ASSERT(!c->receiver.load()); + Q_ASSERT(!c->prev); + c->freeSlotObject(); + c->deref(); } - connectionLists->dirty = false; + o = next; + } +} + +/*! \internal + + Returns \c true if the signal with index \a signal_index from object \a sender is connected. + + \a signal_index must be the index returned by QObjectPrivate::signalIndex; +*/ +bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const +{ + if (checkDeclarative && isDeclarativeSignalConnected(signalIndex)) + return true; + + ConnectionData *cd = connections.load(); + if (!cd) + return false; + SignalVector *signalVector = cd->signalVector.load(); + if (!signalVector) + return false; + + if (signalVector->at(-1).first.load()) + return true; + + if (signalIndex < uint(cd->signalVectorCount())) { + const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.load(); + while (c) { + if (c->receiver.load()) + return true; + c = c->nextConnectionList.load(); + } + } + return false; +} + +bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const +{ + ConnectionData *cd = connections.load(); + if (!cd) + return false; + SignalVector *signalVector = cd->signalVector.load(); + if (!signalVector) + return false; + + if (signalVector->at(-1).first) + return true; + + if (signalIndex < uint(cd->signalVectorCount())) { + const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first; + return c != nullptr; } + return false; +} + +/*! + \internal + */ +QAbstractMetaCallEvent::~QAbstractMetaCallEvent() +{ +#if QT_CONFIG(thread) + if (semaphore_) + semaphore_->release(); +#endif } /*! @@ -470,8 +513,8 @@ void QObjectPrivate::cleanConnectionLists() QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction, const QObject *sender, int signalId, int nargs, int *types, void **args, QSemaphore *semaphore) - : QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId), - nargs_(nargs), types_(types), args_(args), semaphore_(semaphore), + : QAbstractMetaCallEvent(sender, signalId, semaphore), + slotObj_(nullptr), nargs_(nargs), types_(types), args_(args), callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative) { } @@ -480,9 +523,9 @@ QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QOb */ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId, int nargs, int *types, void **args, QSemaphore *semaphore) - : QEvent(MetaCall), slotObj_(slotO), sender_(sender), signalId_(signalId), - nargs_(nargs), types_(types), args_(args), semaphore_(semaphore), - callFunction_(0), method_offset_(0), method_relative_(ushort(-1)) + : QAbstractMetaCallEvent(sender, signalId, semaphore), + slotObj_(slotO), nargs_(nargs), types_(types), args_(args), + callFunction_(nullptr), method_offset_(0), method_relative_(ushort(-1)) { if (slotObj_) slotObj_->ref(); @@ -501,10 +544,6 @@ QMetaCallEvent::~QMetaCallEvent() free(types_); free(args_); } -#if QT_CONFIG(thread) - if (semaphore_) - semaphore_->release(); -#endif if (slotObj_) slotObj_->destroyIfLastRef(); } @@ -921,92 +960,56 @@ QObject::~QObject() } } - // set ref to zero to indicate that this object has been deleted - if (d->currentSender != 0) - d->currentSender->ref = 0; - d->currentSender = 0; + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (cd) { + if (cd->currentSender) { + cd->currentSender->receiverDeleted(); + cd->currentSender = nullptr; + } - if (d->connectionLists || d->senders) { - QMutex *signalSlotMutex = signalSlotLock(this); - QMutexLocker locker(signalSlotMutex); + QBasicMutex *signalSlotMutex = signalSlotLock(this); + QBasicMutexLocker locker(signalSlotMutex); // disconnect all receivers - if (d->connectionLists) { - ++d->connectionLists->inUse; - int connectionListsCount = d->connectionLists->count(); - for (int signal = -1; signal < connectionListsCount; ++signal) { - QObjectPrivate::ConnectionList &connectionList = - (*d->connectionLists)[signal]; - - while (QObjectPrivate::Connection *c = connectionList.first) { - if (!c->receiver) { - connectionList.first = c->nextConnectionList; - c->deref(); - continue; - } + int receiverCount = cd->signalVectorCount(); + for (int signal = -1; signal < receiverCount; ++signal) { + QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); - QMutex *m = signalSlotLock(c->receiver); - bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); + while (QObjectPrivate::Connection *c = connectionList.first.load()) { + Q_ASSERT(c->receiver); - if (c->receiver) { - *c->prev = c->next; - if (c->next) c->next->prev = c->prev; - } - c->receiver = 0; - if (needToUnlock) - m->unlock(); - - connectionList.first = c->nextConnectionList; - - // The destroy operation must happen outside the lock - if (c->isSlotObject) { - c->isSlotObject = false; - locker.unlock(); - c->slotObj->destroyIfLastRef(); - locker.relock(); - } - c->deref(); + QBasicMutex *m = signalSlotLock(c->receiver.load()); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); + if (c->receiver) { + cd->removeConnection(c); + Q_ASSERT(connectionList.first.load() != c); } + if (needToUnlock) + m->unlock(); } - - if (!--d->connectionLists->inUse) { - delete d->connectionLists; - } else { - d->connectionLists->orphaned = true; - } - d->connectionLists = 0; } /* Disconnect all senders: - * This loop basically just does - * for (node = d->senders; node; node = node->next) { ... } - * - * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the - * sender's mutex. And when the mutex is released, node->next might be destroyed by another - * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will - * be updated. */ - QObjectPrivate::Connection *node = d->senders; - while (node) { + while (QObjectPrivate::Connection *node = cd->senders) { + Q_ASSERT(node->receiver); QObject *sender = node->sender; // Send disconnectNotify before removing the connection from sender's connection list. // This ensures any eventual destructor of sender will block on getting receiver's lock // and not finish until we release it. sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); - QMutex *m = signalSlotLock(sender); - node->prev = &node; + QBasicMutex *m = signalSlotLock(sender); bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? - if (!node || node->sender != sender) { + if (node != cd->senders) { // We hold the wrong mutex Q_ASSERT(needToUnlock); m->unlock(); continue; } - node->receiver = 0; - QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists; - if (senderLists) - senderLists->dirty = true; + + QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.load(); + Q_ASSERT(senderData); QtPrivate::QSlotObjectBase *slotObj = nullptr; if (node->isSlotObject) { @@ -1014,19 +1017,24 @@ QObject::~QObject() node->isSlotObject = false; } - node = node->next; + senderData->removeConnection(node); if (needToUnlock) m->unlock(); if (slotObj) { - if (node) - node->prev = &node; locker.unlock(); slotObj->destroyIfLastRef(); locker.relock(); } } + + // invalidate all connections on the object and make sure + // activate() will skip them + cd->currentConnectionId.store(0); } + if (cd && !cd->ref.deref()) + delete cd; + d->connections.store(nullptr); if (!d->children.isEmpty()) d->deleteChildren(); @@ -1253,9 +1261,13 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { - QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); + QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e); - QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId()); + if (!d_func()->connections.load()) { + QBasicMutexLocker locker(signalSlotLock(this)); + d_func()->ensureConnectionData(); + } + QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId()); mce->placeMetaCall(this); break; @@ -1510,6 +1522,9 @@ void QObject::moveToThread(QThread *targetThread) if (!targetData) targetData = new QThreadData(0); + // make sure nobody adds/removes connections to this object while we're moving it + QMutexLocker l(signalSlotLock(this)); + QOrderedMutexLocker locker(¤tData->postEventList.mutex, &targetData->postEventList.mutex); @@ -1559,9 +1574,31 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - if (currentSender) - currentSender->ref = 0; - currentSender = 0; + ConnectionData *cd = connections.load(); + if (cd) { + if (cd->currentSender) { + cd->currentSender->receiverDeleted(); + cd->currentSender = nullptr; + } + + // adjust the receiverThreadId values in the Connections + if (cd) { + auto *c = cd->senders; + while (c) { + QObject *r = c->receiver.load(); + if (r) { + Q_ASSERT(r == q); + targetData->ref(); + QThreadData *old = c->receiverThreadData.load(); + if (old) + old->deref(); + c->receiverThreadData.store(targetData); + } + c = c->next; + } + } + + } // set new thread data targetData->ref(); @@ -2370,13 +2407,14 @@ QObject *QObject::sender() const { Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); - if (!d->currentSender) - return 0; + QBasicMutexLocker locker(signalSlotLock(this)); + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (!cd || !cd->currentSender) + return nullptr; - for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { - if (c->sender == d->currentSender->sender) - return d->currentSender->sender; + for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) { + if (c->sender == cd->currentSender->sender) + return cd->currentSender->sender; } return 0; @@ -2411,14 +2449,15 @@ int QObject::senderSignalIndex() const { Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); - if (!d->currentSender) + QBasicMutexLocker locker(signalSlotLock(this)); + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (!cd || !cd->currentSender) return -1; - for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { - if (c->sender == d->currentSender->sender) { + for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) { + if (c->sender == cd->currentSender->sender) { // Convert from signal range to method range - return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex(); + return QMetaObjectPrivate::signal(c->sender->metaObject(), cd->currentSender->signal).methodIndex(); } } @@ -2474,15 +2513,13 @@ int QObject::receivers(const char *signal) const signal_index); } - QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signal_index < d->connectionLists->count()) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signal_index).first; - while (c) { - receivers += c->receiver ? 1 : 0; - c = c->nextConnectionList; - } + QObjectPrivate::ConnectionData *cd = d->connections.load(); + QBasicMutexLocker locker(signalSlotLock(this)); + if (cd && signal_index < cd->signalVectorCount()) { + const QObjectPrivate::Connection *c = cd->signalVector.load()->at(signal_index).first.load(); + while (c) { + receivers += c->receiver.load() ? 1 : 0; + c = c->nextConnectionList.load(); } } } @@ -2522,22 +2559,8 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); - QMutexLocker locker(signalSlotLock(this)); - if (d->connectionLists) { - if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) - return d->isSignalConnected(signalIndex); - - if (signalIndex < uint(d->connectionLists->count())) { - const QObjectPrivate::Connection *c = - d->connectionLists->at(signalIndex).first; - while (c) { - if (c->receiver) - return true; - c = c->nextConnectionList; - } - } - } - return d->isDeclarativeSignalConnected(signalIndex); + QBasicMutexLocker locker(signalSlotLock(this)); + return d->isSignalConnected(signalIndex, true); } /*! @@ -3300,24 +3323,22 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int method_offset = rmeta ? rmeta->methodOffset() : 0; Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6); - QObjectPrivate::StaticMetaCallFunction callFunction = - rmeta ? rmeta->d.static_metacall : 0; + QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr; QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection) { - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (connectionLists && connectionLists->count() > signal_index) { - const QObjectPrivate::Connection *c2 = - (*connectionLists)[signal_index].first; + QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); + if (type & Qt::UniqueConnection && scd) { + if (scd->signalVectorCount() > signal_index) { + const QObjectPrivate::Connection *c2 = scd->signalVector.load()->at(signal_index).first.load(); int method_index_absolute = method_index + method_offset; while (c2) { - if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute) - return 0; - c2 = c2->nextConnectionList; + if (!c2->isSlotObject && c2->receiver.load() == receiver && c2->method() == method_index_absolute) + return nullptr; + c2 = c2->nextConnectionList.load(); } } type &= Qt::UniqueConnection - 1; @@ -3326,13 +3347,15 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection); c->sender = s; c->signal_index = signal_index; - c->receiver = r; + c->receiver.store(r); + QThreadData *td = r->d_func()->threadData; + td->ref(); + c->receiverThreadData.store(td); c->method_relative = method_index; c->method_offset = method_offset; c->connectionType = type; c->isSlotObject = false; c->argumentTypes.store(types); - c->nextConnectionList = 0; c->callFunction = callFunction; QObjectPrivate::get(s)->addConnection(signal_index, c.data()); @@ -3378,47 +3401,38 @@ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, \internal Helper function to remove the connection from the senders list and setting the receivers to 0 */ -bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, +bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex, const QObject *receiver, int method_index, void **slot, - QMutex *senderMutex, DisconnectType disconnectType) + QBasicMutex *senderMutex, DisconnectType disconnectType) { bool success = false; + + auto &connectionList = connections->connectionsForSignal(signalIndex); + auto *c = connectionList.first.load(); while (c) { - if (c->receiver - && (receiver == 0 || (c->receiver == receiver + QObject *r = c->receiver.load(); + if (r && (receiver == nullptr || (r == receiver && (method_index < 0 || (!c->isSlotObject && c->method() == method_index)) - && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) { + && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; - QMutex *receiverMutex = 0; - if (c->receiver) { - receiverMutex = signalSlotLock(c->receiver); + QBasicMutex *receiverMutex = nullptr; + if (r) { + receiverMutex = signalSlotLock(r); // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex); } - if (c->receiver) { - *c->prev = c->next; - if (c->next) - c->next->prev = c->prev; - } + if (c->receiver.load()) + connections->removeConnection(c); if (needToUnlock) receiverMutex->unlock(); - c->receiver = 0; - - if (c->isSlotObject) { - c->isSlotObject = false; - senderMutex->unlock(); - c->slotObj->destroyIfLastRef(); - senderMutex->lock(); - } - success = true; if (disconnectType == DisconnectOne) return success; } - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } return success; } @@ -3437,43 +3451,34 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast<QObject *>(sender); - QMutex *senderMutex = signalSlotLock(sender); - QMutexLocker locker(senderMutex); + QBasicMutex *senderMutex = signalSlotLock(sender); + QBasicMutexLocker locker(senderMutex); - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (!connectionLists) + QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.load(); + if (!scd) return false; - // prevent incoming connections changing the connectionLists while unlocked - ++connectionLists->inUse; - bool success = false; - if (signal_index < 0) { - // remove from all connection lists - for (int sig_index = -1; sig_index < connectionLists->count(); ++sig_index) { - QObjectPrivate::Connection *c = - (*connectionLists)[sig_index].first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { - success = true; - connectionLists->dirty = true; + { + // prevent incoming connections changing the connections->receivers while unlocked + QObjectPrivate::ConnectionDataPointer connections(scd); + + if (signal_index < 0) { + // remove from all connection lists + for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) { + if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType)) + success = true; } - } - } else if (signal_index < connectionLists->count()) { - QObjectPrivate::Connection *c = - (*connectionLists)[signal_index].first; - if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) { - success = true; - connectionLists->dirty = true; + } else if (signal_index < scd->signalVectorCount()) { + if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType)) + success = true; } } - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned && !connectionLists->inUse) - delete connectionLists; - locker.unlock(); if (success) { + scd->cleanOrphanedConnections(s); + QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index); if (smethod.isValid()) s->disconnectNotify(smethod); @@ -3589,8 +3594,7 @@ void QMetaObject::connectSlotsByName(QObject *o) \a signal must be in the signal index range (see QObjectPrivate::signalIndex()). */ -static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv, - QMutexLocker &locker) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) { const int *argumentTypes = c->argumentTypes.load(); if (!argumentTypes) { @@ -3620,134 +3624,111 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect for (int n = 1; n < nargs; ++n) types[n] = argumentTypes[n-1]; - locker.unlock(); for (int n = 1; n < nargs; ++n) args[n] = QMetaType::create(types[n], argv[n]); - locker.relock(); - - if (!c->receiver) { - locker.unlock(); - // we have been disconnected while the mutex was unlocked - for (int n = 1; n < nargs; ++n) - QMetaType::destroy(types[n], args[n]); - free(types); - free(args); - locker.relock(); - return; - } + } + + QBasicMutexLocker locker(signalSlotLock(c->receiver.load())); + if (!c->receiver.load()) { + // the connection has been disconnected before we got the lock + locker.unlock(); + for (int n = 1; n < nargs; ++n) + QMetaType::destroy(types[n], args[n]); + free(types); + free(args); + return; } QMetaCallEvent *ev = c->isSlotObject ? new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) : new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args); - QCoreApplication::postEvent(c->receiver, ev); + QCoreApplication::postEvent(c->receiver.load(), ev); } -/*! - \internal - */ -void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, - void **argv) -{ - activate(sender, QMetaObjectPrivate::signalOffset(m), local_signal_index, argv); -} - -/*! - \internal - */ -void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) +template <bool callbacks_enabled> +void doActivate(QObject *sender, int signal_index, void **argv) { - int signal_index = signalOffset + local_signal_index; + QObjectPrivate *sp = QObjectPrivate::get(sender); - if (sender->d_func()->blockSig) + if (sp->blockSig) return; - if (sender->d_func()->isDeclarativeSignalConnected(signal_index) + if (sp->isDeclarativeSignalConnected(signal_index) && QAbstractDeclarativeData::signalEmitted) { Q_TRACE(QMetaObject_activate_begin_declarative_signal, sender, signal_index); - QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender, + QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender, signal_index, argv); Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index); } - if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false) - && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback - && !Q_TRACE_ENABLED(QMetaObject_activate_begin_signal) - && !Q_TRACE_ENABLED(QMetaObject_activate_end_signal)) { - // The possible declarative connection is done, and nothing else is connected, so: - return; - } + const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.load() : nullptr; void *empty_argv[] = { nullptr }; if (!argv) argv = empty_argv; - if (qt_signal_spy_callback_set.signal_begin_callback != 0) { - qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv); + if (!sp->maybeSignalConnected(signal_index)) { + // The possible declarative connection is done, and nothing else is connected + if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) + signal_spy_set->signal_begin_callback(sender, signal_index, argv); + Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); + Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); + return; } + + if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr) + signal_spy_set->signal_begin_callback(sender, signal_index, argv); Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); + bool senderDeleted = false; { - QMutexLocker locker(signalSlotLock(sender)); - struct ConnectionListsRef { - QObjectConnectionListVector *connectionLists; - ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists) - { - if (connectionLists) - ++connectionLists->inUse; - } - ~ConnectionListsRef() - { - if (!connectionLists) - return; - - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned) { - if (!connectionLists->inUse) - delete connectionLists; - } - } - - QObjectConnectionListVector *operator->() const { return connectionLists; } - }; - ConnectionListsRef connectionLists = sender->d_func()->connectionLists; - if (!connectionLists.connectionLists) { - locker.unlock(); - if (qt_signal_spy_callback_set.signal_end_callback != 0) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); - Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); - return; - } + Q_ASSERT(sp->connections); + QObjectPrivate::ConnectionDataPointer connections(sp->connections.load()); + QObjectPrivate::SignalVector *signalVector = connections->signalVector.load(); const QObjectPrivate::ConnectionList *list; - if (signal_index < connectionLists->count()) - list = &connectionLists->at(signal_index); + if (signal_index < signalVector->count()) + list = &signalVector->at(signal_index); else - list = &connectionLists->allsignals; + list = &signalVector->at(-1); Qt::HANDLE currentThreadId = QThread::currentThreadId(); + bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData->threadId.load(); + // We need to check against the highest connection id to ensure that signals added + // during the signal emission are not emitted in this emission. + uint highestConnectionId = connections->currentConnectionId.load(); do { - QObjectPrivate::Connection *c = list->first; - if (!c) continue; - // We need to check against last here to ensure that signals added - // during the signal emission are not emitted in this emission. - QObjectPrivate::Connection *last = list->last; + QObjectPrivate::Connection *c = list->first.load(); + if (!c) + continue; do { - if (!c->receiver) + QObject * const receiver = c->receiver.load(); + if (!receiver) continue; - QObject * const receiver = c->receiver; - const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId.load(); + QThreadData *td = c->receiverThreadData.load(); + if (!td) + continue; + + bool receiverInSameThread; + if (inSenderThread) { + receiverInSameThread = currentThreadId == td->threadId.load(); + } else { + // need to lock before reading the threadId, because moveToThread() could interfere + QMutexLocker lock(signalSlotLock(receiver)); + receiverInSameThread = currentThreadId == td->threadId.load(); + } + // determine if this connection should be sent immediately or // put into the event queue if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread) || (c->connectionType == Qt::QueuedConnection)) { - queued_activate(sender, signal_index, c, argv, locker); + queued_activate(sender, signal_index, c, argv); continue; #if QT_CONFIG(thread) } else if (c->connectionType == Qt::BlockingQueuedConnection) { @@ -3758,89 +3739,103 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i receiver->metaObject()->className(), receiver); } QSemaphore semaphore; - QMetaCallEvent *ev = c->isSlotObject ? - new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) : - new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv, &semaphore); - QCoreApplication::postEvent(receiver, ev); - locker.unlock(); + { + QBasicMutexLocker locker(signalSlotLock(sender)); + if (!c->receiver) + continue; + QMetaCallEvent *ev = c->isSlotObject ? + new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) : + new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv, &semaphore); + QCoreApplication::postEvent(receiver, ev); + } semaphore.acquire(); - locker.relock(); continue; #endif } - QConnectionSenderSwitcher sw; + QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index); - if (receiverInSameThread) { - sw.switchSender(receiver, sender, signal_index); - } if (c->isSlotObject) { c->slotObj->ref(); QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj); - locker.unlock(); Q_TRACE(QMetaObject_activate_begin_slot_functor, obj.data()); obj->call(receiver, argv); Q_TRACE(QMetaObject_activate_end_slot_functor, obj.data()); - - // Make sure the slot object gets destroyed before the mutex is locked again, as the - // destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool, - // and that would deadlock if the pool happens to return the same mutex. - obj.reset(); - - locker.relock(); } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { //we compare the vtable to make sure we are not in the destructor of the object. - const int methodIndex = c->method(); const int method_relative = c->method_relative; const auto callFunction = c->callFunction; - locker.unlock(); - if (qt_signal_spy_callback_set.slot_begin_callback != 0) - qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv); + const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0; + if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) + signal_spy_set->slot_begin_callback(receiver, methodIndex, argv); Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex); callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex); - if (qt_signal_spy_callback_set.slot_end_callback != 0) - qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex); - locker.relock(); + if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) + signal_spy_set->slot_end_callback(receiver, methodIndex); } else { const int method = c->method_relative + c->method_offset; - locker.unlock(); - if (qt_signal_spy_callback_set.slot_begin_callback != 0) { - qt_signal_spy_callback_set.slot_begin_callback(receiver, method, argv); + if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) { + signal_spy_set->slot_begin_callback(receiver, method, argv); } Q_TRACE(QMetaObject_activate_begin_slot, receiver, method); - metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); + QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); Q_TRACE(QMetaObject_activate_end_slot, receiver, method); - if (qt_signal_spy_callback_set.slot_end_callback != 0) - qt_signal_spy_callback_set.slot_end_callback(receiver, method); - - locker.relock(); + if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr) + signal_spy_set->slot_end_callback(receiver, method); } + } while ((c = c->nextConnectionList.load()) != nullptr && c->id <= highestConnectionId); - if (connectionLists->orphaned) - break; - } while (c != last && (c = c->nextConnectionList) != 0); - - if (connectionLists->orphaned) - break; - } while (list != &connectionLists->allsignals && + } while (list != &signalVector->at(-1) && //start over for all signals; - ((list = &connectionLists->allsignals), true)); + ((list = &signalVector->at(-1)), true)); + if (connections->currentConnectionId.load() == 0) + senderDeleted = true; } + if (!senderDeleted) + sp->connections.load()->cleanOrphanedConnections(sender); - if (qt_signal_spy_callback_set.signal_end_callback != 0) - qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); + +} + +/*! + \internal + */ +void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, + void **argv) +{ + int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m); + + if (Q_UNLIKELY(qt_signal_spy_callback_set.load())) + doActivate<true>(sender, signal_index, argv); + else + doActivate<false>(sender, signal_index, argv); } /*! \internal + */ +void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) +{ + int signal_index = signalOffset + local_signal_index; + + if (Q_UNLIKELY(qt_signal_spy_callback_set.load())) + doActivate<true>(sender, signal_index, argv); + else + doActivate<false>(sender, signal_index, argv); + } + +/*! + \internal signal_index comes from indexOfMethod() */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) @@ -3853,7 +3848,7 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) /*! \internal - Returns the signal index used in the internal connectionLists vector. + Returns the signal index used in the internal connections->receivers vector. It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots. @@ -4093,37 +4088,40 @@ void QObject::dumpObjectInfo() const objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data()); Q_D(const QObject); - QMutexLocker locker(signalSlotLock(this)); + QBasicMutexLocker locker(signalSlotLock(this)); // first, look for connections where this object is the sender qDebug(" SIGNALS OUT"); - if (d->connectionLists) { - for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) { + QObjectPrivate::ConnectionData *cd = d->connections.load(); + if (cd && cd->signalVectorCount()) { + QObjectPrivate::SignalVector *signalVector = cd->signalVector.load(); + for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) { + const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.load(); + if (!c) + continue; const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index); qDebug(" signal: %s", signal.methodSignature().constData()); // receivers - const QObjectPrivate::Connection *c = - d->connectionLists->at(signal_index).first; while (c) { - if (!c->receiver) { + if (!c->receiver.load()) { qDebug(" <Disconnected receiver>"); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); continue; } if (c->isSlotObject) { qDebug(" <functor or function pointer>"); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); continue; } - const QMetaObject *receiverMetaObject = c->receiver->metaObject(); + const QMetaObject *receiverMetaObject = c->receiver.load()->metaObject(); const QMetaMethod method = receiverMetaObject->method(c->method()); qDebug(" --> %s::%s %s", receiverMetaObject->className(), - c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()), + c->receiver.load()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.load()->objectName()), method.methodSignature().constData()); - c = c->nextConnectionList; + c = c->nextConnectionList.load(); } } } else { @@ -4133,8 +4131,8 @@ void QObject::dumpObjectInfo() const // now look for connections where this object is the receiver qDebug(" SIGNALS IN"); - if (d->senders) { - for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) { + if (cd && cd->senders) { + for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) { QByteArray slotName = QByteArrayLiteral("<unknown>"); if (!s->isSlotObject) { const QMetaMethod slot = metaObject()->method(s->method()); @@ -4869,18 +4867,17 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection && slot) { - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; - if (connectionLists && connectionLists->count() > signal_index) { - const QObjectPrivate::Connection *c2 = - (*connectionLists)[signal_index].first; + if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.load()) { + QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.load(); + if (connections->signalVectorCount() > signal_index) { + const QObjectPrivate::Connection *c2 = connections->signalVector.load()->at(signal_index).first.load(); while (c2) { - if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { + if (c2->receiver.load() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { slotObj->destroyIfLastRef(); return QMetaObject::Connection(); } - c2 = c2->nextConnectionList; + c2 = c2->nextConnectionList.load(); } } type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection); @@ -4889,7 +4886,10 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection); c->sender = s; c->signal_index = signal_index; - c->receiver = r; + QThreadData *td = r->d_func()->threadData; + td->ref(); + c->receiverThreadData.store(td); + c->receiver.store(r); c->slotObj = slotObj; c->connectionType = type; c->isSlotObject = true; @@ -4921,35 +4921,35 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) { QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr); - if (!c || !c->receiver) + if (!c) + return false; + QObject *receiver = c->receiver.load(); + if (!receiver) return false; - QMutex *senderMutex = signalSlotLock(c->sender); - QMutex *receiverMutex = signalSlotLock(c->receiver); + QBasicMutex *senderMutex = signalSlotLock(c->sender); + QBasicMutex *receiverMutex = signalSlotLock(receiver); + QObjectPrivate::ConnectionData *connections; { QOrderedMutexLocker locker(senderMutex, receiverMutex); - QObjectConnectionListVector *connectionLists = QObjectPrivate::get(c->sender)->connectionLists; - Q_ASSERT(connectionLists); - connectionLists->dirty = true; + // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime + receiver = c->receiver.load(); + if (!receiver) + return false; - *c->prev = c->next; - if (c->next) - c->next->prev = c->prev; - c->receiver = 0; + connections = QObjectPrivate::get(c->sender)->connections.load(); + Q_ASSERT(connections); + connections->removeConnection(c); } - // destroy the QSlotObject, if possible - if (c->isSlotObject) { - c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; - } + connections->cleanOrphanedConnections(c->sender); c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(), c->signal_index)); - const_cast<QMetaObject::Connection &>(connection).d_ptr = 0; + const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr; c->deref(); // has been removed from the QMetaObject::Connection object return true; @@ -5131,7 +5131,7 @@ bool QMetaObject::Connection::isConnected_helper() const Q_ASSERT(d_ptr); // we're only called from operator RestrictedBool() const QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(d_ptr); - return c->receiver; + return c->receiver.load(); } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index a762e6f529..2fb11ecc64 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ ** @@ -79,9 +79,9 @@ struct QSignalSpyCallbackSet EndCallback signal_end_callback, slot_end_callback; }; -void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set); +void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set); -extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set; +extern Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set; enum { QObjectPrivateVersion = QT_VERSION }; @@ -124,54 +124,199 @@ public: }; typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **); - struct Connection + struct Connection; + struct SignalVector; + + struct ConnectionOrSignalVector { + union { + // linked list of orphaned connections that need cleaning up + ConnectionOrSignalVector *nextInOrphanList; + // linked list of connections connected to slots in this object + Connection *next; + }; + + static SignalVector *asSignalVector(ConnectionOrSignalVector *c) { + if (reinterpret_cast<quintptr>(c) & 1) + return reinterpret_cast<SignalVector *>(reinterpret_cast<quintptr>(c) & ~quintptr(1u)); + return nullptr; + } + static Connection *fromSignalVector(SignalVector *v) { + return reinterpret_cast<Connection *>(reinterpret_cast<quintptr>(v) | quintptr(1u)); + } + }; + + struct Connection : public ConnectionOrSignalVector { + // linked list of connections connected to slots in this object, next is in base class + Connection **prev; + // linked list of connections connected to signals in this object + QAtomicPointer<Connection> nextConnectionList; + Connection *prevConnectionList; + QObject *sender; - QObject *receiver; + QAtomicPointer<QObject> receiver; + QAtomicPointer<QThreadData> receiverThreadData; union { StaticMetaCallFunction callFunction; QtPrivate::QSlotObjectBase *slotObj; }; - // The next pointer for the singly-linked ConnectionList - Connection *nextConnectionList; - //senders linked list - Connection *next; - Connection **prev; QAtomicPointer<const int> argumentTypes; QAtomicInt ref_; + uint id = 0; ushort method_offset; ushort method_relative; - uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex()) + int signal_index : 27; // In signal range (see QObjectPrivate::signalIndex()) ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking ushort isSlotObject : 1; ushort ownArgumentTypes : 1; - Connection() : nextConnectionList(nullptr), ref_(2), ownArgumentTypes(true) { + Connection() : ref_(2), ownArgumentTypes(true) { //ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection } ~Connection(); int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; } void ref() { ref_.ref(); } + void freeSlotObject() + { + if (isSlotObject) { + slotObj->destroyIfLastRef(); + isSlotObject = false; + } + } void deref() { if (!ref_.deref()) { - Q_ASSERT(!receiver); + Q_ASSERT(!receiver.load()); + Q_ASSERT(!isSlotObject); delete this; } } }; // ConnectionList is a singly-linked list struct ConnectionList { - ConnectionList() : first(nullptr), last(nullptr) {} - Connection *first; - Connection *last; + QAtomicPointer<Connection> first; + QAtomicPointer<Connection> last; }; struct Sender { + Sender(QObject *receiver, QObject *sender, int signal) + : receiver(receiver), sender(sender), signal(signal) + { + if (receiver) { + ConnectionData *cd = receiver->d_func()->connections.load(); + previous = cd->currentSender; + cd->currentSender = this; + } + } + ~Sender() + { + if (receiver) + receiver->d_func()->connections.load()->currentSender = previous; + } + void receiverDeleted() + { + Sender *s = this; + while (s) { + s->receiver = nullptr; + s = s->previous; + } + } + Sender *previous; + QObject *receiver; QObject *sender; int signal; - int ref; }; + struct SignalVector : public ConnectionOrSignalVector { + quintptr allocated; + // ConnectionList signals[] + ConnectionList &at(int i) + { + return reinterpret_cast<ConnectionList *>(this + 1)[i + 1]; + } + const ConnectionList &at(int i) const + { + return reinterpret_cast<const ConnectionList *>(this + 1)[i + 1]; + } + int count() { return static_cast<int>(allocated); } + }; + + + + /* + This contains the all connections from and to an object. + + The signalVector contains the lists of connections for a given signal. The index in the vector correspond + to the signal index. The signal index is the one returned by QObjectPrivate::signalIndex (not + QMetaObject::indexOfSignal). allsignals contains a list of special connections that will get invoked on + any signal emission. This is done by connecting to signal index -1. + + This vector is protected by the object mutex (signalSlotLock()) + + Each Connection is also part of a 'senders' linked list. This one contains all connections connected + to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this + linked list. + */ + struct ConnectionData { + // the id below is used to avoid activating new connections. When the object gets + // deleted it's set to 0, so that signal emission stops + QAtomicInteger<uint> currentConnectionId; + QAtomicInt ref; + QAtomicPointer<SignalVector> signalVector; + Connection *senders = nullptr; + Sender *currentSender = nullptr; // object currently activating the object + QAtomicPointer<Connection> orphaned; + + ~ConnectionData() + { + deleteOrphaned(orphaned.load()); + SignalVector *v = signalVector.load(); + if (v) + free(v); + } + + // must be called on the senders connection data + // assumes the senders and receivers lock are held + void removeConnection(Connection *c); + void cleanOrphanedConnections(QObject *sender) + { + if (orphaned.load() && ref == 1) + cleanOrphanedConnectionsImpl(sender); + } + void cleanOrphanedConnectionsImpl(QObject *sender); + + ConnectionList &connectionsForSignal(int signal) + { + return signalVector.load()->at(signal); + } + + void resizeSignalVector(uint size) { + SignalVector *vector = this->signalVector.load(); + if (vector && vector->allocated > size) + return; + size = (size + 7) & ~7; + SignalVector *newVector = reinterpret_cast<SignalVector *>(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList))); + int start = -1; + if (vector) { + memcpy(newVector, vector, sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList)); + start = vector->count(); + } + for (int i = start; i < int(size); ++i) + newVector->at(i) = ConnectionList(); + newVector->next = nullptr; + newVector->allocated = size; + + signalVector.store(newVector); + if (vector) { + vector->nextInOrphanList = orphaned.load(); + orphaned.store(ConnectionOrSignalVector::fromSignalVector(vector)); + } + } + int signalVectorCount() const { + return signalVector ? signalVector.load()->count() : -1; + } + + static void deleteOrphaned(ConnectionOrSignalVector *c); + }; QObjectPrivate(int version = QObjectPrivateVersion); virtual ~QObjectPrivate(); @@ -187,13 +332,6 @@ public: QObjectList senderList() const; void addConnection(int signal, Connection *c); - void cleanConnectionLists(); - - static inline Sender *setCurrentSender(QObject *receiver, - Sender *sender); - static inline void resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender); static QObjectPrivate *get(QObject *o) { return o->d_func(); @@ -201,7 +339,8 @@ public: static const QObjectPrivate *get(const QObject *o) { return o->d_func(); } int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const; - inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + bool maybeSignalConnected(uint signalIndex) const; inline bool isDeclarativeSignalConnected(uint signalIdx) const; // To allow abitrary objects to call connectNotify()/disconnectNotify() without making @@ -224,15 +363,21 @@ public: const int *types, const QMetaObject *senderMetaObject); static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type); static bool disconnect(const QObject *sender, int signal_index, void **slot); + + void ensureConnectionData() + { + if (connections.load()) + return; + ConnectionData *cd = new ConnectionData; + cd->ref.ref(); + connections.store(cd); + } public: ExtraData *extraData; // extra data set by the user QThreadData *threadData; // id of the thread that owns the object - QObjectConnectionListVector *connectionLists; - - Connection *senders; // linked list of connections connected to this object - Sender *currentSender; // object currently activating the object - mutable quint32 connectedSignals[2]; + using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>; + QAtomicPointer<ConnectionData> connections; union { QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set @@ -246,47 +391,12 @@ public: Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE); -/*! \internal - - Returns \c true if the signal with index \a signal_index from object \a sender is connected. - Signals with indices above a certain range are always considered connected (see connectedSignals - in QObjectPrivate). - - \a signal_index must be the index returned by QObjectPrivate::signalIndex; -*/ -inline bool QObjectPrivate::isSignalConnected(uint signal_index, bool checkDeclarative) const -{ - return signal_index >= sizeof(connectedSignals) * 8 - || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) - || (checkDeclarative && isDeclarativeSignalConnected(signal_index))); -} - inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const { return declarativeData && QAbstractDeclarativeData::isSignalConnected && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index); } -inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, - Sender *sender) -{ - Sender *previousSender = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = sender; - return previousSender; -} - -inline void QObjectPrivate::resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender) -{ - // ref is set to zero when this object is deleted during the metacall - if (currentSender->ref == 1) - receiver->d_func()->currentSender = previousSender; - // if we've recursed, we need to tell the caller about the objects deletion - if (previousSender) - previousSender->ref = currentSender->ref; -} - inline void QObjectPrivate::connectNotify(const QMetaMethod &signal) { q_ptr->connectNotify(signal); @@ -372,7 +482,26 @@ Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); class QSemaphore; -class Q_CORE_EXPORT QMetaCallEvent : public QEvent +class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent +{ +public: + QAbstractMetaCallEvent(const QObject *sender, int signalId, QSemaphore *semaphore = nullptr) + : QEvent(MetaCall), signalId_(signalId), sender_(sender), semaphore_(semaphore) + {} + ~QAbstractMetaCallEvent(); + + virtual void placeMetaCall(QObject *object) = 0; + + inline const QObject *sender() const { return sender_; } + inline int signalId() const { return signalId_; } + +private: + int signalId_; + const QObject *sender_; + QSemaphore *semaphore_; +}; + +class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent { public: QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId, @@ -383,23 +512,18 @@ public: QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId, int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr); - ~QMetaCallEvent(); + ~QMetaCallEvent() override; inline int id() const { return method_offset_ + method_relative_; } - inline const QObject *sender() const { return sender_; } - inline int signalId() const { return signalId_; } inline void **args() const { return args_; } - virtual void placeMetaCall(QObject *object); + virtual void placeMetaCall(QObject *object) override; private: QtPrivate::QSlotObjectBase *slotObj_; - const QObject *sender_; - int signalId_; int nargs_; int *types_; void **args_; - QSemaphore *semaphore_; QObjectPrivate::StaticMetaCallFunction callFunction_; ushort method_offset_; ushort method_relative_; diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 95fe0d1083..59802eb6ce 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -98,7 +98,7 @@ public: { if (q_sm && q_sm->lock()) return true; - q_sm = 0; + q_sm = nullptr; return false; } diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp deleted file mode 100644 index 5437210699..0000000000 --- a/src/corelib/kernel/qtcore_eval.cpp +++ /dev/null @@ -1,560 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore 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$ -** -****************************************************************************/ - -#include <qcoreevent.h> -#include <qdatetime.h> -#include <qlibraryinfo.h> -#include <qobject.h> -#include <qcoreapplication.h> -#include <private/qcoreapplication_p.h> - -#include "stdio.h" -#include "stdlib.h" - -QT_BEGIN_NAMESPACE - -#include "qconfig_eval.cpp" - -static const char boilerplate_supported_but_time_limited[] = - "\nQt %1 Evaluation License\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "This trial version may only be used for evaluation purposes\n" - "and will shut down after 120 minutes.\n" - "Registered to:\n" - " Licensee: %2\n\n" - "The evaluation expires in %4 days\n\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char boilerplate_supported[] = - "\nQt %1 Evaluation License\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "This trial version may only be used for evaluation purposes\n" - "Registered to:\n" - " Licensee: %2\n\n" - "The evaluation expires in %4 days\n\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char boilerplate_expired[] = - "This software is using the trial version of the Qt GUI toolkit.\n" - "The trial period has expired. If you need more time to\n" - "evaluate Qt, or if you have any questions about Qt, contact us\n" - "at: http://www.qt.io/contact-us.\n\n"; - -static const char will_shutdown_1min[] = - "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -static const char will_shutdown_now[] = - "\nThe evaluation of Qt has now reached its automatic\n" - "timeout and will shut down.\n" - "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n"; - -enum EvaluationStatus { - EvaluationNotSupported = 0, - EvaluationSupportedButTimeLimited, - EvaluationSupported -}; - -static EvaluationStatus qt_eval_is_supported() -{ - const volatile char *const license_key = qt_eval_key_data + 12; - - // fast fail - if (!qt_eval_key_data[0] || !*license_key) - return EvaluationNotSupported; - - // is this an unsupported evaluation? - const volatile char *typecode = license_key; - int field = 2; - for ( ; field && *typecode; ++typecode) - if (*typecode == '-') - --field; - - if (!field && typecode[1] == '4' && typecode[2] == 'M') { - if (typecode[0] == 'Q') - return EvaluationSupportedButTimeLimited; - else if (typecode[0] == 'R' || typecode[0] == 'Z') - return EvaluationSupported; - } - return EvaluationNotSupported; -} - -static int qt_eval_days_left() -{ - const volatile char *const expiry_date = qt_eval_expiry_date + 12; - - QDate today = QDate::currentDate(); - QDate lastday = QDate::fromString( - QString::fromLatin1(const_cast<const char*>(expiry_date)), Qt::ISODate); - return today.daysTo(lastday); -} - -static bool qt_eval_is_expired() -{ - return qt_eval_days_left() < 0; -} - -static QString qt_eval_string() -{ - const char *msg; - switch (qt_eval_is_supported()) { - case EvaluationSupportedButTimeLimited: - msg = boilerplate_supported_but_time_limited; - break; - case EvaluationSupported: - msg = boilerplate_supported; - break; - default: - return QString(); - } - - return QString::fromLatin1(msg) - .arg(QLatin1String(QT_VERSION_STR)) - .arg(QLibraryInfo::licensee()) - .arg(qt_eval_days_left()); -} - -#define WARN_TIMEOUT 60 * 1000 * 119 -#define KILL_DELAY 60 * 1000 * 1 - -class QCoreFuriCuri : public QObject -{ -public: - - int warn; - int kill; - - QCoreFuriCuri() : QObject(), warn(-1), kill(-1) - { - if (qt_eval_is_supported() == EvaluationSupportedButTimeLimited) { - warn = startTimer(WARN_TIMEOUT); - kill = 0; - } - } - - void timerEvent(QTimerEvent *e) override { - if (e->timerId() == warn) { - killTimer(warn); - fprintf(stderr, "%s\n", will_shutdown_1min); - kill = startTimer(KILL_DELAY); - } else if (e->timerId() == kill) { - fprintf(stderr, "%s\n", will_shutdown_now); - QCoreApplication::instance()->quit(); - } - } -}; - -#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED) - -void qt_core_eval_init(QCoreApplicationPrivate::Type type) -{ - if (type != QCoreApplicationPrivate::Tty) - return; - - if (!qt_eval_is_supported()) - return; - - if (qt_eval_is_expired()) { - fprintf(stderr, "%s\n", boilerplate_expired); - exit(0); - } else { - fprintf(stderr, "%s\n", qPrintable(qt_eval_string())); - Q_UNUSED(new QCoreFuriCuri()); - } -} -#endif - -#ifdef QT_BUILD_WIDGETS_LIB - -QT_BEGIN_INCLUDE_NAMESPACE -#include <qdialog.h> -#include <qlabel.h> -#include <qlayout.h> -#include <qmessagebox.h> -#if QT_CONFIG(pushbutton) -#include <qpushbutton.h> -#endif -#include <qtimer.h> -#include <qapplication.h> -QT_END_INCLUDE_NAMESPACE - - -static const char * const qtlogo_eval_xpm[] = { -/* columns rows colors chars-per-pixel */ -"46 55 174 2", -" c #002E02", -". c #00370D", -"X c #003A0E", -"o c #003710", -"O c #013C13", -"+ c #043E1A", -"@ c #084F0A", -"# c #0B520C", -"$ c #054413", -"% c #0C4C17", -"& c #07421D", -"* c #09451D", -"= c #0D491E", -"- c #125515", -"; c #13541A", -": c #17591B", -"> c #1B5C1D", -", c #1F611F", -"< c #20621E", -"1 c #337B1E", -"2 c #0B4521", -"3 c #0F4923", -"4 c #114B24", -"5 c #154D2A", -"6 c #175323", -"7 c #1C5924", -"8 c #1C532F", -"9 c #1E5432", -"0 c #245936", -"q c #265938", -"w c #295C3B", -"e c #246324", -"r c #266823", -"t c #2A6C24", -"y c #276628", -"u c #2D7026", -"i c #327427", -"p c #367927", -"a c #37782A", -"s c #397C2A", -"d c #2E613E", -"f c #336C37", -"g c #2F6040", -"h c #356545", -"j c #3C6B4E", -"k c #3F6C51", -"l c #406E4F", -"z c #406D52", -"x c #477457", -"c c #497557", -"v c #4B7857", -"b c #517B5E", -"n c #3C8423", -"m c #3E812C", -"M c #53A61D", -"N c #41862C", -"B c #458A2D", -"V c #498F2D", -"C c #479324", -"Z c #489226", -"A c #4D952C", -"S c #478B30", -"D c #488C30", -"F c #4D9232", -"G c #509632", -"H c #549A33", -"J c #589F35", -"K c #56A526", -"L c #57A821", -"P c #5BAA27", -"I c #57A32A", -"U c #5CA72E", -"Y c #5DAB2A", -"T c #5CA336", -"R c #60AD2E", -"E c #63B12D", -"W c #65AF35", -"Q c #62A53F", -"! c #65AE39", -"~ c #66B036", -"^ c #6AB437", -"/ c #67B138", -"( c #6AB339", -") c #6DB838", -"_ c #70BA3C", -"` c #4D8545", -"' c #4E8942", -"] c #548851", -"[ c #6FAF4A", -"{ c #6DB243", -"} c #71B546", -"| c #70B840", -" . c #73B648", -".. c #79BA4E", -"X. c #7CBB53", -"o. c #598266", -"O. c #62886D", -"+. c #6A8F75", -"@. c #6B9173", -"#. c #70937A", -"$. c #799F79", -"%. c #7BAF66", -"&. c #81BD5B", -"*. c #85BF60", -"=. c #85AC7F", -"-. c #8DBA7B", -";. c #87C061", -":. c #8AC364", -">. c #8DC46A", -",. c #90C56E", -"<. c #93C771", -"1. c #96CA73", -"2. c #9ACB7C", -"3. c #9FD07D", -"4. c #779981", -"5. c #7F9F89", -"6. c #809F88", -"7. c #82A18B", -"8. c #86A192", -"9. c #8DA994", -"0. c #8FA998", -"q. c #94AF9B", -"w. c #97B991", -"e. c #97B19E", -"r. c #9DB6A3", -"t. c #A3BCA7", -"y. c #A6BCAB", -"u. c #A9BEB1", -"i. c #9ECD81", -"p. c #A2CF85", -"a. c #A5D284", -"s. c #A6D189", -"d. c #A9D28E", -"f. c #ABD491", -"g. c #B1D797", -"h. c #B1D699", -"j. c #B5D89E", -"k. c #ADC5AC", -"l. c #B1CAAE", -"z. c #B9DAA3", -"x. c #BDDDA8", -"c. c #ADC1B4", -"v. c #B2C6B6", -"b. c #B5C6BC", -"n. c #B6C9BA", -"m. c #BCD1BA", -"M. c #C6E1B4", -"N. c #CDE5BD", -"B. c #C2D2C6", -"V. c #CADEC2", -"C. c #C6D3CC", -"Z. c #C8D7CB", -"A. c #CEDAD2", -"S. c #D2DDD4", -"D. c #D3E9C6", -"F. c #D7EBC9", -"G. c #D9EBCD", -"H. c #DEEED4", -"J. c #D6E0D9", -"K. c #DAE4DC", -"L. c #E0EFD7", -"P. c #E5F2DD", -"I. c #DFE8E0", -"U. c #E4EBE5", -"Y. c #E9EFEA", -"T. c #EDF4EB", -"R. c #F0FAE6", -"E. c #F1F8EC", -"W. c #EDF0F0", -"Q. c #F4F7F3", -"!. c #F6F9F4", -"~. c #F8FAF7", -"^. c #FEFEFE", -"/. c None", -/* pixels */ -"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.", -"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.", -"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.", -"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.", -"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.", -"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.", -"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ", -"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ", -"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ", -"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ", -"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ", -"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", -"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ", -"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ", -"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ", -"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ", -"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ", -"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ", -"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ", -"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ", -"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ", -"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ", -"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ", -"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ", -"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ", -"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ", -"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .", -"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.", -"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.", -"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.", -"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.", -"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.", -"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.", -"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.", -"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.", -"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.", -"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.", -"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././." -}; - -class EvalMessageBox : public QDialog -{ -public: - EvalMessageBox(bool expired) - { - setWindowTitle(QLatin1String(" ")); - - QString str = expired ? QLatin1String(boilerplate_expired) : qt_eval_string(); - str = str.trimmed(); - - QFrame *border = new QFrame(this); - - QLabel *pixmap_label = new QLabel(border); - pixmap_label->setPixmap(QPixmap(qtlogo_eval_xpm)); - pixmap_label->setAlignment(Qt::AlignTop); - - QLabel *text_label = new QLabel(str, border); - - QHBoxLayout *pm_and_text_layout = new QHBoxLayout(); - pm_and_text_layout->addWidget(pixmap_label); - pm_and_text_layout->addWidget(text_label); - - QVBoxLayout *master_layout = new QVBoxLayout(border); - master_layout->addLayout(pm_and_text_layout); - - QVBoxLayout *border_layout = new QVBoxLayout(this); - border_layout->setMargin(0); - border_layout->addWidget(border); - - if (expired) { - QPushButton *cmd = new QPushButton(QLatin1String("OK"), border); - cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - cmd->setDefault(true); - - QHBoxLayout *button_layout = new QHBoxLayout(); - master_layout->addLayout(button_layout); - button_layout->addWidget(cmd); - - connect(cmd, SIGNAL(clicked()), this, SLOT(close())); - } else { - border->setFrameShape(QFrame::WinPanel); - border->setFrameShadow(QFrame::Raised); - setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); - QTimer::singleShot(7000, this, SLOT(close())); - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_QuitOnClose, false); - } - - setFixedSize(sizeHint()); - } -}; - -class QGuiFuriCuri : public QCoreFuriCuri -{ -public: - void timerEvent(QTimerEvent *e) { - if (e->timerId() == warn) { - killTimer(warn); - QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min)); - kill = startTimer(KILL_DELAY); - } else if (e->timerId() == kill) { - killTimer(kill); - QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now)); - qApp->quit(); - } - } -}; - - -void qt_gui_eval_init(QCoreApplicationPrivate::Type type) -{ - Q_UNUSED(type); - - if (!qt_eval_is_supported()) - return; - - if (qt_eval_is_expired()) { - EvalMessageBox box(true); - box.exec(); - ::exit(0); - } else { - Q_UNUSED(new QGuiFuriCuri()); - } -} - -static QString qt_eval_title_prefix() -{ - return QLatin1String("[Qt Evaluation] "); -} - -QString qt_eval_adapt_window_title(const QString &title) -{ - if (!qt_eval_is_supported()) - return title; - return qt_eval_title_prefix() + title; -} - -void qt_eval_init_widget(QWidget *w) -{ - if (!qt_eval_is_supported()) - return; - if (w->isTopLevel() && w->windowTitle().isEmpty() && w->windowType() != Qt::Desktop ) { - w->setWindowTitle(QLatin1String(" ")); - } -} -#endif - -QT_END_NAMESPACE diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 18c7f7648d..77d2c8cbe1 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2018 Intel Corporation. ** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ @@ -1462,6 +1462,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) if (size <= sizeof(QVariant::Private::Data) && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { type.construct(&d->data.ptr, copy); + d->is_null = d->data.ptr == nullptr; d->is_shared = false; } else { // Private::Data contains long long, and long double is the biggest standard type. @@ -1472,6 +1473,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) void *data = operator new(offset + size); void *ptr = static_cast<char *>(data) + offset; type.construct(ptr, copy); + d->is_null = ptr == nullptr; d->is_shared = true; d->data.shared = new (data) QVariant::PrivateShared(ptr); } @@ -4002,8 +4004,8 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private * return 0; // only do fuzzy comparisons for finite, non-zero numbers - int c1 = std::fpclassify(r1); - int c2 = std::fpclassify(r2); + int c1 = qFpClassify(r1); + int c2 = qFpClassify(r2); if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) { if (qFuzzyCompare(r1, r2)) return 0; diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index b22b7c231e..3d87beac83 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -88,7 +88,7 @@ inline T *v_cast(const QVariant::Private *nd, T * = 0) #else // every other compiler in this world template <typename T> -inline const T *v_cast(const QVariant::Private *d, T * = 0) +inline const T *v_cast(const QVariant::Private *d, T * = nullptr) { return !QVariantIntegrator<T>::CanUseInternalSpace ? static_cast<const T *>(d->data.shared->ptr) @@ -96,7 +96,7 @@ inline const T *v_cast(const QVariant::Private *d, T * = 0) } template <typename T> -inline T *v_cast(QVariant::Private *d, T * = 0) +inline T *v_cast(QVariant::Private *d, T * = nullptr) { return !QVariantIntegrator<T>::CanUseInternalSpace ? static_cast<T *>(d->data.shared->ptr) @@ -154,7 +154,7 @@ inline void v_construct(QVariant::Private *x, const T &t) // constructs a new variant if copy is 0, otherwise copy-constructs template <class T> -inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +inline void v_construct(QVariant::Private *x, const void *copy, T * = nullptr) { if (copy) v_construct<T>(x, *static_cast<const T *>(copy)); @@ -164,7 +164,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) // deletes the internal structures template <class T> -inline void v_clear(QVariant::Private *d, T* = 0) +inline void v_clear(QVariant::Private *d, T* = nullptr) { if (!QVariantIntegrator<T>::CanUseInternalSpace) { @@ -264,7 +264,7 @@ class QVariantIsNull struct No { char unused[2]; }; Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); - template<class C> static decltype(static_cast<const C*>(0)->isNull(), Yes()) test(int); + template<class C> static decltype(static_cast<const C*>(nullptr)->isNull(), Yes()) test(int); template<class C> static No test(...); public: static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes)); diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 37c8e3b157..7e2696b719 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -460,6 +460,7 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result) void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) { #ifdef QT_NO_XMLSTREAMREADER + Q_UNUSED(data); qWarning("Cannot load mime type since QXmlStreamReader is not available."); return; #else diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index d10575cfe9..815e0aa03b 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -194,8 +194,9 @@ static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttribute bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage) { #ifdef QT_NO_XMLSTREAMREADER + Q_UNUSED(dev); if (errorMessage) - *errorMessage = QString::fromLatin1("QXmlStreamReader is not available, cannot parse."); + *errorMessage = QString::fromLatin1("QXmlStreamReader is not available, cannot parse '%1'.").arg(fileName); return false; #else QMimeTypePrivate data; diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 3f650501c8..1a216c98b5 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -96,7 +96,7 @@ public: void setLoadHints(QLibrary::LoadHints lh); static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(), - QLibrary::LoadHints loadHints = 0); + QLibrary::LoadHints loadHints = nullptr); static QStringList suffixes_sys(const QString &fullVersion); static QStringList prefixes_sys(); diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index ead6ed5083..3ea518907b 100644 --- a/src/corelib/serialization/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp @@ -561,6 +561,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_11 Same as Qt_5_6 \value Qt_5_12 Version 18 (Qt 5.12) \value Qt_5_13 Version 19 (Qt 5.13) + \value Qt_5_14 Same as Qt_5_13 \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index 81134f74b0..6e358df02e 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -100,10 +100,11 @@ public: Qt_5_11 = Qt_5_10, Qt_5_12 = 18, Qt_5_13 = 19, -#if QT_VERSION >= 0x050e00 + Qt_5_14 = Qt_5_13, +#if QT_VERSION >= 0x050f00 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_13 + Qt_DefaultCompiledVersion = Qt_5_14 }; enum ByteOrder { diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h index 40b2414e4a..a9e7059cbe 100644 --- a/src/corelib/serialization/qjson_p.h +++ b/src/corelib/serialization/qjson_p.h @@ -686,7 +686,7 @@ public: { } inline Data(int reserved, QJsonValue::Type valueType) - : rawData(0), compactionCounter(0), ownsData(true) + : rawData(nullptr), compactionCounter(0), ownsData(true) { Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object); @@ -728,7 +728,7 @@ public: size = qMax(size + reserve, qMin(size *2, (int)Value::MaxSize)); if (size > Value::MaxSize) { qWarning("QJson: Document too large to store in data structure"); - return 0; + return nullptr; } } char *raw = (char *)malloc(size); diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index c9ba183a50..0d83bb6cd4 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -135,30 +135,30 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; \table \header \li Manipulator \li Description - \row \li \c bin \li Same as setIntegerBase(2). - \row \li \c oct \li Same as setIntegerBase(8). - \row \li \c dec \li Same as setIntegerBase(10). - \row \li \c hex \li Same as setIntegerBase(16). - \row \li \c showbase \li Same as setNumberFlags(numberFlags() | ShowBase). - \row \li \c forcesign \li Same as setNumberFlags(numberFlags() | ForceSign). - \row \li \c forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint). - \row \li \c noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase). - \row \li \c noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign). - \row \li \c noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint). - \row \li \c uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase). - \row \li \c uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits). - \row \li \c lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase). - \row \li \c lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits). - \row \li \c fixed \li Same as setRealNumberNotation(FixedNotation). - \row \li \c scientific \li Same as setRealNumberNotation(ScientificNotation). - \row \li \c left \li Same as setFieldAlignment(AlignLeft). - \row \li \c right \li Same as setFieldAlignment(AlignRight). - \row \li \c center \li Same as setFieldAlignment(AlignCenter). - \row \li \c endl \li Same as operator<<('\\n') and flush(). - \row \li \c flush \li Same as flush(). - \row \li \c reset \li Same as reset(). - \row \li \c ws \li Same as skipWhiteSpace(). - \row \li \c bom \li Same as setGenerateByteOrderMark(true). + \row \li \c Qt::bin \li Same as setIntegerBase(2). + \row \li \c Qt::oct \li Same as setIntegerBase(8). + \row \li \c Qt::dec \li Same as setIntegerBase(10). + \row \li \c Qt::hex \li Same as setIntegerBase(16). + \row \li \c Qt::showbase \li Same as setNumberFlags(numberFlags() | ShowBase). + \row \li \c Qt::forcesign \li Same as setNumberFlags(numberFlags() | ForceSign). + \row \li \c Qt::forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint). + \row \li \c Qt::noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase). + \row \li \c Qt::noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign). + \row \li \c Qt::noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint). + \row \li \c Qt::uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase). + \row \li \c Qt::uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits). + \row \li \c Qt::lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase). + \row \li \c Qt::lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits). + \row \li \c Qt::fixed \li Same as setRealNumberNotation(FixedNotation). + \row \li \c Qt::scientific \li Same as setRealNumberNotation(ScientificNotation). + \row \li \c Qt::left \li Same as setFieldAlignment(AlignLeft). + \row \li \c Qt::right \li Same as setFieldAlignment(AlignRight). + \row \li \c Qt::center \li Same as setFieldAlignment(AlignCenter). + \row \li \c Qt::endl \li Same as operator<<('\\n') and flush(). + \row \li \c Qt::flush \li Same as flush(). + \row \li \c Qt::reset \li Same as reset(). + \row \li \c Qt::ws \li Same as skipWhiteSpace(). + \row \li \c Qt::bom \li Same as setGenerateByteOrderMark(true). \endtable In addition, Qt provides three global manipulators that take a @@ -2689,6 +2689,11 @@ QTextStream &QTextStream::operator<<(const void *ptr) d->params.numberFlags = oldFlags; return *this; } +#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +namespace Qt { +#else +namespace QTextStreamFunctions { +#endif /*! \relates QTextStream @@ -3015,6 +3020,8 @@ QTextStream &ws(QTextStream &stream) return stream; } +} // namespace QTextStreamFunctions + /*! \fn QTextStreamManipulator qSetFieldWidth(int width) \relates QTextStream @@ -3037,6 +3044,12 @@ QTextStream &ws(QTextStream &stream) */ #if QT_CONFIG(textcodec) + +#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +namespace Qt { +#else +namespace QTextStreamFunctions { +#endif /*! \relates QTextStream @@ -3051,6 +3064,8 @@ QTextStream &bom(QTextStream &stream) return stream; } +} // namespace QTextStreamFunctions + /*! Sets the codec for this stream to \a codec. The codec is used for decoding any data that is read from the assigned device, and for @@ -3200,6 +3215,43 @@ QLocale QTextStream::locale() const return d->locale; } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC) +// Binary compatible definitions for Qt<5.14 +Q_CORE_EXPORT QTextStream &bin(QTextStream &s) { return Qt::bin(s); } +Q_CORE_EXPORT QTextStream &oct(QTextStream &s) { return Qt::oct(s); } +Q_CORE_EXPORT QTextStream &dec(QTextStream &s) { return Qt::dec(s); } +Q_CORE_EXPORT QTextStream &hex(QTextStream &s) { return Qt::hex(s); } + +Q_CORE_EXPORT QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); } +Q_CORE_EXPORT QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); } +Q_CORE_EXPORT QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); } +Q_CORE_EXPORT QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); } +Q_CORE_EXPORT QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); } +Q_CORE_EXPORT QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); } + +Q_CORE_EXPORT QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); } +Q_CORE_EXPORT QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); } +Q_CORE_EXPORT QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); } +Q_CORE_EXPORT QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); } + +Q_CORE_EXPORT QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); } +Q_CORE_EXPORT QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); } + +Q_CORE_EXPORT QTextStream &left(QTextStream &s) { return Qt::left(s); } +Q_CORE_EXPORT QTextStream &right(QTextStream &s) { return Qt::right(s); } +Q_CORE_EXPORT QTextStream ¢er(QTextStream &s) { return Qt::center(s); } + +Q_CORE_EXPORT QTextStream &endl(QTextStream &s) { return Qt::endl(s); } +Q_CORE_EXPORT QTextStream &flush(QTextStream &s) { return Qt::flush(s); } +Q_CORE_EXPORT QTextStream &reset(QTextStream &s) { return Qt::reset(s); } + +Q_CORE_EXPORT QTextStream &ws(QTextStream &s) { return Qt::ws(s); } + +#if QT_CONFIG(textcodec) +Q_CORE_EXPORT QTextStream &bom(QTextStream &s) { return Qt::bom(s); } +#endif +#endif + QT_END_NAMESPACE #ifndef QT_NO_QOBJECT diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h index 1d86a18b9c..7673e5d87e 100644 --- a/src/corelib/serialization/qtextstream.h +++ b/src/corelib/serialization/qtextstream.h @@ -233,6 +233,13 @@ inline QTextStream &operator<<(QTextStream &s, QTextStreamFunction f) inline QTextStream &operator<<(QTextStream &s, QTextStreamManipulator m) { m.exec(s); return s; } +#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +namespace Qt { +#else +// This namespace only exists for 'using namespace' declarations. +namespace QTextStreamFunctions { +#endif + Q_CORE_EXPORT QTextStream &bin(QTextStream &s); Q_CORE_EXPORT QTextStream &oct(QTextStream &s); Q_CORE_EXPORT QTextStream &dec(QTextStream &s); @@ -265,6 +272,18 @@ Q_CORE_EXPORT QTextStream &bom(QTextStream &s); Q_CORE_EXPORT QTextStream &ws(QTextStream &s); +} // namespace QTextStreamFunctions + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC) +namespace Qt { +using namespace QTextStreamFunctions; +} + +// We use 'using namespace' as that doesn't cause +// conflicting definitions compiler errors. +using namespace QTextStreamFunctions; +#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC) + inline QTextStreamManipulator qSetFieldWidth(int width) { QTSMFI func = &QTextStream::setFieldWidth; diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index 61f501f81b..cde66a48a3 100644 --- a/src/corelib/serialization/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h @@ -162,12 +162,12 @@ public: const char *const QXmlStreamReader_Table::spell [] = { - "end of file", 0, " ", "<", ">", "&", "#", "\'", "\"", "[", + "end of file", nullptr, " ", "<", ">", "&", "#", "\'", "\"", "[", "]", "(", ")", "|", "=", "%", "/", ":", ";", ",", "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE", "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED", - "EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF", - "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", 0}; + "EMPTY", "ANY", "PCDATA", nullptr, nullptr, nullptr, nullptr, "CDATA", "ID", "IDREF", + "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", nullptr}; const short QXmlStreamReader_Table::lhs [] = { 57, 57, 59, 59, 59, 59, 59, 59, 59, 59, @@ -645,7 +645,7 @@ template <typename T> class QXmlStreamSimpleStack { T *data; int tos, cap; public: - inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){} + inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){} inline ~QXmlStreamSimpleStack(){ if (data) free(data); } inline void reserve(int extraCapacity) { @@ -995,7 +995,7 @@ public: int fastScanLiteralContent(); int fastScanSpace(); int fastScanContentCharList(); - int fastScanName(int *prefix = 0); + int fastScanName(int *prefix = nullptr); inline int fastScanNMTOKEN(); diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 7fb40392e7..ec746caae1 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -68,14 +68,14 @@ QT_BEGIN_NAMESPACE struct QPropertyAssignment { QPropertyAssignment() - : object(0), explicitlySet(true) {} + : object(nullptr), explicitlySet(true) {} QPropertyAssignment(QObject *o, const QByteArray &n, const QVariant &v, bool es = true) : object(o), propertyName(n), value(v), explicitlySet(es) {} bool objectDeleted() const { return !object; } - void write() const { Q_ASSERT(object != 0); object->setProperty(propertyName, value); } + void write() const { Q_ASSERT(object != nullptr); object->setProperty(propertyName, value); } bool hasTarget(QObject *o, const QByteArray &pn) const { return object == o && propertyName == pn; } @@ -99,8 +99,8 @@ public: QStatePrivate(); ~QStatePrivate(); - static QStatePrivate *get(QState *q) { return q ? q->d_func() : 0; } - static const QStatePrivate *get(const QState *q) { return q? q->d_func() : 0; } + static QStatePrivate *get(QState *q) { return q ? q->d_func() : nullptr; } + static const QStatePrivate *get(const QState *q) { return q? q->d_func() : nullptr; } QList<QAbstractState*> childStates() const; QList<QHistoryState*> historyStates() const; diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index f3366ca5f7..c66130b8ce 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -108,7 +108,7 @@ public: ~QStateMachinePrivate(); static QStateMachinePrivate *get(QStateMachine *q) - { return q ? q->d_func() : 0; } + { return q ? q->d_func() : nullptr; } QState *findLCA(const QList<QAbstractState*> &states, bool onlyCompound = false) const; QState *findLCCA(const QList<QAbstractState*> &states) const; @@ -313,7 +313,7 @@ public: DelayedEvent(QEvent *e, int tid) : event(e), timerId(tid) {} DelayedEvent() - : event(0), timerId(0) {} + : event(nullptr), timerId(0) {} }; QHash<int, DelayedEvent> delayedEvents; QHash<int, int> timerIdToDelayedEventId; diff --git a/src/corelib/thread/qatomic_bootstrap.h b/src/corelib/thread/qatomic_bootstrap.h index b463f817bd..27a67fb2ee 100644 --- a/src/corelib/thread/qatomic_bootstrap.h +++ b/src/corelib/thread/qatomic_bootstrap.h @@ -65,7 +65,7 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> > return --_q_value != 0; } - static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW + static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW { if (currentValue) *currentValue = _q_value; diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index ded102d32d..5b2c7ab112 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE +#if QT_CONFIG(thread) + /* Locks 2 mutexes in a defined order, avoiding a recursive lock if we're trying to lock the same mutex twice. @@ -65,9 +67,9 @@ QT_BEGIN_NAMESPACE class QOrderedMutexLocker { public: - QOrderedMutexLocker(QMutex *m1, QMutex *m2) - : mtx1((m1 == m2) ? m1 : (std::less<QMutex *>()(m1, m2) ? m1 : m2)), - mtx2((m1 == m2) ? 0 : (std::less<QMutex *>()(m1, m2) ? m2 : m1)), + QOrderedMutexLocker(QBasicMutex *m1, QBasicMutex *m2) + : mtx1((m1 == m2) ? m1 : (std::less<QBasicMutex *>()(m1, m2) ? m1 : m2)), + mtx2((m1 == m2) ? 0 : (std::less<QBasicMutex *>()(m1, m2) ? m2 : m1)), locked(false) { relock(); @@ -95,12 +97,12 @@ public: } } - static bool relock(QMutex *mtx1, QMutex *mtx2) + static bool relock(QBasicMutex *mtx1, QBasicMutex *mtx2) { // mtx1 is already locked, mtx2 not... do we need to unlock and relock? if (mtx1 == mtx2) return false; - if (std::less<QMutex *>()(mtx1, mtx2)) { + if (std::less<QBasicMutex *>()(mtx1, mtx2)) { mtx2->lock(); return true; } @@ -113,10 +115,58 @@ public: } private: - QMutex *mtx1, *mtx2; + QBasicMutex *mtx1, *mtx2; bool locked; }; +class QBasicMutexLocker +{ +public: + inline explicit QBasicMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT + : m(m), isLocked(true) + { + m->lock(); + } + inline ~QBasicMutexLocker() { if (isLocked) unlock(); } + + inline void unlock() Q_DECL_NOTHROW + { + isLocked = false; + m->unlock(); + } + + inline void relock() QT_MUTEX_LOCK_NOEXCEPT + { + isLocked = true; + m->lock(); + } + +private: + Q_DISABLE_COPY(QBasicMutexLocker) + + QBasicMutex *m; + bool isLocked; +}; + +#else + +class QOrderedMutexLocker +{ +public: + QOrderedMutexLocker(QBasicMutex *, QBasicMutex *) {} + ~QOrderedMutexLocker() {} + + void relock() {} + void unlock() {} + + static bool relock(QBasicMutex *, QBasicMutex *) {} +}; + +using QBasicMutexLocker = QMutexLocker; + +#endif + + QT_END_NAMESPACE #endif diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h index 1f29e8d187..7a65089396 100644 --- a/src/corelib/thread/qresultstore.h +++ b/src/corelib/thread/qresultstore.h @@ -142,7 +142,7 @@ public: template <typename T> int addResult(int index, const T *result) { - if (result == 0) + if (result == nullptr) return addResult(index, static_cast<void *>(nullptr)); else return addResult(index, static_cast<void *>(new T(*result))); @@ -158,7 +158,7 @@ public: int addResults(int index, const QVector<T> *results, int totalCount) { if (m_filterMode == true && results->count() != totalCount && 0 == results->count()) - return addResults(index, 0, 0, totalCount); + return addResults(index, nullptr, 0, totalCount); else return addResults(index, new QVector<T>(*results), results->count(), totalCount); } diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 7d9442ab79..e614ddd004 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -89,7 +89,7 @@ public: QEvent *event; int priority; inline QPostEvent() - : receiver(0), event(0), priority(0) + : receiver(nullptr), event(nullptr), priority(0) { } inline QPostEvent(QObject *r, QEvent *e, int p) : receiver(r), event(e), priority(p) @@ -148,7 +148,7 @@ private: class Q_CORE_EXPORT QDaemonThread : public QThread { public: - QDaemonThread(QObject *parent = 0); + QDaemonThread(QObject *parent = nullptr); ~QDaemonThread(); }; @@ -157,7 +157,7 @@ class QThreadPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QThread) public: - QThreadPrivate(QThreadData *d = 0); + QThreadPrivate(QThreadData *d = nullptr); ~QThreadPrivate(); void setPriority(QThread::Priority prio); @@ -248,7 +248,7 @@ public: #endif static void clearCurrentThreadData(); static QThreadData *get2(QThread *thread) - { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; } + { Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; } void ref(); @@ -281,7 +281,7 @@ public: public: FlaggedDebugSignatures() : idx(0) - { std::fill_n(locations, Count, static_cast<char*>(0)); } + { std::fill_n(locations, Count, static_cast<char*>(nullptr)); } void store(const char* method) { locations[idx++ % Count] = method; } @@ -328,7 +328,7 @@ class QAdoptedThread : public QThread Q_DECLARE_PRIVATE(QThread) public: - QAdoptedThread(QThreadData *data = 0); + QAdoptedThread(QThreadData *data = nullptr); ~QAdoptedThread(); void init(); diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index 952e02ef20..01852d8366 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -162,7 +162,7 @@ public: void tryToStartMoreThreads(); bool tooManyThreadsActive() const; - void startThread(QRunnable *runnable = 0); + void startThread(QRunnable *runnable = nullptr); void reset(); bool waitForDone(int msecs); bool waitForDone(const QDeadlineTimer &timer); diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 55fc482da3..9eb8672e92 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -69,7 +69,7 @@ inline T *&qThreadStorage_localData(QThreadStorageData &d, T **) { void **v = d.get(); - if (!v) v = d.set(0); + if (!v) v = d.set(nullptr); return *(reinterpret_cast<T**>(v)); } @@ -139,7 +139,7 @@ public: inline ~QThreadStorage() { } inline bool hasLocalData() const - { return d.get() != 0; } + { return d.get() != nullptr; } inline T& localData() { return qThreadStorage_localData(d, reinterpret_cast<T*>(0)); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 0f27071176..8bf20350d6 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -4136,10 +4136,9 @@ ushort QByteArray::toUShort(bool *ok, int base) const double QByteArray::toDouble(bool *ok) const { - QByteArray nulled = nulTerminated(); bool nonNullOk = false; int processed = 0; - double d = qt_asciiToDouble(nulled.constData(), nulled.length(), + double d = qt_asciiToDouble(constData(), size(), nonNullOk, processed, WhitespacesAllowed); if (ok) *ok = nonNullOk; diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index 8c0e7860f7..b558a8358d 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -51,7 +51,7 @@ class QCache struct Node { inline Node() : keyPtr(0) {} inline Node(T *data, int cost) - : keyPtr(0), t(data), c(cost), p(0), n(0) {} + : keyPtr(nullptr), t(data), c(cost), p(nullptr), n(nullptr) {} const Key *keyPtr; T *t; int c; Node *p,*n; }; Node *f, *l; @@ -71,14 +71,14 @@ class QCache inline T *relink(const Key &key) { typename QHash<Key, Node>::iterator i = hash.find(key); if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) - return 0; + return nullptr; Node &n = *i; if (f != &n) { if (n.p) n.p->n = n.n; if (n.n) n.n->p = n.p; if (l == &n) l = n.p; - n.p = 0; + n.p = nullptr; n.n = f; f->p = &n; f = &n; @@ -117,12 +117,12 @@ private: template <class Key, class T> inline QCache<Key, T>::QCache(int amaxCost) Q_DECL_NOTHROW - : f(0), l(0), mx(amaxCost), total(0) {} + : f(nullptr), l(nullptr), mx(amaxCost), total(0) {} template <class Key, class T> inline void QCache<Key,T>::clear() { while (f) { delete f->t; f = f->n; } - hash.clear(); l = 0; total = 0; } + hash.clear(); l = nullptr; total = 0; } template <class Key, class T> inline void QCache<Key,T>::setMaxCost(int m) @@ -153,11 +153,11 @@ inline T *QCache<Key,T>::take(const Key &key) { typename QHash<Key, Node>::iterator i = hash.find(key); if (i == hash.end()) - return 0; + return nullptr; Node &n = *i; T *t = n.t; - n.t = 0; + n.t = nullptr; unlink(n); return t; } diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp index 76dcf35833..d73eb0d07c 100644 --- a/src/corelib/tools/qcollator.cpp +++ b/src/corelib/tools/qcollator.cpp @@ -59,20 +59,21 @@ QT_BEGIN_NAMESPACE \ingroup string-processing \ingroup shared - QCollator is initialized with a QLocale and an optional collation strategy. It tries to - initialize the collator with the specified values. The collator can then be used to compare - and sort strings in a locale dependent fashion. + QCollator is initialized with a QLocale and an optional collation strategy. + It tries to initialize the collator with the specified values. The collator + can then be used to compare and sort strings in a locale dependent fashion. - A QCollator object can be used together with template based sorting algorithms such as std::sort - to sort a list of QStrings. + A QCollator object can be used together with template based sorting + algorithms such as std::sort to sort a list of QStrings. - In addition to the locale and collation strategy, several optional flags can be set that influence - the result of the collation. + In addition to the locale and collation strategy, several optional flags can + be set that influence the result of the collation. */ /*! - Constructs a QCollator from \a locale. If \a locale is not specified - the system's default locale is used. + Constructs a QCollator for \a locale. + + If \a locale is not specified, the system's default locale is used. \sa setLocale() */ @@ -128,9 +129,9 @@ QCollator &QCollator::operator=(const QCollator &other) Move constructor. Moves from \a other into this collator. - Note that a moved-from QCollator can only be destroyed or assigned - to. The effect of calling other functions than the destructor or - one of the assignment operators is undefined. + Note that a moved-from QCollator can only be destroyed or assigned to. + The effect of calling other functions than the destructor or one of the + assignment operators is undefined. */ /*! @@ -138,9 +139,9 @@ QCollator &QCollator::operator=(const QCollator &other) Move-assigns from \a other to this collator. - Note that a moved-from QCollator can only be destroyed or assigned - to. The effect of calling other functions than the destructor or - one of the assignment operators is undefined. + Note that a moved-from QCollator can only be destroyed or assigned to. + The effect of calling other functions than the destructor or one of the + assignment operators is undefined. */ /*! @@ -218,7 +219,8 @@ Qt::CaseSensitivity QCollator::caseSensitivity() const Enables numeric sorting mode when \a on is set to true. - This will enable proper sorting of numeric digits, so that e.g. 100 sorts after 99. + This will enable proper sorting of numeric digits, so that e.g. 100 sorts + after 99. By default this mode is off. @@ -248,11 +250,13 @@ bool QCollator::numericMode() const /*! \fn void QCollator::setIgnorePunctuation(bool on) - If \a on is set to true, punctuation characters and symbols are ignored when determining sort order. + If \a on is set to true, punctuation characters and symbols are ignored when + determining sort order. The default is locale dependent. - \note This method is not currently supported if Qt is configured to not use ICU on Linux. + \note This method is not currently supported if Qt is configured to not use + ICU on Linux. \sa ignorePunctuation() */ @@ -268,7 +272,8 @@ void QCollator::setIgnorePunctuation(bool on) /*! \fn bool QCollator::ignorePunctuation() const - Returns \c true if punctuation characters and symbols are ignored when determining sort order. + Returns \c true if punctuation characters and symbols are ignored when + determining sort order. \sa setIgnorePunctuation() */ @@ -278,35 +283,66 @@ bool QCollator::ignorePunctuation() const } /*! - \fn int QCollator::compare(const QString &s1, const QString &s2) const + \since 5.13 + \fn bool QCollator::operator()(QStringView s1, QStringView s2) const + \internal +*/ + +/*! + \since 5.13 + \fn int QCollator::compare(QStringView s1, QStringView s2) const - Compares \a s1 with \a s2. Returns an integer less than, equal to, or greater than zero - depending on whether \a s1 is smaller, equal or larger than \a s2. - */ + Compares \a s1 with \a s2. + Returns an integer less than, equal to, or greater than zero depending on + whether \a s1 sorts before, with or after \a s2. +*/ +#if QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QCollator::operator()(const QString &s1, const QString &s2) const \internal */ /*! - \fn int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const \overload - Compares \a s1 with \a s2. Returns an integer less than, equal to, or greater than zero - depending on whether \a s1 is smaller, equal or larger than \a s2. + Compares \a s1 with \a s2. + + Returns an integer less than, equal to, or greater than zero depending on + whether \a s1 sorts before, with or after \a s2. +*/ +int QCollator::compare(const QString &s1, const QString &s2) const +{ + return compare(QStringView(s1), QStringView(s2)); +} + +/*! + \overload + + Compares \a s1 with \a s2. + + Returns an integer less than, equal to, or greater than zero depending on + whether \a s1 sorts before, with or after \a s2. */ +int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const +{ + return compare(QStringView(s1), QStringView(s2)); +} /*! - \fn int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const \overload - Compares \a s1 with \a s2. \a len1 and \a len2 specify the length of the - QChar arrays pointer to by \a s1 and \a s2. + Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the + QChar arrays pointed to by \a s1 and \a s2. - Returns an integer less than, equal to, or greater than zero - depending on whether \a s1 is smaller, equal or larger than \a s2. + Returns an integer less than, equal to, or greater than zero depending on + whether \a s1 sorts before, with or after \a s2. */ +int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const +{ + return compare(QStringView(s1, len1), QStringView(s2, len2)); +} +#endif // QT_STRINGVIEW_LEVEL < 2 /*! \fn QCollatorSortKey QCollator::sortKey(const QString &string) const @@ -314,9 +350,9 @@ bool QCollator::ignorePunctuation() const Returns a sortKey for \a string. Creating the sort key is usually somewhat slower, than using the compare() - methods directly. But if the string is compared repeatedly (e.g. when sorting - a whole list of strings), it's usually faster to create the sort keys for each - string and then sort using the keys. + methods directly. But if the string is compared repeatedly (e.g. when + sorting a whole list of strings), it's usually faster to create the sort + keys for each string and then sort using the keys. \note Not supported with the C (a.k.a. POSIX) locale on Darwin. */ @@ -328,8 +364,8 @@ bool QCollator::ignorePunctuation() const \since 5.2 - The QCollatorSortKey class is always created by QCollator::sortKey() - and is used for fast strings collation, for example when collating many strings. + The QCollatorSortKey class is always created by QCollator::sortKey() and is + used for fast strings collation, for example when collating many strings. \reentrant \ingroup i18n @@ -398,9 +434,11 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other) /*! \fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const - Compares the key to \a otherKey. Returns a negative value if the key - is less than \a otherKey, 0 if the key is equal to \a otherKey or a - positive value if the key is greater than \a otherKey. + Compares this key to \a otherKey. + + Returns a negative value if the key is less than \a otherKey, 0 if the key + is equal to \a otherKey or a positive value if the key is greater than \a + otherKey. \sa operator<() */ diff --git a/src/corelib/tools/qcollator.h b/src/corelib/tools/qcollator.h index 6fa199cb0f..700de739bb 100644 --- a/src/corelib/tools/qcollator.h +++ b/src/corelib/tools/qcollator.h @@ -109,12 +109,18 @@ public: void setIgnorePunctuation(bool on); bool ignorePunctuation() const; +#if QT_STRINGVIEW_LEVEL < 2 int compare(const QString &s1, const QString &s2) const; int compare(const QStringRef &s1, const QStringRef &s2) const; int compare(const QChar *s1, int len1, const QChar *s2, int len2) const; bool operator()(const QString &s1, const QString &s2) const { return compare(s1, s2) < 0; } +#endif + int compare(QStringView s1, QStringView s2) const; + + bool operator()(QStringView s1, QStringView s2) const + { return compare(s1, s2) < 0; } QCollatorSortKey sortKey(const QString &string) const; diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp index ab45b9a1a1..8acda45070 100644 --- a/src/corelib/tools/qcollator_icu.cpp +++ b/src/corelib/tools/qcollator_icu.cpp @@ -78,7 +78,8 @@ void QCollatorPrivate::init() // and does case sensitive comparison. // UCOL_QUATERNARY is used as default in a few languages such as Japanese to take care of some // additional differences in those languages. - UColAttributeValue val = (caseSensitivity == Qt::CaseSensitive) ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY; + UColAttributeValue val = (caseSensitivity == Qt::CaseSensitive) + ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY; status = U_ZERO_ERROR; ucol_setAttribute(collator, UCOL_STRENGTH, val, &status); @@ -91,7 +92,8 @@ void QCollatorPrivate::init() qWarning("ucol_setAttribute: numeric collation failed: %d", status); status = U_ZERO_ERROR; - ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, ignorePunctuation ? UCOL_SHIFTED : UCOL_NON_IGNORABLE, &status); + ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, + ignorePunctuation ? UCOL_SHIFTED : UCOL_NON_IGNORABLE, &status); if (U_FAILURE(status)) qWarning("ucol_setAttribute: Alternate handling failed: %d", status); @@ -105,37 +107,20 @@ void QCollatorPrivate::cleanup() collator = nullptr; } -int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const +int QCollator::compare(QStringView s1, QStringView s2) const { if (d->dirty) d->init(); - if (d->collator) - return ucol_strcoll(d->collator, (const UChar *)s1, len1, (const UChar *)s2, len2); - - return QString::compare_helper(s1, len1, s2, len2, d->caseSensitivity); -} - -int QCollator::compare(const QString &s1, const QString &s2) const -{ - if (d->dirty) - d->init(); - - if (d->collator) - return compare(s1.constData(), s1.size(), s2.constData(), s2.size()); - - return QString::compare(s1, s2, d->caseSensitivity); -} - -int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const -{ - if (d->dirty) - d->init(); - - if (d->collator) - return compare(s1.constData(), s1.size(), s2.constData(), s2.size()); + if (d->collator) { + return ucol_strcoll(d->collator, + reinterpret_cast<const UChar *>(s1.data()), s1.size(), + reinterpret_cast<const UChar *>(s2.data()), s2.size()); + } - return QStringRef::compare(s1, s2, d->caseSensitivity); + return QString::compare_helper(s1.data(), s1.size(), + s2.data(), s2.size(), + d->caseSensitivity); } QCollatorSortKey QCollator::sortKey(const QString &string) const diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp index 42e67e0c12..071d7c048f 100644 --- a/src/corelib/tools/qcollator_macx.cpp +++ b/src/corelib/tools/qcollator_macx.cpp @@ -65,12 +65,12 @@ void QCollatorPrivate::init() return; LocaleRef localeRef; - int rc = LocaleRefFromLocaleString(QLocalePrivate::get(locale)->bcp47Name().constData(), &localeRef); - if (rc != 0) - qWarning("couldn't initialize the locale"); + OSStatus status = + LocaleRefFromLocaleString(QLocalePrivate::get(locale)->bcp47Name().constData(), &localeRef); + if (status != 0) + qWarning("Couldn't initialize the locale (%d)", int(status)); UInt32 options = 0; - if (caseSensitivity == Qt::CaseInsensitive) options |= kUCCollateCaseInsensitiveMask; if (numericMode) @@ -78,14 +78,9 @@ void QCollatorPrivate::init() if (!ignorePunctuation) options |= kUCCollatePunctuationSignificantMask; - OSStatus status = UCCreateCollator( - localeRef, - 0, - options, - &collator - ); + status = UCCreateCollator(localeRef, 0, options, &collator); if (status != 0) - qWarning("Couldn't initialize the collator"); + qWarning("Couldn't initialize the collator (%d)", int(status)); dirty = false; } @@ -97,18 +92,18 @@ void QCollatorPrivate::cleanup() collator = 0; } -int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const +int QCollator::compare(QStringView s1, QStringView s2) const { if (d->dirty) d->init(); if (!d->collator) - return QStringView(s1, len1).compare(QStringView(s2, len2), caseSensitivity()); + return s1.compare(s2, caseSensitivity()); SInt32 result; Boolean equivalent; UCCompareText(d->collator, - reinterpret_cast<const UniChar *>(s1), len1, - reinterpret_cast<const UniChar *>(s2), len2, + reinterpret_cast<const UniChar *>(s1.data()), s1.size(), + reinterpret_cast<const UniChar *>(s2.data()), s2.size(), &equivalent, &result); if (equivalent) @@ -116,16 +111,6 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con return result < 0 ? -1 : 1; } -int QCollator::compare(const QString &str1, const QString &str2) const -{ - return compare(str1.constData(), str1.size(), str2.constData(), str2.size()); -} - -int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const -{ - return compare(s1.constData(), s1.size(), s2.constData(), s2.size()); -} - QCollatorSortKey QCollator::sortKey(const QString &string) const { if (d->dirty) @@ -139,13 +124,14 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const //Documentation recommends having it 5 times as big as the input QVector<UCCollationValue> ret(string.size() * 5); ItemCount actualSize; - int status = UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()), string.count(), - ret.size(), &actualSize, ret.data()); + int status = UCGetCollationKey(d->collator, + reinterpret_cast<const UniChar *>(string.constData()), + string.count(), ret.size(), &actualSize, ret.data()); - ret.resize(actualSize+1); + ret.resize(actualSize + 1); if (status == kUCOutputBufferTooSmall) { - UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()), string.count(), - ret.size(), &actualSize, ret.data()); + UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()), + string.count(), ret.size(), &actualSize, ret.data()); } ret[actualSize] = 0; return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(ret))); diff --git a/src/corelib/tools/qcollator_posix.cpp b/src/corelib/tools/qcollator_posix.cpp index 81f97a02e1..9cbc539ebe 100644 --- a/src/corelib/tools/qcollator_posix.cpp +++ b/src/corelib/tools/qcollator_posix.cpp @@ -65,7 +65,7 @@ void QCollatorPrivate::cleanup() { } -static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, const QString &string) +static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, QStringView string) { ret.resize(string.length()); int len = string.toWCharArray(ret.data()); @@ -73,12 +73,7 @@ static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, const QString &str ret[len] = 0; } -int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const -{ - return compare(QString::fromRawData(s1, len1), QString::fromRawData(s2, len2)); -} - -int QCollator::compare(const QString &s1, const QString &s2) const +int QCollator::compare(QStringView s1, QStringView s2) const { if (d->isC()) return s1.compare(s2, caseSensitivity()); @@ -91,11 +86,6 @@ int QCollator::compare(const QString &s1, const QString &s2) const return std::wcscoll(array1.constData(), array2.constData()); } -int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const -{ - return compare(s1.toString(), s2.toString()); -} - QCollatorSortKey QCollator::sortKey(const QString &string) const { if (d->dirty) diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp index 10cfdaa264..9d81de882f 100644 --- a/src/corelib/tools/qcollator_win.cpp +++ b/src/corelib/tools/qcollator_win.cpp @@ -87,30 +87,30 @@ void QCollatorPrivate::cleanup() { } - -int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const +int QCollator::compare(QStringView s1, QStringView s2) const { if (d->isC()) - return QString::compare_helper(s1, len1, s2, len2, d->caseSensitivity); + return s1.compare(s2, d->caseSensitivity); if (d->dirty) d->init(); //* from Windows documentation * - // Returns one of the following values if successful. To maintain the C runtime convention of - // comparing strings, the value 2 can be subtracted from a nonzero return value. Then, the - // meaning of <0, ==0, and >0 is consistent with the C runtime. + // Returns one of the following values if successful. To maintain the C + // runtime convention of comparing strings, the value 2 can be subtracted + // from a nonzero return value. Then, the meaning of <0, ==0, and >0 is + // consistent with the C runtime. // [...] The function returns 0 if it does not succeed. // https://docs.microsoft.com/en-us/windows/desktop/api/stringapiset/nf-stringapiset-comparestringex#return-value #ifndef USE_COMPARESTRINGEX const int ret = CompareString(d->localeID, d->collator, - reinterpret_cast<const wchar_t*>(s1), len1, - reinterpret_cast<const wchar_t*>(s2), len2); + reinterpret_cast<const wchar_t *>(s1.data()), s1.size(), + reinterpret_cast<const wchar_t *>(s2.data()), s2.size()); #else const int ret = CompareStringEx(LPCWSTR(d->localeName.utf16()), d->collator, - reinterpret_cast<LPCWSTR>(s1), len1, - reinterpret_cast<LPCWSTR>(s2), len2, + reinterpret_cast<LPCWSTR>(s1.data()), s1.size(), + reinterpret_cast<LPCWSTR>(s2.data()), s2.size(), nullptr, nullptr, 0); #endif if (Q_LIKELY(ret)) @@ -132,16 +132,6 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con return 0; } -int QCollator::compare(const QString &str1, const QString &str2) const -{ - return compare(str1.constData(), str1.size(), str2.constData(), str2.size()); -} - -int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const -{ - return compare(s1.constData(), s1.size(), s2.constData(), s2.size()); -} - QCollatorSortKey QCollator::sortKey(const QString &string) const { if (d->dirty) @@ -170,7 +160,9 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const NULL, NULL, 0); #endif if (finalSize == 0) { - qWarning() << "there were problems when generating the ::sortKey by LCMapStringW with error:" << GetLastError(); + qWarning() + << "there were problems when generating the ::sortKey by LCMapStringW with error:" + << GetLastError(); } return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(ret))); } diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index 4d30d4192b..6e4120d762 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -135,7 +135,7 @@ public: #if QT_CONFIG(timezone) static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone, DaylightStatus hint = UnknownDaylightTime, - QDate *localDate = 0, QTime *localTime = 0); + QDate *localDate = nullptr, QTime *localTime = nullptr); // Inlined for its one caller in qdatetime.cpp inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch); diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index f7e6e351fe..e244fed09a 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -86,7 +86,7 @@ public: DateTimeEdit }; QDateTimeParser(QVariant::Type t, Context ctx) - : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t), + : currentSectionIndex(-1), display(nullptr), cachedDay(-1), parserType(t), fixday(false), spec(Qt::LocalTime), context(ctx) { defaultLocale = QLocale::system(); @@ -218,9 +218,9 @@ private: ParsedSection parseSection(const QDateTime ¤tValue, int sectionIndex, int offset, QString *text) const; int findMonth(const QString &str1, int monthstart, int sectionIndex, - QString *monthName = 0, int *used = 0) const; + QString *monthName = nullptr, int *used = nullptr) const; int findDay(const QString &str1, int intDaystart, int sectionIndex, - QString *dayName = 0, int *used = 0) const; + QString *dayName = nullptr, int *used = nullptr) const; ParsedSection findTimeZone(QStringRef str, const QDateTime &when, int maxVal, int minVal) const; #if QT_CONFIG(timezone) @@ -236,7 +236,7 @@ private: PossiblePM = 3, PossibleBoth = 4 }; - AmPmFinder findAmPm(QString &str, int index, int *used = 0) const; + AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const; #endif // datestring bool potentialValue(const QStringRef &str, int min, int max, int index, diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h index 63be0952ff..d72d6e1b4b 100644 --- a/src/corelib/tools/qfreelist_p.h +++ b/src/corelib/tools/qfreelist_p.h @@ -249,11 +249,11 @@ inline int QFreeList<T, ConstantsType>::next() if (!v) { v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]); - if (!_v[block].testAndSetRelease(0, v)) { + if (!_v[block].testAndSetRelease(nullptr, v)) { // race with another thread lost delete [] v; v = _v[block].loadAcquire(); - Q_ASSERT(v != 0); + Q_ASSERT(v != nullptr); } } diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp index 949f63ea15..6f3c22a6ec 100644 --- a/src/corelib/tools/qline.cpp +++ b/src/corelib/tools/qline.cpp @@ -805,6 +805,7 @@ qreal QLineF::angleTo(const QLineF &l) const return delta_normalized; } +#if QT_DEPRECATED_SINCE(5, 14) /*! \fn qreal QLineF::angle(const QLineF &line) const @@ -837,6 +838,7 @@ qreal QLineF::angle(const QLineF &l) const if (cos_line >= -1.0 && cos_line <= 1.0) rad = qAcos( cos_line ); return rad * 360 / M_2PI; } +#endif #ifndef QT_NO_DEBUG_STREAM diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h index 6361c1af9f..14980b60a0 100644 --- a/src/corelib/tools/qline.h +++ b/src/corelib/tools/qline.h @@ -251,7 +251,10 @@ public: // ### Qt 6: rename intersects() or intersection() and rename IntersectType IntersectionType IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const; +#if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_X("Use angleTo() instead, take care that the return value is between 0 and 360 degree.") qreal angle(const QLineF &l) const; +#endif Q_DECL_CONSTEXPR inline QPointF pointAt(qreal t) const; inline void translate(const QPointF &p); diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 6643288bd5..34577acaa5 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -526,7 +526,7 @@ inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t) Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid"); int iBefore = int(before.i - reinterpret_cast<Node *>(p.begin())); - Node *n = 0; + Node *n = nullptr; if (d->ref.isShared()) n = detach_helper_grow(iBefore, 1); else diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 98b6a31a46..1e8dc28fbf 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -249,7 +249,7 @@ public: if (qIsInf(d)) return float(d); if (std::fabs(d) > std::numeric_limits<float>::max()) { - if (ok != 0) + if (ok != nullptr) *ok = false; const float huge = std::numeric_limits<float>::infinity(); return d < 0 ? -huge : huge; diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index 94977fc826..1af43d0a68 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -97,6 +97,11 @@ struct QPair T2 second; }; +#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606 +template<class T1, class T2> +QPair(T1, T2) -> QPair<T1, T2>; +#endif + template <typename T1, typename T2> void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs) Q_DECL_NOEXCEPT_EXPR(noexcept(lhs.swap(rhs))) { lhs.swap(rhs); } diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 87b30c952e..589eb74520 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -58,9 +58,6 @@ QT_BEGIN_NAMESPACE -int qFindString(const QChar *haystack, int haystackLen, int from, - const QChar *needle, int needleLen, Qt::CaseSensitivity cs); - // error strings for the regexp parser #define RXERR_OK QT_TRANSLATE_NOOP("QRegExp", "no error occurred") #define RXERR_DISABLED QT_TRANSLATE_NOOP("QRegExp", "disabled feature used") @@ -1423,7 +1420,8 @@ void QRegExpMatchState::match(const QChar *str0, int len0, int pos0, #ifndef QT_NO_REGEXP_OPTIM if (eng->trivial && !oneTest) { - pos = qFindString(str0, len0, pos0, eng->goodStr.unicode(), eng->goodStr.length(), eng->cs); + // ### Qt6: qsize + pos = int(QtPrivate::findString(QStringView(str0, len0), pos0, QStringView(eng->goodStr.unicode(), eng->goodStr.length()), eng->cs)); matchLen = eng->goodStr.length(); matched = (pos != -1); } else diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h index 5f76269388..f904b8dfcb 100644 --- a/src/corelib/tools/qscopedvaluerollback.h +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -48,20 +48,20 @@ template <typename T> class QScopedValueRollback { public: - explicit QScopedValueRollback(T &var) : - varRef(var), oldValue(var) + explicit QScopedValueRollback(T &var) + : varRef(var), oldValue(var) { } - explicit QScopedValueRollback(T &var, T value) : - varRef(var), oldValue(var) + explicit QScopedValueRollback(T &var, T value) + : varRef(var), oldValue(std::move(var)) { - varRef = qMove(value); + varRef = std::move(value); } ~QScopedValueRollback() { - varRef = qMove(oldValue); + varRef = std::move(oldValue); } void commit() @@ -70,7 +70,7 @@ public: } private: - T& varRef; + T &varRef; T oldValue; Q_DISABLE_COPY(QScopedValueRollback) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 9d6e0cbdd8..65519d1f98 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2,6 +2,7 @@ ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2019 Mail.ru Group. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -142,19 +143,11 @@ extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const ushort *src, int leng #endif // internal -int qFindString(const QChar *haystack, int haystackLen, int from, - const QChar *needle, int needleLen, Qt::CaseSensitivity cs); -int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, - const QChar *needle, int needleLen, Qt::CaseSensitivity cs); -static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar needle, - int from, Qt::CaseSensitivity cs); -static inline int qt_string_count(const QChar *haystack, int haystackLen, - const QChar *needle, int needleLen, - Qt::CaseSensitivity cs); -static inline int qt_string_count(const QChar *haystack, int haystackLen, - QChar needle, Qt::CaseSensitivity cs); -static inline int qt_find_latin1_string(const QChar *hay, int size, QLatin1String needle, - int from, Qt::CaseSensitivity cs); +qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs); +static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs); +static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs); +static inline qsizetype qt_string_count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs); + static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs); static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs); static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs); @@ -1283,42 +1276,9 @@ int QtPrivate::compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSens return qt_compare_strings(lhs, rhs, cs); } -/*! - \internal - - Returns the index position of the first occurrence of the - character \a ch in the string given by \a str and \a len, - searching forward from index - position \a from. Returns -1 if \a ch could not be found. -*/ -static int findChar(const QChar *str, int len, QChar ch, int from, - Qt::CaseSensitivity cs) -{ - 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; - const ushort *e = s + len; - if (cs == Qt::CaseSensitive) { - n = QtPrivate::qustrchr(QStringView(n, e), c); - if (n != e) - return n - s; - } else { - c = foldCase(c); - --n; - while (++n != e) - if (foldCase(*n) == c) - return n - s; - } - } - return -1; -} - #define REHASH(a) \ - if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \ - hashHaystack -= uint(a) << sl_minus_1; \ + if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \ + hashHaystack -= std::size_t(a) << sl_minus_1; \ hashHaystack <<= 1 inline bool qIsUpper(char ch) @@ -2086,7 +2046,7 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out) \note This function does not append a null character to the array. - \sa utf16(), toUcs4(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString() + \sa utf16(), toUcs4(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString(), QStringView::toWCharArray() */ /*! \fn QString::QString(const QString &other) @@ -3735,7 +3695,8 @@ bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW */ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); + // ### Qt6: qsize + return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } /*! @@ -3759,85 +3720,8 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - return qt_find_latin1_string(unicode(), size(), str, from, cs); -} - -int qFindString( - const QChar *haystack0, int haystackLen, int from, - const QChar *needle0, int needleLen, Qt::CaseSensitivity cs) -{ - const int l = haystackLen; - const int sl = needleLen; - if (from < 0) - from += l; - if (uint(sl + from) > (uint)l) - return -1; - if (!sl) - return from; - if (!l) - return -1; - - if (sl == 1) - return findChar(haystack0, haystackLen, needle0[0], from, cs); - - /* - We use the Boyer-Moore algorithm in cases where the overhead - for the skip table should pay off, otherwise we use a simple - hash function. - */ - if (l > 500 && sl > 5) - return qFindStringBoyerMoore(haystack0, haystackLen, from, - needle0, needleLen, cs); - - auto sv = [sl](const ushort *v) { return QStringView(v, sl); }; - /* - We use some hashing for efficiency's sake. Instead of - comparing strings, we compare the hash value of str with that - of a part of this QString. Only if that matches, we call - qt_string_compare(). - */ - const ushort *needle = (const ushort *)needle0; - const ushort *haystack = (const ushort *)haystack0 + from; - const ushort *end = (const ushort *)haystack0 + (l-sl); - const uint sl_minus_1 = sl - 1; - uint hashNeedle = 0, hashHaystack = 0; - int idx; - - if (cs == Qt::CaseSensitive) { - for (idx = 0; idx < sl; ++idx) { - hashNeedle = ((hashNeedle<<1) + needle[idx]); - hashHaystack = ((hashHaystack<<1) + haystack[idx]); - } - hashHaystack -= haystack[sl_minus_1]; - - while (haystack <= end) { - hashHaystack += haystack[sl_minus_1]; - if (hashHaystack == hashNeedle - && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0) - return haystack - (const ushort *)haystack0; - - REHASH(*haystack); - ++haystack; - } - } else { - const ushort *haystack_start = (const ushort *)haystack0; - for (idx = 0; idx < sl; ++idx) { - hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle); - hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start); - } - hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start); - - while (haystack <= end) { - hashHaystack += foldCase(haystack + sl_minus_1, haystack_start); - if (hashHaystack == hashNeedle - && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseInsensitive) == 0) - return haystack - (const ushort *)haystack0; - - REHASH(foldCase(haystack, haystack_start)); - ++haystack; - } - } - return -1; + // ### Qt6: qsize + return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs)); } /*! @@ -3849,7 +3733,8 @@ int qFindString( */ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - return findChar(unicode(), length(), ch, from, cs); + // ### Qt6: qsize + return int(QtPrivate::findChar(QStringView(unicode(), length()), ch, from, cs)); } /*! @@ -3866,7 +3751,8 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); + // ### Qt6: qsize + return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs) @@ -3989,7 +3875,8 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co */ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - return qt_last_index_of(unicode(), size(), ch, from, cs); + // ### Qt6: qsize + return int(qt_last_index_of(QStringView(unicode(), size()), ch, from, cs)); } /*! @@ -4322,7 +4209,8 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) int QString::count(const QString &str, Qt::CaseSensitivity cs) const { - return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); + // ### Qt6: qsize + return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } /*! @@ -4338,8 +4226,9 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const int QString::count(QChar ch, Qt::CaseSensitivity cs) const { - return qt_string_count(unicode(), size(), ch, cs); - } + // ### Qt6: qsize + return int(qt_string_count(QStringView(unicode(), size()), ch, cs)); +} /*! \since 4.8 @@ -4354,7 +4243,8 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const */ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const { - return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); + // ### Qt6: qsize + return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } @@ -6831,6 +6721,7 @@ QString QString::toUpper_helper(QString &str) return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str); } +#if QT_DEPRECATED_SINCE(5, 14) /*! \obsolete @@ -6844,6 +6735,7 @@ QString &QString::sprintf(const char *cformat, ...) va_end(ap); return *this; } +#endif // ### Qt 6: Consider whether this function shouldn't be removed See task 202871. /*! @@ -6889,6 +6781,7 @@ QString QString::asprintf(const char *cformat, ...) return s; } +#if QT_DEPRECATED_SINCE(5, 14) /*! \obsolete @@ -6898,6 +6791,7 @@ QString &QString::vsprintf(const char *cformat, va_list ap) { return *this = vasprintf(cformat, ap); } +#endif static void append_utf8(QString &qs, const char *cs, int len) { @@ -7778,10 +7672,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs, const int separatorSize) { ResultList list; - int start = 0; - int end; - int extra = 0; - while ((end = qFindString(source.constData(), source.size(), start + extra, sep, separatorSize, cs)) != -1) { + typename StringSource::size_type start = 0; + typename StringSource::size_type end; + typename StringSource::size_type extra = 0; + while ((end = QtPrivate::findString(QStringView(source.constData(), source.size()), start + extra, QStringView(sep, separatorSize), cs)) != -1) { if (start != end || behavior == QString::KeepEmptyParts) list.append(source.mid(start, end - start)); start = end + separatorSize; @@ -11154,7 +11048,8 @@ QStringRef QString::midRef(int position, int n) const */ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); + // ### Qt6: qsize + return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } /*! @@ -11169,7 +11064,8 @@ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) co */ int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - return findChar(unicode(), length(), ch, from, cs); + // ### Qt6: qsize + return int(QtPrivate::findChar(QStringView(unicode(), length()), ch, from, cs)); } /*! @@ -11189,7 +11085,8 @@ int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - return qt_find_latin1_string(unicode(), size(), str, from, cs); + // ### Qt6: qsize + return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs)); } /*! @@ -11208,7 +11105,8 @@ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) con */ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs); + // ### Qt6: qsize + return int(QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs)); } /*! @@ -11241,7 +11139,8 @@ int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs */ int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - return qt_last_index_of(unicode(), size(), ch, from, cs); + // ### Qt6: qsize + return int(qt_last_index_of(QStringView(unicode(), size()), ch, from, cs)); } template<typename T> @@ -11317,7 +11216,8 @@ int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity */ int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const { - return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); + // ### Qt6: qsize + return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } /*! @@ -11334,7 +11234,8 @@ int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const */ int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const { - return qt_string_count(unicode(), size(), ch, cs); + // ### Qt6: qsize + return int(qt_string_count(QStringView(unicode(), size()), ch, cs)); } /*! @@ -11351,7 +11252,8 @@ int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const */ int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const { - return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); + // ### Qt6: qsize + return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } /*! @@ -11588,16 +11490,16 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ -static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar needle, - int from, Qt::CaseSensitivity cs) +static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle, + qsizetype from, Qt::CaseSensitivity cs) { - ushort c = needle.unicode(); if (from < 0) - from += haystackLen; - if (uint(from) >= uint(haystackLen)) + from += haystack.size(); + if (std::size_t(from) >= std::size_t(haystack.size())) return -1; if (from >= 0) { - const ushort *b = reinterpret_cast<const ushort*>(haystack); + ushort c = needle.unicode(); + const ushort *b = reinterpret_cast<const ushort*>(haystack.data()); const ushort *n = b + from; if (cs == Qt::CaseSensitive) { for (; n >= b; --n) @@ -11615,30 +11517,28 @@ static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar } -static inline int qt_string_count(const QChar *haystack, int haystackLen, - const QChar *needle, int needleLen, - Qt::CaseSensitivity cs) +static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) { - int num = 0; - int i = -1; - if (haystackLen > 500 && needleLen > 5) { - QStringMatcher matcher(needle, needleLen, cs); - while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1) + qsizetype num = 0; + qsizetype i = -1; + if (haystack.size() > 500 && needle.size() > 5) { + QStringMatcher matcher(needle, cs); + while ((i = matcher.indexIn(haystack, i + 1)) != -1) ++num; } else { - while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1) + while ((i = QtPrivate::findString(haystack, i + 1, needle, cs)) != -1) ++num; } return num; } -static inline int qt_string_count(const QChar *unicode, int size, QChar ch, +static inline qsizetype qt_string_count(QStringView haystack, QChar ch, Qt::CaseSensitivity cs) { ushort c = ch.unicode(); - int num = 0; - const ushort *b = reinterpret_cast<const ushort*>(unicode); - const ushort *i = b + size; + qsizetype num = 0; + const ushort *b = reinterpret_cast<const ushort*>(haystack.data()); + const ushort *i = b + haystack.size(); if (cs == Qt::CaseSensitive) { while (i != b) if (*--i == c) @@ -11652,22 +11552,6 @@ static inline int qt_string_count(const QChar *unicode, int size, QChar ch, return num; } -static inline int qt_find_latin1_string(const QChar *haystack, int size, - QLatin1String needle, - int from, Qt::CaseSensitivity cs) -{ - if (size < needle.size()) - return -1; - - const char *latin1 = needle.latin1(); - int len = needle.size(); - QVarLengthArray<ushort> s(len); - qt_from_latin1(s.data(), latin1, len); - - return qFindString(haystack, size, from, - reinterpret_cast<const QChar*>(s.constData()), len, cs); -} - template <typename Haystack, typename Needle> bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW { @@ -11815,6 +11699,127 @@ bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseS } /*! + \internal + + Returns the index position of the first occurrence of the + character \a ch in the string given by \a str and \a len, + searching forward from index + position \a from. Returns -1 if \a ch could not be found. +*/ + +qsizetype QtPrivate::findChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ + if (from < 0) + from = qMax(from + str.size(), qsizetype(0)); + if (from < str.size()) { + const ushort *s = (const ushort *)str.data(); + ushort c = ch.unicode(); + const ushort *n = s + from; + const ushort *e = s + str.size(); + if (cs == Qt::CaseSensitive) { + n = QtPrivate::qustrchr(QStringView(n, e), c); + if (n != e) + return n - s; + } else { + c = foldCase(c); + --n; + while (++n != e) + if (foldCase(*n) == c) + return n - s; + } + } + return -1; +} + +qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringView needle0, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ + const qsizetype l = haystack0.size(); + const qsizetype sl = needle0.size(); + if (from < 0) + from += l; + if (std::size_t(sl + from) > std::size_t(l)) + return -1; + if (!sl) + return from; + if (!l) + return -1; + + if (sl == 1) + return QtPrivate::findChar(haystack0, needle0[0], from, cs); + + /* + We use the Boyer-Moore algorithm in cases where the overhead + for the skip table should pay off, otherwise we use a simple + hash function. + */ + if (l > 500 && sl > 5) + return qFindStringBoyerMoore(haystack0, from, needle0, cs); + + auto sv = [sl](const ushort *v) { return QStringView(v, sl); }; + /* + We use some hashing for efficiency's sake. Instead of + comparing strings, we compare the hash value of str with that + of a part of this QString. Only if that matches, we call + qt_string_compare(). + */ + const ushort *needle = (const ushort *)needle0.data(); + const ushort *haystack = (const ushort *)(haystack0.data()) + from; + const ushort *end = (const ushort *)(haystack0.data()) + (l - sl); + const std::size_t sl_minus_1 = sl - 1; + std::size_t hashNeedle = 0, hashHaystack = 0; + qsizetype idx; + + if (cs == Qt::CaseSensitive) { + for (idx = 0; idx < sl; ++idx) { + hashNeedle = ((hashNeedle<<1) + needle[idx]); + hashHaystack = ((hashHaystack<<1) + haystack[idx]); + } + hashHaystack -= haystack[sl_minus_1]; + + while (haystack <= end) { + hashHaystack += haystack[sl_minus_1]; + if (hashHaystack == hashNeedle + && qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0) + return haystack - (const ushort *)haystack0.data(); + + REHASH(*haystack); + ++haystack; + } + } else { + const ushort *haystack_start = (const ushort *)haystack0.data(); + for (idx = 0; idx < sl; ++idx) { + hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle); + hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start); + } + hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start); + + while (haystack <= end) { + hashHaystack += foldCase(haystack + sl_minus_1, haystack_start); + if (hashHaystack == hashNeedle + && qt_compare_strings(needle0, sv(haystack), Qt::CaseInsensitive) == 0) + return haystack - (const ushort *)haystack0.data(); + + REHASH(foldCase(haystack, haystack_start)); + ++haystack; + } + } + return -1; +} + +qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ + if (haystack.size() < needle.size()) + return -1; + + const char *latin1 = needle.latin1(); + const qsizetype len = needle.size(); + QVarLengthArray<ushort> s(len); + qt_from_latin1(s.data(), latin1, len); + + return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast<const QChar*>(s.constData()), len), cs); +} + +/*! \since 4.8 Returns a Latin-1 representation of the string as a QByteArray. diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index da76601e88..e9a205dfdf 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -320,8 +320,12 @@ public: const QString &a4, const QString &a5, const QString &a6, const QString &a7, const QString &a8, const QString &a9) const; +#if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_X("Use vasprintf(), arg() or QTextStream instead") QString &vsprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(2, 0); + QT_DEPRECATED_X("Use asprintf(), arg() or QTextStream instead") QString &sprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(2, 3); +#endif static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1, 0); static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2); @@ -1017,12 +1021,7 @@ QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable" inline int QString::toWCharArray(wchar_t *array) const { - if (sizeof(wchar_t) == sizeof(QChar)) { - memcpy(array, d->data(), sizeof(QChar) * size()); - return size(); - } else { - return toUcs4_helper(d->data(), size(), reinterpret_cast<uint *>(array)); - } + return QStringView(*this).toWCharArray(array); } QT_WARNING_POP @@ -1376,14 +1375,12 @@ inline std::wstring QString::toStdWString() const { std::wstring str; str.resize(length()); - -#ifdef Q_CC_MSVC - // VS2005 crashes if the string is empty - if (!length()) - return str; +#if __cplusplus >= 201703L + str.resize(toWCharArray(str.data())); +#else + if (length()) + str.resize(toWCharArray(&str.front())); #endif - - str.resize(toWCharArray(&(*str.begin()))); return str; } diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h index cc0eda71f3..e94f725598 100644 --- a/src/corelib/tools/qstringalgorithms.h +++ b/src/corelib/tools/qstringalgorithms.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE class QByteArray; class QLatin1String; class QStringView; +class QChar; template <typename T> class QVector; namespace QtPrivate { @@ -74,6 +75,10 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; +Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; + Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) Q_DECL_NOTHROW; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) Q_DECL_NOTHROW; diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp index 67d3f0ebc8..417910b6ec 100644 --- a/src/corelib/tools/qstringmatcher.cpp +++ b/src/corelib/tools/qstringmatcher.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Mail.ru Group. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -41,43 +42,43 @@ QT_BEGIN_NAMESPACE -static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs) +static void bm_init_skiptable(const ushort *uc, qsizetype len, uchar *skiptable, Qt::CaseSensitivity cs) { - int l = qMin(len, 255); - memset(skiptable, l, 256*sizeof(uchar)); + int l = int(qMin(len, qsizetype(255))); + memset(skiptable, l, 256 * sizeof(uchar)); uc += len - l; if (cs == Qt::CaseSensitive) { while (l--) { skiptable[*uc & 0xff] = l; - uc++; + ++uc; } } else { const ushort *start = uc; while (l--) { skiptable[foldCase(uc, start) & 0xff] = l; - uc++; + ++uc; } } } -static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl, +static inline qsizetype bm_find(const ushort *uc, qsizetype l, qsizetype index, const ushort *puc, qsizetype pl, const uchar *skiptable, Qt::CaseSensitivity cs) { if (pl == 0) - return index > (int)l ? -1 : index; - const uint pl_minus_one = pl - 1; + return index > l ? -1 : index; + const qsizetype pl_minus_one = pl - 1; const ushort *current = uc + index + pl_minus_one; const ushort *end = uc + l; if (cs == Qt::CaseSensitive) { while (current < end) { - uint skip = skiptable[*current & 0xff]; + qsizetype skip = skiptable[*current & 0xff]; if (!skip) { // possible match while (skip < pl) { if (*(current - skip) != puc[pl_minus_one-skip]) break; - skip++; + ++skip; } if (skip > pl_minus_one) // we have a match return (current - uc) - pl_minus_one; @@ -95,13 +96,13 @@ static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc } } else { while (current < end) { - uint skip = skiptable[foldCase(current, uc) & 0xff]; + qsizetype skip = skiptable[foldCase(current, uc) & 0xff]; if (!skip) { // possible match while (skip < pl) { if (foldCase(current - skip, uc) != foldCase(puc + pl_minus_one - skip, puc)) break; - skip++; + ++skip; } if (skip > pl_minus_one) // we have a match return (current - uc) - pl_minus_one; @@ -175,14 +176,27 @@ QStringMatcher::QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs) by \a uc with the given \a length and case sensitivity specified by \a cs. */ QStringMatcher::QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs) - : d_ptr(0), q_cs(cs) + : QStringMatcher(QStringView(uc, len), cs) { - p.uc = uc; - p.len = len; - bm_init_skiptable((const ushort *)p.uc, len, p.q_skiptable, cs); } /*! + \fn QStringMatcher::QStringMatcher(QStringView str, Qt::CaseSensitivity cs) + \since 5.14 + + Constructs a string matcher that will search for \a pattern, with + case sensitivity \a cs. + + Call indexIn() to perform a search. +*/ +QStringMatcher::QStringMatcher(QStringView str, Qt::CaseSensitivity cs) + : d_ptr(nullptr), q_cs(cs) +{ + p.uc = str.data(); + p.len = int(str.size()); + bm_init_skiptable((const ushort *)p.uc, p.len, p.q_skiptable, cs); +} +/*! Copies the \a other string matcher to this string matcher. */ QStringMatcher::QStringMatcher(const QStringMatcher &other) @@ -267,11 +281,7 @@ void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs) */ int QStringMatcher::indexIn(const QString &str, int from) const { - if (from < 0) - from = 0; - return bm_find((const ushort *)str.unicode(), str.size(), from, - (const ushort *)p.uc, p.len, - p.q_skiptable, q_cs); + return int(indexIn(QStringView(str), from)); } /*! @@ -288,9 +298,25 @@ int QStringMatcher::indexIn(const QString &str, int from) const */ int QStringMatcher::indexIn(const QChar *str, int length, int from) const { + return int(indexIn(QStringView(str, length), from)); +} + +/*! + \since 5.14 + + Searches the string \a str from character position \a from + (default 0, i.e. from the first character), for the string + pattern() that was set in the constructor or in the most recent + call to setPattern(). Returns the position where the pattern() + matched in \a str, or -1 if no match was found. + + \sa setPattern(), setCaseSensitivity() +*/ +qsizetype QStringMatcher::indexIn(QStringView str, qsizetype from) const +{ if (from < 0) from = 0; - return bm_find((const ushort *)str, length, from, + return bm_find((const ushort *)str.data(), str.size(), from, (const ushort *)p.uc, p.len, p.q_skiptable, q_cs); } @@ -307,16 +333,16 @@ int QStringMatcher::indexIn(const QChar *str, int length, int from) const \internal */ -int qFindStringBoyerMoore( - const QChar *haystack, int haystackLen, int haystackOffset, - const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +qsizetype qFindStringBoyerMoore( + QStringView haystack, qsizetype haystackOffset, + QStringView needle, Qt::CaseSensitivity cs) { uchar skiptable[256]; - bm_init_skiptable((const ushort *)needle, needleLen, skiptable, cs); + bm_init_skiptable((const ushort *)needle.data(), needle.size(), skiptable, cs); if (haystackOffset < 0) haystackOffset = 0; - return bm_find((const ushort *)haystack, haystackLen, haystackOffset, - (const ushort *)needle, needleLen, skiptable, cs); + return bm_find((const ushort *)haystack.data(), haystack.size(), haystackOffset, + (const ushort *)needle.data(), needle.size(), skiptable, cs); } QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h index 549bff9f29..6de4353930 100644 --- a/src/corelib/tools/qstringmatcher.h +++ b/src/corelib/tools/qstringmatcher.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Mail.ru Group. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -41,6 +42,7 @@ #define QSTRINGMATCHER_H #include <QtCore/qstring.h> +#include <QtCore/qstringview.h> QT_BEGIN_NAMESPACE @@ -55,6 +57,8 @@ public: Qt::CaseSensitivity cs = Qt::CaseSensitive); QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QStringMatcher(QStringView pattern, + Qt::CaseSensitivity cs = Qt::CaseSensitive); QStringMatcher(const QStringMatcher &other); ~QStringMatcher(); @@ -65,6 +69,7 @@ public: int indexIn(const QString &str, int from = 0) const; int indexIn(const QChar *str, int length, int from = 0) const; + qsizetype indexIn(QStringView str, qsizetype from = 0) const; QString pattern() const; inline Qt::CaseSensitivity caseSensitivity() const { return q_cs; } diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp index b97e989110..c863ca7ce2 100644 --- a/src/corelib/tools/qstringview.cpp +++ b/src/corelib/tools/qstringview.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qstringview.h" +#include "qstring.h" QT_BEGIN_NAMESPACE @@ -794,4 +795,34 @@ QT_BEGIN_NAMESPACE \sa QString::isRightToLeft() */ +/*! + \since 5.14 + + Transcribes this string into the given \a array. + + Caller is responsible for ensuring \a array is large enough to hold the \t + wchar_t encoding of this string (allocating the array with the same length + as the string is always sufficient). The array is encoded in UTF-16 on + platforms where \t wchar_t is 2 bytes wide (e.g. Windows); otherwise (Unix + systems), \t wchar_t is assumed to be 4 bytes wide and the data is written + in UCS-4. + + \note This function writes no null terminator to the end of \a array. + + Returns the number of \t wchar_t entries written to \a array. + + \sa QString::toWCharArray() +*/ + +int QStringView::toWCharArray(wchar_t *array) const +{ + if (sizeof(wchar_t) == sizeof(QChar)) { + memcpy(array, data(), sizeof(QChar) * size()); + return size(); + } else { + return QString::toUcs4_helper(reinterpret_cast<const ushort *>(data()), int(size()), + reinterpret_cast<uint *>(array)); + } +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h index 2e95c2b218..4a900b5e89 100644 --- a/src/corelib/tools/qstringview.h +++ b/src/corelib/tools/qstringview.h @@ -272,6 +272,8 @@ public: Q_REQUIRED_RESULT bool isRightToLeft() const Q_DECL_NOTHROW { return QtPrivate::isRightToLeft(*this); } + Q_REQUIRED_RESULT Q_CORE_EXPORT int toWCharArray(wchar_t *array) const; + // // STL compatibility API: // diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 988d5a9e1b..9762ec1b5b 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -79,6 +79,7 @@ public: void swap(QVector<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QVector(std::initializer_list<T> args); + QVector<T> &operator=(std::initializer_list<T> args); #endif bool operator==(const QVector<T> &v) const; inline bool operator!=(const QVector<T> &v) const { return !(*this == v); } @@ -542,10 +543,19 @@ QVector<T>::QVector(std::initializer_list<T> args) d = Data::sharedNull(); } } + +template <typename T> +QVector<T> &QVector<T>::operator=(std::initializer_list<T> args) +{ + QVector<T> tmp(args); + tmp.swap(*this); + return *this; +} + # if defined(Q_CC_MSVC) QT_WARNING_POP # endif // Q_CC_MSVC -#endif // Q_COMPILER_INITALIZER_LISTS +#endif // Q_COMPILER_INITIALIZER_LISTS template <typename T> void QVector<T>::freeData(Data *x) diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc index 75b17a4207..69bbb5f9a2 100644 --- a/src/corelib/tools/qvector.qdoc +++ b/src/corelib/tools/qvector.qdoc @@ -263,6 +263,17 @@ \since 5.2 */ +/*! + \fn template <typename T> QVector<T> &QVector<T>::operator=(std::initializer_list<T> args) + + Assigns the collection of values in \a args to this QVector instance. + + This operator is only enabled if the compiler supports C++11 initializer + lists. + + \since 5.14 +*/ + /*! \fn template <typename T> void QVector<T>::swap(QVector<T> &other) \since 4.8 |