diff options
Diffstat (limited to 'src/corelib/tools')
50 files changed, 2166 insertions, 783 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index ff4d5a3ebd..57fbdf0eba 100644..100755 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -584,6 +584,131 @@ Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qPopulationCount(long unsigne #undef QALGORITHMS_USE_BUILTIN_POPCOUNT #endif +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctz(v) : 32U; +#else + // see http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightParallel + unsigned int c = 32; // c will be the number of zero bits on the right + v &= -signed(v); + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctz(v) : 8U; +#else + unsigned int c = 8; // c will be the number of zero bits on the right + v &= -signed(v); + if (v) c--; + if (v & 0x0000000F) c -= 4; + if (v & 0x00000033) c -= 2; + if (v & 0x00000055) c -= 1; + return c; +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctz(v) : 16U; +#else + unsigned int c = 16; // c will be the number of zero bits on the right + v &= -signed(v); + if (v) c--; + if (v & 0x000000FF) c -= 8; + if (v & 0x00000F0F) c -= 4; + if (v & 0x00003333) c -= 2; + if (v & 0x00005555) c -= 1; + return c; +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint64 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_ctzll(v) : 64; +#else + quint32 x = static_cast<quint32>(v); + return x ? qCountTrailingZeroBits(x) + : 32 + qCountTrailingZeroBits(static_cast<quint32>(v >> 32)); +#endif +} + +Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) Q_DECL_NOTHROW +{ + return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clz(v) : 32U; +#else + // Hacker's Delight, 2nd ed. Fig 5-16, p. 102 + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + v = v | (v >> 8); + v = v | (v >> 16); + return qPopulationCount(~v); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clz(v)-24U : 8U; +#else + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + return qPopulationCount(static_cast<quint8>(~v)); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clz(v)-16U : 16U; +#else + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + v = v | (v >> 8); + return qPopulationCount(static_cast<quint16>(~v)); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW +{ +#if defined(Q_CC_GNU) + return v ? __builtin_clzll(v) : 64U; +#else + v = v | (v >> 1); + v = v | (v >> 2); + v = v | (v >> 4); + v = v | (v >> 8); + v = v | (v >> 16); + v = v | (v >> 32); + return qPopulationCount(~v); +#endif +} + +Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW +{ + return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); +} + QT_WARNING_POP QT_END_NAMESPACE diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index 193042e017..dac353fa70 100644..100755 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -785,3 +785,73 @@ \since 5.2 \overload */ + +/*! + \fn uint qCountTrailingZeroBits(quint8 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the LSB. + For example, qCountTrailingZeroBits(1) returns 0 and qCountTrailingZeroBits(8) returns 3. + */ + +/*! + \fn uint qCountTrailingZeroBits(quint16 v) + \relates <QtAlgorithms> + \since 5.6 + \overload + */ + +/*! + \fn uint qCountTrailingZeroBits(quint32 v) + \relates <QtAlgorithms> + \since 5.6 + \overload + */ + +/*! + \fn uint qCountTrailingZeroBits(quint64 v) + \relates <QtAlgorithms> + \since 5.6 + \overload + */ + +/*! + \fn uint qCountLeadingZeroBits(quint8 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint8(1)) returns 7 and + qCountLeadingZeroBits(quint8(8)) returns 4. + */ + +/*! + \fn uint qCountLeadingZeroBits(quint16 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint16(1)) returns 15 and + qCountLeadingZeroBits(quint16(8)) returns 12. + */ + +/*! + \fn uint qCountLeadingZeroBits(quint32 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint32(1)) returns 31 and + qCountLeadingZeroBits(quint32(8)) returns 28. + */ + +/*! + \fn uint qCountLeadingZeroBits(quint64 v) + \relates <QtAlgorithms> + \since 5.6 + + Returns the number of consecutive zero bits in \a v, when searching from the MSB. + For example, qCountLeadingZeroBits(quint64(1)) returns 63 and + qCountLeadingZeroBits(quint64(8)) returns 60. + */ diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index df35a1cb62..95c1d5f22e 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -132,7 +132,7 @@ struct QTypedArrayData typedef T *pointer; typedef T &reference; - inline iterator() : i(0) {} + inline iterator() : i(Q_NULLPTR) {} inline iterator(T *n) : i(n) {} inline iterator(const iterator &o): i(o.i){} // #### Qt 6: remove, the implicit version is fine inline T &operator*() const { return *i; } @@ -166,7 +166,7 @@ struct QTypedArrayData typedef const T *pointer; typedef const T &reference; - inline const_iterator() : i(0) {} + inline const_iterator() : i(Q_NULLPTR) {} inline const_iterator(const T *n) : i(n) {} inline const_iterator(const const_iterator &o): i(o.i) {} // #### Qt 6: remove, the default version is fine inline explicit const_iterator(const iterator &o): i(o.i) {} diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index da5d00311a..0ed701f4fa 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -41,6 +41,7 @@ #include "qlocale_p.h" #include "qstringalgorithms_p.h" #include "qscopedpointer.h" +#include "qbytearray_p.h" #include <qdatastream.h> #include <qmath.h> @@ -123,8 +124,8 @@ int qFindByteArray( int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW { - Q_ASSERT(alloc >= 0 && extra >= 0); - Q_ASSERT_X(uint(alloc) < QByteArray::MaxSize, "qAllocMore", "Requested size is too large!"); + Q_ASSERT(alloc >= 0 && extra >= 0 && extra <= MaxAllocSize); + Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!"); unsigned nalloc = qNextPowerOfTwo(alloc + extra); @@ -838,15 +839,6 @@ static inline char qToLower(char c) */ /*! - \variable QByteArray::MaxSize - \internal - \since 5.4 - - The maximum size of a QByteArray, in bytes. Also applies to a the maximum - storage size of QString and QVector, though not the number of elements. -*/ - -/*! \enum QByteArray::Base64Option \since 5.2 @@ -1574,7 +1566,7 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) d = x; } else { if (options & Data::Grow) { - if (alloc > uint(MaxAllocSize) - uint(sizeof(Data))) + if (alloc > MaxByteArraySize) qBadAlloc(); alloc = qAllocMore(alloc, sizeof(Data)); } diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 6d14cd5131..7388c4eee5 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -162,9 +162,6 @@ private: typedef QTypedArrayData<char> Data; public: - // undocumented: - static const quint64 MaxSize = (1 << 30) - sizeof(Data); - enum Base64Option { Base64Encoding = 0, Base64UrlEncoding = 1, @@ -338,16 +335,16 @@ public: inline QT_ASCII_CAST_WARN bool operator>=(const QString &s2) const; #endif - short toShort(bool *ok = 0, int base = 10) const; - ushort toUShort(bool *ok = 0, int base = 10) const; - int toInt(bool *ok = 0, int base = 10) const; - uint toUInt(bool *ok = 0, int base = 10) const; - long toLong(bool *ok = 0, int base = 10) const; - ulong toULong(bool *ok = 0, int base = 10) const; - qlonglong toLongLong(bool *ok = 0, int base = 10) const; - qulonglong toULongLong(bool *ok = 0, int base = 10) const; - float toFloat(bool *ok = 0) const; - double toDouble(bool *ok = 0) const; + short toShort(bool *ok = Q_NULLPTR, int base = 10) const; + ushort toUShort(bool *ok = Q_NULLPTR, int base = 10) const; + int toInt(bool *ok = Q_NULLPTR, int base = 10) const; + uint toUInt(bool *ok = Q_NULLPTR, int base = 10) const; + long toLong(bool *ok = Q_NULLPTR, int base = 10) const; + ulong toULong(bool *ok = Q_NULLPTR, int base = 10) const; + qlonglong toLongLong(bool *ok = Q_NULLPTR, int base = 10) const; + qulonglong toULongLong(bool *ok = Q_NULLPTR, int base = 10) const; + float toFloat(bool *ok = Q_NULLPTR) const; + double toDouble(bool *ok = Q_NULLPTR) const; QByteArray toBase64(Base64Options options) const; QByteArray toBase64() const; // ### Qt6 merge with previous QByteArray toHex() const; diff --git a/src/corelib/tools/qbytearray_p.h b/src/corelib/tools/qbytearray_p.h new file mode 100644 index 0000000000..78c667aa90 --- /dev/null +++ b/src/corelib/tools/qbytearray_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBYTEARRAY_P_H +#define QBYTEARRAY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qbytearray.h> +#include <QtCore/qtypetraits.h> +#include "qtools_p.h" + +QT_BEGIN_NAMESPACE + +enum { + // Define as enum to force inlining. Don't expose MaxAllocSize in a public header. + MaxByteArraySize = MaxAllocSize - sizeof(QtPrivate::remove_pointer<QByteArray::DataPtr>::type) +}; + +QT_END_NAMESPACE + +#endif // QBYTEARRAY_P_H diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h index f8539ca07a..8b832b7760 100644 --- a/src/corelib/tools/qbytearraylist.h +++ b/src/corelib/tools/qbytearraylist.h @@ -61,7 +61,7 @@ protected: #endif public: inline QByteArray join() const - { return QtPrivate::QByteArrayList_join(self(), 0, 0); } + { return QtPrivate::QByteArrayList_join(self(), Q_NULLPTR, 0); } inline QByteArray join(const QByteArray &sep) const { return QtPrivate::QByteArrayList_join(self(), sep.constData(), sep.size()); } inline QByteArray join(char sep) const diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 5c094772b8..56904c91d7 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -681,7 +681,7 @@ QT_BEGIN_NAMESPACE Note that this gives no indication of whether the character is available in a particular font. */ -bool QChar::isPrint(uint ucs4) +bool QChar::isPrint(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -714,7 +714,7 @@ bool QChar::isPrint(uint ucs4) /*! \internal */ -bool QT_FASTCALL QChar::isSpace_helper(uint ucs4) +bool QT_FASTCALL QChar::isSpace_helper(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -740,7 +740,7 @@ bool QT_FASTCALL QChar::isSpace_helper(uint ucs4) Returns \c true if the UCS-4-encoded character specified by \a ucs4 is a mark (Mark_* categories); otherwise returns \c false. */ -bool QChar::isMark(uint ucs4) +bool QChar::isMark(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -764,7 +764,7 @@ bool QChar::isMark(uint ucs4) Returns \c true if the UCS-4-encoded character specified by \a ucs4 is a punctuation mark (Punctuation_* categories); otherwise returns \c false. */ -bool QChar::isPunct(uint ucs4) +bool QChar::isPunct(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -792,7 +792,7 @@ bool QChar::isPunct(uint ucs4) Returns \c true if the UCS-4-encoded character specified by \a ucs4 is a symbol (Symbol_* categories); otherwise returns \c false. */ -bool QChar::isSymbol(uint ucs4) +bool QChar::isSymbol(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -822,7 +822,7 @@ bool QChar::isSymbol(uint ucs4) /*! \internal */ -bool QT_FASTCALL QChar::isLetter_helper(uint ucs4) +bool QT_FASTCALL QChar::isLetter_helper(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -857,7 +857,7 @@ bool QT_FASTCALL QChar::isLetter_helper(uint ucs4) /*! \internal */ -bool QT_FASTCALL QChar::isNumber_helper(uint ucs4) +bool QT_FASTCALL QChar::isNumber_helper(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -886,7 +886,7 @@ bool QT_FASTCALL QChar::isNumber_helper(uint ucs4) /*! \internal */ -bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) +bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -1049,7 +1049,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Returns the numeric value of the digit specified by the UCS-4-encoded character, \a ucs4, or -1 if the character is not a digit. */ -int QChar::digitValue(uint ucs4) +int QChar::digitValue(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return -1; @@ -1066,7 +1066,7 @@ int QChar::digitValue(uint ucs4) \overload Returns the category of the UCS-4-encoded character specified by \a ucs4. */ -QChar::Category QChar::category(uint ucs4) +QChar::Category QChar::category(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return QChar::Other_NotAssigned; @@ -1083,7 +1083,7 @@ QChar::Category QChar::category(uint ucs4) \overload Returns the direction of the UCS-4-encoded character specified by \a ucs4. */ -QChar::Direction QChar::direction(uint ucs4) +QChar::Direction QChar::direction(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return QChar::DirL; @@ -1106,7 +1106,7 @@ QChar::Direction QChar::direction(uint ucs4) character specified by \a ucs4 (needed for certain languages such as Arabic or Syriac). */ -QChar::JoiningType QChar::joiningType(uint ucs4) +QChar::JoiningType QChar::joiningType(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return QChar::Joining_None; @@ -1129,7 +1129,7 @@ QChar::JoiningType QChar::joiningType(uint ucs4) Returns information about the joining properties of the UCS-4-encoded character specified by \a ucs4 (needed for certain languages such as Arabic). */ -QChar::Joining QChar::joining(uint ucs4) +QChar::Joining QChar::joining(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return QChar::OtherJoining; @@ -1165,7 +1165,7 @@ QChar::Joining QChar::joining(uint ucs4) \sa mirroredChar() */ -bool QChar::hasMirrored(uint ucs4) +bool QChar::hasMirrored(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return false; @@ -1247,7 +1247,7 @@ bool QChar::hasMirrored(uint ucs4) \sa hasMirrored() */ -uint QChar::mirroredChar(uint ucs4) +uint QChar::mirroredChar(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return ucs4; @@ -1331,7 +1331,7 @@ QString QChar::decomposition(uint ucs4) Returns the tag defining the composition of the UCS-4-encoded character specified by \a ucs4. Returns QChar::NoDecomposition if no decomposition exists. */ -QChar::Decomposition QChar::decompositionTag(uint ucs4) +QChar::Decomposition QChar::decompositionTag(uint ucs4) Q_DECL_NOTHROW { if (ucs4 >= Hangul_SBase && ucs4 < Hangul_SBase + Hangul_SCount) return QChar::Canonical; @@ -1357,7 +1357,7 @@ QChar::Decomposition QChar::decompositionTag(uint ucs4) Returns the combining class for the UCS-4-encoded character specified by \a ucs4, as defined in the Unicode standard. */ -unsigned char QChar::combiningClass(uint ucs4) +unsigned char QChar::combiningClass(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return 0; @@ -1378,7 +1378,7 @@ unsigned char QChar::combiningClass(uint ucs4) Returns the Unicode script property value for the character specified in its UCS-4-encoded form as \a ucs4. */ -QChar::Script QChar::script(uint ucs4) +QChar::Script QChar::script(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return QChar::Script_Unknown; @@ -1396,7 +1396,7 @@ QChar::Script QChar::script(uint ucs4) Returns the Unicode version that introduced the character specified in its UCS-4-encoded form as \a ucs4. */ -QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) +QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return QChar::Unicode_Unassigned; @@ -1406,14 +1406,14 @@ QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) /*! Returns the most recent supported Unicode version. */ -QChar::UnicodeVersion QChar::currentUnicodeVersion() +QChar::UnicodeVersion QChar::currentUnicodeVersion() Q_DECL_NOTHROW { return UNICODE_DATA_VERSION; } template <typename T> -Q_DECL_CONST_FUNCTION static inline T toLowerCase_helper(T uc) +Q_DECL_CONST_FUNCTION static inline T toLowerCase_helper(T uc) Q_DECL_NOTHROW { const QUnicodeTables::Properties *p = qGetProp(uc); if (p->lowerCaseSpecial) { @@ -1424,7 +1424,7 @@ Q_DECL_CONST_FUNCTION static inline T toLowerCase_helper(T uc) } template <typename T> -Q_DECL_CONST_FUNCTION static inline T toUpperCase_helper(T uc) +Q_DECL_CONST_FUNCTION static inline T toUpperCase_helper(T uc) Q_DECL_NOTHROW { const QUnicodeTables::Properties *p = qGetProp(uc); if (p->upperCaseSpecial) { @@ -1435,7 +1435,7 @@ Q_DECL_CONST_FUNCTION static inline T toUpperCase_helper(T uc) } template <typename T> -Q_DECL_CONST_FUNCTION static inline T toTitleCase_helper(T uc) +Q_DECL_CONST_FUNCTION static inline T toTitleCase_helper(T uc) Q_DECL_NOTHROW { const QUnicodeTables::Properties *p = qGetProp(uc); if (p->titleCaseSpecial) { @@ -1446,7 +1446,7 @@ Q_DECL_CONST_FUNCTION static inline T toTitleCase_helper(T uc) } template <typename T> -Q_DECL_CONST_FUNCTION static inline T toCaseFolded_helper(T uc) +Q_DECL_CONST_FUNCTION static inline T toCaseFolded_helper(T uc) Q_DECL_NOTHROW { const QUnicodeTables::Properties *p = qGetProp(uc); if (p->caseFoldSpecial) { @@ -1469,7 +1469,7 @@ Q_DECL_CONST_FUNCTION static inline T toCaseFolded_helper(T uc) by \a ucs4 if the character is uppercase or titlecase; otherwise returns the character itself. */ -uint QChar::toLower(uint ucs4) +uint QChar::toLower(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return ucs4; @@ -1489,7 +1489,7 @@ uint QChar::toLower(uint ucs4) by \a ucs4 if the character is lowercase or titlecase; otherwise returns the character itself. */ -uint QChar::toUpper(uint ucs4) +uint QChar::toUpper(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return ucs4; @@ -1509,7 +1509,7 @@ uint QChar::toUpper(uint ucs4) by \a ucs4 if the character is lowercase or uppercase; otherwise returns the character itself. */ -uint QChar::toTitleCase(uint ucs4) +uint QChar::toTitleCase(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return ucs4; @@ -1524,7 +1524,7 @@ static inline uint foldCase(const ushort *ch, const ushort *start) return toCaseFolded_helper<uint>(c); } -static inline uint foldCase(uint ch, uint &last) +static inline uint foldCase(uint ch, uint &last) Q_DECL_NOTHROW { uint c = ch; if (QChar(c).isLowSurrogate() && QChar(last).isHighSurrogate()) @@ -1533,7 +1533,7 @@ static inline uint foldCase(uint ch, uint &last) return toCaseFolded_helper<uint>(c); } -static inline ushort foldCase(ushort ch) +static inline ushort foldCase(ushort ch) Q_DECL_NOTHROW { return toCaseFolded_helper<ushort>(ch); } @@ -1550,7 +1550,7 @@ static inline ushort foldCase(ushort ch) Returns the case folded equivalent of the UCS-4-encoded character specified by \a ucs4. For most Unicode characters this is the same as toLower(). */ -uint QChar::toCaseFolded(uint ucs4) +uint QChar::toCaseFolded(uint ucs4) Q_DECL_NOTHROW { if (ucs4 > LastValidCodePoint) return ucs4; diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index 97e2aa7088..fc1fc7bc16 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -44,9 +44,9 @@ class QString; struct QLatin1Char { public: - Q_DECL_CONSTEXPR inline explicit QLatin1Char(char c) : ch(c) {} - Q_DECL_CONSTEXPR inline char toLatin1() const { return ch; } - Q_DECL_CONSTEXPR inline ushort unicode() const { return ushort(uchar(ch)); } + Q_DECL_CONSTEXPR inline explicit QLatin1Char(char c) Q_DECL_NOTHROW : ch(c) {} + Q_DECL_CONSTEXPR inline char toLatin1() const Q_DECL_NOTHROW { return ch; } + Q_DECL_CONSTEXPR inline ushort unicode() const Q_DECL_NOTHROW { return ushort(uchar(ch)); } private: char ch; @@ -72,19 +72,19 @@ public: LastValidCodePoint = 0x10ffff }; - Q_DECL_CONSTEXPR QChar() : ucs(0) {} - Q_DECL_CONSTEXPR QChar(ushort rc) : ucs(rc){} // implicit - Q_DECL_CONSTEXPR QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){} - Q_DECL_CONSTEXPR QChar(short rc) : ucs(ushort(rc)){} // implicit - Q_DECL_CONSTEXPR QChar(uint rc) : ucs(ushort(rc & 0xffff)){} - Q_DECL_CONSTEXPR QChar(int rc) : ucs(ushort(rc & 0xffff)){} - Q_DECL_CONSTEXPR QChar(SpecialCharacter s) : ucs(ushort(s)) {} // implicit - Q_DECL_CONSTEXPR QChar(QLatin1Char ch) : ucs(ch.unicode()) {} // implicit + Q_DECL_CONSTEXPR QChar() Q_DECL_NOTHROW : ucs(0) {} + Q_DECL_CONSTEXPR QChar(ushort rc) Q_DECL_NOTHROW : ucs(rc) {} // implicit + Q_DECL_CONSTEXPR QChar(uchar c, uchar r) Q_DECL_NOTHROW : ucs(ushort((r << 8) | c)) {} + Q_DECL_CONSTEXPR QChar(short rc) Q_DECL_NOTHROW : ucs(ushort(rc)) {} // implicit + Q_DECL_CONSTEXPR QChar(uint rc) Q_DECL_NOTHROW : ucs(ushort(rc & 0xffff)) {} + Q_DECL_CONSTEXPR QChar(int rc) Q_DECL_NOTHROW : ucs(ushort(rc & 0xffff)) {} + Q_DECL_CONSTEXPR QChar(SpecialCharacter s) Q_DECL_NOTHROW : ucs(ushort(s)) {} // implicit + Q_DECL_CONSTEXPR QChar(QLatin1Char ch) Q_DECL_NOTHROW : ucs(ch.unicode()) {} // implicit #ifndef QT_NO_CAST_FROM_ASCII - QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) : ucs(uchar(c)) { } + QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) Q_DECL_NOTHROW : ucs(uchar(c)) { } #ifndef QT_RESTRICTED_CAST_FROM_ASCII - QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(uchar c) : ucs(c) { } + QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(uchar c) Q_DECL_NOTHROW : ucs(c) { } #endif #endif // Unicode information @@ -369,11 +369,11 @@ public: }; // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO - inline Category category() const { return QChar::category(ucs); } - inline Direction direction() const { return QChar::direction(ucs); } - inline JoiningType joiningType() const { return QChar::joiningType(ucs); } + inline Category category() const Q_DECL_NOTHROW { return QChar::category(ucs); } + inline Direction direction() const Q_DECL_NOTHROW { return QChar::direction(ucs); } + inline JoiningType joiningType() const Q_DECL_NOTHROW { return QChar::joiningType(ucs); } #if QT_DEPRECATED_SINCE(5, 3) - QT_DEPRECATED inline Joining joining() const + QT_DEPRECATED inline Joining joining() const Q_DECL_NOTHROW { switch (QChar::joiningType(ucs)) { case QChar::Joining_Causing: return QChar::Center; @@ -386,194 +386,177 @@ public: } } #endif - inline unsigned char combiningClass() const { return QChar::combiningClass(ucs); } + inline unsigned char combiningClass() const Q_DECL_NOTHROW { return QChar::combiningClass(ucs); } - inline QChar mirroredChar() const { return QChar::mirroredChar(ucs); } - inline bool hasMirrored() const { return QChar::hasMirrored(ucs); } + inline QChar mirroredChar() const Q_DECL_NOTHROW { return QChar::mirroredChar(ucs); } + inline bool hasMirrored() const Q_DECL_NOTHROW { return QChar::hasMirrored(ucs); } QString decomposition() const; - inline Decomposition decompositionTag() const { return QChar::decompositionTag(ucs); } + inline Decomposition decompositionTag() const Q_DECL_NOTHROW { return QChar::decompositionTag(ucs); } - inline int digitValue() const { return QChar::digitValue(ucs); } - inline QChar toLower() const { return QChar::toLower(ucs); } - inline QChar toUpper() const { return QChar::toUpper(ucs); } - inline QChar toTitleCase() const { return QChar::toTitleCase(ucs); } - inline QChar toCaseFolded() const { return QChar::toCaseFolded(ucs); } + inline int digitValue() const Q_DECL_NOTHROW { return QChar::digitValue(ucs); } + inline QChar toLower() const Q_DECL_NOTHROW { return QChar::toLower(ucs); } + inline QChar toUpper() const Q_DECL_NOTHROW { return QChar::toUpper(ucs); } + inline QChar toTitleCase() const Q_DECL_NOTHROW { return QChar::toTitleCase(ucs); } + inline QChar toCaseFolded() const Q_DECL_NOTHROW { return QChar::toCaseFolded(ucs); } - inline Script script() const { return QChar::script(ucs); } + inline Script script() const Q_DECL_NOTHROW { return QChar::script(ucs); } - inline UnicodeVersion unicodeVersion() const { return QChar::unicodeVersion(ucs); } + inline UnicodeVersion unicodeVersion() const Q_DECL_NOTHROW { return QChar::unicodeVersion(ucs); } #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED Q_DECL_CONSTEXPR inline char toAscii() const { return toLatin1(); } + QT_DEPRECATED Q_DECL_CONSTEXPR inline char toAscii() const Q_DECL_NOTHROW { return toLatin1(); } #endif - Q_DECL_CONSTEXPR inline char toLatin1() const; - Q_DECL_CONSTEXPR inline ushort unicode() const { return ucs; } - inline ushort &unicode() { return ucs; } + Q_DECL_CONSTEXPR inline char toLatin1() const Q_DECL_NOTHROW { return ucs > 0xff ? '\0' : char(ucs); } + Q_DECL_CONSTEXPR inline ushort unicode() const Q_DECL_NOTHROW { return ucs; } + Q_DECL_RELAXED_CONSTEXPR inline ushort &unicode() Q_DECL_NOTHROW { return ucs; } #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED static Q_DECL_CONSTEXPR inline QChar fromAscii(char c) + QT_DEPRECATED static Q_DECL_CONSTEXPR inline QChar fromAscii(char c) Q_DECL_NOTHROW { return fromLatin1(c); } #endif - Q_DECL_CONSTEXPR static inline QChar fromLatin1(char c); - - Q_DECL_CONSTEXPR inline bool isNull() const { return ucs == 0; } - - inline bool isPrint() const { return QChar::isPrint(ucs); } - Q_DECL_CONSTEXPR inline bool isSpace() const { return QChar::isSpace(ucs); } - inline bool isMark() const { return QChar::isMark(ucs); } - inline bool isPunct() const { return QChar::isPunct(ucs); } - inline bool isSymbol() const { return QChar::isSymbol(ucs); } - Q_DECL_CONSTEXPR inline bool isLetter() const { return QChar::isLetter(ucs); } - Q_DECL_CONSTEXPR inline bool isNumber() const { return QChar::isNumber(ucs); } - Q_DECL_CONSTEXPR inline bool isLetterOrNumber() const { return QChar::isLetterOrNumber(ucs); } - Q_DECL_CONSTEXPR inline bool isDigit() const { return QChar::isDigit(ucs); } - Q_DECL_CONSTEXPR inline bool isLower() const { return QChar::isLower(ucs); } - Q_DECL_CONSTEXPR inline bool isUpper() const { return QChar::isUpper(ucs); } - Q_DECL_CONSTEXPR inline bool isTitleCase() const { return QChar::isTitleCase(ucs); } - - Q_DECL_CONSTEXPR inline bool isNonCharacter() const { return QChar::isNonCharacter(ucs); } - Q_DECL_CONSTEXPR inline bool isHighSurrogate() const { return QChar::isHighSurrogate(ucs); } - Q_DECL_CONSTEXPR inline bool isLowSurrogate() const { return QChar::isLowSurrogate(ucs); } - Q_DECL_CONSTEXPR inline bool isSurrogate() const { return QChar::isSurrogate(ucs); } - - Q_DECL_CONSTEXPR inline uchar cell() const { return uchar(ucs & 0xff); } - Q_DECL_CONSTEXPR inline uchar row() const { return uchar((ucs>>8)&0xff); } - inline void setCell(uchar cell); - inline void setRow(uchar row); - - static Q_DECL_CONSTEXPR inline bool isNonCharacter(uint ucs4) + static Q_DECL_CONSTEXPR inline QChar fromLatin1(char c) Q_DECL_NOTHROW { return QChar(ushort(uchar(c))); } + + Q_DECL_CONSTEXPR inline bool isNull() const Q_DECL_NOTHROW { return ucs == 0; } + + inline bool isPrint() const Q_DECL_NOTHROW { return QChar::isPrint(ucs); } + Q_DECL_CONSTEXPR inline bool isSpace() const Q_DECL_NOTHROW { return QChar::isSpace(ucs); } + inline bool isMark() const Q_DECL_NOTHROW { return QChar::isMark(ucs); } + inline bool isPunct() const Q_DECL_NOTHROW { return QChar::isPunct(ucs); } + inline bool isSymbol() const Q_DECL_NOTHROW { return QChar::isSymbol(ucs); } + Q_DECL_CONSTEXPR inline bool isLetter() const Q_DECL_NOTHROW { return QChar::isLetter(ucs); } + Q_DECL_CONSTEXPR inline bool isNumber() const Q_DECL_NOTHROW { return QChar::isNumber(ucs); } + Q_DECL_CONSTEXPR inline bool isLetterOrNumber() const Q_DECL_NOTHROW { return QChar::isLetterOrNumber(ucs); } + Q_DECL_CONSTEXPR inline bool isDigit() const Q_DECL_NOTHROW { return QChar::isDigit(ucs); } + Q_DECL_CONSTEXPR inline bool isLower() const Q_DECL_NOTHROW { return QChar::isLower(ucs); } + Q_DECL_CONSTEXPR inline bool isUpper() const Q_DECL_NOTHROW { return QChar::isUpper(ucs); } + Q_DECL_CONSTEXPR inline bool isTitleCase() const Q_DECL_NOTHROW { return QChar::isTitleCase(ucs); } + + Q_DECL_CONSTEXPR inline bool isNonCharacter() const Q_DECL_NOTHROW { return QChar::isNonCharacter(ucs); } + Q_DECL_CONSTEXPR inline bool isHighSurrogate() const Q_DECL_NOTHROW { return QChar::isHighSurrogate(ucs); } + Q_DECL_CONSTEXPR inline bool isLowSurrogate() const Q_DECL_NOTHROW { return QChar::isLowSurrogate(ucs); } + Q_DECL_CONSTEXPR inline bool isSurrogate() const Q_DECL_NOTHROW { return QChar::isSurrogate(ucs); } + + Q_DECL_CONSTEXPR inline uchar cell() const Q_DECL_NOTHROW { return uchar(ucs & 0xff); } + Q_DECL_CONSTEXPR inline uchar row() const Q_DECL_NOTHROW { return uchar((ucs>>8)&0xff); } + Q_DECL_RELAXED_CONSTEXPR inline void setCell(uchar acell) Q_DECL_NOTHROW { ucs = ushort((ucs & 0xff00) + acell); } + Q_DECL_RELAXED_CONSTEXPR inline void setRow(uchar arow) Q_DECL_NOTHROW { ucs = ushort((ushort(arow)<<8) + (ucs&0xff)); } + + static Q_DECL_CONSTEXPR inline bool isNonCharacter(uint ucs4) Q_DECL_NOTHROW { return ucs4 >= 0xfdd0 && (ucs4 <= 0xfdef || (ucs4 & 0xfffe) == 0xfffe); } - static Q_DECL_CONSTEXPR inline bool isHighSurrogate(uint ucs4) + static Q_DECL_CONSTEXPR inline bool isHighSurrogate(uint ucs4) Q_DECL_NOTHROW { return ((ucs4 & 0xfffffc00) == 0xd800); } - static Q_DECL_CONSTEXPR inline bool isLowSurrogate(uint ucs4) + static Q_DECL_CONSTEXPR inline bool isLowSurrogate(uint ucs4) Q_DECL_NOTHROW { return ((ucs4 & 0xfffffc00) == 0xdc00); } - static Q_DECL_CONSTEXPR inline bool isSurrogate(uint ucs4) + static Q_DECL_CONSTEXPR inline bool isSurrogate(uint ucs4) Q_DECL_NOTHROW { return (ucs4 - 0xd800u < 2048u); } - static Q_DECL_CONSTEXPR inline bool requiresSurrogates(uint ucs4) + static Q_DECL_CONSTEXPR inline bool requiresSurrogates(uint ucs4) Q_DECL_NOTHROW { return (ucs4 >= 0x10000); } - static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(ushort high, ushort low) + static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(ushort high, ushort low) Q_DECL_NOTHROW { return (uint(high)<<10) + low - 0x35fdc00; } - static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(QChar high, QChar low) + static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(QChar high, QChar low) Q_DECL_NOTHROW { return surrogateToUcs4(high.ucs, low.ucs); } - static Q_DECL_CONSTEXPR inline ushort highSurrogate(uint ucs4) + static Q_DECL_CONSTEXPR inline ushort highSurrogate(uint ucs4) Q_DECL_NOTHROW { return ushort((ucs4>>10) + 0xd7c0); } - static Q_DECL_CONSTEXPR inline ushort lowSurrogate(uint ucs4) + static Q_DECL_CONSTEXPR inline ushort lowSurrogate(uint ucs4) Q_DECL_NOTHROW { return ushort(ucs4%0x400 + 0xdc00); } - static Category QT_FASTCALL category(uint ucs4) Q_DECL_CONST_FUNCTION; - static Direction QT_FASTCALL direction(uint ucs4) Q_DECL_CONST_FUNCTION; - static JoiningType QT_FASTCALL joiningType(uint ucs4) Q_DECL_CONST_FUNCTION; + static Category QT_FASTCALL category(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static Direction QT_FASTCALL direction(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static JoiningType QT_FASTCALL joiningType(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; #if QT_DEPRECATED_SINCE(5, 3) - QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4) Q_DECL_CONST_FUNCTION; + QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; #endif - static unsigned char QT_FASTCALL combiningClass(uint ucs4) Q_DECL_CONST_FUNCTION; + static unsigned char QT_FASTCALL combiningClass(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; - static uint QT_FASTCALL mirroredChar(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL hasMirrored(uint ucs4) Q_DECL_CONST_FUNCTION; + static uint QT_FASTCALL mirroredChar(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL hasMirrored(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; static QString QT_FASTCALL decomposition(uint ucs4); - static Decomposition QT_FASTCALL decompositionTag(uint ucs4) Q_DECL_CONST_FUNCTION; + static Decomposition QT_FASTCALL decompositionTag(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; - static int QT_FASTCALL digitValue(uint ucs4) Q_DECL_CONST_FUNCTION; - static uint QT_FASTCALL toLower(uint ucs4) Q_DECL_CONST_FUNCTION; - static uint QT_FASTCALL toUpper(uint ucs4) Q_DECL_CONST_FUNCTION; - static uint QT_FASTCALL toTitleCase(uint ucs4) Q_DECL_CONST_FUNCTION; - static uint QT_FASTCALL toCaseFolded(uint ucs4) Q_DECL_CONST_FUNCTION; + static int QT_FASTCALL digitValue(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static uint QT_FASTCALL toLower(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static uint QT_FASTCALL toUpper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static uint QT_FASTCALL toTitleCase(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static uint QT_FASTCALL toCaseFolded(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; - static Script QT_FASTCALL script(uint ucs4) Q_DECL_CONST_FUNCTION; + static Script QT_FASTCALL script(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; - static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4) Q_DECL_CONST_FUNCTION; + static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; - static UnicodeVersion QT_FASTCALL currentUnicodeVersion() Q_DECL_CONST_FUNCTION; + static UnicodeVersion QT_FASTCALL currentUnicodeVersion() Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isPrint(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isSpace(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isMark(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isPunct(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isSymbol(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isLetter(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isNumber(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isLetterOrNumber(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isDigit(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isLower(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isUpper(uint ucs4) Q_DECL_CONST_FUNCTION; - static Q_DECL_CONSTEXPR inline bool isTitleCase(uint ucs4) Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isPrint(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static Q_DECL_CONSTEXPR inline bool isSpace(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { + // note that [0x09..0x0d] + 0x85 are exceptional Cc-s and must be handled explicitly + return ucs4 == 0x20 || (ucs4 <= 0x0d && ucs4 >= 0x09) + || (ucs4 > 127 && (ucs4 == 0x85 || ucs4 == 0xa0 || QChar::isSpace_helper(ucs4))); + } + static bool QT_FASTCALL isMark(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isPunct(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isSymbol(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static Q_DECL_CONSTEXPR inline bool isLetter(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { + return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z')) + || (ucs4 > 127 && QChar::isLetter_helper(ucs4)); + } + static Q_DECL_CONSTEXPR inline bool isNumber(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::isNumber_helper(ucs4)); } + static Q_DECL_CONSTEXPR inline bool isLetterOrNumber(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { + return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z')) + || (ucs4 >= '0' && ucs4 <= '9') + || (ucs4 > 127 && QChar::isLetterOrNumber_helper(ucs4)); + } + static Q_DECL_CONSTEXPR inline bool isDigit(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::category(ucs4) == Number_DecimalDigit); } + static Q_DECL_CONSTEXPR inline bool isLower(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { return (ucs4 <= 'z' && ucs4 >= 'a') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Lowercase); } + static Q_DECL_CONSTEXPR inline bool isUpper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { return (ucs4 <= 'Z' && ucs4 >= 'A') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Uppercase); } + static Q_DECL_CONSTEXPR inline bool isTitleCase(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION + { return ucs4 > 127 && QChar::category(ucs4) == Letter_Titlecase; } private: - static bool QT_FASTCALL isSpace_helper(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isLetter_helper(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isNumber_helper(uint ucs4) Q_DECL_CONST_FUNCTION; - static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4) Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isSpace_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isLetter_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isNumber_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; + static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION; #ifdef QT_NO_CAST_FROM_ASCII - QChar(char c); - QChar(uchar c); + QChar(char c) Q_DECL_NOTHROW; + QChar(uchar c) Q_DECL_NOTHROW; #endif - friend Q_DECL_CONSTEXPR bool operator==(QChar, QChar); - friend Q_DECL_CONSTEXPR bool operator< (QChar, QChar); + friend Q_DECL_CONSTEXPR bool operator==(QChar, QChar) Q_DECL_NOTHROW; + friend Q_DECL_CONSTEXPR bool operator< (QChar, QChar) Q_DECL_NOTHROW; ushort ucs; }; Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE); -Q_DECL_CONSTEXPR inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } -Q_DECL_CONSTEXPR inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); } - -inline void QChar::setCell(uchar acell) -{ ucs = ushort((ucs & 0xff00) + acell); } -inline void QChar::setRow(uchar arow) -{ ucs = ushort((ushort(arow)<<8) + (ucs&0xff)); } - -Q_DECL_CONSTEXPR inline bool QChar::isSpace(uint ucs4) -{ - // note that [0x09..0x0d] + 0x85 are exceptional Cc-s and must be handled explicitly - return ucs4 == 0x20 || (ucs4 <= 0x0d && ucs4 >= 0x09) - || (ucs4 > 127 && (ucs4 == 0x85 || ucs4 == 0xa0 || QChar::isSpace_helper(ucs4))); -} -Q_DECL_CONSTEXPR inline bool QChar::isLetter(uint ucs4) -{ - return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z')) - || (ucs4 > 127 && QChar::isLetter_helper(ucs4)); -} -Q_DECL_CONSTEXPR inline bool QChar::isNumber(uint ucs4) -{ return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::isNumber_helper(ucs4)); } -Q_DECL_CONSTEXPR inline bool QChar::isLetterOrNumber(uint ucs4) -{ - return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z')) - || (ucs4 >= '0' && ucs4 <= '9') - || (ucs4 > 127 && QChar::isLetterOrNumber_helper(ucs4)); -} -Q_DECL_CONSTEXPR inline bool QChar::isDigit(uint ucs4) -{ return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::category(ucs4) == Number_DecimalDigit); } -Q_DECL_CONSTEXPR inline bool QChar::isLower(uint ucs4) -{ return (ucs4 <= 'z' && ucs4 >= 'a') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Lowercase); } -Q_DECL_CONSTEXPR inline bool QChar::isUpper(uint ucs4) -{ return (ucs4 <= 'Z' && ucs4 >= 'A') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Uppercase); } -Q_DECL_CONSTEXPR inline bool QChar::isTitleCase(uint ucs4) -{ return ucs4 > 127 && QChar::category(ucs4) == Letter_Titlecase; } - -Q_DECL_CONSTEXPR inline bool operator==(QChar c1, QChar c2) { return c1.ucs == c2.ucs; } -Q_DECL_CONSTEXPR inline bool operator< (QChar c1, QChar c2) { return c1.ucs < c2.ucs; } +Q_DECL_CONSTEXPR inline bool operator==(QChar c1, QChar c2) Q_DECL_NOTHROW { return c1.ucs == c2.ucs; } +Q_DECL_CONSTEXPR inline bool operator< (QChar c1, QChar c2) Q_DECL_NOTHROW { return c1.ucs < c2.ucs; } Q_DECL_CONSTEXPR inline bool operator!=(QChar c1, QChar c2) { return !operator==(c1, c2); } Q_DECL_CONSTEXPR inline bool operator>=(QChar c1, QChar c2) { return !operator< (c1, c2); } diff --git a/src/corelib/tools/qcollator.h b/src/corelib/tools/qcollator.h index e1fa161257..57133165c4 100644 --- a/src/corelib/tools/qcollator.h +++ b/src/corelib/tools/qcollator.h @@ -83,7 +83,7 @@ public: QCollator &operator=(const QCollator &); #ifdef Q_COMPILER_RVALUE_REFS QCollator(QCollator &&other) Q_DECL_NOTHROW - : d(other.d) { other.d = 0; } + : d(other.d) { other.d = Q_NULLPTR; } QCollator &operator=(QCollator &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index 7f898f68a8..8ab98741f5 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -41,10 +41,19 @@ QT_BEGIN_NAMESPACE class QCommandLineOptionPrivate : public QSharedData { public: - inline QCommandLineOptionPrivate() + Q_NEVER_INLINE + explicit QCommandLineOptionPrivate(const QString &name) + : names(removeInvalidNames(QStringList(name))), + hidden(false) { } - void setNames(const QStringList &nameList); + Q_NEVER_INLINE + explicit QCommandLineOptionPrivate(const QStringList &names) + : names(removeInvalidNames(names)), + hidden(false) + { } + + static QStringList removeInvalidNames(QStringList nameList); //! The list of names used for this option. QStringList names; @@ -58,6 +67,9 @@ public: //! The list of default values used for this option. QStringList defaultValues; + + //! Show or hide in --help + bool hidden; }; /*! @@ -98,9 +110,8 @@ public: \sa setDescription(), setValueName(), setDefaultValues() */ QCommandLineOption::QCommandLineOption(const QString &name) - : d(new QCommandLineOptionPrivate) + : d(new QCommandLineOptionPrivate(name)) { - d->setNames(QStringList(name)); } /*! @@ -117,9 +128,8 @@ QCommandLineOption::QCommandLineOption(const QString &name) \sa setDescription(), setValueName(), setDefaultValues() */ QCommandLineOption::QCommandLineOption(const QStringList &names) - : d(new QCommandLineOptionPrivate) + : d(new QCommandLineOptionPrivate(names)) { - d->setNames(names); } /*! @@ -148,9 +158,8 @@ QCommandLineOption::QCommandLineOption(const QStringList &names) QCommandLineOption::QCommandLineOption(const QString &name, const QString &description, const QString &valueName, const QString &defaultValue) - : d(new QCommandLineOptionPrivate) + : d(new QCommandLineOptionPrivate(name)) { - d->setNames(QStringList(name)); setValueName(valueName); setDescription(description); setDefaultValue(defaultValue); @@ -185,9 +194,8 @@ QCommandLineOption::QCommandLineOption(const QString &name, const QString &descr QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description, const QString &valueName, const QString &defaultValue) - : d(new QCommandLineOptionPrivate) + : d(new QCommandLineOptionPrivate(names)) { - d->setNames(names); setValueName(valueName); setDescription(description); setDefaultValue(defaultValue); @@ -236,29 +244,44 @@ QStringList QCommandLineOption::names() const return d->names; } -void QCommandLineOptionPrivate::setNames(const QStringList &nameList) +namespace { + struct IsInvalidName + { + typedef bool result_type; + typedef QString argument_type; + + result_type operator()(const QString &name) const Q_DECL_NOEXCEPT + { + if (name.isEmpty()) { + qWarning("QCommandLineOption: Option names cannot be empty"); + return true; + } else { + const QChar c = name.at(0); + if (c == QLatin1Char('-')) { + qWarning("QCommandLineOption: Option names cannot start with a '-'"); + return true; + } else if (c == QLatin1Char('/')) { + qWarning("QCommandLineOption: Option names cannot start with a '/'"); + return true; + } else if (name.contains(QLatin1Char('='))) { + qWarning("QCommandLineOption: Option names cannot contain a '='"); + return true; + } + } + return false; + } + }; +} // unnamed namespace + +// static +QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList) { - QStringList newNames; - newNames.reserve(nameList.size()); if (nameList.isEmpty()) qWarning("QCommandLineOption: Options must have at least one name"); - foreach (const QString &name, nameList) { - if (name.isEmpty()) { - qWarning("QCommandLineOption: Option names cannot be empty"); - } else { - const QChar c = name.at(0); - if (c == QLatin1Char('-')) - qWarning("QCommandLineOption: Option names cannot start with a '-'"); - else if (c == QLatin1Char('/')) - qWarning("QCommandLineOption: Option names cannot start with a '/'"); - else if (name.contains(QLatin1Char('='))) - qWarning("QCommandLineOption: Option names cannot contain a '='"); - else - newNames.append(name); - } - } - // commit - names.swap(newNames); + else + nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()), + nameList.end()); + return qMove(nameList); } /*! @@ -362,4 +385,30 @@ QStringList QCommandLineOption::defaultValues() const return d->defaultValues; } +/*! + Sets whether to hide this option in the user-visible help output. + + All options are visible by default. Setting \a hidden to true for + a particular option makes it internal, i.e. not listed in the help output. + + \since 5.6 + \sa isHidden + */ +void QCommandLineOption::setHidden(bool hide) +{ + d->hidden = hide; +} + +/*! + Returns true if this option is omitted from the help output, + false if the option is listed. + + \since 5.6 + \sa setHidden() + */ +bool QCommandLineOption::isHidden() const +{ + return d->hidden; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h index cf4160ecd2..828522cbc5 100644 --- a/src/corelib/tools/qcommandlineoption.h +++ b/src/corelib/tools/qcommandlineoption.h @@ -58,11 +58,10 @@ public: QCommandLineOption &operator=(const QCommandLineOption &other); #ifdef Q_COMPILER_RVALUE_REFS - inline QCommandLineOption &operator=(QCommandLineOption &&other) - { qSwap(d, other.d); return *this; } + QCommandLineOption &operator=(QCommandLineOption &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif - inline void swap(QCommandLineOption &other) + void swap(QCommandLineOption &other) Q_DECL_NOTHROW { qSwap(d, other.d); } QStringList names() const; @@ -77,6 +76,9 @@ public: void setDefaultValues(const QStringList &defaultValues); QStringList defaultValues() const; + void setHidden(bool hidden); + bool isHidden() const; + private: QSharedDataPointer<QCommandLineOptionPrivate> d; }; diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 0814921a58..4cc3a2c293 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -53,6 +53,7 @@ class QCommandLineParserPrivate public: inline QCommandLineParserPrivate() : singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions), + optionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsOptions), builtinVersionOption(false), builtinHelpOption(false), needsParsing(true) @@ -103,6 +104,9 @@ public: //! The parsing mode for "-abc" QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode; + //! How to parse "arg -option" + QCommandLineParser::OptionsAfterPositionalArgumentsMode optionsAfterPositionalArgumentsMode; + //! Whether addVersionOption was called bool builtinVersionOption; @@ -299,6 +303,41 @@ void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleD } /*! + \enum QCommandLineParser::OptionsAfterPositionalArgumentsMode + + This enum describes the way the parser interprets options that + occur after positional arguments. + + \value ParseAsOptions \c{application argument --opt -t} is interpreted as setting + the options \c{opt} and \c{t}, just like \c{application --opt -t argument} would do. + This is the default parsing mode. In order to specify that \c{--opt} and \c{-t} + are positional arguments instead, the user can use \c{--}, as in + \c{application argument -- --opt -t}. + + \value ParseAsPositionalArguments \c{application argument --opt} is interpreted as + having two positional arguments, \c{argument} and \c{--opt}. + This mode is useful for executables that aim to launch other executables + (e.g. wrappers, debugging tools, etc.) or that support internal commands + followed by options for the command. \c{argument} is the name of the command, + and all options occurring after it can be collected and parsed by another + command line parser, possibly in another executable. + + \sa setOptionsAfterPositionalArgumentsMode() + + \since 5.5 +*/ + +/*! + Sets the parsing mode to \a parsingMode. + This must be called before process() or parse(). + \since 5.5 +*/ +void QCommandLineParser::setOptionsAfterPositionalArgumentsMode(QCommandLineParser::OptionsAfterPositionalArgumentsMode parsingMode) +{ + d->optionsAfterPositionalArgumentsMode = parsingMode; +} + +/*! Adds the option \a option to look for while parsing. Returns \c true if adding the option was successful; otherwise returns \c false. @@ -640,7 +679,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) const QLatin1Char dashChar('-'); const QLatin1Char assignChar('='); - bool doubleDashFound = false; + bool forcePositional = false; errorText.clear(); positionalArgumentList.clear(); optionNames.clear(); @@ -658,7 +697,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) for (; argumentIterator != args.end() ; ++argumentIterator) { QString argument = *argumentIterator; - if (doubleDashFound) { + if (forcePositional) { positionalArgumentList.append(argument); } else if (argument.startsWith(doubleDashString)) { if (argument.length() > 2) { @@ -670,7 +709,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) error = true; } } else { - doubleDashFound = true; + forcePositional = true; } } else if (argument.startsWith(dashChar)) { if (argument.size() == 1) { // single dash ("stdin") @@ -722,6 +761,8 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) } } else { positionalArgumentList.append(argument); + if (optionsAfterPositionalArgumentsMode == QCommandLineParser::ParseAsPositionalArguments) + forcePositional = true; } if (argumentIterator == args.end()) break; @@ -1062,6 +1103,8 @@ QString QCommandLineParserPrivate::helpText() const ++longestOptionNameString; for (int i = 0; i < commandLineOptionList.count(); ++i) { const QCommandLineOption &option = commandLineOptionList.at(i); + if (option.isHidden()) + continue; text += wrapText(optionNameList.at(i), longestOptionNameString, option.description()); } if (!positionalArgumentDefinitions.isEmpty()) { diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h index 91a799b4d5..8c528ba69e 100644 --- a/src/corelib/tools/qcommandlineparser.h +++ b/src/corelib/tools/qcommandlineparser.h @@ -57,6 +57,12 @@ public: }; void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode); + enum OptionsAfterPositionalArgumentsMode { + ParseAsOptions, + ParseAsPositionalArguments + }; + void setOptionsAfterPositionalArgumentsMode(OptionsAfterPositionalArgumentsMode mode); + bool addOption(const QCommandLineOption &commandLineOption); bool addOptions(const QList<QCommandLineOption> &options); diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 6651efdc13..c44f7f8fee 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -74,7 +74,7 @@ public: int dayOfYear() const; int daysInMonth() const; int daysInYear() const; - int weekNumber(int *yearNum = 0) const; + int weekNumber(int *yearNum = Q_NULLPTR) const; #ifndef QT_NO_TEXTDATE static QString shortMonthName(int month, MonthNameType type = DateFormat); @@ -222,9 +222,12 @@ public: QDateTime(const QDateTime &other); ~QDateTime(); +#ifdef Q_COMPILER_RVALUE_REFS + QDateTime &operator=(QDateTime &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QDateTime &operator=(const QDateTime &other); - inline void swap(QDateTime &other) { qSwap(d, other.d); } + void swap(QDateTime &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool isNull() const; bool isValid() const; diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 1bd9c5ebb9..58ccd32c5e 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -1219,6 +1219,7 @@ QVector<QPointF> static inline tcbToBezier(const TCBPoints &tcbPoints) { const int count = tcbPoints.count(); QVector<QPointF> bezierPoints; + bezierPoints.reserve(3 * (count - 1)); for (int i = 1; i < count; i++) { const qreal t_0 = tcbPoints.at(i - 1)._t; diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h index 4065de1366..d04d5ef30a 100644 --- a/src/corelib/tools/qeasingcurve.h +++ b/src/corelib/tools/qeasingcurve.h @@ -75,7 +75,7 @@ public: QEasingCurve &operator=(const QEasingCurve &other) { if ( this != &other ) { QEasingCurve copy(other); swap(copy); } return *this; } #ifdef Q_COMPILER_RVALUE_REFS - QEasingCurve(QEasingCurve &&other) : d_ptr(other.d_ptr) { other.d_ptr = 0; } + QEasingCurve(QEasingCurve &&other) : d_ptr(other.d_ptr) { other.d_ptr = Q_NULLPTR; } QEasingCurve &operator=(QEasingCurve &&other) { qSwap(d_ptr, other.d_ptr); return *this; } #endif diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp index afc8b23473..fa279949ea 100644 --- a/src/corelib/tools/qharfbuzz.cpp +++ b/src/corelib/tools/qharfbuzz.cpp @@ -65,6 +65,9 @@ HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch) void (*HB_Library_Resolve(const char *library, int version, const char *symbol))() { #ifdef QT_NO_LIBRARY + Q_UNUSED(library); + Q_UNUSED(version); + Q_UNUSED(symbol); return 0; #else return QLibrary::resolve(QLatin1String(library), version, symbol); diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index a9ece12670..c83dcaabe1 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -38,10 +38,9 @@ #include <QtCore/qchar.h> #include <QtCore/qiterator.h> #include <QtCore/qlist.h> -#include <QtCore/qpair.h> #include <QtCore/qrefcount.h> +#include <QtCore/qhashfunctions.h> -#include <numeric> // for std::accumulate #ifdef Q_COMPILER_INITIALIZER_LISTS #include <initializer_list> #endif @@ -54,101 +53,6 @@ QT_BEGIN_NAMESPACE -class QBitArray; -class QByteArray; -class QString; -class QStringRef; -class QLatin1String; - -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW; - -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW -{ - return (sizeof(ulong) > sizeof(uint)) - ? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed) - : (uint(key & (~0U)) ^ seed); -} -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); } -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW -{ - return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed; -} -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); } -Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW; -#ifndef Q_OS_DARWIN -Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW; -#endif -Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); } -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QString &key) Q_DECL_NOTHROW; -Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW; - -template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW -{ - return qHash(reinterpret_cast<quintptr>(key), seed); -} -template<typename T> inline uint qHash(const T &t, uint seed) - Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) -{ return (qHash(t) ^ seed); } - -namespace QtPrivate { - -struct QHashCombine { - typedef uint result_type; - template <typename T> - Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) - // combiner taken from N3876 / boost::hash_combine - { return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; } -}; - -struct QHashCombineCommutative { - // QHashCombine is a good hash combiner, but is not commutative, - // ie. it depends on the order of the input elements. That is - // usually what we want: {0,1,3} should hash differently than - // {1,3,0}. Except when it isn't (e.g. for QSet and - // QHash). Therefore, provide a commutative combiner, too. - typedef uint result_type; - template <typename T> - Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) - { return seed + qHash(t); } // don't use xor! -}; - -} // namespace QtPrivate - -template <typename InputIterator> -inline uint qHashRange(InputIterator first, InputIterator last, uint seed = 0) - Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(*first))) // assume iterator operations don't throw -{ - return std::accumulate(first, last, seed, QtPrivate::QHashCombine()); -} - -template <typename InputIterator> -inline uint qHashRangeCommutative(InputIterator first, InputIterator last, uint seed = 0) - Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(*first))) // assume iterator operations don't throw -{ - return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative()); -} - -template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key, uint seed = 0) - Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed))) -{ - uint h1 = qHash(key.first, seed); - uint h2 = qHash(key.second, seed); - return ((h1 << 16) | (h1 >> 16)) ^ h2 ^ seed; -} - struct Q_CORE_EXPORT QHashData { struct Node { @@ -402,7 +306,7 @@ public: typedef T *pointer; typedef T &reference; - inline iterator() : i(0) { } + inline iterator() : i(Q_NULLPTR) { } explicit inline iterator(void *node) : i(reinterpret_cast<QHashData::Node *>(node)) { } inline const Key &key() const { return concrete(i)->key; } @@ -449,6 +353,7 @@ public: class const_iterator { friend class iterator; + friend class QSet<Key>; QHashData::Node *i; public: @@ -458,7 +363,7 @@ public: typedef const T *pointer; typedef const T &reference; - inline const_iterator() : i(0) { } + inline const_iterator() : i(Q_NULLPTR) { } explicit inline const_iterator(void *node) : i(reinterpret_cast<QHashData::Node *>(node)) { } #ifdef QT_STRICT_ITERATORS @@ -546,7 +451,8 @@ public: private: void detach_helper(); void freeData(QHashData *d); - Node **findNode(const Key &key, uint *hp = 0) const; + Node **findNode(const Key &key, uint *hp = Q_NULLPTR) const; + Node **findNode(const Key &key, uint h) const; Node *createNode(uint h, const Key &key, const T &value, Node **nextNode); void deleteNode(Node *node); static void deleteNode2(QHashData::Node *node); @@ -590,7 +496,7 @@ template <class Key, class T> Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode) { Node *concreteNode = concrete(node); - new (newNode) Node(concreteNode->key, concreteNode->value, concreteNode->h, 0); + new (newNode) Node(concreteNode->key, concreteNode->value, concreteNode->h, Q_NULLPTR); } template <class Key, class T> @@ -942,17 +848,10 @@ Q_INLINE_TEMPLATE bool QHash<Key, T>::contains(const Key &akey) const } template <class Key, class T> -Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey, - uint *ahp) const +Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey, uint h) const { Node **node; - uint h = 0; - if (d->numBuckets || ahp) { - h = qHash(akey, d->seed); - if (ahp) - *ahp = h; - } if (d->numBuckets) { node = reinterpret_cast<Node **>(&d->buckets[h % d->numBuckets]); Q_ASSERT(*node == e || (*node)->next); @@ -965,6 +864,20 @@ Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(cons } template <class Key, class T> +Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey, + uint *ahp) const +{ + uint h = 0; + + if (d->numBuckets || ahp) { + h = qHash(akey, d->seed); + if (ahp) + *ahp = h; + } + return findNode(akey, h); +} + +template <class Key, class T> Q_OUTOFLINE_TEMPLATE bool QHash<Key, T>::operator==(const QHash &other) const { if (size() != other.size()) diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h new file mode 100644 index 0000000000..e15fbb07ac --- /dev/null +++ b/src/corelib/tools/qhashfunctions.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHASHFUNCTIONS_H +#define QHASHFUNCTIONS_H + +#include <QtCore/qchar.h> +#include <QtCore/qpair.h> + +#include <numeric> // for std::accumulate + +#if 0 +#pragma qt_class(QHashFunctions) +#endif + +#if defined(Q_CC_MSVC) +#pragma warning( push ) +#pragma warning( disable : 4311 ) // disable pointer truncation warning +#pragma warning( disable : 4127 ) // conditional expression is constant +#endif + +QT_BEGIN_NAMESPACE + +class QBitArray; +class QByteArray; +class QString; +class QStringRef; +class QLatin1String; + +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW; + +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW +{ + return (sizeof(ulong) > sizeof(uint)) + ? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed) + : (uint(key & (~0U)) ^ seed); +} +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); } +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW +{ + return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed; +} +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); } +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW; +#ifndef Q_OS_DARWIN +Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW; +#endif +Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); } +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QString &key) Q_DECL_NOTHROW; +Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW; + +template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(reinterpret_cast<quintptr>(key), seed); +} +template<typename T> inline uint qHash(const T &t, uint seed) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) +{ return qHash(t) ^ seed; } + +namespace QtPrivate { + +struct QHashCombine { + typedef uint result_type; + template <typename T> + Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) + // combiner taken from N3876 / boost::hash_combine + { return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; } +}; + +struct QHashCombineCommutative { + // QHashCombine is a good hash combiner, but is not commutative, + // ie. it depends on the order of the input elements. That is + // usually what we want: {0,1,3} should hash differently than + // {1,3,0}. Except when it isn't (e.g. for QSet and + // QHash). Therefore, provide a commutative combiner, too. + typedef uint result_type; + template <typename T> + Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) + { return seed + qHash(t); } // don't use xor! +}; + +} // namespace QtPrivate + +template <typename InputIterator> +inline uint qHashRange(InputIterator first, InputIterator last, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(*first))) // assume iterator operations don't throw +{ + return std::accumulate(first, last, seed, QtPrivate::QHashCombine()); +} + +template <typename InputIterator> +inline uint qHashRangeCommutative(InputIterator first, InputIterator last, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(*first))) // assume iterator operations don't throw +{ + return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative()); +} + +template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed))) +{ + uint h1 = qHash(key.first, seed); + uint h2 = qHash(key.second, seed); + return ((h1 << 16) | (h1 >> 16)) ^ h2 ^ seed; +} + +QT_END_NAMESPACE + +#if defined(Q_CC_MSVC) +#pragma warning( pop ) +#endif + +#endif // QHASHFUNCTIONS_H diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index db00dcb458..d774548d3a 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -584,6 +584,65 @@ void **QListData::erase(void **xi) \sa operator==() */ +/*! \fn bool operator<(const QList<T> &lhs, const QList<T> &rhs) + \since 5.6 + \relates QList + + Returns \c true if list \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator<=(const QList<T> &lhs, const QList<T> &rhs) + \since 5.6 + \relates QList + + Returns \c true if list \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator>(const QList<T> &lhs, const QList<T> &rhs) + \since 5.6 + \relates QList + + Returns \c true if list \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator>=(const QList<T> &lhs, const QList<T> &rhs) + \since 5.6 + \relates QList + + Returns \c true if list \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! + \fn uint qHash(const QList<T> &key, uint seed = 0) + \since 5.6 + \relates QList + + Returns the hash value for \a key, + using \a seed to seed the calculation. + + This function requires qHash() to be overloaded for the value type \c T. +*/ + /*! \fn int QList::size() const @@ -1000,6 +1059,52 @@ void **QListData::erase(void **xi) \sa constBegin(), end() */ +/*! \fn QList::reverse_iterator QList::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the list, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QList::const_reverse_iterator QList::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QList::const_reverse_iterator QList::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the list, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QList::reverse_iterator QList::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last item in the list, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QList::const_reverse_iterator QList::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QList::const_reverse_iterator QList::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last item in the list, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \fn QList::iterator QList::erase(iterator pos) Removes the item associated with the iterator \a pos from the @@ -1070,6 +1175,38 @@ void **QListData::erase(void **xi) Typedef for const T &. Provided for STL compatibility. */ +/*! \typedef QList::reverse_iterator + \since 5.6 + + The QList::reverse_iterator typedef provides an STL-style non-const + reverse iterator for QList. + + It is simply a typedef for \c{std::reverse_iterator<iterator>}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QList::rbegin(), QList::rend(), QList::const_reverse_iterator, QList::iterator +*/ + +/*! \typedef QList::const_reverse_iterator + \since 5.6 + + The QList::const_reverse_iterator typedef provides an STL-style const + reverse iterator for QList. + + It is simply a typedef for \c{std::reverse_iterator<const_iterator>}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QList::rbegin(), QList::rend(), QList::reverse_iterator, QList::const_iterator +*/ + /*! \fn int QList::count() const Returns the number of items in the list. This is effectively the @@ -1090,7 +1227,7 @@ void **QListData::erase(void **xi) not be empty. If the list can be empty, call isEmpty() before calling this function. - \sa last(), isEmpty() + \sa constFirst(), last(), isEmpty() */ /*! \fn const T& QList::first() const @@ -1098,13 +1235,23 @@ void **QListData::erase(void **xi) \overload */ +/*! \fn const T& QList::constFirst() const + \since 5.6 + + Returns a const reference to the first item in the list. The list must + not be empty. If the list can be empty, call isEmpty() before + calling this function. + + \sa constLast(), isEmpty(), first() +*/ + /*! \fn T& QList::last() Returns a reference to the last item in the list. The list must not be empty. If the list can be empty, call isEmpty() before calling this function. - \sa first(), isEmpty() + \sa constLast(), first(), isEmpty() */ /*! \fn const T& QList::last() const @@ -1112,6 +1259,16 @@ void **QListData::erase(void **xi) \overload */ +/*! \fn const T& QList::constLast() const + \since 5.6 + + Returns a reference to the last item in the list. The list must + not be empty. If the list can be empty, call isEmpty() before + calling this function. + + \sa constFirst(), isEmpty(), last() +*/ + /*! \fn void QList::removeFirst() Removes the first item in the list. Calling this function is diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index f5ff952f97..ac46dc3244 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -38,6 +38,7 @@ #include <QtCore/qiterator.h> #include <QtCore/qrefcount.h> #include <QtCore/qarraydata.h> +#include <QtCore/qhashfunctions.h> #include <iterator> #include <list> @@ -220,7 +221,11 @@ public: inline iterator() : i(0) {} inline iterator(Node *n) : i(n) {} +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + // can't remove it in Qt 5, since doing so would make the type trivial, + // which changes the way it's passed to functions by value. inline iterator(const iterator &o): i(o.i){} +#endif inline T &operator*() const { return i->t(); } inline T *operator->() const { return &i->t(); } inline T &operator[](difference_type j) const { return i[j].t(); } @@ -268,7 +273,11 @@ public: inline const_iterator() : i(0) {} inline const_iterator(Node *n) : i(n) {} +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + // can't remove it in Qt 5, since doing so would make the type trivial, + // which changes the way it's passed to functions by value. inline const_iterator(const const_iterator &o): i(o.i) {} +#endif #ifdef QT_STRICT_ITERATORS inline explicit const_iterator(const iterator &o): i(o.i) {} #else @@ -296,6 +305,8 @@ public: friend class const_iterator; // stl style + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; inline iterator begin() { detach(); return reinterpret_cast<Node *>(p.begin()); } inline const_iterator begin() const { return reinterpret_cast<Node *>(p.begin()); } inline const_iterator cbegin() const { return reinterpret_cast<Node *>(p.begin()); } @@ -304,6 +315,12 @@ public: inline const_iterator end() const { return reinterpret_cast<Node *>(p.end()); } inline const_iterator cend() const { return reinterpret_cast<Node *>(p.end()); } inline const_iterator constEnd() const { return reinterpret_cast<Node *>(p.end()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } iterator insert(iterator before, const T &t); iterator erase(iterator pos); iterator erase(iterator first, iterator last); @@ -314,9 +331,11 @@ public: inline int count() const { return p.size(); } inline int length() const { return p.size(); } // Same as count() inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); } + inline const T& constFirst() const { return first(); } inline const T& first() const { Q_ASSERT(!isEmpty()); return at(0); } T& last() { Q_ASSERT(!isEmpty()); return *(--end()); } const T& last() const { Q_ASSERT(!isEmpty()); return at(count() - 1); } + inline const T& constLast() const { return last(); } inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); } inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); } inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; } @@ -1020,6 +1039,43 @@ inline int QList<T>::count_impl(const T &t, QListData::ArrayCompatibleLayout) co Q_DECLARE_SEQUENTIAL_ITERATOR(List) Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List) +template <typename T> +uint qHash(const QList<T> &key, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRange(key.cbegin(), key.cend(), seed))) +{ + return qHashRange(key.cbegin(), key.cend(), seed); +} + +template <typename T> +bool operator<(const QList<T> &lhs, const QList<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()))) +{ + return std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()); +} + +template <typename T> +inline bool operator>(const QList<T> &lhs, const QList<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return rhs < lhs; +} + +template <typename T> +inline bool operator<=(const QList<T> &lhs, const QList<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return !(lhs > rhs); +} + +template <typename T> +inline bool operator>=(const QList<T> &lhs, const QList<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return !(lhs < rhs); +} + QT_END_NAMESPACE #include <QtCore/qbytearraylist.h> diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 824b70c3fd..703341cc36 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -42,6 +42,7 @@ #include "qdatastream.h" #include "qdebug.h" +#include "qhashfunctions.h" #include "qstring.h" #include "qlocale.h" #include "qlocale_p.h" @@ -420,7 +421,7 @@ bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QSt state = ScriptState; break; case ScriptState: { - QString scripts = QString::fromLatin1((const char *)script_code_list, sizeof(script_code_list)); + QString scripts = QString::fromLatin1((const char *)script_code_list, sizeof(script_code_list) - 1); if (value.length() == 4 && scripts.indexOf(value) % 4 == 0) { // script name is always 4 characters script = value; @@ -866,6 +867,21 @@ bool QLocale::operator!=(const QLocale &other) const } /*! + \since 5.6 + \relates QLocale + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QLocale &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.d->m_data); + seed = hash(seed, key.d->m_numberOptions); + return seed; +} + +/*! \since 4.2 Sets the \a options related to number conversions for this diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index 61574ba44f..0cbfa6710c 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE class QDataStream; class QDate; class QDateTime; +class QLocale; class QTime; class QVariant; class QTextStream; @@ -52,6 +53,8 @@ class QTextStreamPrivate; class QLocalePrivate; +Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed = 0) Q_DECL_NOTHROW; + class Q_CORE_EXPORT QLocale { Q_GADGET @@ -868,23 +871,23 @@ public: QString nativeLanguageName() const; QString nativeCountryName() const; - short toShort(const QString &s, bool *ok = 0) const; - ushort toUShort(const QString &s, bool *ok = 0) const; - int toInt(const QString &s, bool *ok = 0) const; - uint toUInt(const QString &s, bool *ok = 0) const; - qlonglong toLongLong(const QString &s, bool *ok = 0) const; - qulonglong toULongLong(const QString &s, bool *ok = 0) const; - float toFloat(const QString &s, bool *ok = 0) const; - double toDouble(const QString &s, bool *ok = 0) const; - - short toShort(const QStringRef &s, bool *ok = 0) const; - ushort toUShort(const QStringRef &s, bool *ok = 0) const; - int toInt(const QStringRef &s, bool *ok = 0) const; - uint toUInt(const QStringRef &s, bool *ok = 0) const; - qlonglong toLongLong(const QStringRef &s, bool *ok = 0) const; - qulonglong toULongLong(const QStringRef &s, bool *ok = 0) const; - float toFloat(const QStringRef &s, bool *ok = 0) const; - double toDouble(const QStringRef &s, bool *ok = 0) const; + short toShort(const QString &s, bool *ok = Q_NULLPTR) const; + ushort toUShort(const QString &s, bool *ok = Q_NULLPTR) const; + int toInt(const QString &s, bool *ok = Q_NULLPTR) const; + uint toUInt(const QString &s, bool *ok = Q_NULLPTR) const; + qlonglong toLongLong(const QString &s, bool *ok = Q_NULLPTR) const; + qulonglong toULongLong(const QString &s, bool *ok = Q_NULLPTR) const; + float toFloat(const QString &s, bool *ok = Q_NULLPTR) const; + double toDouble(const QString &s, bool *ok = Q_NULLPTR) const; + + short toShort(const QStringRef &s, bool *ok = Q_NULLPTR) const; + ushort toUShort(const QStringRef &s, bool *ok = Q_NULLPTR) const; + int toInt(const QStringRef &s, bool *ok = Q_NULLPTR) const; + uint toUInt(const QStringRef &s, bool *ok = Q_NULLPTR) const; + qlonglong toLongLong(const QStringRef &s, bool *ok = Q_NULLPTR) const; + qulonglong toULongLong(const QStringRef &s, bool *ok = Q_NULLPTR) const; + float toFloat(const QStringRef &s, bool *ok = Q_NULLPTR) const; + double toDouble(const QStringRef &s, bool *ok = Q_NULLPTR) const; QString toString(qlonglong i) const; QString toString(qulonglong i) const; @@ -979,6 +982,8 @@ public: private: QLocale(QLocalePrivate &dd); friend class QLocalePrivate; + friend Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed) Q_DECL_NOTHROW; + QSharedDataPointer<QLocalePrivate> d; }; Q_DECLARE_TYPEINFO(QLocale, Q_MOVABLE_TYPE); diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm index 37a63a2ca4..c0818f07d7 100644 --- a/src/corelib/tools/qlocale_mac.mm +++ b/src/corelib/tools/qlocale_mac.mm @@ -44,18 +44,6 @@ QT_BEGIN_NAMESPACE -namespace { -class AutoReleasePool -{ -public: - AutoReleasePool(): pool([[NSAutoreleasePool alloc] init]) {} - ~AutoReleasePool() { [pool release]; } - -private: - NSAutoreleasePool *pool; -}; -} - /****************************************************************************** ** Wrappers for Mac locale system functions */ @@ -426,7 +414,7 @@ QLocale QSystemLocale::fallbackUiLocale() const QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const { - AutoReleasePool pool; + QMacAutoReleasePool pool; switch(type) { // case Name: // return getMacLocaleName(); diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 1b7a8007cd..61e19252b3 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -1161,6 +1161,12 @@ void QMapDataBase::freeData(QMapDataBase *d) are stored under \a key. */ +/*! + \fn QPair<const_iterator, const_iterator> QMap::equal_range(const Key &key) const + \overload + \since 5.6 +*/ + /*! \class QMap::iterator \inmodule QtCore diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 1f80e8f0f4..bf0a36aa88 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -38,6 +38,7 @@ #include <QtCore/qlist.h> #include <QtCore/qrefcount.h> #include <QtCore/qpair.h> +#include <QtCore/qtypetraits.h> #ifdef Q_MAP_DEBUG #include <QtCore/qdebug.h> @@ -94,6 +95,13 @@ struct Q_CORE_EXPORT QMapNodeBase void setColor(Color c) { if (c == Black) p |= Black; else p &= ~Black; } QMapNodeBase *parent() const { return reinterpret_cast<QMapNodeBase *>(p & ~Mask); } void setParent(QMapNodeBase *pp) { p = (p & Mask) | quintptr(pp); } + + template <typename T> + static typename QtPrivate::QEnableIf<QTypeInfo<T>::isComplex>::Type + callDestructorIfNecessary(T &t) Q_DECL_NOTHROW { Q_UNUSED(t); t.~T(); } // Q_UNUSED: silence MSVC unused 't' warning + template <typename T> + static typename QtPrivate::QEnableIf<!QTypeInfo<T>::isComplex>::Type + callDestructorIfNecessary(T &) Q_DECL_NOTHROW {} }; template <class Key, class T> @@ -112,12 +120,26 @@ struct QMapNode : public QMapNodeBase QMapNode<Key, T> *copy(QMapData<Key, T> *d) const; - void destroySubTree(); + void destroySubTree() + { + callDestructorIfNecessary(key); + callDestructorIfNecessary(value); + doDestroySubTree(QtPrivate::integral_constant<bool, QTypeInfo<T>::isComplex || QTypeInfo<Key>::isComplex>()); + } QMapNode<Key, T> *lowerBound(const Key &key); QMapNode<Key, T> *upperBound(const Key &key); private: + void doDestroySubTree(QtPrivate::false_type) {} + void doDestroySubTree(QtPrivate::true_type) + { + if (left) + leftNode()->destroySubTree(); + if (right) + rightNode()->destroySubTree(); + } + QMapNode() Q_DECL_EQ_DELETE; Q_DISABLE_COPY(QMapNode) }; @@ -126,7 +148,7 @@ template <class Key, class T> inline QMapNode<Key, T> *QMapNode<Key, T>::lowerBound(const Key &akey) { QMapNode<Key, T> *n = this; - QMapNode<Key, T> *lastNode = 0; + QMapNode<Key, T> *lastNode = Q_NULLPTR; while (n) { if (!qMapLessThanKey(n->key, akey)) { lastNode = n; @@ -142,7 +164,7 @@ template <class Key, class T> inline QMapNode<Key, T> *QMapNode<Key, T>::upperBound(const Key &akey) { QMapNode<Key, T> *n = this; - QMapNode<Key, T> *lastNode = 0; + QMapNode<Key, T> *lastNode = Q_NULLPTR; while (n) { if (qMapLessThanKey(akey, n->key)) { lastNode = n; @@ -194,7 +216,7 @@ struct QMapData : public QMapDataBase Node *findNode(const Key &akey) const; void nodeRange(const Key &akey, Node **firstNode, Node **lastNode); - Node *createNode(const Key &k, const T &v, Node *parent = 0, bool left = false) + Node *createNode(const Key &k, const T &v, Node *parent = Q_NULLPTR, bool left = false) { Node *n = static_cast<Node *>(QMapDataBase::createNode(sizeof(Node), Q_ALIGNOF(Node), parent, left)); @@ -235,48 +257,22 @@ QMapNode<Key, T> *QMapNode<Key, T>::copy(QMapData<Key, T> *d) const n->left = leftNode()->copy(d); n->left->setParent(n); } else { - n->left = 0; + n->left = Q_NULLPTR; } if (right) { n->right = rightNode()->copy(d); n->right->setParent(n); } else { - n->right = 0; + n->right = Q_NULLPTR; } return n; } -#if defined(Q_CC_MSVC) -#pragma warning( push ) -#pragma warning( disable : 4127 ) // conditional expression is constant -#endif - -template <class Key, class T> -void QMapNode<Key, T>::destroySubTree() -{ - if (QTypeInfo<Key>::isComplex) - key.~Key(); - if (QTypeInfo<T>::isComplex) - value.~T(); - if (QTypeInfo<Key>::isComplex || QTypeInfo<T>::isComplex) { - if (left) - leftNode()->destroySubTree(); - if (right) - rightNode()->destroySubTree(); - } -} - -#if defined(Q_CC_MSVC) -#pragma warning( pop ) -#endif - template <class Key, class T> void QMapData<Key, T>::deleteNode(QMapNode<Key, T> *z) { - if (QTypeInfo<Key>::isComplex) - z->key.~Key(); - if (QTypeInfo<T>::isComplex) - z->value.~T(); + QMapNodeBase::callDestructorIfNecessary(z->key); + QMapNodeBase::callDestructorIfNecessary(z->value); freeNodeAndRebalance(z); } @@ -288,7 +284,7 @@ QMapNode<Key, T> *QMapData<Key, T>::findNode(const Key &akey) const if (lb && !qMapLessThanKey(akey, lb->key)) return lb; } - return 0; + return Q_NULLPTR; } @@ -304,10 +300,10 @@ void QMapData<Key, T>::nodeRange(const Key &akey, QMapNode<Key, T> **firstNode, } else if (qMapLessThanKey(n->key, akey)) { n = n->rightNode(); } else { - *firstNode = n->leftNode() ? n->leftNode()->lowerBound(akey) : 0; + *firstNode = n->leftNode() ? n->leftNode()->lowerBound(akey) : Q_NULLPTR; if (!*firstNode) *firstNode = n; - *lastNode = n->rightNode() ? n->rightNode()->upperBound(akey) : 0; + *lastNode = n->rightNode() ? n->rightNode()->upperBound(akey) : Q_NULLPTR; if (!*lastNode) *lastNode = l; return; @@ -416,7 +412,7 @@ public: typedef T *pointer; typedef T &reference; - inline iterator() : i(0) { } + inline iterator() : i(Q_NULLPTR) { } inline iterator(Node *node) : i(node) { } inline const Key &key() const { return i->key; } @@ -473,7 +469,7 @@ public: typedef const T *pointer; typedef const T &reference; - inline const_iterator() : i(0) { } + inline const_iterator() : i(Q_NULLPTR) { } inline const_iterator(const Node *node) : i(node) { } #ifdef QT_STRICT_ITERATORS explicit inline const_iterator(const iterator &o) @@ -557,6 +553,7 @@ public: typedef int size_type; inline bool empty() const { return isEmpty(); } QPair<iterator, iterator> equal_range(const Key &akey); + QPair<const_iterator, const_iterator> equal_range(const Key &akey) const; #ifdef Q_MAP_DEBUG void dump() const; @@ -653,7 +650,7 @@ Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const template <class Key, class T> Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const { - return d->findNode(akey) != 0; + return d->findNode(akey) != Q_NULLPTR; } template <class Key, class T> @@ -662,7 +659,7 @@ Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key detach(); Node *n = d->root(); Node *y = d->end(); - Node *lastNode = 0; + Node *lastNode = Q_NULLPTR; bool left = true; while (n) { y = n; @@ -737,15 +734,15 @@ typename QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const K } // we need to insert (not overwrite) - if (prev->right == 0) { + if (prev->right == Q_NULLPTR) { Node *z = d->createNode(akey, avalue, prev, false); return iterator(z); } - if (next->left == 0) { + if (next->left == Q_NULLPTR) { Node *z = d->createNode(akey, avalue, next, true); return iterator(z); } - Q_ASSERT(false); // We should have prev->right == 0 or next->left == 0. + Q_ASSERT(false); // We should have prev->right == Q_NULLPTR or next->left == Q_NULLPTR. return this->insert(akey, avalue); } } @@ -759,7 +756,7 @@ Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(cons Node* y = d->end(); Node* x = static_cast<Node *>(d->root()); bool left = true; - while (x != 0) { + while (x != Q_NULLPTR) { left = !qMapLessThanKey(x->key, akey); y = x; x = left ? x->leftNode() : x->rightNode(); @@ -806,15 +803,15 @@ typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const_iterator pos, co return this->insertMulti(akey, avalue); // ignore hint // Hint is ok - do insert - if (prev->right == 0) { + if (prev->right == Q_NULLPTR) { Node *z = d->createNode(akey, avalue, prev, false); return iterator(z); } - if (next->left == 0) { + if (next->left == Q_NULLPTR) { Node *z = d->createNode(akey, avalue, next, true); return iterator(z); } - Q_ASSERT(false); // We should have prev->right == 0 or next->left == 0. + Q_ASSERT(false); // We should have prev->right == Q_NULLPTR or next->left == Q_NULLPTR. return this->insertMulti(akey, avalue); } } @@ -864,6 +861,15 @@ QPair<typename QMap<Key, T>::iterator, typename QMap<Key, T>::iterator> QMap<Key return QPair<iterator, iterator>(iterator(firstNode), iterator(lastNode)); } +template <class Key, class T> +QPair<typename QMap<Key, T>::const_iterator, typename QMap<Key, T>::const_iterator> +QMap<Key, T>::equal_range(const Key &akey) const +{ + Node *firstNode, *lastNode; + d->nodeRange(akey, &firstNode, &lastNode); + return qMakePair(const_iterator(firstNode), const_iterator(lastNode)); +} + #ifdef Q_MAP_DEBUG template <class Key, class T> void QMap<Key, T>::dump() const @@ -1051,7 +1057,7 @@ Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values(const Key &akey) const template <class Key, class T> Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::lowerBound(const Key &akey) const { - Node *lb = d->root() ? d->root()->lowerBound(akey) : 0; + Node *lb = d->root() ? d->root()->lowerBound(akey) : Q_NULLPTR; if (!lb) lb = d->end(); return const_iterator(lb); @@ -1061,7 +1067,7 @@ template <class Key, class T> Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &akey) { detach(); - Node *lb = d->root() ? d->root()->lowerBound(akey) : 0; + Node *lb = d->root() ? d->root()->lowerBound(akey) : Q_NULLPTR; if (!lb) lb = d->end(); return iterator(lb); @@ -1071,7 +1077,7 @@ template <class Key, class T> Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::upperBound(const Key &akey) const { - Node *ub = d->root() ? d->root()->upperBound(akey) : 0; + Node *ub = d->root() ? d->root()->upperBound(akey) : Q_NULLPTR; if (!ub) ub = d->end(); return const_iterator(ub); @@ -1081,7 +1087,7 @@ template <class Key, class T> Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &akey) { detach(); - Node *ub = d->root() ? d->root()->upperBound(akey) : 0; + Node *ub = d->root() ? d->root()->upperBound(akey) : Q_NULLPTR; if (!ub) ub = d->end(); return iterator(ub); diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index cd8c393d51..5aa9d54843 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -38,6 +38,7 @@ #include "qcache.h" #include "qdatastream.h" #include "qdebug.h" +#include "qhashfunctions.h" #include "qlist.h" #include "qmap.h" #include "qmutex.h" @@ -882,6 +883,15 @@ static bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key && key1.cs == key2.cs; } +static uint qHash(const QRegExpEngineKey &key, uint seed = 0) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.pattern); + seed = hash(seed, key.patternSyntax); + seed = hash(seed, key.cs); + return seed; +} + class QRegExpEngine; //Q_DECLARE_TYPEINFO(QVector<int>, Q_MOVABLE_TYPE); @@ -3807,11 +3817,6 @@ struct QRegExpPrivate }; #if !defined(QT_NO_REGEXP_OPTIM) -uint qHash(const QRegExpEngineKey &key, uint seed = 0) Q_DECL_NOTHROW -{ - return qHash(key.pattern, seed); -} - typedef QCache<QRegExpEngineKey, QRegExpEngine> EngineCache; Q_GLOBAL_STATIC(EngineCache, globalEngineCache) static QBasicMutex globalEngineCacheMutex; @@ -4033,6 +4038,21 @@ bool QRegExp::operator==(const QRegExp &rx) const } /*! + \since 5.6 + \relates QRegExp + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.priv->engineKey); + seed = hash(seed, key.priv->minimal); + return seed; +} + +/*! \fn bool QRegExp::operator!=(const QRegExp &rx) const Returns \c true if this regular expression is not equal to \a rx; diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index b08a8bd282..f384e6c51f 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -45,6 +45,9 @@ QT_BEGIN_NAMESPACE struct QRegExpPrivate; class QStringList; +class QRegExp; + +Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed = 0) Q_DECL_NOTHROW; class Q_CORE_EXPORT QRegExp { @@ -104,6 +107,8 @@ public: static QString escape(const QString &str); + friend Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW; + private: QRegExpPrivate *priv; }; diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 2e3c2ca79f..88a048d826 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -38,6 +38,7 @@ #ifndef QT_NO_REGULAREXPRESSION #include <QtCore/qcoreapplication.h> +#include <QtCore/qhashfunctions.h> #include <QtCore/qmutex.h> #include <QtCore/qvector.h> #include <QtCore/qstringlist.h> @@ -1845,6 +1846,21 @@ bool QRegularExpression::operator==(const QRegularExpression &re) const */ /*! + \since 5.6 + \relates QRegularExpression + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.d->pattern); + seed = hash(seed, key.d->patternOptions); + return seed; +} + +/*! Escapes all characters of \a str so that they no longer have any special meaning when used as a regular expression pattern string, and returns the escaped string. For instance: @@ -2112,7 +2128,8 @@ QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const QStringList QRegularExpressionMatch::capturedTexts() const { QStringList texts; - for (int i = 0; i <= lastCapturedIndex(); ++i) + texts.reserve(d->capturedCount); + for (int i = 0; i < d->capturedCount; ++i) texts << captured(i); return texts; } diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index d2abfc7701..2bca6a211b 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -49,6 +49,9 @@ QT_BEGIN_NAMESPACE class QRegularExpressionMatch; class QRegularExpressionMatchIterator; struct QRegularExpressionPrivate; +class QRegularExpression; + +Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed = 0) Q_DECL_NOTHROW; class Q_CORE_EXPORT QRegularExpression { @@ -139,6 +142,7 @@ private: friend class QRegularExpressionMatch; friend struct QRegularExpressionMatchPrivate; friend class QRegularExpressionMatchIterator; + friend Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW; QRegularExpression(QRegularExpressionPrivate &dd); QExplicitlySharedDataPointer<QRegularExpressionPrivate> d; diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp new file mode 100644 index 0000000000..658267a521 --- /dev/null +++ b/src/corelib/tools/qringbuffer.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Alex Trotsenko <alex1973tr@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qringbuffer_p.h" +#include "private/qbytearray_p.h" +#include <string.h> + +QT_BEGIN_NAMESPACE + +/*! + \internal + + Access the bytes at a specified position the out-variable length will + contain the amount of bytes readable from there, e.g. the amount still + the same QByteArray +*/ +const char *QRingBuffer::readPointerAtPosition(qint64 pos, qint64 &length) const +{ + if (pos >= 0) { + pos += head; + for (int i = 0; i < buffers.size(); ++i) { + length = (i == tailBuffer ? tail : buffers[i].size()); + if (length > pos) { + length -= pos; + return buffers[i].constData() + pos; + } + pos -= length; + } + } + + length = 0; + return 0; +} + +void QRingBuffer::free(qint64 bytes) +{ + while (bytes > 0) { + const qint64 blockSize = buffers.first().size() - head; + + if (tailBuffer == 0 || blockSize > bytes) { + // keep a single block around if it does not exceed + // the basic block size, to avoid repeated allocations + // between uses of the buffer + if (bufferSize <= bytes) { + if (buffers.first().size() <= basicBlockSize) { + bufferSize = 0; + head = tail = 0; + } else { + clear(); // try to minify/squeeze us + } + } else { + Q_ASSERT(bytes < MaxByteArraySize); + head += int(bytes); + bufferSize -= bytes; + } + return; + } + + bufferSize -= blockSize; + bytes -= blockSize; + buffers.removeFirst(); + --tailBuffer; + head = 0; + } +} + +char *QRingBuffer::reserve(qint64 bytes) +{ + if (bytes <= 0 || bytes >= MaxByteArraySize) + return 0; + + const qint64 newSize = bytes + tail; + // if need buffer reallocation + if (newSize > buffers.last().size()) { + if (newSize > buffers.last().capacity() && (tail >= basicBlockSize + || newSize >= MaxByteArraySize)) { + // shrink this buffer to its current size + buffers.last().resize(tail); + + // create a new QByteArray + buffers.append(QByteArray()); + ++tailBuffer; + tail = 0; + } + buffers.last().resize(qMax(basicBlockSize, tail + int(bytes))); + } + + char *writePtr = buffers.last().data() + tail; + bufferSize += bytes; + Q_ASSERT(bytes < MaxByteArraySize); + tail += int(bytes); + return writePtr; +} + +/*! + \internal + + Allocate data at buffer head +*/ +char *QRingBuffer::reserveFront(qint64 bytes) +{ + if (bytes <= 0 || bytes >= MaxByteArraySize) + return 0; + + if (head < bytes) { + buffers.first().remove(0, head); + if (tailBuffer == 0) + tail -= head; + + buffers.prepend(QByteArray()); + head = qMax(basicBlockSize, int(bytes)); + buffers.first().resize(head); + ++tailBuffer; + } + + head -= int(bytes); + bufferSize += bytes; + return buffers.first().data() + head; +} + +void QRingBuffer::chop(qint64 bytes) +{ + while (bytes > 0) { + if (tailBuffer == 0 || tail > bytes) { + // keep a single block around if it does not exceed + // the basic block size, to avoid repeated allocations + // between uses of the buffer + if (bufferSize <= bytes) { + if (buffers.first().size() <= basicBlockSize) { + bufferSize = 0; + head = tail = 0; + } else { + clear(); // try to minify/squeeze us + } + } else { + Q_ASSERT(bytes < MaxByteArraySize); + tail -= int(bytes); + bufferSize -= bytes; + } + return; + } + + bufferSize -= tail; + bytes -= tail; + buffers.removeLast(); + --tailBuffer; + tail = buffers.last().size(); + } +} + +void QRingBuffer::clear() +{ + buffers.erase(buffers.begin() + 1, buffers.end()); + buffers.first().clear(); + + head = tail = 0; + tailBuffer = 0; + bufferSize = 0; +} + +qint64 QRingBuffer::indexOf(char c, qint64 maxLength) const +{ + qint64 index = 0; + qint64 j = head; + for (int i = 0; index < maxLength && i < buffers.size(); ++i) { + const char *ptr = buffers[i].constData() + j; + j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength); + + while (index < j) { + if (*ptr++ == c) + return index; + ++index; + } + j = 0; + } + return -1; +} + +qint64 QRingBuffer::read(char *data, qint64 maxLength) +{ + const qint64 bytesToRead = qMin(size(), maxLength); + qint64 readSoFar = 0; + while (readSoFar < bytesToRead) { + const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, + nextDataBlockSize()); + if (data) + memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock); + readSoFar += bytesToReadFromThisBlock; + free(bytesToReadFromThisBlock); + } + return readSoFar; +} + +/*! + \internal + + Read an unspecified amount (will read the first buffer) +*/ +QByteArray QRingBuffer::read() +{ + if (bufferSize == 0) + return QByteArray(); + + QByteArray qba(buffers.takeFirst()); + + qba.reserve(0); // avoid that resizing needlessly reallocates + if (tailBuffer == 0) { + qba.resize(tail); + tail = 0; + buffers.append(QByteArray()); + } else { + --tailBuffer; + } + qba.remove(0, head); // does nothing if head is 0 + head = 0; + bufferSize -= qba.size(); + return qba; +} + +/*! + \internal + + Peek the bytes from a specified position +*/ +qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const +{ + qint64 readSoFar = 0; + + if (pos >= 0) { + pos += head; + for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) { + qint64 blockLength = (i == tailBuffer ? tail : buffers[i].size()); + + if (pos < blockLength) { + blockLength = qMin(blockLength - pos, maxLength - readSoFar); + memcpy(data + readSoFar, buffers[i].constData() + pos, blockLength); + readSoFar += blockLength; + pos = 0; + } else { + pos -= blockLength; + } + } + } + + return readSoFar; +} + +/*! + \internal + + Append a new buffer to the end +*/ +void QRingBuffer::append(const QByteArray &qba) +{ + if (tail == 0) { + buffers.last() = qba; + } else { + buffers.last().resize(tail); + buffers.append(qba); + ++tailBuffer; + } + tail = qba.size(); + bufferSize += tail; +} + +qint64 QRingBuffer::readLine(char *data, qint64 maxLength) +{ + if (!data || --maxLength <= 0) + return -1; + + qint64 i = indexOf('\n', maxLength); + i = read(data, i >= 0 ? (i + 1) : maxLength); + + // Terminate it. + data[i] = '\0'; + return i; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index ead85e9da0..68509a6a80 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -58,7 +58,7 @@ public: buffers.append(QByteArray()); } - inline int nextDataBlockSize() const { + inline qint64 nextDataBlockSize() const { return (tailBuffer == 0 ? tail : buffers.first().size()) - head; } @@ -66,112 +66,17 @@ public: return bufferSize == 0 ? Q_NULLPTR : (buffers.first().constData() + head); } - // access the bytes at a specified position - // the out-variable length will contain the amount of bytes readable - // from there, e.g. the amount still the same QByteArray - inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const { - if (pos >= 0) { - pos += head; - for (int i = 0; i < buffers.size(); ++i) { - length = (i == tailBuffer ? tail : buffers[i].size()); - if (length > pos) { - length -= pos; - return buffers[i].constData() + pos; - } - pos -= length; - } - } - - length = 0; - return 0; - } - - inline void free(int bytes) { - while (bytes > 0) { - int blockSize = buffers.first().size() - head; - - if (tailBuffer == 0 || blockSize > bytes) { - // keep a single block around if it does not exceed - // the basic block size, to avoid repeated allocations - // between uses of the buffer - if (bufferSize <= bytes) { - if (buffers.first().size() <= basicBlockSize) { - bufferSize = 0; - head = tail = 0; - } else { - clear(); // try to minify/squeeze us - } - } else { - head += bytes; - bufferSize -= bytes; - } - return; - } - - bufferSize -= blockSize; - bytes -= blockSize; - buffers.removeFirst(); - --tailBuffer; - head = 0; - } - } - - inline char *reserve(int bytes) { - if (bytes <= 0) - return 0; - - // if need buffer reallocation - if (tail + bytes > buffers.last().size()) { - if (tail + bytes > buffers.last().capacity() && tail >= basicBlockSize) { - // shrink this buffer to its current size - buffers.last().resize(tail); - - // create a new QByteArray - buffers.append(QByteArray()); - ++tailBuffer; - tail = 0; - } - buffers.last().resize(qMax(basicBlockSize, tail + bytes)); - } + Q_CORE_EXPORT const char *readPointerAtPosition(qint64 pos, qint64 &length) const; + Q_CORE_EXPORT void free(qint64 bytes); + Q_CORE_EXPORT char *reserve(qint64 bytes); + Q_CORE_EXPORT char *reserveFront(qint64 bytes); - char *writePtr = buffers.last().data() + tail; - bufferSize += bytes; - tail += bytes; - return writePtr; - } - - inline void truncate(int pos) { + inline void truncate(qint64 pos) { if (pos < size()) chop(size() - pos); } - inline void chop(int bytes) { - while (bytes > 0) { - if (tailBuffer == 0 || tail > bytes) { - // keep a single block around if it does not exceed - // the basic block size, to avoid repeated allocations - // between uses of the buffer - if (bufferSize <= bytes) { - if (buffers.first().size() <= basicBlockSize) { - bufferSize = 0; - head = tail = 0; - } else { - clear(); // try to minify/squeeze us - } - } else { - tail -= bytes; - bufferSize -= bytes; - } - return; - } - - bufferSize -= tail; - bytes -= tail; - buffers.removeLast(); - --tailBuffer; - tail = buffers.last().size(); - } - } + Q_CORE_EXPORT void chop(qint64 bytes); inline bool isEmpty() const { return bufferSize == 0; @@ -190,131 +95,36 @@ public: *ptr = c; } - inline void ungetChar(char c) { - --head; - if (head < 0) { - if (bufferSize != 0) { - buffers.prepend(QByteArray()); - ++tailBuffer; - } else { - tail = basicBlockSize; - } - buffers.first().resize(basicBlockSize); - head = basicBlockSize - 1; - } - buffers.first()[head] = c; - ++bufferSize; - } - - inline int size() const { - return bufferSize; - } - - inline void clear() { - buffers.erase(buffers.begin() + 1, buffers.end()); - buffers.first().clear(); - - head = tail = 0; - tailBuffer = 0; - bufferSize = 0; - } - - inline int indexOf(char c) const { - int index = 0; - int j = head; - for (int i = 0; i < buffers.size(); ++i) { - const char *ptr = buffers[i].constData() + j; - j = index + (i == tailBuffer ? tail : buffers[i].size()) - j; - - while (index < j) { - if (*ptr++ == c) - return index; - ++index; - } - j = 0; - } - return -1; - } - - inline int indexOf(char c, int maxLength) const { - int index = 0; - int j = head; - for (int i = 0; index < maxLength && i < buffers.size(); ++i) { - const char *ptr = buffers[i].constData() + j; - j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength); - - while (index < j) { - if (*ptr++ == c) - return index; - ++index; - } - j = 0; - } - return -1; - } - - inline int read(char *data, int maxLength) { - int bytesToRead = qMin(size(), maxLength); - int readSoFar = 0; - while (readSoFar < bytesToRead) { - int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize()); - if (data) - memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock); - readSoFar += bytesToReadFromThisBlock; - free(bytesToReadFromThisBlock); + void ungetChar(char c) + { + if (head > 0) { + --head; + buffers.first()[head] = c; + ++bufferSize; + } else { + char *ptr = reserveFront(1); + *ptr = c; } - return readSoFar; } - // read an unspecified amount (will read the first buffer) - inline QByteArray read() { - if (bufferSize == 0) - return QByteArray(); - QByteArray qba(buffers.takeFirst()); - - qba.reserve(0); // avoid that resizing needlessly reallocates - if (tailBuffer == 0) { - qba.resize(tail); - tail = 0; - buffers.append(QByteArray()); - } else { - --tailBuffer; - } - qba.remove(0, head); // does nothing if head is 0 - head = 0; - bufferSize -= qba.size(); - return qba; + inline qint64 size() const { + return bufferSize; } - // append a new buffer to the end - inline void append(const QByteArray &qba) { - if (tail == 0) { - buffers.last() = qba; - } else { - buffers.last().resize(tail); - buffers.append(qba); - ++tailBuffer; - } - tail = qba.size(); - bufferSize += tail; - } + Q_CORE_EXPORT void clear(); + inline qint64 indexOf(char c) const { return indexOf(c, size()); } + Q_CORE_EXPORT qint64 indexOf(char c, qint64 maxLength) const; + Q_CORE_EXPORT qint64 read(char *data, qint64 maxLength); + Q_CORE_EXPORT QByteArray read(); + Q_CORE_EXPORT qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const; + Q_CORE_EXPORT void append(const QByteArray &qba); - inline int skip(int length) { + inline qint64 skip(qint64 length) { return read(0, length); } - inline int readLine(char *data, int maxLength) { - if (!data || --maxLength <= 0) - return -1; - - int i = indexOf('\n', maxLength); - i = read(data, i >= 0 ? (i + 1) : maxLength); - - // Terminate it. - data[i] = '\0'; - return i; - } + Q_CORE_EXPORT qint64 readLine(char *data, qint64 maxLength); inline bool canReadLine() const { return indexOf('\n') >= 0; @@ -325,7 +135,7 @@ private: int head, tail; int tailBuffer; // always buffers.size() - 1 const int basicBlockSize; - int bufferSize; + qint64 bufferSize; }; QT_END_NAMESPACE diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index e4688711d6..5a9c75fe07 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -137,6 +137,7 @@ public: typedef QHash<T, QHashDummyValue> Hash; typename Hash::const_iterator i; friend class iterator; + friend class QSet<T>; public: typedef std::bidirectional_iterator_tag iterator_category; @@ -191,6 +192,7 @@ public: inline const_iterator constFind(const T &value) const { return find(value); } QSet<T> &unite(const QSet<T> &other); QSet<T> &intersect(const QSet<T> &other); + bool intersects(const QSet<T> &other) const; QSet<T> &subtract(const QSet<T> &other); // STL compatibility @@ -284,6 +286,34 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other) } template <class T> +Q_INLINE_TEMPLATE bool QSet<T>::intersects(const QSet<T> &other) const +{ + const bool otherIsBigger = other.size() > size(); + const QSet &smallestSet = otherIsBigger ? *this : other; + const QSet &biggestSet = otherIsBigger ? other : *this; + const bool equalSeeds = q_hash.d->seed == other.q_hash.d->seed; + typename QSet::const_iterator i = smallestSet.cbegin(); + typename QSet::const_iterator e = smallestSet.cend(); + + if (Q_LIKELY(equalSeeds)) { + // If seeds are equal we take the fast path so no hash is recalculated. + while (i != e) { + if (*biggestSet.q_hash.findNode(*i, i.i.i->h) != biggestSet.q_hash.e) + return true; + ++i; + } + } else { + while (i != e) { + if (biggestSet.contains(*i)) + return true; + ++i; + } + } + + return false; +} + +template <class T> Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other) { QSet<T> copy1(*this); diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index c38fe858fb..495329b90d 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -503,7 +503,17 @@ Removes all items from this set that are not contained in the \a other set. A reference to this set is returned. - \sa operator&=(), unite(), subtract() + \sa intersects(), operator&=(), unite(), subtract() +*/ + +/*! + \fn bool QSet::intersects(const QSet<T> &other) const + \since 5.6 + + Returns \c true if this set has at least one item in common with + \a other. + + \sa contains(), intersect() */ /*! diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 9dd8fff9cb..a9f71c7b57 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -36,7 +36,10 @@ #include <QtCore/qglobal.h> #include <QtCore/qatomic.h> +#if QT_DEPRECATED_SINCE(5, 5) #include <QtCore/qhash.h> +#endif +#include <QtCore/qhashfunctions.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 9e6b48a97d..3be10d9d87 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -55,7 +55,10 @@ QT_END_NAMESPACE #include <new> #include <QtCore/qatomic.h> #include <QtCore/qobject.h> // for qobject_cast -#include <QtCore/qhash.h> // for qHash +#if QT_DEPRECATED_SINCE(5, 5) +#include <QtCore/qhash.h> +#endif +#include <QtCore/qhashfunctions.h> #if defined(Q_COMPILER_RVALUE_REFS) && defined(Q_COMPILER_VARIADIC_TEMPLATES) # include <utility> // for std::forward @@ -329,7 +332,8 @@ public: } inline QSharedPointer &operator=(QSharedPointer &&other) { - swap(other); + QSharedPointer moved(std::move(other)); + swap(moved); return *this; } #endif @@ -587,7 +591,7 @@ public: inline bool operator !() const { return isNull(); } inline T *data() const { return d == 0 || d->strongref.load() == 0 ? 0 : value; } - Q_DECL_CONSTEXPR inline QWeakPointer() : d(0), value(0) { } + inline QWeakPointer() : d(0), value(0) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } #ifndef QT_NO_QOBJECT diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 52ffc161bf..d572dd209c 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -39,7 +39,9 @@ #if defined(Q_OS_WIN) # if defined(Q_OS_WINCE) # include <qt_windows.h> -# include <cmnintrin.h> +# if _WIN32_WCE < 0x800 +# include <cmnintrin.h> +# endif # endif # if !defined(Q_CC_GNU) # ifndef Q_OS_WINCE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index bbb5647eea..07ca62145b 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -50,7 +50,6 @@ #include "qstringmatcher.h" #include "qvarlengtharray.h" #include "qtools_p.h" -#include "qhash.h" #include "qdebug.h" #include "qendian.h" #include "qcollator.h" @@ -1828,6 +1827,51 @@ QString &QString::operator=(QChar ch) /*! + \fn QString& QString::insert(int position, const QStringRef &str) + \since 5.5 + \overload insert() + + Inserts the string reference \a str at the given index \a position and + returns a reference to this string. + + If the given \a position is greater than size(), the array is + first extended using resize(). +*/ + + +/*! + \fn QString& QString::insert(int position, const char *str) + \since 5.5 + \overload insert() + + Inserts the C string \a str at the given index \a position and + returns a reference to this string. + + If the given \a position is greater than size(), the array is + first extended using resize(). + + This function is not available when QT_NO_CAST_FROM_ASCII is + defined. +*/ + + +/*! + \fn QString& QString::insert(int position, const QByteArray &str) + \since 5.5 + \overload insert() + + Inserts the byte array \a str at the given index \a position and + returns a reference to this string. + + If the given \a position is greater than size(), the array is + first extended using resize(). + + This function is not available when QT_NO_CAST_FROM_ASCII is + defined. +*/ + + +/*! \fn QString &QString::insert(int position, QLatin1String str) \overload insert() @@ -2027,6 +2071,22 @@ QString &QString::append(QChar ch) Prepends the Latin-1 string \a str to this string. */ +/*! \fn QString &QString::prepend(const QChar *str, int len) + \since 5.5 + \overload prepend() + + Prepends \a len characters from the QChar array \a str to this string and + returns a reference to this string. +*/ + +/*! \fn QString &QString::prepend(const QStringRef &str) + \since 5.5 + \overload prepend() + + Prepends the string reference \a str to the beginning of this string and + returns a reference to this string. +*/ + /*! \fn QString &QString::prepend(const QByteArray &ba) \overload prepend() @@ -2659,9 +2719,9 @@ bool QString::operator<(QLatin1String other) const go through QObject::tr(), for example. */ -/*! \fn bool QString::operator<=(const QString &s1, const QString &s2) +/*! \fn bool operator<=(const QString &s1, const QString &s2) - \relates Qstring + \relates QString Returns \c true if string \a s1 is lexically less than or equal to string \a s2; otherwise returns \c false. @@ -2707,7 +2767,7 @@ bool QString::operator<(QLatin1String other) const go through QObject::tr(), for example. */ -/*! \fn bool QString::operator>(const QString &s1, const QString &s2) +/*! \fn bool operator>(const QString &s1, const QString &s2) \relates QString Returns \c true if string \a s1 is lexically greater than string \a s2; @@ -3939,10 +3999,9 @@ int QString::count(const QRegularExpression &re) const QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const { - QStringList sections = split(sep, KeepEmptyParts, - (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive); + const QVector<QStringRef> sections = splitRef(sep, KeepEmptyParts, + (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive); const int sectionsSize = sections.size(); - if (!(flags & SectionSkipEmpty)) { if (start < 0) start += sectionsSize; @@ -3962,11 +4021,10 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl if (start >= sectionsSize || end < 0 || start > end) return QString(); - int x = 0; QString ret; int first_i = start, last_i = end; - for (int i = 0; x <= end && i < sectionsSize; ++i) { - QString section = sections.at(i); + for (int x = 0, i = 0; x <= end && i < sectionsSize; ++i) { + const QStringRef §ion = sections.at(i); const bool empty = section.isEmpty(); if (x >= start) { if(x == start) @@ -3991,9 +4049,9 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl class qt_section_chunk { public: qt_section_chunk() {} - qt_section_chunk(int l, QString s) : length(l), string(qMove(s)) {} + qt_section_chunk(int l, QStringRef s) : length(l), string(qMove(s)) {} int length; - QString string; + QStringRef string; }; Q_DECLARE_TYPEINFO(qt_section_chunk, Q_MOVABLE_TYPE); @@ -4086,12 +4144,12 @@ QString QString::section(const QRegExp ®, int start, int end, SectionFlags fl QVector<qt_section_chunk> sections; int n = length(), m = 0, last_m = 0, last_len = 0; while ((m = sep.indexIn(*this, m)) != -1) { - sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m))); + sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, m - last_m))); last_m = m; last_len = sep.matchedLength(); m += qMax(sep.matchedLength(), 1); } - sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m))); + sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, n - last_m))); return extractSections(sections, start, end, flags); } @@ -4134,11 +4192,11 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); m = match.capturedStart(); - sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m))); + sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, m - last_m))); last_m = m; last_len = match.capturedLength(); } - sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m))); + sections.append(qt_section_chunk(last_len, QStringRef(this, last_m, n - last_m))); return extractSections(sections, start, end, flags); } @@ -4822,7 +4880,7 @@ modifiable reference. If \a position is negative, it is equivalent to passing zero. - \sa chop(), resize(), left() + \sa chop(), resize(), left(), QStringRef::truncate() */ void QString::truncate(int pos) @@ -7622,86 +7680,155 @@ static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999) return -1; } +/* + Algorithm for multiArg: + + 1. Parse the string as a sequence of verbatim text and placeholders (%L?\d{,3}). + The L is parsed and accepted for compatibility with non-multi-arg, but since + multiArg only accepts strings as replacements, the localization request can + be safely ignored. + 2. The result of step (1) is a list of (string-ref,int)-tuples. The string-ref + either points at text to be copied verbatim (in which case the int is -1), + or, initially, at the textual representation of the placeholder. In that case, + the int contains the numerical number as parsed from the placeholder. + 3. Next, collect all the non-negative ints found, sort them in ascending order and + remove duplicates. + 3a. If the result has more entires than multiArg() was given replacement strings, + we have found placeholders we can't satisfy with replacement strings. That is + fine (there could be another .arg() call coming after this one), so just + truncate the result to the number of actual multiArg() replacement strings. + 3b. If the result has less entries than multiArg() was given replacement strings, + the string is missing placeholders. This is an error that the user should be + warned about. + 4. The result of step (3) is a mapping from the index of any replacement string to + placeholder number. This is the wrong way around, but since placeholder + numbers could get as large as 999, while we typically don't have more than 9 + replacement strings, we trade 4K of sparsely-used memory for doing a reverse lookup + each time we need to map a placeholder number to a replacement string index + (that's a linear search; but still *much* faster than using an associative container). + 5. Next, for each of the tuples found in step (1), do the following: + 5a. If the int is negative, do nothing. + 5b. Otherwise, if the int is found in the result of step (3) at index I, replace + the string-ref with a string-ref for the (complete) I'th replacement string. + 5c. Otherwise, do nothing. + 6. Concatenate all string refs into a single result string. +*/ + namespace { -class ArgMapper { - QVarLengthArray<int, 16> argPosToNumberMap; // maps from argument position to number -public: - void found(int n) { argPosToNumberMap.push_back(n); } +struct Part +{ + Part() : stringRef(), number(0) {} + Part(const QString &s, int pos, int len, int num = -1) Q_DECL_NOTHROW + : stringRef(&s, pos, len), number(num) {} - struct AssignmentResult { - int numArgs; - int lastNumber; - }; + QStringRef stringRef; + int number; +}; +} // unnamed namespace - AssignmentResult assignArgumentNumberToEachOfTheNs(int numArgs) - { - std::sort(argPosToNumberMap.begin(), argPosToNumberMap.end()); - argPosToNumberMap.erase(std::unique(argPosToNumberMap.begin(), argPosToNumberMap.end()), - argPosToNumberMap.end()); +template <> +class QTypeInfo<Part> : public QTypeInfoMerger<Part, QStringRef, int> {}; // Q_DECLARE_METATYPE - if (argPosToNumberMap.size() > numArgs) - argPosToNumberMap.resize(numArgs); - int lastNumber = argPosToNumberMap.empty() ? -1 : argPosToNumberMap.back(); - int arg = argPosToNumberMap.size(); +namespace { - const AssignmentResult result = {arg, lastNumber}; - return result; - } +enum { ExpectedParts = 32 }; - int numberToArgsIndex(int number) const - { - if (number != -1) { - const int * const it = std::find(argPosToNumberMap.begin(), argPosToNumberMap.end(), number); - return it == argPosToNumberMap.end() ? -1 : it - argPosToNumberMap.begin(); - } else { - return -1; - } - } -}; -} // unnamed namespace +typedef QVarLengthArray<Part, ExpectedParts> ParseResult; +typedef QVarLengthArray<int, ExpectedParts/2> ArgIndexToPlaceholderMap; -QString QString::multiArg(int numArgs, const QString **args) const +static ParseResult parseMultiArgFormatString(const QString &s) { - QString result; - ArgMapper mapper; - const QChar *uc = (const QChar *) d->data(); - const int len = d->size; + ParseResult result; + + const QChar *uc = s.constData(); + const int len = s.size(); const int end = len - 1; int i = 0; + int last = 0; - // populate the arg-mapper with the %n's that actually occur in the string while (i < end) { if (uc[i] == QLatin1Char('%')) { + int percent = i; int number = getEscape(uc, &i, len); if (number != -1) { - mapper.found(number); + if (last != percent) + result.push_back(Part(s, last, percent - last)); // literal text (incl. failed placeholders) + result.push_back(Part(s, percent, i - percent, number)); // parsed placeholder + last = i; continue; } } ++i; } - const ArgMapper::AssignmentResult r = mapper.assignArgumentNumberToEachOfTheNs(numArgs); + if (last < len) + result.push_back(Part(s, last, len - last)); // trailing literal text - // sanity - if (numArgs > r.numArgs) { - qWarning("QString::arg: %d argument(s) missing in %s", numArgs - r.numArgs, toLocal8Bit().data()); - numArgs = r.numArgs; + return result; +} + +static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult &parts) +{ + ArgIndexToPlaceholderMap result; + + for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) { + if (it->number >= 0) + result.push_back(it->number); } - i = 0; - while (i < len) { - if (uc[i] == QLatin1Char('%') && i != end) { - int number = getEscape(uc, &i, len, r.lastNumber); - int arg = mapper.numberToArgsIndex(number); - if (number != -1 && arg != -1) { - result += *args[arg]; - continue; - } + std::sort(result.begin(), result.end()); + result.erase(std::unique(result.begin(), result.end()), + result.end()); + + return result; +} + +static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[]) +{ + int totalSize = 0; + for (ParseResult::iterator pit = parts.begin(), end = parts.end(); pit != end; ++pit) { + if (pit->number != -1) { + const ArgIndexToPlaceholderMap::const_iterator ait + = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), pit->number); + if (ait != argIndexToPlaceholderMap.end()) + pit->stringRef = QStringRef(args[ait - argIndexToPlaceholderMap.begin()]); } - result += uc[i++]; + totalSize += pit->stringRef.size(); } + return totalSize; +} + +} // unnamed namespace + +QString QString::multiArg(int numArgs, const QString **args) const +{ + // Step 1-2 above + ParseResult parts = parseMultiArgFormatString(*this); + + // 3-4 + ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts); + + if (argIndexToPlaceholderMap.size() > numArgs) // 3a + argIndexToPlaceholderMap.resize(numArgs); + else if (argIndexToPlaceholderMap.size() < numArgs) // 3b + qWarning("QString::arg: %d argument(s) missing in %s", + numArgs - argIndexToPlaceholderMap.size(), toLocal8Bit().data()); + + // 5 + const int totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args); + + // 6: + QString result(totalSize, Qt::Uninitialized); + QChar *out = result.data(); + + for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) { + if (const int sz = it->stringRef.size()) { + memcpy(out, it->stringRef.constData(), sz * sizeof(QChar)); + out += sz; + } + } + return result; } @@ -9268,6 +9395,20 @@ QStringRef QString::midRef(int position, int n) const } /*! + \fn void QStringRef::truncate(int position) + \since 5.6 + + Truncates the string at the given \a position index. + + If the specified \a position index is beyond the end of the + string, nothing happens. + + If \a position is negative, it is equivalent to passing zero. + + \sa QString::truncate() +*/ + +/*! \since 4.8 Returns the index position of the first occurrence of the string \a diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 63107ff688..c084433d51 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -84,7 +84,7 @@ class QLatin1String public: Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) : m_size(s ? int(strlen(s)) : 0), m_data(s) {} Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) : m_size(sz), m_data(s) {} - inline explicit QLatin1String(const QByteArray &s) : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {} + inline explicit QLatin1String(const QByteArray &s) : m_size(s.size()), m_data(s.constData()) {} inline const char *latin1() const { return m_data; } inline int size() const { return m_size; } @@ -420,6 +420,7 @@ public: QString &insert(int i, QChar c); QString &insert(int i, const QChar *uc, int len); inline QString &insert(int i, const QString &s) { return insert(i, s.constData(), s.length()); } + inline QString &insert(int i, const QStringRef &s); QString &insert(int i, QLatin1String s); QString &append(QChar c); QString &append(const QChar *uc, int len); @@ -427,7 +428,9 @@ public: QString &append(const QStringRef &s); QString &append(QLatin1String s); inline QString &prepend(QChar c) { return insert(0, c); } + inline QString &prepend(const QChar *uc, int len) { return insert(0, uc, len); } inline QString &prepend(const QString &s) { return insert(0, s); } + inline QString &prepend(const QStringRef &s) { return insert(0, s); } inline QString &prepend(QLatin1String s) { return insert(0, s); } inline QString &operator+=(QChar c) { @@ -534,11 +537,11 @@ public: return fromLocal8Bit_helper(str, (str && size == -1) ? int(strlen(str)) : size); } static inline QString fromLatin1(const QByteArray &str) - { return fromLatin1(str.data(), qstrnlen(str.constData(), str.size())); } + { return str.isNull() ? QString() : fromLatin1(str.data(), str.size()); } static inline QString fromUtf8(const QByteArray &str) - { return fromUtf8(str.data(), qstrnlen(str.constData(), str.size())); } + { return str.isNull() ? QString() : fromUtf8(str.data(), str.size()); } static inline QString fromLocal8Bit(const QByteArray &str) - { return fromLocal8Bit(str.data(), qstrnlen(str.constData(), str.size())); } + { return str.isNull() ? QString() : fromLocal8Bit(str.data(), str.size()); } static QString fromUtf16(const ushort *, int size = -1); static QString fromUcs4(const uint *, int size = -1); static QString fromRawData(const QChar *, int size); @@ -591,16 +594,16 @@ public: static int localeAwareCompare(const QString& s1, const QStringRef& s2); // ### Qt6: make inline except for the long long versions - short toShort(bool *ok=0, int base=10) const; - ushort toUShort(bool *ok=0, int base=10) const; - int toInt(bool *ok=0, int base=10) const; - uint toUInt(bool *ok=0, int base=10) const; - long toLong(bool *ok=0, int base=10) const; - ulong toULong(bool *ok=0, int base=10) const; - qlonglong toLongLong(bool *ok=0, int base=10) const; - qulonglong toULongLong(bool *ok=0, int base=10) const; - float toFloat(bool *ok=0) const; - double toDouble(bool *ok=0) const; + short toShort(bool *ok=Q_NULLPTR, int base=10) const; + ushort toUShort(bool *ok=Q_NULLPTR, int base=10) const; + int toInt(bool *ok=Q_NULLPTR, int base=10) const; + uint toUInt(bool *ok=Q_NULLPTR, int base=10) const; + long toLong(bool *ok=Q_NULLPTR, int base=10) const; + ulong toULong(bool *ok=Q_NULLPTR, int base=10) const; + qlonglong toLongLong(bool *ok=Q_NULLPTR, int base=10) const; + qulonglong toULongLong(bool *ok=Q_NULLPTR, int base=10) const; + float toFloat(bool *ok=Q_NULLPTR) const; + double toDouble(bool *ok=Q_NULLPTR) const; QString &setNum(short, int base=10); QString &setNum(ushort, int base=10); @@ -650,7 +653,7 @@ public: : d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1)) {} inline QT_ASCII_CAST_WARN QString(const QByteArray &a) - : d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size()))) + : d(fromAscii_helper(a.constData(), a.size())) {} inline QT_ASCII_CAST_WARN QString &operator=(const char *ch) { return (*this = fromUtf8(ch)); } @@ -668,6 +671,10 @@ public: { return append(QString::fromUtf8(s)); } inline QT_ASCII_CAST_WARN QString &append(const QByteArray &s) { return append(QString::fromUtf8(s)); } + inline QT_ASCII_CAST_WARN QString &insert(int i, const char *s) + { return insert(i, QString::fromUtf8(s)); } + inline QT_ASCII_CAST_WARN QString &insert(int i, const QByteArray &s) + { return insert(i, QString::fromUtf8(s)); } inline QT_ASCII_CAST_WARN QString &operator+=(const char *s) { return append(QString::fromUtf8(s)); } inline QT_ASCII_CAST_WARN QString &operator+=(const QByteArray &s) @@ -1211,30 +1218,30 @@ inline QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const QByteArray &s) co { return QString::fromUtf8(s) <= *this; } inline QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) == 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; } inline QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) != 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; } inline QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) < 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) < 0; } inline QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) > 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) > 0; } inline QT_ASCII_CAST_WARN bool QString::operator<=(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) <= 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) <= 0; } inline QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) >= 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) >= 0; } inline bool QByteArray::operator==(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) == 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) == 0; } inline bool QByteArray::operator!=(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) != 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; } inline bool QByteArray::operator<(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) < 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; } inline bool QByteArray::operator>(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) > 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; } inline bool QByteArray::operator<=(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) <= 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; } inline bool QByteArray::operator>=(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) >= 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; } #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) #ifndef QT_NO_CAST_TO_ASCII @@ -1343,7 +1350,7 @@ public: typedef QString::const_reference const_reference; // ### Qt 6: make this constructor constexpr, after the destructor is made trivial - inline QStringRef():m_string(0), m_position(0), m_size(0){} + inline QStringRef() : m_string(Q_NULLPTR), m_position(0), m_size(0) {} inline QStringRef(const QString *string, int position, int size); inline QStringRef(const QString *string); @@ -1392,6 +1399,8 @@ public: QStringRef right(int n) const Q_REQUIRED_RESULT; QStringRef mid(int pos, int n = -1) const Q_REQUIRED_RESULT; + void truncate(int pos) Q_DECL_NOTHROW { m_size = qBound(0, pos, m_size); } + bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -1425,10 +1434,10 @@ public: QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; QVector<uint> toUcs4() const Q_REQUIRED_RESULT; - inline void clear() { m_string = 0; m_position = m_size = 0; } + inline void clear() { m_string = Q_NULLPTR; m_position = m_size = 0; } QString toString() const; inline bool isEmpty() const { return m_size == 0; } - inline bool isNull() const { return m_string == 0 || m_string->isNull(); } + inline bool isNull() const { return m_string == Q_NULLPTR || m_string->isNull(); } QStringRef appendTo(QString *string) const; @@ -1461,16 +1470,16 @@ public: static int localeAwareCompare(const QStringRef &s1, const QStringRef &s2); QStringRef trimmed() const Q_REQUIRED_RESULT; - short toShort(bool *ok = 0, int base = 10) const; - ushort toUShort(bool *ok = 0, int base = 10) const; - int toInt(bool *ok = 0, int base = 10) const; - uint toUInt(bool *ok = 0, int base = 10) const; - long toLong(bool *ok = 0, int base = 10) const; - ulong toULong(bool *ok = 0, int base = 10) const; - qlonglong toLongLong(bool *ok = 0, int base = 10) const; - qulonglong toULongLong(bool *ok = 0, int base = 10) const; - float toFloat(bool *ok = 0) const; - double toDouble(bool *ok = 0) const; + short toShort(bool *ok = Q_NULLPTR, int base = 10) const; + ushort toUShort(bool *ok = Q_NULLPTR, int base = 10) const; + int toInt(bool *ok = Q_NULLPTR, int base = 10) const; + uint toUInt(bool *ok = Q_NULLPTR, int base = 10) const; + long toLong(bool *ok = Q_NULLPTR, int base = 10) const; + ulong toULong(bool *ok = Q_NULLPTR, int base = 10) const; + qlonglong toLongLong(bool *ok = Q_NULLPTR, int base = 10) const; + qulonglong toULongLong(bool *ok = Q_NULLPTR, int base = 10) const; + float toFloat(bool *ok = Q_NULLPTR) const; + double toDouble(bool *ok = Q_NULLPTR) const; }; Q_DECLARE_TYPEINFO(QStringRef, Q_PRIMITIVE_TYPE); @@ -1576,6 +1585,9 @@ inline bool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } +inline QString &QString::insert(int i, const QStringRef &s) +{ return insert(i, s.constData(), s.length()); } + namespace Qt { #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED inline QString escape(const QString &plain) { diff --git a/src/corelib/tools/qtextboundaryfinder.h b/src/corelib/tools/qtextboundaryfinder.h index beec5de607..a79fb50dad 100644 --- a/src/corelib/tools/qtextboundaryfinder.h +++ b/src/corelib/tools/qtextboundaryfinder.h @@ -68,7 +68,7 @@ public: Q_DECLARE_FLAGS( BoundaryReasons, BoundaryReason ) QTextBoundaryFinder(BoundaryType type, const QString &string); - QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer = 0, int bufferSize = 0); + QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer = Q_NULLPTR, int bufferSize = 0); inline bool isValid() const { return d; } diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h index 21139b37a8..94e60dce45 100644 --- a/src/corelib/tools/qtimeline.h +++ b/src/corelib/tools/qtimeline.h @@ -70,7 +70,7 @@ public: CosineCurve }; - explicit QTimeLine(int duration = 1000, QObject *parent = 0); + explicit QTimeLine(int duration = 1000, QObject *parent = Q_NULLPTR); virtual ~QTimeLine(); State state() const; diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 3627045a40..5cd594455c 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -764,6 +764,7 @@ QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime, if (hasTransitions()) { QTimeZonePrivate::DataList plist = d->transitions(fromDateTime.toMSecsSinceEpoch(), toDateTime.toMSecsSinceEpoch()); + list.reserve(plist.count()); foreach (const QTimeZonePrivate::Data &pdata, plist) list.append(d->toOffsetData(pdata)); } diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 8e6a0a0578..5bc3610af0 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -700,6 +700,7 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const { QList<QByteArray> result; + result.reserve(utcDataTableSize); for (int i = 0; i < utcDataTableSize; ++i) result << utcId(utcData(i)); std::sort(result.begin(), result.end()); // ### or already sorted?? diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 29f0e17012..7c5e5bd2cf 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -630,6 +630,7 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId) } // Now for each transition time calculate our rule and save them + m_tranTimes.reserve(tranList.count()); foreach (const QTzTransition &tz_tran, tranList) { QTzTransitionTime tran; QTzTransitionRule rule; diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 90b54b7297..bb15d66439 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -45,6 +45,7 @@ #ifdef Q_COMPILER_INITIALIZER_LISTS #include <initializer_list> #endif +#include <iterator> QT_BEGIN_NAMESPACE @@ -174,6 +175,8 @@ public: typedef T* iterator; typedef const T* const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; inline iterator begin() { return ptr; } inline const_iterator begin() const { return ptr; } @@ -183,6 +186,12 @@ public: inline const_iterator end() const { return ptr + s; } inline const_iterator cend() const { return ptr + s; } inline const_iterator constEnd() const { return ptr + s; } + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } iterator insert(const_iterator before, int n, const T &x); inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); } iterator erase(const_iterator begin, const_iterator end); @@ -489,6 +498,36 @@ bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, return !(l == r); } +template <typename T, int Prealloc1, int Prealloc2> +bool operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()))) +{ + return std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()); +} + +template <typename T, int Prealloc1, int Prealloc2> +inline bool operator>(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return rhs < lhs; +} + +template <typename T, int Prealloc1, int Prealloc2> +inline bool operator<=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return !(lhs > rhs); +} + +template <typename T, int Prealloc1, int Prealloc2> +inline bool operator>=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return !(lhs < rhs); +} + QT_END_NAMESPACE #endif // QVARLENGTHARRAY_H diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index a2d4c55f7a..2b7f9c5241 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -468,6 +468,20 @@ Typedef for T *. Provided for STL compatibility. */ +/*! + \typedef QVarLengthArray::const_reverse_iterator + \since 5.6 + + Typedef for \c{std::reverse_iterator<const T*>}. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::reverse_iterator + \since 5.6 + + Typedef for \c{std::reverse_iterator<T*>}. Provided for STL compatibility. +*/ + /*! \fn void QVarLengthArray::prepend(const T &value) \since 4.8 @@ -582,6 +596,52 @@ \sa constBegin(), end() */ +/*! \fn QVarLengthArray::reverse_iterator QVarLengthArray::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the variable length array, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QVarLengthArray::const_reverse_iterator QVarLengthArray::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QVarLengthArray::const_reverse_iterator QVarLengthArray::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the variable length array, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QVarLengthArray::reverse_iterator QVarLengthArray::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last item in the variable length array, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QVarLengthArray::const_reverse_iterator QVarLengthArray::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QVarLengthArray::const_reverse_iterator QVarLengthArray::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last item in the variable length array, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \fn QVarLengthArray::iterator QVarLengthArray::erase(const_iterator pos) \since 4.8 @@ -676,6 +736,54 @@ \sa operator==() */ +/*! \fn bool operator<(const QVarLengthArray<T,Prealloc1> &lhs, const QVarLengthArray<T,Prealloc2> &rhs) + \since 5.6 + \relates QVarLengthArray + + Returns \c true if variable length array \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator<=(const QVarLengthArray<T,Prealloc1> &lhs, const QVarLengthArray<T,Prealloc2> &rhs) + \since 5.6 + \relates QVarLengthArray + + Returns \c true if variable length array \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator>(const QVarLengthArray<T,Prealloc1> &lhs, const QVarLengthArray<T,Prealloc2> &rhs) + \since 5.6 + \relates QVarLengthArray + + Returns \c true if variable length array \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator>=(const QVarLengthArray<T,Prealloc1> &lhs, const QVarLengthArray<T,Prealloc2> &rhs) + \since 5.6 + \relates QVarLengthArray + + Returns \c true if variable length array \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + /*! \fn QVarLengthArray &QVarLengthArray::operator<<(const T &value) \since 4.8 diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index d10f82fbb4..77afe9d00e 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -290,6 +290,65 @@ \sa operator==() */ +/*! \fn bool operator<(const QVector<T> &lhs, const QVector<T> &rhs) + \since 5.6 + \relates QVector + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator<=(const QVector<T> &lhs, const QVector<T> &rhs) + \since 5.6 + \relates QVector + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator>(const QVector<T> &lhs, const QVector<T> &rhs) + \since 5.6 + \relates QVector + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn bool operator>=(const QVector<T> &lhs, const QVector<T> &rhs) + \since 5.6 + \relates QVector + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! + \fn uint qHash(const QVector<T> &key, uint seed = 0) + \since 5.6 + \relates QVector + + Returns the hash value for \a key, + using \a seed to seed the calculation. + + This function requires qHash() to be overloaded for the value type \c T. +*/ + /*! \fn int QVector::size() const Returns the number of items in the vector. @@ -629,6 +688,16 @@ \sa takeFirst(), takeLast(), QList::takeAt() */ +/*! \fn void QVector::move(int from, int to) + \since 5.6 + + Moves the item at index position \a from to index position \a to. + + Provided for compatibility with QList. + + \sa QList::move() +*/ + /*! \fn void QVector::removeFirst() \since 5.1 Removes the first item in the vector. Calling this function is @@ -823,6 +892,52 @@ \sa constBegin(), end() */ +/*! \fn QVector::reverse_iterator QVector::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the vector, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QVector::const_reverse_iterator QVector::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QVector::const_reverse_iterator QVector::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the vector, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QVector::reverse_iterator QVector::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last item in the vector, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QVector::const_reverse_iterator QVector::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QVector::const_reverse_iterator QVector::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last item in the vector, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \fn QVector::iterator QVector::erase(iterator pos) Removes the item pointed to by the iterator \a pos from the @@ -846,7 +961,7 @@ Returns a reference to the first item in the vector. This function assumes that the vector isn't empty. - \sa last(), isEmpty() + \sa last(), isEmpty(), constFirst() */ /*! \fn const T& QVector::first() const @@ -854,12 +969,21 @@ \overload */ +/*! \fn const T& QVector::constFirst() const + \since 5.6 + + Returns a const reference to the first item in the vector. This + function assumes that the vector isn't empty. + + \sa constLast(), isEmpty(), first() +*/ + /*! \fn T& QVector::last() Returns a reference to the last item in the vector. This function assumes that the vector isn't empty. - \sa first(), isEmpty() + \sa first(), isEmpty(), constLast() */ /*! \fn const T& QVector::last() const @@ -867,6 +991,15 @@ \overload */ +/*! \fn const T& QVector::constLast() const + \since 5.6 + + Returns a const reference to the last item in the vector. This function + assumes that the vector isn't empty. + + \sa constFirst(), isEmpty(), last() +*/ + /*! \fn T QVector::value(int i) const Returns the value at index position \a i in the vector. @@ -1013,6 +1146,38 @@ \sa QVector::constBegin(), QVector::constEnd(), QVector::iterator, QVectorIterator */ +/*! \typedef QVector::reverse_iterator + \since 5.6 + + The QVector::reverse_iterator typedef provides an STL-style non-const + reverse iterator for QVector. + + It is simply a typedef for \c{std::reverse_iterator<T*>}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QVector::rbegin(), QVector::rend(), QVector::const_reverse_iterator, QVector::iterator +*/ + +/*! \typedef QVector::const_reverse_iterator + \since 5.6 + + The QVector::const_reverse_iterator typedef provides an STL-style const + reverse iterator for QVector. + + It is simply a typedef for \c{std::reverse_iterator<const T*>}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QVector::rbegin(), QVector::rend(), QVector::reverse_iterator, QVector::const_iterator +*/ + /*! \typedef QVector::Iterator Qt-style synonym for QVector::iterator. diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index eed5d17cad..821fc9b68a 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -39,6 +39,7 @@ #include <QtCore/qlist.h> #include <QtCore/qrefcount.h> #include <QtCore/qarraydata.h> +#include <QtCore/qhashfunctions.h> #include <iterator> #include <vector> @@ -68,11 +69,10 @@ public: inline ~QVector() { if (!d->ref.deref()) freeData(d); } QVector<T> &operator=(const QVector<T> &v); #ifdef Q_COMPILER_RVALUE_REFS - inline QVector(QVector<T> &&other) : d(other.d) { other.d = Data::sharedNull(); } - inline QVector<T> operator=(QVector<T> &&other) - { qSwap(d, other.d); return *this; } + QVector(QVector<T> &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); } + QVector<T> operator=(QVector<T> &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif - inline void swap(QVector<T> &other) { qSwap(d, other.d); } + void swap(QVector<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QVector(std::initializer_list<T> args); #endif @@ -171,10 +171,25 @@ public: } int length() const { return size(); } T takeAt(int i) { T t = at(i); remove(i); return t; } + void move(int from, int to) + { + Q_ASSERT_X(from >= 0 && from < size(), "QVector::move(int,int)", "'from' is out-of-range"); + Q_ASSERT_X(to >= 0 && to < size(), "QVector::move(int,int)", "'to' is out-of-range"); + if (from == to) // don't detach when no-op + return; + detach(); + T * const b = d->begin(); + if (from < to) + std::rotate(b + from, b + from + 1, b + to + 1); + else + std::rotate(b + to, b + from, b + from + 1); + } // STL-style typedef typename Data::iterator iterator; typedef typename Data::const_iterator const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; #if !defined(QT_STRICT_ITERATORS) || defined(Q_QDOC) inline iterator begin() { detach(); return d->begin(); } inline const_iterator begin() const { return d->constBegin(); } @@ -194,6 +209,12 @@ public: inline const_iterator cend(const_iterator = const_iterator()) const { return d->constEnd(); } inline const_iterator constEnd(const_iterator = const_iterator()) const { return d->constEnd(); } #endif + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } iterator insert(iterator before, int n, const T &x); inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); } iterator erase(iterator begin, iterator end); @@ -203,8 +224,10 @@ public: inline int count() const { return d->size; } inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); } inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); } + inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); } inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); } inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); } + inline const T &constLast() const { Q_ASSERT(!isEmpty()); return *(end()-1); } inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; } inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; } QVector<T> mid(int pos, int len = -1) const; @@ -265,7 +288,6 @@ private: { return (i <= d->end()) && (d->begin() <= i); } - iterator c2m(const_iterator it) { return begin() + (it - cbegin()); } class AlignmentDummy { Data header; T array[1]; }; }; @@ -873,6 +895,43 @@ QList<T> QList<T>::fromVector(const QVector<T> &vector) Q_DECLARE_SEQUENTIAL_ITERATOR(Vector) Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector) +template <typename T> +uint qHash(const QVector<T> &key, uint seed = 0) + Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRange(key.cbegin(), key.cend(), seed))) +{ + return qHashRange(key.cbegin(), key.cend(), seed); +} + +template <typename T> +bool operator<(const QVector<T> &lhs, const QVector<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()))) +{ + return std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()); +} + +template <typename T> +inline bool operator>(const QVector<T> &lhs, const QVector<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return rhs < lhs; +} + +template <typename T> +inline bool operator<=(const QVector<T> &lhs, const QVector<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return !(lhs > rhs); +} + +template <typename T> +inline bool operator>=(const QVector<T> &lhs, const QVector<T> &rhs) + Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs)) +{ + return !(lhs < rhs); +} + /* ### Qt 5: ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 5de0c09a4d..60b53a3d8a 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -9,6 +9,7 @@ HEADERS += \ tools/qarraydatapointer.h \ tools/qbitarray.h \ tools/qbytearray.h \ + tools/qbytearray_p.h \ tools/qbytearraylist.h \ tools/qbytearraymatcher.h \ tools/qbytedata_p.h \ @@ -26,6 +27,7 @@ HEADERS += \ tools/qeasingcurve.h \ tools/qfreelist_p.h \ tools/qhash.h \ + tools/qhashfunctions.h \ tools/qiterator.h \ tools/qline.h \ tools/qlinkedlist.h \ @@ -105,6 +107,7 @@ SOURCES += \ tools/qrect.cpp \ tools/qregexp.cpp \ tools/qrefcount.cpp \ + tools/qringbuffer.cpp \ tools/qshareddata.cpp \ tools/qsharedpointer.cpp \ tools/qsimd.cpp \ |