diff options
Diffstat (limited to 'src/corelib/tools')
67 files changed, 3443 insertions, 1354 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index ff4d5a3ebd..ffa3082d5e 100644 --- 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_RELAXED_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_RELAXED_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_RELAXED_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_RELAXED_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_RELAXED_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.cpp b/src/corelib/tools/qarraydata.cpp index ef15fae83a..d9519745b0 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -103,7 +103,11 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1); +#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) header->ref.atomic.store(bool(!(options & Unsharable))); +#else + header->ref.atomic.store(1); +#endif header->size = 0; header->alloc = capacity; header->capacityReserved = bool(options & CapacityReserved); diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index df35a1cb62..865bd4325d 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) {} @@ -249,11 +249,13 @@ struct QTypedArrayData return allocate(/* capacity */ 0); } +#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) static QTypedArrayData *unsharableEmpty() { Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData)); return allocate(/* capacity */ 0, Unsharable); } +#endif }; template <class T, size_t N> diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index 103eb073a9..9804d2c2d5 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -46,7 +46,7 @@ private: typedef QArrayDataOps<T> DataOps; public: - QArrayDataPointer() + QArrayDataPointer() Q_DECL_NOTHROW : d(Data::sharedNull()) { } @@ -77,15 +77,16 @@ public: } #ifdef Q_COMPILER_RVALUE_REFS - QArrayDataPointer(QArrayDataPointer &&other) + QArrayDataPointer(QArrayDataPointer &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); } - QArrayDataPointer &operator=(QArrayDataPointer &&other) + QArrayDataPointer &operator=(QArrayDataPointer &&other) Q_DECL_NOTHROW { - this->swap(other); + QArrayDataPointer moved(std::move(other)); + this->swap(moved); return *this; } #endif @@ -143,7 +144,7 @@ public: bool isSharable() const { return d->isSharable(); } #endif - void swap(QArrayDataPointer &other) + void swap(QArrayDataPointer &other) Q_DECL_NOTHROW { qSwap(d, other.d); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 9d6c9d4ed1..5ed72fc341 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,7 +124,7 @@ int qFindByteArray( int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW { - Q_ASSERT(alloc >= 0 && extra >= 0); + 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); @@ -488,8 +489,8 @@ quint16 qChecksum(const char *data, uint len) \overload - Compresses the first \a nbytes of \a data and returns the - compressed data in a new byte array. + Compresses the first \a nbytes of \a data at compression level + \a compressionLevel and returns the compressed data in a new byte array. */ #ifndef QT_NO_COMPRESS @@ -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 @@ -927,6 +919,52 @@ static inline char qToLower(char c) \sa constBegin(), end() */ +/*! \fn QByteArray::reverse_iterator QByteArray::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + character in the byte-array, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QByteArray::const_reverse_iterator QByteArray::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QByteArray::const_reverse_iterator QByteArray::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + character in the byte-array, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QByteArray::reverse_iterator QByteArray::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last character in the byte-array, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QByteArray::const_reverse_iterator QByteArray::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QByteArray::const_reverse_iterator QByteArray::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last character in the byte-array, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \fn void QByteArray::push_back(const QByteArray &other) This function is provided for STL compatibility. It is equivalent @@ -1574,7 +1612,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)); } @@ -4489,11 +4527,33 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA */ /*! \typedef QByteArray::const_iterator - \internal + + This typedef provides an STL-style const iterator for QByteArray. + + \sa QByteArray::const_reverse_iterator, QByteArray::iterator */ /*! \typedef QByteArray::iterator - \internal + + This typedef provides an STL-style non-const iterator for QByteArray. + + \sa QByteArray::reverse_iterator, QByteArray::const_iterator +*/ + +/*! \typedef QByteArray::const_reverse_iterator + \since 5.6 + + This typedef provides an STL-style const reverse iterator for QByteArray. + + \sa QByteArray::reverse_iterator, QByteArray::const_iterator +*/ + +/*! \typedef QByteArray::reverse_iterator + \since 5.6 + + This typedef provides an STL-style non-const reverse iterator for QByteArray. + + \sa QByteArray::const_reverse_iterator, QByteArray::iterator */ /*! \typedef QByteArray::size_type diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 6d14cd5131..f0032227e8 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -43,6 +43,7 @@ #include <stdarg.h> #include <string> +#include <iterator> #ifdef truncate #error qbytearray.h must be included before any header file that defines truncate @@ -162,9 +163,6 @@ private: typedef QTypedArrayData<char> Data; public: - // undocumented: - static const quint64 MaxSize = (1 << 30) - sizeof(Data); - enum Base64Option { Base64Encoding = 0, Base64UrlEncoding = 1, @@ -338,16 +336,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; @@ -393,14 +391,22 @@ public: typedef const char *const_iterator; typedef iterator Iterator; typedef const_iterator ConstIterator; - iterator begin(); - const_iterator begin() const; - const_iterator cbegin() const; - const_iterator constBegin() const; - iterator end(); - const_iterator end() const; - const_iterator cend() const; - const_iterator constEnd() const; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + inline iterator begin(); + inline const_iterator begin() const; + inline const_iterator cbegin() const; + inline const_iterator constBegin() const; + inline iterator end(); + inline const_iterator end() const; + inline const_iterator cend() const; + inline const_iterator constEnd() const; + 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()); } // stl compatibility typedef int size_type; 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 014d91162a..5469eee14d 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -178,6 +178,7 @@ QT_BEGIN_NAMESPACE \value Unicode_6_1 Version 6.1 \value Unicode_6_2 Version 6.2 \value Unicode_6_3 Version 6.3 Since Qt 5.3 + \value Unicode_7_0 Version 7.0 Since Qt 5.5 \value Unicode_Unassigned The value is not assigned to any character in version 6.3 of Unicode. @@ -691,7 +692,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; @@ -724,7 +725,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; @@ -750,7 +751,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; @@ -774,7 +775,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; @@ -802,7 +803,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; @@ -832,7 +833,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; @@ -867,7 +868,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; @@ -896,7 +897,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; @@ -1059,7 +1060,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; @@ -1076,7 +1077,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; @@ -1093,7 +1094,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; @@ -1116,7 +1117,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; @@ -1139,7 +1140,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; @@ -1175,7 +1176,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; @@ -1257,7 +1258,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; @@ -1341,7 +1342,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; @@ -1367,7 +1368,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; @@ -1388,7 +1389,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; @@ -1406,7 +1407,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; @@ -1416,14 +1417,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) { @@ -1434,7 +1435,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) { @@ -1445,7 +1446,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) { @@ -1456,7 +1457,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) { @@ -1479,7 +1480,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; @@ -1499,7 +1500,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; @@ -1519,7 +1520,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; @@ -1534,7 +1535,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()) @@ -1543,7 +1544,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); } @@ -1560,7 +1561,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..8c0ba8cb2b 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,47 @@ QStringList QCommandLineOption::names() const return d->names; } -void QCommandLineOptionPrivate::setNames(const 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 { +namespace { + struct IsInvalidName + { + typedef bool result_type; + typedef QString argument_type; + + Q_NEVER_INLINE + result_type operator()(const QString &name) const Q_DECL_NOEXCEPT + { + if (Q_UNLIKELY(name.isEmpty())) + return warn("be empty"); + 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); + if (Q_UNLIKELY(c == QLatin1Char('-'))) + return warn("start with a '-'"); + if (Q_UNLIKELY(c == QLatin1Char('/'))) + return warn("start with a '/'"); + if (Q_UNLIKELY(name.contains(QLatin1Char('=')))) + return warn("contain a '='"); + + return false; } - } - // commit - names.swap(newNames); + + Q_NEVER_INLINE + static bool warn(const char *what) Q_DECL_NOEXCEPT + { + qWarning("QCommandLineOption: Option names cannot %s", what); + return true; + } + }; +} // unnamed namespace + +// static +QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList) +{ + if (Q_UNLIKELY(nameList.isEmpty())) + qWarning("QCommandLineOption: Options must have at least one name"); + else + nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()), + nameList.end()); + return nameList; } /*! @@ -362,4 +388,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 hide 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..20e0688f45 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; @@ -112,6 +116,7 @@ public: //! True if parse() needs to be called bool needsParsing; }; +Q_DECLARE_TYPEINFO(QCommandLineParserPrivate::PositionalArgumentDefinition, Q_MOVABLE_TYPE); QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const { @@ -299,6 +304,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 +680,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 +698,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 +710,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 +762,8 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) } } else { positionalArgumentList.append(argument); + if (optionsAfterPositionalArgumentsMode == QCommandLineParser::ParseAsPositionalArguments) + forcePositional = true; } if (argumentIterator == args.end()) break; @@ -1062,6 +1104,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/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index 9457e35ad5..a1cf8f283f 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -252,6 +252,7 @@ public: Qt::TimeSpec spec; // spec if used by QDateTimeEdit Context context; }; +Q_DECLARE_TYPEINFO(QDateTimeParser::SectionNode, Q_PRIMITIVE_TYPE); Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2); diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 1bd9c5ebb9..22f5c65a40 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -340,6 +340,7 @@ struct TCBPoint { qFuzzyCompare(_b, other._b); } }; +Q_DECLARE_TYPEINFO(TCBPoint, Q_PRIMITIVE_TYPE); typedef QVector<TCBPoint> TCBPoints; @@ -1219,6 +1220,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.cpp b/src/corelib/tools/qhash.cpp index a8a461e868..1f3ea36121 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1536,6 +1536,15 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW \sa begin(), constEnd() */ +/*! \fn QHash::key_iterator QHash::keyBegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key + in the hash. + + \sa keyEnd() +*/ + /*! \fn QHash::iterator QHash::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item @@ -1566,6 +1575,15 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW \sa cbegin(), end() */ +/*! \fn QHash::key_iterator QHash::keyEnd() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary + item after the last key in the hash. + + \sa keyBegin() +*/ + /*! \fn QHash::iterator QHash::erase(iterator pos) Removes the (key, value) pair associated with the iterator \a pos @@ -1729,6 +1747,26 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW \internal */ +/*! \typedef QHash::key_iterator::difference_type + \internal +*/ + +/*! \typedef QHash::key_iterator::iterator_category + \internal +*/ + +/*! \typedef QHash::key_iterator::pointer + \internal +*/ + +/*! \typedef QHash::key_iterator::reference + \internal +*/ + +/*! \typedef QHash::key_iterator::value_type + \internal +*/ + /*! \class QHash::iterator \inmodule QtCore \brief The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash. @@ -1802,7 +1840,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW while iterators are active on that container. For more information, read \l{Implicit sharing iterator problem}. - \sa QHash::const_iterator, QMutableHashIterator + \sa QHash::const_iterator, QHash::key_iterator, QMutableHashIterator */ /*! \fn QHash::iterator::iterator() @@ -2155,6 +2193,114 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW \sa operator+=(), operator-() */ +/*! \class QHash::key_iterator + \inmodule QtCore + \since 5.6 + \brief The QHash::key_iterator class provides an STL-style const iterator for QHash and QMultiHash keys. + + QHash::key_iterator is essentially the same as QHash::const_iterator + with the difference that operator*() and operator->() return a key + instead of a value. + + For most uses QHash::iterator and QHash::const_iterator should be used, + you can easily access the key by calling QHash::iterator::key(): + + \snippet code/src_corelib_tools_qhash.cpp 27 + + However, to have interoperability between QHash's keys and STL-style + algorithms we need an iterator that dereferences to a key instead + of a value. With QHash::key_iterator we can apply an algorithm to a + range of keys without having to call QHash::keys(), which is inefficient + as it costs one QHash iteration and memory allocation to create a temporary + QList. + + \snippet code/src_corelib_tools_qhash.cpp 28 + + QHash::key_iterator is const, it's not possible to modify the key. + + The default QHash::key_iterator constructor creates an uninitialized + iterator. You must initialize it using a QHash function like + QHash::keyBegin() or QHash::keyEnd(). + + \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 QHash::const_iterator, QHash::iterator +*/ + +/*! \fn const T &QHash::key_iterator::operator*() const + + Returns the current item's key. +*/ + +/*! \fn const T *QHash::key_iterator::operator->() const + + Returns a pointer to the current item's key. +*/ + +/*! \fn bool QHash::key_iterator::operator==(key_iterator other) const + + Returns \c true if \a other points to the same item as this + iterator; otherwise returns \c false. + + \sa operator!=() +*/ + +/*! \fn bool QHash::key_iterator::operator!=(key_iterator other) const + + Returns \c true if \a other points to a different item than this + iterator; otherwise returns \c false. + + \sa operator==() +*/ + +/*! + \fn QHash::key_iterator &QHash::key_iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the hash and returns an iterator to the new current + item. + + Calling this function on QHash::keyEnd() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QHash::key_iterator QHash::key_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the hash and returns an iterator to the previous + item. +*/ + +/*! \fn QHash::key_iterator &QHash::key_iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QHash::keyBegin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QHash::key_iterator QHash::key_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) makes the preceding item + current and returns an iterator pointing to the previous + item. +*/ + +/*! \fn const_iterator QHash::key_iterator::base() const + Returns the underlying const_iterator this key_iterator is based on. +*/ + /*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash) \relates QHash diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index a9ece12670..e367cc0068 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 { @@ -345,7 +249,7 @@ public: #ifdef Q_COMPILER_RVALUE_REFS QHash(QHash &&other) Q_DECL_NOTHROW : d(other.d) { other.d = const_cast<QHashData *>(&QHashData::shared_null); } QHash &operator=(QHash &&other) Q_DECL_NOTHROW - { qSwap(d, other.d); return *this; } + { QHash moved(std::move(other)); swap(moved); return *this; } #endif void swap(QHash &other) Q_DECL_NOTHROW { qSwap(d, other.d); } @@ -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 @@ -508,6 +413,31 @@ public: }; friend class const_iterator; + class key_iterator + { + const_iterator i; + + public: + typedef typename const_iterator::iterator_category iterator_category; + typedef typename const_iterator::difference_type difference_type; + typedef Key value_type; + typedef const Key *pointer; + typedef const Key &reference; + + explicit key_iterator(const_iterator o) : i(o) { } + + const Key &operator*() const { return i.key(); } + const Key *operator->() const { return &i.key(); } + bool operator==(key_iterator o) const { return i == o.i; } + bool operator!=(key_iterator o) const { return i != o.i; } + + inline key_iterator &operator++() { ++i; return *this; } + inline key_iterator operator++(int) { return key_iterator(i++);} + inline key_iterator &operator--() { --i; return *this; } + inline key_iterator operator--(int) { return key_iterator(i--); } + const_iterator base() const { return i; } + }; + // STL style inline iterator begin() { detach(); return iterator(d->firstNode()); } inline const_iterator begin() const { return const_iterator(d->firstNode()); } @@ -517,6 +447,9 @@ public: inline const_iterator end() const { return const_iterator(e); } inline const_iterator cend() const { return const_iterator(e); } inline const_iterator constEnd() const { return const_iterator(e); } + inline key_iterator keyBegin() const { return key_iterator(begin()); } + inline key_iterator keyEnd() const { return key_iterator(end()); } + iterator erase(iterator it); // more Qt @@ -546,7 +479,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 +524,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 +876,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 +892,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()) @@ -1003,6 +944,9 @@ public: insert(it->first, it->second); } #endif + // compiler-generated copy/move ctors/assignment operators are fine! + // compiler-generated destructor is fine! + QMultiHash(const QHash<Key, T> &other) : QHash<Key, T>(other) {} void swap(QMultiHash &other) { QHash<Key, T>::swap(other); } // prevent QMultiHash<->QHash swaps 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/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 7908bf5137..f216aa121c 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -88,7 +88,7 @@ public: #ifdef Q_COMPILER_RVALUE_REFS inline QLinkedList(QLinkedList<T> &&other) : d(other.d) { other.d = const_cast<QLinkedListData *>(&QLinkedListData::shared_null); } inline QLinkedList<T> &operator=(QLinkedList<T> &&other) - { qSwap(d, other.d); return *this; } + { QLinkedList moved(std::move(other)); swap(moved); return *this; } #endif inline void swap(QLinkedList<T> &other) { qSwap(d, other.d); } bool operator==(const QLinkedList<T> &l) const; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index db00dcb458..8ed0da7ca0 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -148,6 +149,17 @@ void QListData::realloc(int alloc) d->begin = d->end = 0; } +void QListData::realloc_grow(int growth) +{ + Q_ASSERT(!d->ref.isShared()); + int alloc = grow(d->alloc + growth); + Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *))); + Q_CHECK_PTR(x); + + d = x; + d->alloc = alloc; +} + void QListData::dispose(Data *d) { Q_ASSERT(!d->ref.isShared()); @@ -167,7 +179,7 @@ void **QListData::append(int n) ::memcpy(d->array, d->array + b, e * sizeof(void *)); d->begin = 0; } else { - realloc(grow(d->alloc + n)); + realloc_grow(n); } } d->end = e + n; @@ -191,7 +203,7 @@ void **QListData::prepend() Q_ASSERT(!d->ref.isShared()); if (d->begin == 0) { if (d->end >= d->alloc / 3) - realloc(grow(d->alloc + 1)); + realloc_grow(1); if (d->end < d->alloc / 3) d->begin = d->alloc - 2 * d->end; @@ -218,7 +230,7 @@ void **QListData::insert(int i) if (d->begin == 0) { if (d->end == d->alloc) { // If the array is full, we expand it and move some items rightward - realloc(grow(d->alloc + 1)); + realloc_grow(1); } else { // If there is free space at the end of the array, we move some items rightward } @@ -332,41 +344,56 @@ void **QListData::erase(void **xi) \reentrant QList\<T\> is one of Qt's generic \l{container classes}. It - stores a list of values and provides fast index-based access as - well as fast insertions and removals. + stores items in a list that provides fast index-based access + and index-based insertions and removals. QList\<T\>, QLinkedList\<T\>, and QVector\<T\> provide similar - functionality. Here's an overview: + APIs and functionality. They are often interchangeable, but there + are performance consequences. Here is an overview of use cases: \list - \li For most purposes, QList is the right class to use. Its - index-based API is more convenient than QLinkedList's - iterator-based API, and it is usually faster than - QVector because of the way it stores its items in - memory. It also expands to less code in your executable. - \li If you need a real linked list, with guarantees of \l{constant - time} insertions in the middle of the list and iterators to - items rather than indexes, use QLinkedList. - \li If you want the items to occupy adjacent memory positions, - use QVector. + \li QVector should be your default first choice. + QVector\<T\> will usually give better performance than QList\<T\>, + because QVector\<T\> always stores its items sequentially in memory, + where QList\<T\> will allocate its items on the heap unless + \c {sizeof(T) <= sizeof(void*)} and T has been declared to be + either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using + \l {Q_DECLARE_TYPEINFO}. See the \l {Pros and Cons of Using QList} + for an explanation. + \li However, QList is used throughout the Qt APIs for passing + parameters and for returning values. Use QList to interface with + those APIs. + \li If you need a real linked list, which guarantees + \l {Algorithmic Complexity}{constant time} insertions mid-list and + uses iterators to items rather than indexes, use QLinkedList. \endlist + \note QVector and QVarLengthArray both guarantee C-compatible + array layout. QList does not. This might be important if your + application must interface with a C API. - Internally, QList\<T\> is represented as an array of pointers to - items of type T. If T is itself a pointer type or a basic type - that is no larger than a pointer, or if T is one of Qt's \l{shared - classes}, then QList\<T\> stores the items directly in the pointer - array. For lists under a thousand items, this array representation - allows for very fast insertions in the middle, and it allows - index-based access. Furthermore, operations like prepend() and - append() are very fast, because QList preallocates memory at both + \note Iterators into a QLinkedList and references into + heap-allocating QLists remain valid long as the referenced items + remain in the container. This is not true for iterators and + references into a QVector and non-heap-allocating QLists. + + Internally, QList\<T\> is represented as an array of T if + \c{sizeof(T) <= sizeof(void*)} and T has been declared to be + either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using + \l {Q_DECLARE_TYPEINFO}. Otherwise, QList\<T\> is represented + as an array of T* and the items are allocated on the heap. + + The array representation allows very fast insertions and + index-based access. The prepend() and append() operations are + also very fast because QList preallocates memory at both ends of its internal array. (See \l{Algorithmic Complexity} for - details.) Note, however, that for unshared list items that are - larger than a pointer, each append or insert of a new item - requires allocating the new item on the heap, and this per item - allocation might make QVector a better choice in cases that do - lots of appending or inserting, since QVector allocates memory for - its items in a single heap allocation. + details. + + Note, however, that when the conditions specified above are not met, + each append or insert of a new item requires allocating the new item + on the heap, and this per item allocation will make QVector a better + choice for use cases that do a lot of appending or inserting, because + QVector can allocate memory for many items in a single heap allocation. Note that the internal array only ever gets bigger over the life of the list. It never shrinks. The internal array is deallocated @@ -401,9 +428,10 @@ void **QListData::erase(void **xi) \snippet code/src_corelib_tools_qlistdata.cpp 2 - Because QList is implemented as an array of pointers, this - operation is very fast (\l{constant time}). For read-only access, - an alternative syntax is to use at(): + Because QList is implemented as an array of pointers for types + that are larger than a pointer or are not movable, this operation + requires (\l{Algorithmic Complexity}{constant time}). For read-only + access, an alternative syntax is to use at(): \snippet code/src_corelib_tools_qlistdata.cpp 3 @@ -417,10 +445,10 @@ void **QListData::erase(void **xi) \snippet code/src_corelib_tools_qlistdata.cpp 4 - Inserting and removing items at either ends of the list is very - fast (\l{constant time} in most cases), because QList - preallocates extra space on both sides of its internal buffer to - allow for fast growth at both ends of the list. + Inserting and removing items at either end of the list is very + fast (\l{Algorithmic Complexity}{constant time} in most cases), + because QList preallocates extra space on both sides of its + internal buffer to allow for fast growth at both ends of the list. If you want to find all occurrences of a particular value in a list, use indexOf() or lastIndexOf(). The former searches forward @@ -481,6 +509,11 @@ void **QListData::erase(void **xi) \l{QStringList::removeDuplicates()}{removeDuplicates}, \l{QStringList::sort()}{sort}. + \section1 More Information on Using Qt Containers + + For a detailed discussion comparing Qt containers with each other and + with STL containers, see \l {Understand the Qt Containers}. + \sa QListIterator, QMutableListIterator, QLinkedList, QVector */ @@ -512,10 +545,11 @@ void **QListData::erase(void **xi) Constructs a copy of \a other. - This operation takes \l{constant time}, because QList is - \l{implicitly shared}. This makes returning a QList from a - function very fast. If a shared instance is modified, it will be - copied (copy-on-write), and that takes \l{linear time}. + This operation takes \l{Algorithmic Complexity}{constant time}, + because QList is \l{implicitly shared}. This makes returning a + QList from a function very fast. If a shared instance is modified, + it will be copied (copy-on-write), and that takes + \l{Algorithmic Complexity}{linear time}. \sa operator=() */ @@ -584,6 +618,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 @@ -641,7 +734,7 @@ void **QListData::erase(void **xi) Returns the item at index position \a i in the list. \a i must be a valid index position in the list (i.e., 0 <= \a i < size()). - This function is very fast (\l{constant time}). + This function is very fast (\l{Algorithmic Complexity}{constant time}). \sa value(), operator[]() */ @@ -654,8 +747,8 @@ void **QListData::erase(void **xi) If this function is called on a list that is currently being shared, it will trigger a copy of all elements. Otherwise, this function runs in - \l{constant time}. If you do not want to modify the list you should use - QList::at(). + \l{Algorithmic Complexity}{constant time}. If you do not want to modify + the list you should use QList::at(). \sa at(), value() */ @@ -664,7 +757,7 @@ void **QListData::erase(void **xi) \overload - Same as at(). This function runs in \l{constant time}. + Same as at(). This function runs in \l{Algorithmic Complexity}{constant time}. */ /*! \fn QList::reserve(int alloc) @@ -690,9 +783,9 @@ void **QListData::erase(void **xi) This is the same as list.insert(size(), \a value). If this list is not shared, this operation is typically - very fast (amortized \l{constant time}), because QList - preallocates extra space on both sides of its internal - buffer to allow for fast growth at both ends of the list. + very fast (amortized \l{Algorithmic Complexity}{constant time}), + because QList preallocates extra space on both sides of its + internal buffer to allow for fast growth at both ends of the list. \sa operator<<(), prepend(), insert() */ @@ -718,9 +811,9 @@ void **QListData::erase(void **xi) This is the same as list.insert(0, \a value). If this list is not shared, this operation is typically - very fast (amortized \l{constant time}), because QList - preallocates extra space on both sides of its internal - buffer to allow for fast growth at both ends of the list. + very fast (amortized \l{Algorithmic Complexity}{constant time}), + because QList preallocates extra space on both sides of its + internal buffer to allow for fast growth at both ends of the list. \sa append(), insert() */ @@ -811,7 +904,8 @@ void **QListData::erase(void **xi) same as takeAt(0). This function assumes the list is not empty. To avoid failure, call isEmpty() before calling this function. - If this list is not shared, this operation takes \l{constant time}. + If this list is not shared, this operation takes + \l {Algorithmic Complexity}{constant time}. If you don't use the return value, removeFirst() is more efficient. @@ -826,7 +920,8 @@ void **QListData::erase(void **xi) not empty. To avoid failure, call isEmpty() before calling this function. - If this list is not shared, this operation takes \l{constant time}. + If this list is not shared, this operation takes + \l {Algorithmic Complexity}{constant time}. If you don't use the return value, removeLast() is more efficient. @@ -1000,6 +1095,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 +1211,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 +1263,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 +1271,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 +1295,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..32e0141d55 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> @@ -89,6 +90,7 @@ struct Q_CORE_EXPORT QListData { Data *detach(int alloc); Data *detach_grow(int *i, int n); void realloc(int alloc); + void realloc_grow(int growth); inline void dispose() { dispose(d); } static void dispose(Data *d); static const Data shared_null; @@ -102,11 +104,11 @@ struct Q_CORE_EXPORT QListData { void remove(int i); void remove(int i, int n); void move(int from, int to); - inline int size() const { return d->end - d->begin; } - inline bool isEmpty() const { return d->end == d->begin; } - inline void **at(int i) const { return d->array + d->begin + i; } - inline void **begin() const { return d->array + d->begin; } - inline void **end() const { return d->array + d->end; } + inline int size() const Q_DECL_NOTHROW { return d->end - d->begin; } + inline bool isEmpty() const Q_DECL_NOTHROW { return d->end == d->begin; } + inline void **at(int i) const Q_DECL_NOTHROW { return d->array + d->begin + i; } + inline void **begin() const Q_DECL_NOTHROW { return d->array + d->begin; } + inline void **end() const Q_DECL_NOTHROW { return d->array + d->end; } }; template <typename T> @@ -143,7 +145,7 @@ public: #ifdef Q_COMPILER_RVALUE_REFS inline QList(QList<T> &&other) : d(other.d) { other.d = const_cast<QListData::Data *>(&QListData::shared_null); } inline QList &operator=(QList<T> &&other) - { qSwap(d, other.d); return *this; } + { QList moved(std::move(other)); swap(moved); return *this; } #endif inline void swap(QList<T> &other) { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS @@ -154,7 +156,7 @@ public: bool operator==(const QList<T> &l) const; inline bool operator!=(const QList<T> &l) const { return !(*this == l); } - inline int size() const { return p.size(); } + inline int size() const Q_DECL_NOTHROW { return p.size(); } inline void detach() { if (d->ref.isShared()) detach_helper(); } @@ -177,9 +179,9 @@ public: d->ref.setSharable(sharable); } #endif - inline bool isSharedWith(const QList<T> &other) const { return d == other.d; } + inline bool isSharedWith(const QList<T> &other) const Q_DECL_NOTHROW { return d == other.d; } - inline bool isEmpty() const { return p.isEmpty(); } + inline bool isEmpty() const Q_DECL_NOTHROW { return p.isEmpty(); } void clear(); @@ -218,30 +220,34 @@ public: typedef T *pointer; typedef T &reference; - inline iterator() : i(0) {} - inline iterator(Node *n) : i(n) {} - inline iterator(const iterator &o): i(o.i){} + inline iterator() Q_DECL_NOTHROW : i(Q_NULLPTR) {} + inline iterator(Node *n) Q_DECL_NOTHROW : 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) Q_DECL_NOTHROW : 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(); } - inline bool operator==(const iterator &o) const { return i == o.i; } - inline bool operator!=(const iterator &o) const { return i != o.i; } - inline bool operator<(const iterator& other) const { return i < other.i; } - inline bool operator<=(const iterator& other) const { return i <= other.i; } - inline bool operator>(const iterator& other) const { return i > other.i; } - inline bool operator>=(const iterator& other) const { return i >= other.i; } + inline bool operator==(const iterator &o) const Q_DECL_NOTHROW { return i == o.i; } + inline bool operator!=(const iterator &o) const Q_DECL_NOTHROW { return i != o.i; } + inline bool operator<(const iterator& other) const Q_DECL_NOTHROW { return i < other.i; } + inline bool operator<=(const iterator& other) const Q_DECL_NOTHROW { return i <= other.i; } + inline bool operator>(const iterator& other) const Q_DECL_NOTHROW { return i > other.i; } + inline bool operator>=(const iterator& other) const Q_DECL_NOTHROW { return i >= other.i; } #ifndef QT_STRICT_ITERATORS - inline bool operator==(const const_iterator &o) const + inline bool operator==(const const_iterator &o) const Q_DECL_NOTHROW { return i == o.i; } - inline bool operator!=(const const_iterator &o) const + inline bool operator!=(const const_iterator &o) const Q_DECL_NOTHROW { return i != o.i; } - inline bool operator<(const const_iterator& other) const + inline bool operator<(const const_iterator& other) const Q_DECL_NOTHROW { return i < other.i; } - inline bool operator<=(const const_iterator& other) const + inline bool operator<=(const const_iterator& other) const Q_DECL_NOTHROW { return i <= other.i; } - inline bool operator>(const const_iterator& other) const + inline bool operator>(const const_iterator& other) const Q_DECL_NOTHROW { return i > other.i; } - inline bool operator>=(const const_iterator& other) const + inline bool operator>=(const const_iterator& other) const Q_DECL_NOTHROW { return i >= other.i; } #endif inline iterator &operator++() { ++i; return *this; } @@ -266,23 +272,27 @@ public: typedef const T *pointer; typedef const T &reference; - inline const_iterator() : i(0) {} - inline const_iterator(Node *n) : i(n) {} - inline const_iterator(const const_iterator &o): i(o.i) {} + inline const_iterator() Q_DECL_NOTHROW : i(Q_NULLPTR) {} + inline const_iterator(Node *n) Q_DECL_NOTHROW : 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) Q_DECL_NOTHROW : i(o.i) {} +#endif #ifdef QT_STRICT_ITERATORS - inline explicit const_iterator(const iterator &o): i(o.i) {} + inline explicit const_iterator(const iterator &o) Q_DECL_NOTHROW : i(o.i) {} #else - inline const_iterator(const iterator &o): i(o.i) {} + inline const_iterator(const iterator &o) Q_DECL_NOTHROW : i(o.i) {} #endif inline const T &operator*() const { return i->t(); } inline const T *operator->() const { return &i->t(); } inline const T &operator[](difference_type j) const { return i[j].t(); } - inline bool operator==(const const_iterator &o) const { return i == o.i; } - inline bool operator!=(const const_iterator &o) const { return i != o.i; } - inline bool operator<(const const_iterator& other) const { return i < other.i; } - inline bool operator<=(const const_iterator& other) const { return i <= other.i; } - inline bool operator>(const const_iterator& other) const { return i > other.i; } - inline bool operator>=(const const_iterator& other) const { return i >= other.i; } + inline bool operator==(const const_iterator &o) const Q_DECL_NOTHROW { return i == o.i; } + inline bool operator!=(const const_iterator &o) const Q_DECL_NOTHROW { return i != o.i; } + inline bool operator<(const const_iterator& other) const Q_DECL_NOTHROW { return i < other.i; } + inline bool operator<=(const const_iterator& other) const Q_DECL_NOTHROW { return i <= other.i; } + inline bool operator>(const const_iterator& other) const Q_DECL_NOTHROW { return i > other.i; } + inline bool operator>=(const const_iterator& other) const Q_DECL_NOTHROW { return i >= other.i; } inline const_iterator &operator++() { ++i; return *this; } inline const_iterator operator++(int) { Node *n = i; ++i; return n; } inline const_iterator &operator--() { i--; return *this; } @@ -296,14 +306,22 @@ 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()); } - inline const_iterator constBegin() const { return reinterpret_cast<Node *>(p.begin()); } + inline const_iterator begin() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.begin()); } + inline const_iterator cbegin() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.begin()); } + inline const_iterator constBegin() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.begin()); } inline iterator end() { detach(); return reinterpret_cast<Node *>(p.end()); } - 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()); } + inline const_iterator end() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.end()); } + inline const_iterator cend() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.end()); } + inline const_iterator constEnd() const Q_DECL_NOTHROW { 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 Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } iterator insert(iterator before, const T &t); iterator erase(iterator pos); iterator erase(iterator first, iterator last); @@ -314,9 +332,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; } @@ -378,7 +398,7 @@ private: void node_copy(Node *from, Node *to, Node *src); void node_destruct(Node *from, Node *to); - bool isValidIterator(const iterator &i) const + bool isValidIterator(const iterator &i) const Q_DECL_NOTHROW { return (constBegin().i <= i.i) && (i.i <= constEnd().i); } @@ -1020,6 +1040,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/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 430f95dcda..b3fd7a96b8 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -122,6 +122,8 @@ private: QSystemLocale(bool); friend class QSystemLocaleSingleton; }; +Q_DECLARE_TYPEINFO(QSystemLocale::QueryType, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(QSystemLocale::CurrencyToStringArgument, Q_MOVABLE_TYPE); #endif #ifdef QT_USE_ICU @@ -153,6 +155,7 @@ struct QLocaleId ushort language_id, script_id, country_id; }; +Q_DECLARE_TYPEINFO(QLocaleId, Q_PRIMITIVE_TYPE); struct QLocaleData { diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 1b7a8007cd..e49a1a098d 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -858,6 +858,15 @@ void QMapDataBase::freeData(QMapDataBase *d) \sa begin(), constEnd() */ +/*! \fn QMap::key_iterator QMap::keyBegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key + in the map. + + \sa keyEnd(), firstKey() +*/ + /*! \fn QMap::iterator QMap::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item @@ -888,6 +897,15 @@ void QMapDataBase::freeData(QMapDataBase *d) \sa constBegin(), end() */ +/*! \fn QMap::key_iterator QMap::keyEnd() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary + item after the last key in the map. + + \sa keyBegin(), lastKey() +*/ + /*! \fn const Key &QMap::firstKey() const \since 5.2 @@ -896,7 +914,7 @@ void QMapDataBase::freeData(QMapDataBase *d) This executes in \l{constant time}. - \sa lastKey(), first(), isEmpty() + \sa lastKey(), first(), keyBegin(), isEmpty() */ /*! \fn const Key &QMap::lastKey() const @@ -907,7 +925,7 @@ void QMapDataBase::freeData(QMapDataBase *d) This executes in \l{logarithmic time}. - \sa firstKey(), last(), isEmpty() + \sa firstKey(), last(), keyEnd(), isEmpty() */ /*! \fn T &QMap::first() @@ -1161,6 +1179,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 @@ -1229,7 +1253,7 @@ void QMapDataBase::freeData(QMapDataBase *d) while iterators are active on that container. For more information, read \l{Implicit sharing iterator problem}. - \sa QMap::const_iterator, QMutableMapIterator + \sa QMap::const_iterator, QMap::key_iterator, QMutableMapIterator */ /*! \typedef QMap::iterator::difference_type @@ -1452,7 +1476,7 @@ void QMapDataBase::freeData(QMapDataBase *d) while iterators are active on that container. For more information, read \l{Implicit sharing iterator problem}. - \sa QMap::iterator, QMapIterator + \sa QMap::iterator, QMap::key_iterator, QMapIterator */ /*! \typedef QMap::const_iterator::difference_type @@ -1628,6 +1652,134 @@ void QMapDataBase::freeData(QMapDataBase *d) \sa operator+=(), operator-() */ +/*! \class QMap::key_iterator + \inmodule QtCore + \since 5.6 + \brief The QMap::key_iterator class provides an STL-style const iterator for QMap and QMultiMap keys. + + QMap::key_iterator is essentially the same as QMap::const_iterator + with the difference that operator*() and operator->() return a key + instead of a value. + + For most uses QMap::iterator and QMap::const_iterator should be used, + you can easily access the key by calling QMap::iterator::key(): + + \snippet code/src_corelib_tools_qmap.cpp keyiterator1 + + However, to have interoperability between QMap's keys and STL-style + algorithms we need an iterator that dereferences to a key instead + of a value. With QMap::key_iterator we can apply an algorithm to a + range of keys without having to call QMap::keys(), which is inefficient + as it costs one QMap iteration and memory allocation to create a temporary + QList. + + \snippet code/src_corelib_tools_qmap.cpp keyiterator2 + + QMap::key_iterator is const, it's not possible to modify the key. + + The default QMap::key_iterator constructor creates an uninitialized + iterator. You must initialize it using a QMap function like + QMap::keyBegin() or QMap::keyEnd(). + + \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 QMap::const_iterator, QMap::iterator +*/ + +/*! \typedef QMap::key_iterator::difference_type + \internal +*/ + +/*! \typedef QMap::key_iterator::iterator_category + \internal +*/ + +/*! \typedef QMap::key_iterator::pointer + \internal +*/ + +/*! \typedef QMap::key_iterator::reference + \internal +*/ + +/*! \typedef QMap::key_iterator::value_type + \internal +*/ + +/*! \fn const T &QMap::key_iterator::operator*() const + + Returns the current item's key. +*/ + +/*! \fn const T *QMap::key_iterator::operator->() const + + Returns a pointer to the current item's key. +*/ + +/*! \fn bool QMap::key_iterator::operator==(key_iterator other) const + + Returns \c true if \a other points to the same item as this + iterator; otherwise returns \c false. + + \sa operator!=() +*/ + +/*! \fn bool QMap::key_iterator::operator!=(key_iterator other) const + + Returns \c true if \a other points to a different item than this + iterator; otherwise returns \c false. + + \sa operator==() +*/ + +/*! + \fn QMap::key_iterator &QMap::key_iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the hash and returns an iterator to the new current + item. + + Calling this function on QMap::keyEnd() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QMap::key_iterator QMap::key_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the hash and returns an iterator to the previous + item. +*/ + +/*! \fn QMap::key_iterator &QMap::key_iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QMap::keyBegin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QMap::key_iterator QMap::key_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) makes the preceding item + current and returns an iterator pointing to the previous + item. +*/ + +/*! \fn const_iterator QMap::key_iterator::base() const + Returns the underlying const_iterator this key_iterator is based on. +*/ + /*! \fn QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map) \relates QMap diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 1f80e8f0f4..b7bd268bda 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; @@ -348,7 +344,7 @@ public: } inline QMap<Key, T> &operator=(QMap<Key, T> &&other) - { qSwap(d, other.d); return *this; } + { QMap moved(std::move(other)); swap(moved); return *this; } #endif inline void swap(QMap<Key, T> &other) { qSwap(d, other.d); } explicit QMap(const typename std::map<Key, T> &other); @@ -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) @@ -522,6 +518,32 @@ public: }; friend class const_iterator; + class key_iterator + { + const_iterator i; + + public: + typedef typename const_iterator::iterator_category iterator_category; + typedef typename const_iterator::difference_type difference_type; + typedef Key value_type; + typedef const Key *pointer; + typedef const Key &reference; + + explicit key_iterator(const_iterator o) : i(o) { } + + const Key &operator*() const { return i.key(); } + const Key *operator->() const { return &i.key(); } + bool operator==(key_iterator o) const { return i == o.i; } + bool operator!=(key_iterator o) const { return i != o.i; } + + inline key_iterator &operator++() { ++i; return *this; } + inline key_iterator operator++(int) { return key_iterator(i++);} + inline key_iterator &operator--() { --i; return *this; } + inline key_iterator operator--(int) { return key_iterator(i--); } + const_iterator base() const { return i; } + }; + + // STL style inline iterator begin() { detach(); return iterator(d->begin()); } inline const_iterator begin() const { return const_iterator(d->begin()); } @@ -531,6 +553,8 @@ public: inline const_iterator end() const { return const_iterator(d->end()); } inline const_iterator constEnd() const { return const_iterator(d->end()); } inline const_iterator cend() const { return const_iterator(d->end()); } + inline key_iterator keyBegin() const { return key_iterator(begin()); } + inline key_iterator keyEnd() const { return key_iterator(end()); } iterator erase(iterator it); // more Qt @@ -557,6 +581,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 +678,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 +687,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 +762,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 +784,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 +831,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 +889,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 +1085,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 +1095,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 +1105,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 +1115,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/qqueue.cpp b/src/corelib/tools/qqueue.cpp index 65b50c4e03..a8b5051616 100644 --- a/src/corelib/tools/qqueue.cpp +++ b/src/corelib/tools/qqueue.cpp @@ -71,19 +71,6 @@ */ /*! - \fn QQueue::QQueue() - - Constructs an empty queue. -*/ - -/*! - \fn QQueue::~QQueue() - - Destroys the queue. References to the values in the queue, and all - iterators over this queue, become invalid. -*/ - -/*! \fn void QQueue::swap(QQueue<T> &other) \since 4.8 diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h index 9d5bda1210..7a7abab070 100644 --- a/src/corelib/tools/qqueue.h +++ b/src/corelib/tools/qqueue.h @@ -43,8 +43,7 @@ template <class T> class QQueue : public QList<T> { public: - inline QQueue() {} - inline ~QQueue() {} + // compiler-generated special member functions are fine! inline void swap(QQueue<T> &other) { QList<T>::swap(other); } // prevent QList<->QQueue swaps #ifndef Q_QDOC // bring in QList::swap(int, int). We cannot say using QList<T>::swap, diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index b2174745e4..847f650a70 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -2403,7 +2403,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::marginsAdded(const QMarginsF &margins) const - \relates QRectF \since 5.3 Returns a rectangle grown by the \a margins. @@ -2413,7 +2412,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::marginsRemoved(const QMarginsF &margins) const - \relates QRectF \since 5.3 Removes the \a margins from the rectangle, shrinking it. @@ -2423,7 +2421,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::operator+=(const QMarginsF &margins) - \relates QRectF \since 5.3 Adds the \a margins to the rectangle, growing it. @@ -2433,7 +2430,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::operator-=(const QMarginsF &margins) - \relates QRectF \since 5.3 Returns a rectangle shrunk by the \a margins. diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index f896828e2e..c52e4b5a7c 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" @@ -886,6 +887,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); @@ -1019,9 +1029,6 @@ class QRegExpCharClass { public: QRegExpCharClass(); - inline QRegExpCharClass(const QRegExpCharClass &cc) { operator=(cc); } - - QRegExpCharClass &operator=(const QRegExpCharClass &cc); void clear(); bool negative() const { return n; } @@ -2319,17 +2326,6 @@ QRegExpCharClass::QRegExpCharClass() #endif } -QRegExpCharClass &QRegExpCharClass::operator=(const QRegExpCharClass &cc) -{ - c = cc.c; - r = cc.r; - n = cc.n; -#ifndef QT_NO_REGEXP_OPTIM - occ1 = cc.occ1; -#endif - return *this; -} - void QRegExpCharClass::clear() { c = 0; @@ -3811,11 +3807,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; @@ -4037,6 +4028,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 070e68154f..d8b0bf6e9f 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> @@ -1842,6 +1843,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: @@ -2109,7 +2125,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..85cfdaf129 --- /dev/null +++ b/src/corelib/tools/qringbuffer.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** 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; + + head = qMax(basicBlockSize, int(bytes)); + if (bufferSize == 0) { + tail = head; + } else { + buffers.prepend(QByteArray()); + ++tailBuffer; + } + buffers.first().resize(head); + } + + 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/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index 819ab00584..8d478f81f9 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -91,7 +91,7 @@ class QScopedPointer { typedef T *QScopedPointer:: *RestrictedBool; public: - explicit inline QScopedPointer(T *p = 0) : d(p) + explicit inline QScopedPointer(T *p = Q_NULLPTR) : d(p) { } @@ -121,12 +121,12 @@ public: #if defined(Q_QDOC) inline operator bool() const { - return isNull() ? 0 : &QScopedPointer::d; + return isNull() ? Q_NULLPTR : &QScopedPointer::d; } #else inline operator RestrictedBool() const { - return isNull() ? 0 : &QScopedPointer::d; + return isNull() ? Q_NULLPTR : &QScopedPointer::d; } #endif @@ -140,7 +140,7 @@ public: return !d; } - inline void reset(T *other = 0) + inline void reset(T *other = Q_NULLPTR) { if (d == other) return; @@ -152,7 +152,7 @@ public: inline T *take() { T *oldD = d; - d = 0; + d = Q_NULLPTR; return oldD; } @@ -206,10 +206,10 @@ template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > class QScopedArrayPointer : public QScopedPointer<T, Cleanup> { public: - inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(0) {} + inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(Q_NULLPTR) {} template <typename D> - explicit inline QScopedArrayPointer(D *p, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = 0) + explicit inline QScopedArrayPointer(D *p, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = Q_NULLPTR) : QScopedPointer<T, Cleanup>(p) { } diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index e4688711d6..aeba6cf68d 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -57,15 +57,9 @@ public: insert(*it); } #endif - inline QSet(const QSet<T> &other) : q_hash(other.q_hash) {} - - inline QSet<T> &operator=(const QSet<T> &other) - { q_hash = other.q_hash; return *this; } -#ifdef Q_COMPILER_RVALUE_REFS - inline QSet(QSet &&other) : q_hash(qMove(other.q_hash)) {} - inline QSet<T> &operator=(QSet<T> &&other) - { qSwap(q_hash, other.q_hash); return *this; } -#endif + // compiler-generated copy/move ctor/assignment operators are fine! + // compiler-generated destructor is fine! + inline void swap(QSet<T> &other) { q_hash.swap(other.q_hash); } inline bool operator==(const QSet<T> &other) const @@ -137,6 +131,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 +186,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 +280,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 072e65af0e..d91a589aa1 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -114,40 +114,6 @@ */ /*! - \fn QSet::QSet(const QSet<T> &other) - - Constructs a copy of \a other. - - This operation occurs in \l{constant time}, because QSet is - \l{implicitly shared}. This makes returning a QSet from a - function very fast. If a shared instance is modified, it will be - copied (copy-on-write), and this takes \l{linear time}. - - \sa operator=() -*/ - -/*! - \fn QSet::QSet(QSet && other) - - Move-constructs a QSet instance, making it point to the same object that - \a other was pointing to. -*/ - - -/*! - \fn QSet<T> &QSet::operator=(const QSet<T> &other) - - Assigns the \a other set to this set and returns a reference to - this set. -*/ - -/*! - \fn QSet<T> &QSet::operator=(QSet<T> &&other) - - Move-assigns the \a other set to this set. -*/ - -/*! \fn void QSet::swap(QSet<T> &other) Swaps set \a other with this set. This operation is very fast and @@ -504,7 +470,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..6a0900cf3f 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 @@ -76,7 +79,7 @@ public: inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; } inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; } - inline QSharedDataPointer() { d = 0; } + inline QSharedDataPointer() { d = Q_NULLPTR; } inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; } explicit QSharedDataPointer(T *data) Q_DECL_NOTHROW; @@ -142,17 +145,17 @@ public: if(d && !d->ref.deref()) delete d; - d = 0; + d = Q_NULLPTR; } - inline operator bool () const { return d != 0; } + inline operator bool () const { return d != Q_NULLPTR; } inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; } inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; } inline bool operator==(const T *ptr) const { return d == ptr; } inline bool operator!=(const T *ptr) const { return d != ptr; } - inline QExplicitlySharedDataPointer() { d = 0; } + inline QExplicitlySharedDataPointer() { d = Q_NULLPTR; } inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; } explicit QExplicitlySharedDataPointer(T *data) Q_DECL_NOTHROW; diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 9e6b48a97d..1323dd6b1c 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 @@ -297,12 +300,12 @@ public: inline T *data() const { return value; } inline bool isNull() const { return !data(); } - inline operator RestrictedBool() const { return isNull() ? 0 : &QSharedPointer::value; } + inline operator RestrictedBool() const { return isNull() ? Q_NULLPTR : &QSharedPointer::value; } inline bool operator !() const { return isNull(); } inline T &operator*() const { return *data(); } inline T *operator->() const { return data(); } - QSharedPointer() : value(0), d(0) { } + QSharedPointer() : value(Q_NULLPTR), d(Q_NULLPTR) { } ~QSharedPointer() { deref(); } inline explicit QSharedPointer(T *ptr) : value(ptr) // noexcept @@ -324,14 +327,32 @@ public: inline QSharedPointer(QSharedPointer &&other) : value(other.value), d(other.d) { - other.d = 0; - other.value = 0; + other.d = Q_NULLPTR; + other.value = Q_NULLPTR; } inline QSharedPointer &operator=(QSharedPointer &&other) { - swap(other); + QSharedPointer moved(std::move(other)); + swap(moved); + return *this; + } + + template <class X> + QSharedPointer(QSharedPointer<X> &&other) Q_DECL_NOTHROW + : value(other.value), d(other.d) + { + other.d = Q_NULLPTR; + other.value = Q_NULLPTR; + } + + template <class X> + QSharedPointer &operator=(QSharedPointer<X> &&other) Q_DECL_NOTHROW + { + QSharedPointer moved(std::move(other)); + swap(moved); return *this; } + #endif template <class X> @@ -341,13 +362,13 @@ public: template <class X> inline QSharedPointer &operator=(const QSharedPointer<X> &other) { - QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid - internalCopy(other); + QSharedPointer copy(other); + swap(copy); return *this; } template <class X> - inline QSharedPointer(const QWeakPointer<X> &other) : value(0), d(0) + inline QSharedPointer(const QWeakPointer<X> &other) : value(Q_NULLPTR), d(Q_NULLPTR) { *this = other; } template <class X> @@ -463,9 +484,9 @@ public: private: explicit QSharedPointer(Qt::Initialization) {} - inline void deref() + void deref() Q_DECL_NOTHROW { deref(d); } - static inline void deref(Data *d) + static void deref(Data *d) Q_DECL_NOTHROW { if (!d) return; if (!d->strongref.deref()) { @@ -487,7 +508,7 @@ private: inline void internalConstruct(T *ptr, Deleter deleter) { if (!ptr) { - d = 0; + d = Q_NULLPTR; return; } @@ -506,19 +527,7 @@ private: enableSharedFromThis(ptr); } - template <class X> - inline void internalCopy(const QSharedPointer<X> &other) - { - Data *o = other.d; - T *actual = other.value; - if (o) - other.ref(); - qSwap(d, o); - qSwap(this->value, actual); - deref(o); - } - - inline void internalSwap(QSharedPointer &other) + void internalSwap(QSharedPointer &other) Q_DECL_NOTHROW { qSwap(d, other.d); qSwap(this->value, other.value); @@ -531,7 +540,7 @@ public: template <class X> friend class QWeakPointer; template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); #endif - inline void ref() const { d->weakref.ref(); d->strongref.ref(); } + void ref() const Q_DECL_NOTHROW { d->weakref.ref(); d->strongref.ref(); } inline void internalSet(Data *o, T *actual) { @@ -550,14 +559,14 @@ public: o->weakref.ref(); } else { o->checkQObjectShared(actual); - o = 0; + o = Q_NULLPTR; } } qSwap(d, o); qSwap(this->value, actual); if (!d || d->strongref.load() == 0) - this->value = 0; + this->value = Q_NULLPTR; // dereference saved data deref(o); @@ -582,19 +591,19 @@ public: typedef const value_type &const_reference; typedef qptrdiff difference_type; - inline bool isNull() const { return d == 0 || d->strongref.load() == 0 || value == 0; } - inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; } + inline bool isNull() const { return d == Q_NULLPTR || d->strongref.load() == 0 || value == Q_NULLPTR; } + inline operator RestrictedBool() const { return isNull() ? Q_NULLPTR : &QWeakPointer::value; } inline bool operator !() const { return isNull(); } - inline T *data() const { return d == 0 || d->strongref.load() == 0 ? 0 : value; } + inline T *data() const { return d == Q_NULLPTR || d->strongref.load() == 0 ? Q_NULLPTR : value; } - Q_DECL_CONSTEXPR inline QWeakPointer() : d(0), value(0) { } + inline QWeakPointer() : d(Q_NULLPTR), value(Q_NULLPTR) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } #ifndef QT_NO_QOBJECT // special constructor that is enabled only if X derives from QObject #if QT_DEPRECATED_SINCE(5, 0) template <class X> - QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : 0), value(ptr) + QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : Q_NULLPTR), value(ptr) { } #endif #endif @@ -628,7 +637,7 @@ public: } template <class X> - inline QWeakPointer(const QWeakPointer<X> &o) : d(0), value(0) + inline QWeakPointer(const QWeakPointer<X> &o) : d(Q_NULLPTR), value(Q_NULLPTR) { *this = o; } template <class X> @@ -649,7 +658,7 @@ public: { return !(*this == o); } template <class X> - inline QWeakPointer(const QSharedPointer<X> &o) : d(0), value(0) + inline QWeakPointer(const QSharedPointer<X> &o) : d(Q_NULLPTR), value(Q_NULLPTR) { *this = o; } template <class X> @@ -693,7 +702,7 @@ public: #ifndef QT_NO_QOBJECT template <class X> - inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : 0), value(ptr) + inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : Q_NULLPTR), value(ptr) { } #endif diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 4459d89e07..e7917ffdac 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -43,7 +43,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/qsimd_p.h b/src/corelib/tools/qsimd_p.h index dd93b4fd26..8523fb09c1 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -54,9 +54,9 @@ * for the x86 and ARM intrinsics: * - GCC: the -mXXX or march=YYY flag is necessary before #include * up to 4.8; GCC >= 4.9 can include unconditionally + * - Clang: same as GCC, with unconditional inclusion with version 3.7 * - Intel CC: #include can happen unconditionally * - MSVC: #include can happen unconditionally - * - RVCT: ??? * * We will try to include all headers possible under this configuration. * @@ -138,7 +138,8 @@ #define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0) #if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \ - || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \ + || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409) \ + || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 307)) \ && !defined(QT_BOOTSTRAPPED) # define QT_COMPILER_SUPPORTS_SIMD_ALWAYS # define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x) diff --git a/src/corelib/tools/qstack.cpp b/src/corelib/tools/qstack.cpp index e367622c0d..224f72926b 100644 --- a/src/corelib/tools/qstack.cpp +++ b/src/corelib/tools/qstack.cpp @@ -71,19 +71,6 @@ */ /*! - \fn QStack::QStack() - - Constructs an empty stack. -*/ - -/*! - \fn QStack::~QStack() - - Destroys the stack. References to the values in the stack, and all - iterators over this stack, become invalid. -*/ - -/*! \fn void QStack::swap(QStack<T> &other) \since 4.8 diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h index fa05e22de1..278e89ca2f 100644 --- a/src/corelib/tools/qstack.h +++ b/src/corelib/tools/qstack.h @@ -43,8 +43,7 @@ template<class T> class QStack : public QVector<T> { public: - inline QStack() {} - inline ~QStack() {} + // compiler-generated special member functions are fine! inline void swap(QStack<T> &other) { QVector<T>::swap(other); } // prevent QVector<->QStack swaps inline void push(const T &t) { QVector<T>::append(t); } T pop(); diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b623c62043..e3a3cc79c6 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" @@ -1201,6 +1200,22 @@ const QString::Null QString::null = { }; \sa QString::const_iterator */ +/*! \typedef QString::const_reverse_iterator + \since 5.6 + + This typedef provides an STL-style const reverse iterator for QString. + + \sa QString::reverse_iterator, QString::const_iterator +*/ + +/*! \typedef QString::reverse_iterator + \since 5.6 + + This typedef provides an STL-style non-const reverse iterator for QString. + + \sa QString::const_reverse_iterator, QString::iterator +*/ + /*! \typedef QString::size_type @@ -1304,6 +1319,52 @@ const QString::Null QString::null = { }; \sa constBegin(), end() */ +/*! \fn QString::reverse_iterator QString::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + character in the string, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn QString::const_reverse_iterator QString::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn QString::const_reverse_iterator QString::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + character in the string, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn QString::reverse_iterator QString::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last character in the string, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn QString::const_reverse_iterator QString::rend() const + \since 5.6 + \overload +*/ + +/*! \fn QString::const_reverse_iterator QString::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last character in the string, in reverse order. + + \sa end(), rend(), rbegin() +*/ + /*! \fn QString::QString() @@ -1828,6 +1889,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 +2133,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() @@ -2558,6 +2680,8 @@ bool operator==(const QString &s1, const QString &s2) /*! \overload operator==() + Returns \c true if this string is equal to \a other; otherwise + returns \c false. */ bool QString::operator==(QLatin1String other) const { @@ -2616,7 +2740,7 @@ bool operator<(const QString &s1, const QString &s2) } /*! \overload operator<() - \relates QString + Returns \c true if this string is lexically less than the parameter string called \a other; otherwise returns \c false. */ @@ -2659,9 +2783,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 +2831,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; @@ -2721,7 +2845,7 @@ bool QString::operator<(QLatin1String other) const /*! \overload operator>() - \relates QString + Returns \c true if this string is lexically greater than the parameter string \a other; otherwise returns \c false. */ @@ -3184,6 +3308,7 @@ struct QStringCapture int len; int no; }; +Q_DECLARE_TYPEINFO(QStringCapture, Q_PRIMITIVE_TYPE); #endif #ifndef QT_NO_REGEXP @@ -3491,9 +3616,14 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const } /*! - \overload count() + \overload count() + + Returns the number of occurrences of character \a ch in the string. - Returns the number of occurrences of character \a ch in the string. + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa contains(), indexOf() */ int QString::count(QChar ch, Qt::CaseSensitivity cs) const @@ -3939,10 +4069,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 +4091,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 +4119,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 +4214,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 +4262,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); } @@ -4149,8 +4277,8 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti Returns a substring that contains the \a n leftmost characters of the string. - The entire string is returned if \a n is greater than size() or - less than zero. + The entire string is returned if \a n is greater than or equal + to size(), or less than zero. \snippet qstring/main.cpp 31 @@ -4167,8 +4295,8 @@ QString QString::left(int n) const Returns a substring that contains the \a n rightmost characters of the string. - The entire string is returned if \a n is greater than size() or - less than zero. + The entire string is returned if \a n is greater than or equal + to size(), or less than zero. \snippet qstring/main.cpp 48 @@ -4822,7 +4950,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) @@ -4835,7 +4963,8 @@ void QString::truncate(int pos) /*! Removes \a n characters from the end of the string. - If \a n is greater than size(), the result is an empty string. + If \a n is greater than or equal to size(), the result is an + empty string. Example: \snippet qstring/main.cpp 15 @@ -7622,86 +7751,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; } @@ -9125,8 +9323,8 @@ QString &QString::append(const QStringRef &str) Returns a substring reference to the \a n leftmost characters of the string. - If \a n is greater than size() or less than zero, a reference to the entire - string is returned. + If \a n is greater than or equal to size(), or less than zero, + a reference to the entire string is returned. \sa right(), mid(), startsWith() */ @@ -9143,8 +9341,8 @@ QStringRef QStringRef::left(int n) const Returns a substring reference to the \a n leftmost characters of the string. - If \a n is greater than size() or less than zero, a reference to the entire - string is returned. + If \a n is greater than or equal to size(), or less than zero, + a reference to the entire string is returned. \snippet qstring/main.cpp leftRef @@ -9164,8 +9362,8 @@ QStringRef QString::leftRef(int n) const Returns a substring reference to the \a n rightmost characters of the string. - If \a n is greater than size() or less than zero, a reference to the entire - string is returned. + If \a n is greater than or equal to size(), or less than zero, + a reference to the entire string is returned. \sa left(), mid(), endsWith() */ @@ -9182,8 +9380,8 @@ QStringRef QStringRef::right(int n) const Returns a substring reference to the \a n rightmost characters of the string. - If \a n is greater than size() or less than zero, a reference to the entire - string is returned. + If \a n is greater than or equal to size(), or less than zero, + a reference to the entire string is returned. \snippet qstring/main.cpp rightRef @@ -9268,6 +9466,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..643378a7bd 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -44,6 +44,7 @@ #include <QtCore/qnamespace.h> #include <string> +#include <iterator> #if defined(Q_OS_ANDROID) // std::wstring is disabled on android's glibc, as bionic lacks certain features @@ -84,7 +85,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 +421,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 +429,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 +538,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 +595,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 +654,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 +672,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) @@ -708,14 +716,22 @@ public: typedef const QChar *const_iterator; typedef iterator Iterator; typedef const_iterator ConstIterator; - iterator begin(); - const_iterator begin() const; - const_iterator cbegin() const; - const_iterator constBegin() const; - iterator end(); - const_iterator end() const; - const_iterator cend() const; - const_iterator constEnd() const; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + inline iterator begin(); + inline const_iterator begin() const; + inline const_iterator cbegin() const; + inline const_iterator constBegin() const; + inline iterator end(); + inline const_iterator end() const; + inline const_iterator cend() const; + inline const_iterator constEnd() const; + 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()); } // STL compatibility typedef int size_type; @@ -1211,30 +1227,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,28 +1359,32 @@ 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); - // ### Qt 6: remove this copy constructor, the implicit one is fine - inline QStringRef(const QStringRef &other) +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + // ### Qt 6: remove all of these, the implicit ones are fine + QStringRef(const QStringRef &other) Q_DECL_NOTHROW :m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} - - // ### Qt 6: remove this destructor, the implicit one is fine +#ifdef Q_COMPILER_RVALUE_REFS + QStringRef(QStringRef &&other) Q_DECL_NOTHROW : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} + QStringRef &operator=(QStringRef &&other) Q_DECL_NOTHROW { return *this = other; } +#endif + QStringRef &operator=(const QStringRef &other) Q_DECL_NOTHROW { + m_string = other.m_string; m_position = other.m_position; + m_size = other.m_size; return *this; + } inline ~QStringRef(){} +#endif // Qt < 6.0.0 + inline const QString *string() const { return m_string; } inline int position() const { return m_position; } inline int size() const { return m_size; } inline int count() const { return m_size; } inline int length() const { return m_size; } - inline QStringRef &operator=(const QStringRef &other) { - m_string = other.m_string; m_position = other.m_position; - m_size = other.m_size; return *this; - } - int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -1392,6 +1412,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 +1447,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 +1483,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 +1598,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..900c8ff14e 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -310,9 +310,8 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); /*! \typedef QTimeZone::OffsetDataList - \relates QTimeZone - Synonym for QList<OffsetData>. + Synonym for QVector<OffsetData>. */ /*! @@ -764,6 +763,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_p.h b/src/corelib/tools/qtimezoneprivate_p.h index e15ac801bc..14aeac3a02 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -165,6 +165,7 @@ public: protected: QByteArray m_id; }; +Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_MOVABLE_TYPE); template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone(); diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 35380b882a..90ce8e3b68 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -637,6 +637,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..9afd2c624a 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -45,34 +45,42 @@ stores its items in adjacent memory locations and provides fast index-based access. - QList\<T\>, QLinkedList\<T\>, and QVarLengthArray\<T\> provide - similar functionality. Here's an overview: + QList\<T\>, QLinkedList\<T\>, QVector\<T\>, and QVarLengthArray\<T\> + provide similar APIs and functionality. They are often interchangeable, + but there are performance consequences. Here is an overview of use cases: \list - \li For most purposes, QList is the right class to use. Operations - like prepend() and insert() are usually faster than with - QVector because of the way QList stores its items in memory - (see \l{Algorithmic Complexity} for details), - and its index-based API is more convenient than QLinkedList's - iterator-based API. It also expands to less code in your - executable. - \li If you need a real linked list, with guarantees of \l{constant - time} insertions in the middle of the list and iterators to - items rather than indexes, use QLinkedList. - \li If you want the items to occupy adjacent memory positions, or - if your items are larger than a pointer and you want to avoid - the overhead of allocating them on the heap individually at - insertion time, then use QVector. - \li If you want a low-level variable-size array, QVarLengthArray - may be sufficient. + \li QVector should be your default first choice. + QVector\<T\> will usually give better performance than QList\<T\>, + because QVector\<T\> always stores its items sequentially in memory, + where QList\<T\> will allocate its items on the heap unless + \c {sizeof(T) <= sizeof(void*)} and T has been declared to be + either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using + \l {Q_DECLARE_TYPEINFO}. See the \l {Pros and Cons of Using QList} + for an explanation. + \li However, QList is used throughout the Qt APIs for passing + parameters and for returning values. Use QList to interface with + those APIs. + \li If you need a real linked list, which guarantees + \l{Algorithmic Complexity}{constant time} insertions mid-list and + uses iterators to items rather than indexes, use QLinkedList. \endlist + \note QVector and QVarLengthArray both guarantee C-compatible + array layout. QList does not. This might be important if your + application must interface with a C API. + + \note Iterators into a QLinkedList and references into + heap-allocating QLists remain valid long as the referenced items + remain in the container. This is not true for iterators and + references into a QVector and non-heap-allocating QLists. + Here's an example of a QVector that stores integers and a QVector that stores QString values: \snippet code/src_corelib_tools_qvector.cpp 0 - QVector stores a vector (or array) of items. Typically, vectors + QVector stores its items in a vector (array). Typically, vectors are created with an initial size. For example, the following code constructs a QVector with 200 elements: @@ -166,6 +174,11 @@ with references to its own values. Doing so will cause your application to abort with an error message. + \section2 More Information on Using Qt Containers + + For a detailed discussion comparing Qt containers with each other and + with STL containers, see \l {Understand the Qt Containers}. + \sa QVectorIterator, QMutableVectorIterator, QList, QLinkedList */ @@ -218,10 +231,11 @@ Constructs a copy of \a other. - This operation takes \l{constant time}, because QVector is - \l{implicitly shared}. This makes returning a QVector from a - function very fast. If a shared instance is modified, it will be - copied (copy-on-write), and that takes \l{linear time}. + This operation takes \l{Algorithmic Complexity}{constant time}, + because QVector is \l{implicitly shared}. This makes returning + a QVector from a function very fast. If a shared instance is + modified, it will be copied (copy-on-write), and that takes + \l{Algorithmic Complexity}{linear time}. \sa operator=() */ @@ -290,6 +304,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. @@ -463,6 +536,16 @@ \sa operator<<(), prepend(), insert() */ +/*! + \fn void QVector::append(T &&value) + \since 5.6 + + \overload + + Example: + \snippet code/src_corelib_tools_qvector.cpp move-append +*/ + /*! \fn void QVector::append(const QVector<T> &value) \overload @@ -629,6 +712,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 +916,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 +985,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 +993,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 +1015,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. @@ -893,6 +1050,11 @@ to append(\a value). */ +/*! \fn void QVector::push_back(T &&value) + \since 5.6 + \overload +*/ + /*! \fn void QVector::push_front(const T &value) This function is provided for STL compatibility. It is equivalent @@ -1013,6 +1175,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..890dbd317d 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,11 @@ 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 + { QVector moved(std::move(other)); swap(moved); 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 @@ -128,6 +129,9 @@ public: T &operator[](int i); const T &operator[](int i) const; void append(const T &t); +#ifdef Q_COMPILER_RVALUE_REFS + void append(T &&t); +#endif inline void append(const QVector<T> &l) { *this += l; } void prepend(const T &t); void insert(int i, const T &t); @@ -171,29 +175,50 @@ 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(); } - inline const_iterator cbegin() const { return d->constBegin(); } - inline const_iterator constBegin() const { return d->constBegin(); } + inline const_iterator begin() const Q_DECL_NOTHROW { return d->constBegin(); } + inline const_iterator cbegin() const Q_DECL_NOTHROW { return d->constBegin(); } + inline const_iterator constBegin() const Q_DECL_NOTHROW { return d->constBegin(); } inline iterator end() { detach(); return d->end(); } - inline const_iterator end() const { return d->constEnd(); } - inline const_iterator cend() const { return d->constEnd(); } - inline const_iterator constEnd() const { return d->constEnd(); } + inline const_iterator end() const Q_DECL_NOTHROW { return d->constEnd(); } + inline const_iterator cend() const Q_DECL_NOTHROW { return d->constEnd(); } + inline const_iterator constEnd() const Q_DECL_NOTHROW { return d->constEnd(); } #else inline iterator begin(iterator = iterator()) { detach(); return d->begin(); } - inline const_iterator begin(const_iterator = const_iterator()) const { return d->constBegin(); } - inline const_iterator cbegin(const_iterator = const_iterator()) const { return d->constBegin(); } - inline const_iterator constBegin(const_iterator = const_iterator()) const { return d->constBegin(); } + inline const_iterator begin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); } + inline const_iterator cbegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); } + inline const_iterator constBegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); } inline iterator end(iterator = iterator()) { detach(); return d->end(); } - inline const_iterator end(const_iterator = const_iterator()) const { return d->constEnd(); } - inline const_iterator cend(const_iterator = const_iterator()) const { return d->constEnd(); } - inline const_iterator constEnd(const_iterator = const_iterator()) const { return d->constEnd(); } + inline const_iterator end(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); } + inline const_iterator cend(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); } + inline const_iterator constEnd(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); } #endif + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator crend() const Q_DECL_NOTHROW { 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 +228,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; @@ -223,6 +250,9 @@ public: typedef const_iterator ConstIterator; typedef int size_type; inline void push_back(const T &t) { append(t); } +#ifdef Q_COMPILER_RVALUE_REFS + void push_back(T &&t) { append(std::move(t)); } +#endif inline void push_front(const T &t) { prepend(t); } void pop_back() { removeLast(); } void pop_front() { removeFirst(); } @@ -265,7 +295,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]; }; }; @@ -602,14 +631,14 @@ void QVector<T>::append(const T &t) { const bool isTooSmall = uint(d->size + 1) > d->alloc; if (!isDetached() || isTooSmall) { - const T copy(t); + T copy(t); QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default); reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt); if (QTypeInfo<T>::isComplex) - new (d->end()) T(copy); + new (d->end()) T(qMove(copy)); else - *d->end() = copy; + *d->end() = qMove(copy); } else { if (QTypeInfo<T>::isComplex) @@ -620,6 +649,22 @@ void QVector<T>::append(const T &t) ++d->size; } +#ifdef Q_COMPILER_RVALUE_REFS +template <typename T> +void QVector<T>::append(T &&t) +{ + const bool isTooSmall = uint(d->size + 1) > d->alloc; + if (!isDetached() || isTooSmall) { + QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default); + reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt); + } + + new (d->end()) T(std::move(t)); + + ++d->size; +} +#endif + template <typename T> void QVector<T>::removeLast() { @@ -873,6 +918,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/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp index 660f40b107..4197fc47b1 100644 --- a/src/corelib/tools/qversionnumber.cpp +++ b/src/corelib/tools/qversionnumber.cpp @@ -32,7 +32,7 @@ ** ****************************************************************************/ -#include <QtCore/private/qversionnumber_p.h> +#include <QtCore/qversionnumber.h> #include <QtCore/qhash.h> #include <QtCore/private/qlocale_tools_p.h> #include <QtCore/qcollator.h> @@ -53,8 +53,7 @@ QT_BEGIN_NAMESPACE /*! \class QVersionNumber \inmodule QtCore - \internal - \since 5.4 + \since 5.6 \brief The QVersionNumber class contains a version number with an arbitrary number of segments. @@ -168,6 +167,17 @@ QT_BEGIN_NAMESPACE \sa majorVersion(), minorVersion(), microVersion() */ +QVector<int> QVersionNumber::segments() const +{ + if (m_segments.isUsingPointer()) + return *m_segments.pointer_segments; + + QVector<int> result; + result.resize(segmentCount()); + for (int i = 0; i < segmentCount(); ++i) + result[i] = segmentAt(i); + return result; +} /*! \fn int QVersionNumber::segmentAt(int index) const @@ -196,6 +206,17 @@ QT_BEGIN_NAMESPACE \snippet qversionnumber/main.cpp 4 */ +QVersionNumber QVersionNumber::normalized() const +{ + int i; + for (i = m_segments.size(); i; --i) + if (m_segments.at(i - 1) != 0) + break; + + QVersionNumber result(*this); + result.m_segments.resize(i); + return result; +} /*! \fn bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const @@ -209,8 +230,13 @@ QT_BEGIN_NAMESPACE */ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW { - return m_segments.size() <= other.m_segments.size() && - std::equal(m_segments.begin(), m_segments.end(), other.m_segments.begin()); + if (segmentCount() > other.segmentCount()) + return false; + for (int i = 0; i < segmentCount(); ++i) { + if (segmentAt(i) != other.segmentAt(i)) + return false; + } + return true; } /*! @@ -228,30 +254,37 @@ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHRO */ int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW { - QVector<int>::const_iterator i1 = v1.m_segments.constBegin(); - const QVector<int>::const_iterator e1 = v1.m_segments.constEnd(); - QVector<int>::const_iterator i2 = v2.m_segments.constBegin(); - const QVector<int>::const_iterator e2 = v2.m_segments.constEnd(); - - while (i1 != e1 && i2 != e2) { - if (*i1 != *i2) - return (*i1 - *i2); - ++i1; - ++i2; + int commonlen; + + if (Q_LIKELY(!v1.m_segments.isUsingPointer() && !v2.m_segments.isUsingPointer())) { + // we can't use memcmp because it interprets the data as unsigned bytes + const qint8 *ptr1 = v1.m_segments.inline_segments + InlineSegmentStartIdx; + const qint8 *ptr2 = v2.m_segments.inline_segments + InlineSegmentStartIdx; + commonlen = qMin(v1.m_segments.size(), + v2.m_segments.size()); + for (int i = 0; i < commonlen; ++i) + if (int x = ptr1[i] - ptr2[i]) + return x; + } else { + commonlen = qMin(v1.segmentCount(), v2.segmentCount()); + for (int i = 0; i < commonlen; ++i) { + if (v1.segmentAt(i) != v2.segmentAt(i)) + return v1.segmentAt(i) - v2.segmentAt(i); + } } // ran out of segments in v1 and/or v2 and need to check the first trailing // segment to finish the compare - if (i1 != e1) { + if (v1.segmentCount() > commonlen) { // v1 is longer - if (*i1 != 0) - return *i1; + if (v1.segmentAt(commonlen) != 0) + return v1.segmentAt(commonlen); else return 1; - } else if (i2 != e2) { + } else if (v2.segmentCount() > commonlen) { // v2 is longer - if (*i2 != 0) - return -*i2; + if (v2.segmentAt(commonlen) != 0) + return -v2.segmentAt(commonlen); else return -1; } @@ -271,13 +304,20 @@ int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2) { - int min = qMin(v1.m_segments.size(), v2.m_segments.size()); - QVector<int>::const_iterator i1 = v1.m_segments.begin(); - QVector<int>::const_iterator e1; - e1 = std::mismatch(i1, - v1.m_segments.begin() + min, - v2.m_segments.begin()).first; - return QVersionNumber(v1.m_segments.mid(0, e1 - i1)); + int commonlen = qMin(v1.segmentCount(), v2.segmentCount()); + int i; + for (i = 0; i < commonlen; ++i) { + if (v1.segmentAt(i) != v2.segmentAt(i)) + break; + } + + if (i == 0) + return QVersionNumber(); + + // try to use the one with inline segments, if there's one + QVersionNumber result(!v1.m_segments.isUsingPointer() ? v1 : v2); + result.m_segments.resize(i); + return result; } /*! @@ -348,12 +388,12 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1, QString QVersionNumber::toString() const { QString version; - version.reserve(qMax(m_segments.size() * 2 - 1, 0)); + version.reserve(qMax(segmentCount() * 2 - 1, 0)); bool first = true; - for (QVector<int>::const_iterator it = m_segments.begin(), end = m_segments.end(); it != end; ++it) { + for (int i = 0; i < segmentCount(); ++i) { if (!first) version += QLatin1Char('.'); - version += QString::number(*it); + version += QString::number(segmentAt(i)); first = false; } return version; @@ -401,19 +441,17 @@ QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixInde return QVersionNumber(qMove(seg)); } -/*! - \fn QVersionNumber QVersionNumber::normalizedImpl(QVector<int> &segs) - - Implementation of the normalized() function. Takes the movable list \a segs - and normalizes them. - - \internal - */ -QVersionNumber QVersionNumber::normalizedImpl(QVector<int> &segs) +void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic) { - while (segs.size() && segs.last() == 0) - segs.pop_back(); - return QVersionNumber(qMove(segs)); + pointer_segments = new QVector<int>; + pointer_segments->resize(len); + pointer_segments->data()[0] = maj; + if (len > 1) { + pointer_segments->data()[1] = min; + if (len > 2) { + pointer_segments->data()[2] = mic; + } + } } #ifndef QT_NO_DATASTREAM @@ -442,7 +480,9 @@ QDataStream& operator<<(QDataStream &out, const QVersionNumber &version) */ QDataStream& operator>>(QDataStream &in, QVersionNumber &version) { - in >> version.m_segments; + if (!version.m_segments.isUsingPointer()) + version.m_segments.pointer_segments = new QVector<int>; + in >> *version.m_segments.pointer_segments; return in; } #endif @@ -459,14 +499,18 @@ QDebug operator<<(QDebug debug, const QVersionNumber &version) /*! \fn uint qHash(const QVersionNumber &key, uint seed) \relates QHash - \since 5.4 + \since 5.6 Returns the hash value for the \a key, using \a seed to seed the calculation. */ uint qHash(const QVersionNumber &key, uint seed) { - return qHashRange(key.m_segments.begin(), key.m_segments.end(), seed); + QtPrivate::QHashCombine hash; + for (int i = 0; i < key.segmentCount(); ++i) + seed = hash(seed, key.segmentAt(i)); + return seed; } QT_END_NAMESPACE + diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h new file mode 100644 index 0000000000..ebf1844f38 --- /dev/null +++ b/src/corelib/tools/qversionnumber.h @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2014 Keith Gardner <kreios4004@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$ +** +****************************************************************************/ + +#ifndef QVERSIONNUMBER_H +#define QVERSIONNUMBER_H + +#include <QtCore/qnamespace.h> +#include <QtCore/qstring.h> +#include <QtCore/qvector.h> +#include <QtCore/qmetatype.h> +#include <QtCore/qtypeinfo.h> + +QT_BEGIN_NAMESPACE + +class QVersionNumber; +Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed = 0); + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QVersionNumber &version); +Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); +#endif + +class QVersionNumber +{ + /* + * QVersionNumber stores small values inline, without memory allocation. + * We do that by setting the LSB in the pointer that would otherwise hold + * the longer form of the segments. + * The constants below help us deal with the permutations for 32- and 64-bit, + * little- and big-endian architectures. + */ + enum { + // in little-endian, inline_segments[0] is shared with the pointer's LSB, while + // in big-endian, it's inline_segments[7] + InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void*) - 1, + InlineSegmentStartIdx = !InlineSegmentMarker, // 0 for BE, 1 for LE + InlineSegmentCount = sizeof(void*) - 1 + }; + Q_STATIC_ASSERT(InlineSegmentCount >= 3); // at least major, minor, micro + + struct SegmentStorage { + // Note: we alias the use of dummy and inline_segments in the use of the + // union below. This is undefined behavior in C++98, but most compilers implement + // the C++11 behavior. The one known exception is older versions of Sun Studio. + union { + quintptr dummy; + qint8 inline_segments[sizeof(void*)]; + QVector<int> *pointer_segments; + }; + + // set the InlineSegmentMarker and set length to zero + SegmentStorage() Q_DECL_NOTHROW : dummy(1) {} + + SegmentStorage(const QVector<int> &seg) + { + if (dataFitsInline(seg.begin(), seg.size())) + setInlineData(seg.begin(), seg.size()); + else + pointer_segments = new QVector<int>(seg); + } + + SegmentStorage(const SegmentStorage &other) + { + if (other.isUsingPointer()) + pointer_segments = new QVector<int>(*other.pointer_segments); + else + dummy = other.dummy; + } + + SegmentStorage &operator=(const SegmentStorage &other) + { + if (isUsingPointer() && other.isUsingPointer()) { + *pointer_segments = *other.pointer_segments; + } else if (other.isUsingPointer()) { + pointer_segments = new QVector<int>(*other.pointer_segments); + } else { + if (isUsingPointer()) + delete pointer_segments; + dummy = other.dummy; + } + return *this; + } + +#ifdef Q_COMPILER_RVALUE_REFS + SegmentStorage(SegmentStorage &&other) Q_DECL_NOTHROW + : dummy(other.dummy) + { + other.dummy = 1; + } + + SegmentStorage &operator=(SegmentStorage &&other) Q_DECL_NOTHROW + { + qSwap(dummy, other.dummy); + return *this; + } + + explicit SegmentStorage(QVector<int> &&seg) + { + if (dataFitsInline(seg.begin(), seg.size())) + setInlineData(seg.begin(), seg.size()); + else + pointer_segments = new QVector<int>(std::move(seg)); + } +#endif +#ifdef Q_COMPILER_INITIALIZER_LISTS + SegmentStorage(std::initializer_list<int> args) + { + if (dataFitsInline(args.begin(), int(args.size()))) { + setInlineData(args.begin(), int(args.size())); + } else { + pointer_segments = new QVector<int>(args); + } + } +#endif + + ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; } + + bool isUsingPointer() const Q_DECL_NOTHROW + { return (inline_segments[InlineSegmentMarker] & 1) == 0; } + + int size() const Q_DECL_NOTHROW + { return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); } + + void setInlineSize(int len) + { inline_segments[InlineSegmentMarker] = 1 + 2 * len; } + + void resize(int len) + { + if (isUsingPointer()) + pointer_segments->resize(len); + else + setInlineSize(len); + } + + int at(int index) const + { + return isUsingPointer() ? + pointer_segments->at(index) : + inline_segments[InlineSegmentStartIdx + index]; + } + + void setSegments(int len, int maj, int min = 0, int mic = 0) + { + if (maj == qint8(maj) && min == qint8(min) && mic == qint8(mic)) { + int data[] = { maj, min, mic }; + setInlineData(data, len); + } else { + setVector(len, maj, min, mic); + } + } + + private: + static bool dataFitsInline(const int *data, int len) + { + if (len > InlineSegmentCount) + return false; + for (int i = 0; i < len; ++i) + if (data[i] != qint8(data[i])) + return false; + return true; + } + void setInlineData(const int *data, int len) + { + dummy = 1 + len * 2; +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + for (int i = 0; i < len; ++i) + dummy |= quintptr(data[i] & 0xFF) << (8 * (i + 1)); +#elif Q_BYTE_ORDER == Q_BIG_ENDIAN + for (int i = 0; i < len; ++i) + dummy |= quintptr(data[i] & 0xFF) << (8 * (sizeof(void *) - i - 1)); +#else + // the code above is equivalent to: + setInlineSize(len); + for (int i = 0; i < len; ++i) + inline_segments[InlineSegmentStartIdx + i] = data[i] & 0xFF; +#endif + } + + Q_CORE_EXPORT void setVector(int len, int maj, int min, int mic); + } m_segments; + +public: + inline QVersionNumber() Q_DECL_NOTHROW + : m_segments() + {} + inline explicit QVersionNumber(const QVector<int> &seg) + : m_segments(seg) + {} + + // compiler-generated copy/move ctor/assignment operators and the destructor are ok + +#ifdef Q_COMPILER_RVALUE_REFS + explicit QVersionNumber(QVector<int> &&seg) + : m_segments(std::move(seg)) + {} +#endif + +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QVersionNumber(std::initializer_list<int> args) + : m_segments(args) + {} +#endif + + inline explicit QVersionNumber(int maj) + { m_segments.setSegments(1, maj); } + + inline explicit QVersionNumber(int maj, int min) + { m_segments.setSegments(2, maj, min); } + + inline explicit QVersionNumber(int maj, int min, int mic) + { m_segments.setSegments(3, maj, min, mic); } + + inline bool isNull() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return segmentCount() == 0; } + + inline bool isNormalized() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return isNull() || segmentAt(segmentCount() - 1) != 0; } + + inline int majorVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return segmentAt(0); } + + inline int minorVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return segmentAt(1); } + + inline int microVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return segmentAt(2); } + + Q_CORE_EXPORT QVersionNumber normalized() const Q_REQUIRED_RESULT; + + Q_CORE_EXPORT QVector<int> segments() const Q_REQUIRED_RESULT; + + inline int segmentAt(int index) const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return (m_segments.size() > index) ? m_segments.at(index) : 0; } + + inline int segmentCount() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { return m_segments.size(); } + + Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW Q_REQUIRED_RESULT; + + Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW Q_REQUIRED_RESULT; + + Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2) Q_REQUIRED_RESULT; + + Q_CORE_EXPORT QString toString() const Q_REQUIRED_RESULT; + Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = 0) Q_REQUIRED_RESULT; + +private: +#ifndef QT_NO_DATASTREAM + friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); +#endif + friend Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed); +}; + +Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE); + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version); +#endif + +Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW +{ return QVersionNumber::compare(lhs, rhs) > 0; } + +Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW +{ return QVersionNumber::compare(lhs, rhs) >= 0; } + +Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW +{ return QVersionNumber::compare(lhs, rhs) < 0; } + +Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW +{ return QVersionNumber::compare(lhs, rhs) <= 0; } + +Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW +{ return QVersionNumber::compare(lhs, rhs) == 0; } + +Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW +{ return QVersionNumber::compare(lhs, rhs) != 0; } + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QVersionNumber) + +#endif //QVERSIONNUMBER_H diff --git a/src/corelib/tools/qversionnumber_p.h b/src/corelib/tools/qversionnumber_p.h deleted file mode 100644 index 2da3103be3..0000000000 --- a/src/corelib/tools/qversionnumber_p.h +++ /dev/null @@ -1,193 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Keith Gardner <kreios4004@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$ -** -****************************************************************************/ - -#ifndef QVERSIONNUMBER_H -#define QVERSIONNUMBER_H - -#include <QtCore/qnamespace.h> -#include <QtCore/qstring.h> -#include <QtCore/qvector.h> -#include <QtCore/qmetatype.h> -#include <QtCore/qtypeinfo.h> - -QT_BEGIN_NAMESPACE - -class QVersionNumber; -Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed = 0); - -#ifndef QT_NO_DATASTREAM -Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QVersionNumber &version); -Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); -#endif - -class QVersionNumber -{ -public: - inline QVersionNumber() Q_DECL_NOTHROW - : m_segments() - {} - // compiler-generated copy/move ctor/assignment operators are ok - - inline explicit QVersionNumber(const QVector<int> &seg) Q_DECL_NOTHROW - : m_segments(seg) - {} -#ifdef Q_COMPILER_RVALUE_REFS - inline explicit QVersionNumber(QVector<int> &&seg) Q_DECL_NOTHROW - : m_segments(qMove(seg)) - {} -#endif -#ifdef Q_COMPILER_INITIALIZER_LISTS - inline QVersionNumber(std::initializer_list<int> args) - : m_segments(args) - {} -#endif - - inline explicit QVersionNumber(int maj) - { m_segments.reserve(1); m_segments << maj; } - - inline explicit QVersionNumber(int maj, int min) - { m_segments.reserve(2); m_segments << maj << min; } - - inline explicit QVersionNumber(int maj, int min, int mic) - { m_segments.reserve(3); m_segments << maj << min << mic; } - - inline bool isNull() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return m_segments.isEmpty(); } - - inline bool isNormalized() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return isNull() || m_segments.last() != 0; } - - inline int majorVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return segmentAt(0); } - - inline int minorVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return segmentAt(1); } - - inline int microVersion() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return segmentAt(2); } - -#if defined(Q_COMPILER_REF_QUALIFIERS) -# if defined(Q_CC_GNU) - // required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941 -# pragma push_macro("Q_REQUIRED_RESULT") -# undef Q_REQUIRED_RESULT -# define Q_REQUIRED_RESULT -# define Q_REQUIRED_RESULT_pushed -# endif - inline QVersionNumber normalized() const & Q_REQUIRED_RESULT - { - QVector<int> segs(m_segments); - return normalizedImpl(segs); - } - - inline QVersionNumber normalized() && Q_REQUIRED_RESULT - { - return normalizedImpl(m_segments); - } - - inline QVector<int> segments() const & Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return m_segments; } - - inline QVector<int> segments() && Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return qMove(m_segments); } - -# ifdef Q_REQUIRED_RESULT_pushed -# pragma pop_macro("Q_REQUIRED_RESULT") -# endif -#else - inline QVersionNumber normalized() const Q_REQUIRED_RESULT - { - QVector<int> segs(m_segments); - return normalizedImpl(segs); - } - - inline QVector<int> segments() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return m_segments; } -#endif - - inline int segmentAt(int index) const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return (m_segments.size() > index) ? m_segments.at(index) : 0; } - - inline int segmentCount() const Q_DECL_NOTHROW Q_REQUIRED_RESULT - { return m_segments.size(); } - - Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW Q_REQUIRED_RESULT; - - Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW Q_REQUIRED_RESULT; - - Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2) Q_REQUIRED_RESULT; - - Q_CORE_EXPORT QString toString() const Q_REQUIRED_RESULT; - Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = 0) Q_REQUIRED_RESULT; - -private: - Q_CORE_EXPORT static QVersionNumber normalizedImpl(QVector<int> &segs) Q_REQUIRED_RESULT; - -#ifndef QT_NO_DATASTREAM - friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); -#endif - friend Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed); - - QVector<int> m_segments; -}; - -Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE); - -#ifndef QT_NO_DEBUG_STREAM -Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version); -#endif - -Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) > 0; } - -Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) >= 0; } - -Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) < 0; } - -Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) <= 0; } - -Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) == 0; } - -Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) != 0; } - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QVersionNumber) - -#endif //QVERSIONNUMBER_H diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 5de0c09a4d..c43fd761d8 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 \ @@ -73,7 +75,7 @@ HEADERS += \ tools/qunicodetools_p.h \ tools/qvarlengtharray.h \ tools/qvector.h \ - tools/qversionnumber_p.h + tools/qversionnumber.h SOURCES += \ @@ -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 \ |