summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qalgorithms.h125
-rw-r--r--src/corelib/tools/qalgorithms.qdoc70
-rw-r--r--src/corelib/tools/qarraydata.cpp4
-rw-r--r--src/corelib/tools/qarraydata.h6
-rw-r--r--src/corelib/tools/qarraydatapointer.h11
-rw-r--r--src/corelib/tools/qbitarray.h2
-rw-r--r--src/corelib/tools/qbytearray.cpp94
-rw-r--r--src/corelib/tools/qbytearray.h48
-rw-r--r--src/corelib/tools/qbytearray_p.h61
-rw-r--r--src/corelib/tools/qbytearraylist.h2
-rw-r--r--src/corelib/tools/qchar.cpp61
-rw-r--r--src/corelib/tools/qchar.h269
-rw-r--r--src/corelib/tools/qcollator.h2
-rw-r--r--src/corelib/tools/qcommandlineoption.cpp114
-rw-r--r--src/corelib/tools/qcommandlineoption.h8
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp50
-rw-r--r--src/corelib/tools/qcommandlineparser.h6
-rw-r--r--src/corelib/tools/qcryptographichash.cpp2
-rw-r--r--src/corelib/tools/qdatetime.cpp28
-rw-r--r--src/corelib/tools/qdatetime.h7
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h1
-rw-r--r--src/corelib/tools/qeasingcurve.cpp10
-rw-r--r--src/corelib/tools/qeasingcurve.h2
-rw-r--r--src/corelib/tools/qharfbuzz.cpp3
-rw-r--r--src/corelib/tools/qhash.cpp198
-rw-r--r--src/corelib/tools/qhash.h174
-rw-r--r--src/corelib/tools/qhashfunctions.h156
-rw-r--r--src/corelib/tools/qlinkedlist.cpp78
-rw-r--r--src/corelib/tools/qlinkedlist.h34
-rw-r--r--src/corelib/tools/qlist.cpp303
-rw-r--r--src/corelib/tools/qlist.h148
-rw-r--r--src/corelib/tools/qlocale.cpp39
-rw-r--r--src/corelib/tools/qlocale.h39
-rw-r--r--src/corelib/tools/qlocale_mac.mm14
-rw-r--r--src/corelib/tools/qlocale_p.h3
-rw-r--r--src/corelib/tools/qlocale_win.cpp6
-rw-r--r--src/corelib/tools/qmap.cpp160
-rw-r--r--src/corelib/tools/qmap.h155
-rw-r--r--src/corelib/tools/qqueue.cpp13
-rw-r--r--src/corelib/tools/qqueue.h5
-rw-r--r--src/corelib/tools/qrect.cpp4
-rw-r--r--src/corelib/tools/qregexp.cpp46
-rw-r--r--src/corelib/tools/qregexp.h5
-rw-r--r--src/corelib/tools/qregularexpression.cpp29
-rw-r--r--src/corelib/tools/qregularexpression.h4
-rw-r--r--src/corelib/tools/qringbuffer.cpp314
-rw-r--r--src/corelib/tools/qringbuffer_p.h246
-rw-r--r--src/corelib/tools/qscopedpointer.h14
-rw-r--r--src/corelib/tools/qset.h71
-rw-r--r--src/corelib/tools/qset.qdoc124
-rw-r--r--src/corelib/tools/qshareddata.h11
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h81
-rw-r--r--src/corelib/tools/qsimd.cpp298
-rw-r--r--src/corelib/tools/qsimd_p.h175
-rw-r--r--src/corelib/tools/qstack.cpp13
-rw-r--r--src/corelib/tools/qstack.h5
-rw-r--r--src/corelib/tools/qstring.cpp407
-rw-r--r--src/corelib/tools/qstring.h190
-rw-r--r--src/corelib/tools/qstringbuilder.h2
-rw-r--r--src/corelib/tools/qtextboundaryfinder.h2
-rw-r--r--src/corelib/tools/qtimeline.h2
-rw-r--r--src/corelib/tools/qtimezone.cpp4
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp1
-rw-r--r--src/corelib/tools/qtimezoneprivate_p.h1
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp1
-rw-r--r--src/corelib/tools/qvarlengtharray.h39
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc108
-rw-r--r--src/corelib/tools/qvector.cpp244
-rw-r--r--src/corelib/tools/qvector.h122
-rw-r--r--src/corelib/tools/qversionnumber.cpp138
-rw-r--r--src/corelib/tools/qversionnumber.h313
-rw-r--r--src/corelib/tools/qversionnumber_p.h193
-rw-r--r--src/corelib/tools/tools.pri5
73 files changed, 4144 insertions, 1579 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
--- 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/qbitarray.h b/src/corelib/tools/qbitarray.h
index 4e5c26b86a..e686d53db4 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -48,7 +48,7 @@ class Q_CORE_EXPORT QBitArray
QByteArray d;
public:
- inline QBitArray() {}
+ inline QBitArray() Q_DECL_NOTHROW {}
explicit QBitArray(int size, bool val = false);
QBitArray(const QBitArray &other) : d(other.d) {}
inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; }
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 9d6c9d4ed1..a9f361c205 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
@@ -577,8 +578,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
qWarning("qUncompress: Input data is corrupted");
return QByteArray();
}
- ulong expectedSize = (data[0] << 24) | (data[1] << 16) |
- (data[2] << 8) | (data[3] );
+ ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) |
+ (data[2] << 8) | (data[3] ));
ulong len = qMax(expectedSize, 1ul);
QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d;
@@ -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..15c7a0646f 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.6
+*/
+
+/*!
+ Sets the parsing mode to \a parsingMode.
+ This must be called before process() or parse().
+ \since 5.6
+*/
+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/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 42877ec664..1c74a602c6 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -65,7 +65,7 @@ typedef HashReturn (SHA3Init)(hashState *state, int hashbitlen);
typedef HashReturn (SHA3Update)(hashState *state, const BitSequence *data, DataLength databitlen);
typedef HashReturn (SHA3Final)(hashState *state, BitSequence *hashval);
-#if QT_POINTER_SIZE == 8 // 64 bit version
+#if Q_PROCESSOR_WORDSIZE == 8 // 64 bit version
#include "../../3rdparty/sha3/KeccakF-1600-opt64.c"
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index d6428920e5..4854ceb5ca 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -4793,23 +4793,21 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
// From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
dateAndTime = dateTime.d->getDateTime();
out << dateAndTime;
- if (out.version() >= QDataStream::Qt_4_0) {
- switch (dateTime.timeSpec()) {
- case Qt::UTC:
- out << (qint8)QDateTimePrivate::UTC;
- break;
- case Qt::OffsetFromUTC:
- out << (qint8)QDateTimePrivate::OffsetFromUTC;
- break;
- case Qt::TimeZone:
+ switch (dateTime.timeSpec()) {
+ case Qt::UTC:
+ out << (qint8)QDateTimePrivate::UTC;
+ break;
+ case Qt::OffsetFromUTC:
+ out << (qint8)QDateTimePrivate::OffsetFromUTC;
+ break;
+ case Qt::TimeZone:
#ifndef QT_BOOTSTRAPPED
- out << (qint8)QDateTimePrivate::TimeZone;
- break;
+ out << (qint8)QDateTimePrivate::TimeZone;
+ break;
#endif // QT_BOOTSTRAPPED
- case Qt::LocalTime:
- out << (qint8)QDateTimePrivate::LocalUnknown;
- break;
- }
+ case Qt::LocalTime:
+ out << (qint8)QDateTimePrivate::LocalUnknown;
+ break;
}
} else { // version < QDataStream::Qt_4_0
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..012e6a95e8 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -170,7 +170,7 @@
\value OutSine \image qeasingcurve-outsine.png
\caption
Easing curve for a sinusoidal (sin(t)) function:
- decelerating from zero velocity.
+ decelerating to zero velocity.
\value InOutSine \image qeasingcurve-inoutsine.png
\caption
Easing curve for a sinusoidal (sin(t)) function:
@@ -186,7 +186,7 @@
\value OutExpo \image qeasingcurve-outexpo.png
\caption
Easing curve for an exponential (2^t) function:
- decelerating from zero velocity.
+ decelerating to zero velocity.
\value InOutExpo \image qeasingcurve-inoutexpo.png
\caption
Easing curve for an exponential (2^t) function:
@@ -202,7 +202,7 @@
\value OutCirc \image qeasingcurve-outcirc.png
\caption
Easing curve for a circular (sqrt(1-t^2)) function:
- decelerating from zero velocity.
+ decelerating to zero velocity.
\value InOutCirc \image qeasingcurve-inoutcirc.png
\caption
Easing curve for a circular (sqrt(1-t^2)) function:
@@ -222,7 +222,7 @@
\caption
Easing curve for an elastic
(exponentially decaying sine wave) function:
- decelerating from zero velocity. The peak amplitude
+ decelerating to zero velocity. The peak amplitude
can be set with the \e amplitude parameter, and the
period of decay by the \e period parameter.
\value InOutElastic \image qeasingcurve-inoutelastic.png
@@ -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..b334a697a9 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -290,6 +290,53 @@ static void qt_initialize_qhash_seed()
}
}
+/*! \relates QHash
+ \since 5.6
+
+ Returns the current global QHash seed.
+
+ The seed is set in any newly created QHash. See \l{qHash} about how this seed
+ is being used by QHash.
+
+ \sa qSetGlobalQHashSeed
+ */
+int qGlobalQHashSeed()
+{
+ return qt_qhash_seed.load();
+}
+
+/*! \relates QHash
+ \since 5.6
+
+ Sets the global QHash seed.
+
+ Manually setting the global QHash seed value should be done only for testing
+ and debugging purposes, when deterministic and reproducible behavior on a QHash
+ is needed. We discourage to do it in production code as it can make your
+ application susceptible to \l{algorithmic complexity attacks}.
+
+ The seed is set in any newly created QHash. See \l{qHash} about how this seed
+ is being used by QHash.
+
+ If the environment variable \c QT_HASH_SEED is set, calling this function will
+ result in a no-op.
+
+ Passing the value -1 will reinitialize the global QHash seed to a random value.
+
+ \sa qGlobalQHashSeed
+ */
+void qSetGlobalQHashSeed(int newSeed)
+{
+ if (qEnvironmentVariableIsSet("QT_HASH_SEED"))
+ return;
+ if (newSeed == -1) {
+ int x(qt_create_qhash_seed() & INT_MAX);
+ qt_qhash_seed.store(x);
+ } else {
+ qt_qhash_seed.store(newSeed & INT_MAX);
+ }
+}
+
/*!
\internal
@@ -1132,7 +1179,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
where you temporarily need deterministic behavior, for example for debugging or
regression testing. To disable the randomization, define the environment
variable \c QT_HASH_SEED. The contents of that variable, interpreted as a
- decimal value, will be used as the seed for qHash().
+ decimal value, will be used as the seed for qHash(). Alternatively, you can
+ call the qSetGlobalQHashSeed() function.
\sa QHashIterator, QMutableHashIterator, QMap, QSet
*/
@@ -1536,6 +1584,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 +1623,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 +1795,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 +1888,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 +2241,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..a18dd74706 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())
@@ -994,7 +935,7 @@ template <class Key, class T>
class QMultiHash : public QHash<Key, T>
{
public:
- QMultiHash() {}
+ QMultiHash() Q_DECL_NOTHROW {}
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QMultiHash(std::initializer_list<std::pair<Key,T> > list)
{
@@ -1003,8 +944,14 @@ 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
+#ifdef Q_COMPILER_RVALUE_REFS
+ QMultiHash(QHash<Key, T> &&other) Q_DECL_NOTHROW : QHash<Key, T>(std::move(other)) {}
+#endif
+ void swap(QMultiHash &other) Q_DECL_NOTHROW { QHash<Key, T>::swap(other); } // prevent QMultiHash<->QHash swaps
inline typename QHash<Key, T>::iterator replace(const Key &key, const T &value)
{ return QHash<Key, T>::insert(key, value); }
@@ -1093,6 +1040,9 @@ Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value)
return n;
}
+Q_CORE_EXPORT int qGlobalQHashSeed();
+Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed);
+
Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash)
Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash)
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.cpp b/src/corelib/tools/qlinkedlist.cpp
index fbd263e88b..5d91bfe924 100644
--- a/src/corelib/tools/qlinkedlist.cpp
+++ b/src/corelib/tools/qlinkedlist.cpp
@@ -388,6 +388,52 @@ const QLinkedListData QLinkedListData::shared_null = {
\sa constBegin(), end()
*/
+/*! \fn QLinkedList::reverse_iterator QLinkedList::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 QLinkedList::const_reverse_iterator QLinkedList::rbegin() const
+ \since 5.6
+ \overload
+*/
+
+/*! \fn QLinkedList::const_reverse_iterator QLinkedList::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 QLinkedList::reverse_iterator QLinkedList::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 QLinkedList::const_reverse_iterator QLinkedList::rend() const
+ \since 5.6
+ \overload
+*/
+
+/*! \fn QLinkedList::const_reverse_iterator QLinkedList::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 QLinkedList::iterator QLinkedList::insert(iterator before, const T &value)
Inserts \a value in front of the item pointed to by the iterator
@@ -423,6 +469,38 @@ const QLinkedListData QLinkedListData::shared_null = {
Qt-style synonym for QLinkedList::const_iterator.
*/
+/*! \typedef QLinkedList::reverse_iterator
+ \since 5.6
+
+ The QLinkedList::reverse_iterator typedef provides an STL-style non-const
+ reverse iterator for QLinkedList.
+
+ It is simply a typedef for \c{std::reverse_iterator<QLinkedList::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 QLinkedList::rbegin(), QLinkedList::rend(), QLinkedList::const_reverse_iterator, QLinkedList::iterator
+*/
+
+/*! \typedef QLinkedList::const_reverse_iterator
+ \since 5.6
+
+ The QLinkedList::const_reverse_iterator typedef provides an STL-style const
+ reverse iterator for QLinkedList.
+
+ It is simply a typedef for \c{std::reverse_iterator<QLinkedList::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 QLinkedList::rbegin(), QLinkedList::rend(), QLinkedList::reverse_iterator, QLinkedList::const_iterator
+*/
+
/*!
\typedef QLinkedList::size_type
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index 7908bf5137..110529d843 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -74,7 +74,7 @@ class QLinkedList
union { QLinkedListData *d; QLinkedListNode<T> *e; };
public:
- inline QLinkedList() : d(const_cast<QLinkedListData *>(&QLinkedListData::shared_null)) { }
+ inline QLinkedList() Q_DECL_NOTHROW : d(const_cast<QLinkedListData *>(&QLinkedListData::shared_null)) { }
inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); }
#if defined(Q_COMPILER_INITIALIZER_LISTS)
inline QLinkedList(std::initializer_list<T> list)
@@ -86,11 +86,12 @@ public:
~QLinkedList();
QLinkedList<T> &operator=(const QLinkedList<T> &);
#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(QLinkedList<T> &&other) Q_DECL_NOTHROW
+ : d(other.d) { other.d = const_cast<QLinkedListData *>(&QLinkedListData::shared_null); }
+ QLinkedList<T> &operator=(QLinkedList<T> &&other) Q_DECL_NOTHROW
+ { QLinkedList moved(std::move(other)); swap(moved); return *this; }
#endif
- inline void swap(QLinkedList<T> &other) { qSwap(d, other.d); }
+ inline void swap(QLinkedList<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
bool operator==(const QLinkedList<T> &l) const;
inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); }
@@ -182,14 +183,25 @@ 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 e->n; }
- inline const_iterator begin() const { return e->n; }
- inline const_iterator cbegin() const { return e->n; }
- inline const_iterator constBegin() const { return e->n; }
+ inline const_iterator begin() const Q_DECL_NOTHROW { return e->n; }
+ inline const_iterator cbegin() const Q_DECL_NOTHROW { return e->n; }
+ inline const_iterator constBegin() const Q_DECL_NOTHROW { return e->n; }
inline iterator end() { detach(); return e; }
- inline const_iterator end() const { return e; }
- inline const_iterator cend() const { return e; }
- inline const_iterator constEnd() const { return e; }
+ inline const_iterator end() const Q_DECL_NOTHROW { return e; }
+ inline const_iterator cend() const Q_DECL_NOTHROW { return e; }
+ inline const_iterator constEnd() const Q_DECL_NOTHROW { return e; }
+
+ 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);
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..9a57a2c6a5 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>
@@ -141,11 +143,12 @@ public:
~QList();
QList<T> &operator=(const QList<T> &l);
#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; }
+ inline QList(QList<T> &&other) Q_DECL_NOTHROW
+ : d(other.d) { other.d = const_cast<QListData::Data *>(&QListData::shared_null); }
+ inline QList &operator=(QList<T> &&other) Q_DECL_NOTHROW
+ { QList moved(std::move(other)); swap(moved); return *this; }
#endif
- inline void swap(QList<T> &other) { qSwap(d, other.d); }
+ inline void swap(QList<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QList(std::initializer_list<T> args)
: d(const_cast<QListData::Data *>(&QListData::shared_null))
@@ -154,7 +157,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 +180,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 +221,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 +273,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 +307,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 +333,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 +399,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 +1041,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..b1f53dc7a2 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"
@@ -88,9 +89,9 @@ QLocale::Language QLocalePrivate::codeToLanguage(const QString &code)
int len = code.length();
if (len != 2 && len != 3)
return QLocale::C;
- ushort uc1 = len-- > 0 ? code[0].toLower().unicode() : 0;
- ushort uc2 = len-- > 0 ? code[1].toLower().unicode() : 0;
- ushort uc3 = len-- > 0 ? code[2].toLower().unicode() : 0;
+ ushort uc1 = code[0].toLower().unicode();
+ ushort uc2 = code[1].toLower().unicode();
+ ushort uc3 = len > 2 ? code[2].toLower().unicode() : 0;
const unsigned char *c = language_code_list;
for (; *c != 0; c += 3) {
@@ -144,9 +145,9 @@ QLocale::Country QLocalePrivate::codeToCountry(const QString &code)
int len = code.length();
if (len != 2 && len != 3)
return QLocale::AnyCountry;
- ushort uc1 = len-- > 0 ? code[0].toUpper().unicode() : 0;
- ushort uc2 = len-- > 0 ? code[1].toUpper().unicode() : 0;
- ushort uc3 = len-- > 0 ? code[2].toUpper().unicode() : 0;
+ ushort uc1 = code[0].toUpper().unicode();
+ ushort uc2 = code[1].toUpper().unicode();
+ ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
const unsigned char *c = country_code_list;
for (; *c != 0; c += 3) {
@@ -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;
@@ -525,7 +526,7 @@ static uint default_number_options = 0;
static const QLocaleData *const c_data = locale_data;
static QLocalePrivate *c_private()
{
- static QLocalePrivate c_locale = { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), 0 };
+ static QLocalePrivate c_locale = { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), QLocale::OmitGroupSeparator };
return &c_locale;
}
@@ -697,7 +698,8 @@ static QLocalePrivate *localePrivateByName(const QString &name)
{
if (name == QLatin1String("C"))
return c_private();
- return QLocalePrivate::create(findLocaleData(name));
+ const QLocaleData *data = findLocaleData(name);
+ return QLocalePrivate::create(data, data->m_language_id == QLocale::C ? QLocale::OmitGroupSeparator : 0);
}
static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Script script,
@@ -866,6 +868,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
@@ -2726,9 +2743,9 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
const QChar exponential, const QChar group, const QChar decimal,
double d, int precision, DoubleForm form, int width, unsigned flags)
{
- if (precision == -1)
+ if (precision < 0)
precision = 6;
- if (width == -1)
+ if (width < 0)
width = 0;
bool negative = false;
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/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
index 1cad9b32e3..4781bab172 100644
--- a/src/corelib/tools/qlocale_win.cpp
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -51,9 +51,7 @@
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
-#ifndef Q_OS_WINPHONE
#include <windows.globalization.h>
-#endif
#endif // Q_OS_WINRT
QT_BEGIN_NAMESPACE
@@ -639,7 +637,6 @@ QVariant QSystemLocalePrivate::uiLanguages()
return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage())));
#else // !Q_OS_WINRT
QStringList result;
-#ifndef Q_OS_WINPHONE
ComPtr<ABI::Windows::Globalization::IApplicationLanguagesStatics> appLanguagesStatics;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), &appLanguagesStatics))) {
qWarning("Could not obtain ApplicationLanguagesStatic");
@@ -661,9 +658,6 @@ QVariant QSystemLocalePrivate::uiLanguages()
PCWSTR rawString = language.GetRawBuffer(&length);
result << QString::fromWCharArray(rawString, length);
}
-#else // !Q_OS_WINPHONE
- result << QString::fromWCharArray(lcName);
-#endif // Q_OS_WINPHONE
return result;
#endif // Q_OS_WINRT
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..fe9ddaaa32 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;
@@ -325,7 +321,7 @@ class QMap
QMapData<Key, T> *d;
public:
- inline QMap() : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null))) { }
+ inline QMap() Q_DECL_NOTHROW : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null))) { }
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QMap(std::initializer_list<std::pair<Key,T> > list)
: d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null)))
@@ -340,17 +336,17 @@ public:
QMap<Key, T> &operator=(const QMap<Key, T> &other);
#ifdef Q_COMPILER_RVALUE_REFS
- inline QMap(QMap<Key, T> &&other)
+ inline QMap(QMap<Key, T> &&other) Q_DECL_NOTHROW
: d(other.d)
{
other.d = static_cast<QMapData<Key, T> *>(
const_cast<QMapDataBase *>(&QMapDataBase::shared_null));
}
- inline QMap<Key, T> &operator=(QMap<Key, T> &&other)
- { qSwap(d, other.d); return *this; }
+ inline QMap<Key, T> &operator=(QMap<Key, T> &&other) Q_DECL_NOTHROW
+ { QMap moved(std::move(other)); swap(moved); return *this; }
#endif
- inline void swap(QMap<Key, T> &other) { qSwap(d, other.d); }
+ inline void swap(QMap<Key, T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
explicit QMap(const typename std::map<Key, T> &other);
std::map<Key, T> toStdMap() const;
@@ -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);
@@ -1134,7 +1168,7 @@ template <class Key, class T>
class QMultiMap : public QMap<Key, T>
{
public:
- QMultiMap() {}
+ QMultiMap() Q_DECL_NOTHROW {}
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QMultiMap(std::initializer_list<std::pair<Key,T> > list)
{
@@ -1143,7 +1177,10 @@ public:
}
#endif
QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {}
- inline void swap(QMultiMap<Key, T> &other) { QMap<Key, T>::swap(other); }
+#ifdef Q_COMPILER_RVALUE_REFS
+ QMultiMap(QMap<Key, T> &&other) Q_DECL_NOTHROW : QMap<Key, T>(std::move(other)) {}
+#endif
+ void swap(QMultiMap<Key, T> &other) Q_DECL_NOTHROW { QMap<Key, T>::swap(other); }
inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value)
{ return QMap<Key, T>::insert(key, value); }
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..0cb8353d0f 100644
--- a/src/corelib/tools/qqueue.h
+++ b/src/corelib/tools/qqueue.h
@@ -43,9 +43,8 @@ template <class T>
class QQueue : public QList<T>
{
public:
- inline QQueue() {}
- inline ~QQueue() {}
- inline void swap(QQueue<T> &other) { QList<T>::swap(other); } // prevent QList<->QQueue swaps
+ // compiler-generated special member functions are fine!
+ inline void swap(QQueue<T> &other) Q_DECL_NOTHROW { QList<T>::swap(other); } // prevent QList<->QQueue swaps
#ifndef Q_QDOC
// bring in QList::swap(int, int). We cannot say using QList<T>::swap,
// because we don't want to make swap(QList&) available.
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..82de664a56 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"
@@ -491,7 +492,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
when it is followed by 'char'.
\endtable
- \keyword QRegExp wildcard matching
+ \target QRegExp wildcard matching
\section1 Wildcard Matching
Most command shells such as \e bash or \e cmd.exe support "file
@@ -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..81b108059b 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;
}
@@ -2462,7 +2479,7 @@ QDataStream &operator>>(QDataStream &in, QRegularExpression &re)
QDebug operator<<(QDebug debug, const QRegularExpression &re)
{
QDebugStateSaver saver(debug);
- debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ")";
+ debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ')';
return debug;
}
@@ -2504,7 +2521,7 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.chop(1);
}
- debug.nospace() << "QRegularExpression::PatternOptions(" << flags << ")";
+ debug.nospace() << "QRegularExpression::PatternOptions(" << flags << ')';
return debug;
}
@@ -2533,7 +2550,7 @@ QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match)
for (int i = 0; i <= match.lastCapturedIndex(); ++i) {
debug << i
<< ":(" << match.capturedStart(i) << ", " << match.capturedEnd(i)
- << ", " << match.captured(i) << ")";
+ << ", " << match.captured(i) << ')';
if (i < match.lastCapturedIndex())
debug << ", ";
}
@@ -2541,12 +2558,12 @@ QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match)
debug << ", has partial match: ("
<< match.capturedStart(0) << ", "
<< match.capturedEnd(0) << ", "
- << match.captured(0) << ")";
+ << match.captured(0) << ')';
} else {
debug << ", no match";
}
- debug << ")";
+ debug << ')';
return debug;
}
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..3f4208e8b3 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -39,6 +39,8 @@
#include <initializer_list>
#endif
+#include <iterator>
+
QT_BEGIN_NAMESPACE
@@ -48,7 +50,7 @@ class QSet
typedef QHash<T, QHashDummyValue> Hash;
public:
- inline QSet() {}
+ inline QSet() Q_DECL_NOTHROW {}
#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QSet(std::initializer_list<T> list)
{
@@ -57,16 +59,10 @@ 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
- inline void swap(QSet<T> &other) { q_hash.swap(other.q_hash); }
+ // compiler-generated copy/move ctor/assignment operators are fine!
+ // compiler-generated destructor is fine!
+
+ inline void swap(QSet<T> &other) Q_DECL_NOTHROW { q_hash.swap(other.q_hash); }
inline bool operator==(const QSet<T> &other) const
{ return q_hash == other.q_hash; }
@@ -137,6 +133,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;
@@ -166,14 +163,25 @@ public:
};
// STL style
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
inline iterator begin() { return q_hash.begin(); }
- inline const_iterator begin() const { return q_hash.begin(); }
- inline const_iterator cbegin() const { return q_hash.begin(); }
- inline const_iterator constBegin() const { return q_hash.constBegin(); }
+ inline const_iterator begin() const Q_DECL_NOTHROW { return q_hash.begin(); }
+ inline const_iterator cbegin() const Q_DECL_NOTHROW { return q_hash.begin(); }
+ inline const_iterator constBegin() const Q_DECL_NOTHROW { return q_hash.constBegin(); }
inline iterator end() { return q_hash.end(); }
- inline const_iterator end() const { return q_hash.end(); }
- inline const_iterator cend() const { return q_hash.end(); }
- inline const_iterator constEnd() const { return q_hash.constEnd(); }
+ inline const_iterator end() const Q_DECL_NOTHROW { return q_hash.end(); }
+ inline const_iterator cend() const Q_DECL_NOTHROW { return q_hash.end(); }
+ inline const_iterator constEnd() const Q_DECL_NOTHROW { return q_hash.constEnd(); }
+
+ 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 erase(iterator i)
{
Q_ASSERT_X(isValidIterator(i), "QSet::erase", "The specified const_iterator argument 'i' is invalid");
@@ -191,6 +199,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 +293,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..542def4651 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
@@ -418,6 +384,52 @@
\sa constBegin(), end()
*/
+/*! \fn QSet::reverse_iterator QSet::rbegin()
+ \since 5.6
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ item in the set, in reverse order.
+
+ \sa begin(), crbegin(), rend()
+*/
+
+/*! \fn QSet::const_reverse_iterator QSet::rbegin() const
+ \since 5.6
+ \overload
+*/
+
+/*! \fn QSet::const_reverse_iterator QSet::crbegin() const
+ \since 5.6
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ item in the set, in reverse order.
+
+ \sa begin(), rbegin(), rend()
+*/
+
+/*! \fn QSet::reverse_iterator QSet::rend()
+ \since 5.6
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last item in the set, in reverse order.
+
+ \sa end(), crend(), rbegin()
+*/
+
+/*! \fn QSet::const_reverse_iterator QSet::rend() const
+ \since 5.6
+ \overload
+*/
+
+/*! \fn QSet::const_reverse_iterator QSet::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 set, in reverse order.
+
+ \sa end(), rend(), rbegin()
+*/
+
/*!
\typedef QSet::Iterator
\since 4.2
@@ -479,6 +491,38 @@
Typedef for T. Provided for STL compatibility.
*/
+/*! \typedef QSet::reverse_iterator
+ \since 5.6
+
+ The QSet::reverse_iterator typedef provides an STL-style non-const
+ reverse iterator for QSet.
+
+ It is simply a typedef for \c{std::reverse_iterator<QSet::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 QSet::rbegin(), QSet::rend(), QSet::const_reverse_iterator, QSet::iterator
+*/
+
+/*! \typedef QSet::const_reverse_iterator
+ \since 5.6
+
+ The QSet::const_reverse_iterator typedef provides an STL-style const
+ reverse iterator for QSet.
+
+ It is simply a typedef for \c{std::reverse_iterator<QSet::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 QSet::rbegin(), QSet::rend(), QSet::reverse_iterator, QSet::const_iterator
+*/
+
/*!
\fn QSet::const_iterator QSet::insert(const T &value)
@@ -504,7 +548,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..ad02d2c147 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
@@ -76,28 +78,28 @@ static inline uint detectProcessorFeatures()
return 0;
}
#elif defined (Q_OS_WINCE)
-static inline uint detectProcessorFeatures()
+static inline quint64 detectProcessorFeatures()
{
- uint features = 0;
+ quint64 features = 0;
#if defined (ARM)
# ifdef PF_ARM_NEON
if (IsProcessorFeaturePresent(PF_ARM_NEON))
- features |= ARM_NEON;
+ features |= Q_UINT64_C(1) << CpuFeatureNEON;
# endif
#elif defined(_X86_)
if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
- features |= SSE2;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE2;
if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
- features |= SSE3;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE3;
#endif
return features;
}
#elif defined(Q_PROCESSOR_ARM)
-static inline uint detectProcessorFeatures()
+static inline quint64 detectProcessorFeatures()
{
- uint features = 0;
+ quint64 features = 0;
#if defined(Q_OS_LINUX)
int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY);
@@ -115,7 +117,7 @@ static inline uint detectProcessorFeatures()
for (int i = 0; i < max; i += 2)
if (vector[i] == AT_HWCAP) {
if (vector[i+1] & HWCAP_NEON)
- features |= NEON;
+ features |= Q_UINT64_C(1) << CpuFeatureNEON;
break;
}
}
@@ -127,7 +129,7 @@ static inline uint detectProcessorFeatures()
#endif
#if defined(__ARM_NEON__)
- features = NEON;
+ features = Q_UINT64_C(1) << CpuFeatureNEON;
#endif
return features;
@@ -203,21 +205,24 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));}
#endif
-static void cpuidFeatures07_00(uint &ebx)
+static void cpuidFeatures07_00(uint &ebx, uint &ecx)
{
#if defined(Q_CC_GNU)
qregisteruint rbx; // in case it's 64-bit
+ qregisteruint rcx = 0;
asm ("xchg " PICreg", %0\n"
"cpuid\n"
"xchg " PICreg", %0\n"
- : "=&r" (rbx)
- : "a" (7), "c" (0)
+ : "=&r" (rbx), "+&c" (rcx)
+ : "a" (7)
: "%edx");
ebx = rbx;
+ ecx = rcx;
#elif defined(Q_OS_WIN)
int info[4];
__cpuidex(info, 7, 0);
ebx = info[1];
+ ecx = info[2];
#endif
}
@@ -238,7 +243,7 @@ static void xgetbv(uint in, uint &eax, uint &edx)
#endif
}
-static inline uint detectProcessorFeatures()
+static quint64 detectProcessorFeatures()
{
// Flags from the CR0 / XCR0 state register
enum XCR0Flags {
@@ -255,8 +260,15 @@ static inline uint detectProcessorFeatures()
AVXState = XMM0_15 | YMM0_15Hi128,
AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31
};
-
- uint features = 0;
+ static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512VL) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI);
+ static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512;
+ static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2;
+
+ quint64 features = 0;
int cpuidLevel = maxBasicCpuidSupported();
#if Q_PROCESSOR_X86 < 5
if (cpuidLevel < 1)
@@ -267,28 +279,23 @@ static inline uint detectProcessorFeatures()
uint cpuid01ECX = 0, cpuid01EDX = 0;
cpuidFeatures01(cpuid01ECX, cpuid01EDX);
+
+ // the low 32-bits of features is cpuid01ECX
+ // note: we need to check OS support for saving the AVX register state
+ features = cpuid01ECX;
+
#if defined(Q_PROCESSOR_X86_32)
// x86 might not have SSE2 support
if (cpuid01EDX & (1u << 26))
- features |= SSE2;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE2;
+ else
+ features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2);
// we should verify that the OS enabled saving of the SSE state...
#else
// x86-64 or x32
- features = SSE2;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE2;
#endif
- // common part between 32- and 64-bit
- if (cpuid01ECX & (1u))
- features |= SSE3;
- if (cpuid01ECX & (1u << 9))
- features |= SSSE3;
- if (cpuid01ECX & (1u << 19))
- features |= SSE4_1;
- if (cpuid01ECX & (1u << 20))
- features |= SSE4_2;
- if (cpuid01ECX & (1u << 25))
- features |= 0; // AES, enable if needed
-
uint xgetbvA = 0, xgetbvD = 0;
if (cpuid01ECX & (1u << 27)) {
// XGETBV enabled
@@ -296,22 +303,27 @@ static inline uint detectProcessorFeatures()
}
uint cpuid0700EBX = 0;
- if (cpuidLevel >= 7)
- cpuidFeatures07_00(cpuid0700EBX);
-
- if ((xgetbvA & AVXState) == AVXState) {
- // support for YMM and XMM registers is enabled
- if (cpuid01ECX & (1u << 28))
- features |= AVX;
+ uint cpuid0700ECX = 0;
+ if (cpuidLevel >= 7) {
+ cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX);
- if (cpuid0700EBX & (1u << 5))
- features |= AVX2;
+ // the high 32-bits of features is cpuid0700EBX
+ features |= quint64(cpuid0700EBX) << 32;
}
- if (cpuid0700EBX & (1u << 4))
- features |= HLE; // Hardware Lock Ellision
- if (cpuid0700EBX & (1u << 11))
- features |= RTM; // Restricted Transactional Memory
+ if ((xgetbvA & AVXState) != AVXState) {
+ // support for YMM registers is disabled, disable all AVX
+ features &= ~AllAVX;
+ } else if ((xgetbvA & AVX512State) != AVX512State) {
+ // support for ZMM registers or mask registers is disabled, disable all AVX512
+ features &= ~AllAVX512;
+ } else {
+ // this feature is out of order
+ if (cpuid0700ECX & (1u << 1))
+ features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI;
+ else
+ features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI);
+ }
return features;
}
@@ -428,24 +440,24 @@ static bool procCpuinfoContains(const char *prefix, const char *string)
}
#endif
-static inline uint detectProcessorFeatures()
+static inline quint64 detectProcessorFeatures()
{
// NOTE: MIPS 74K cores are the only ones supporting DSPr2.
- uint flags = 0;
+ quint64 flags = 0;
#if defined __mips_dsp
- flags |= DSP;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSP;
# if defined __mips_dsp_rev && __mips_dsp_rev >= 2
- flags |= DSPR2;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
# elif defined(Q_OS_LINUX)
if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
- flags |= DSPR2;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
# endif
#elif defined(Q_OS_LINUX)
if (procCpuinfoContains("ASEs implemented", "dsp")) {
- flags |= DSP;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSP;
if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
- flags |= DSPR2;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
}
#endif
@@ -460,70 +472,179 @@ static inline uint detectProcessorFeatures()
#endif
/*
- * Use kdesdk/scripts/generate_string_table.pl to update the table below.
- * Here's the data (don't forget the ONE leading space):
+ * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note
+ * that the x86 version has a lot of blanks that must be kept and that the
+ * offset table's type is changed to make the table smaller. We also remove the
+ * terminating -1 that the script adds.
+ */
+// begin generated
+#if defined(Q_PROCESSOR_ARM)
+/* Data:
neon
- sse2
+ */
+static const char features_string[] = " neon\0";
+static const int features_indices[] = { 0 };
+#elif defined(Q_PROCESSOR_MIPS)
+/* Data:
+ dsp
+ dspr2
+*/
+static const char features_string[] =
+ " dsp\0"
+ " dspr2\0"
+ "\0";
+
+static const int features_indices[] = {
+ 0, 5
+};
+#elif defined(Q_PROCESSOR_X86)
+/* Data:
sse3
+ sse2
+ avx512vbmi
+
+
+
+
+
+
ssse3
+
+
+ fma
+ cmpxchg16b
+
+
+
+
+
sse4.1
sse4.2
+
+ movbe
+ popcnt
+
+ aes
+
+
avx
- avx2
+ f16c
+ rdrand
+
+
+
+
+ bmi
hle
+ avx2
+
+
+ bmi2
+
+
rtm
- dsp
- dspr2
- */
-// begin generated
+
+
+
+ avx512f
+ avx512dq
+ rdseed
+
+
+ avx512ifma
+
+
+
+
+ avx512pf
+ avx512er
+ avx512cd
+ sha
+ avx512bw
+ avx512vl
+ */
static const char features_string[] =
- "\0"
- " neon\0"
- " sse2\0"
" sse3\0"
+ " sse2\0"
+ " avx512vbmi\0"
" ssse3\0"
+ " fma\0"
+ " cmpxchg16b\0"
" sse4.1\0"
" sse4.2\0"
+ " movbe\0"
+ " popcnt\0"
+ " aes\0"
" avx\0"
- " avx2\0"
+ " f16c\0"
+ " rdrand\0"
+ " bmi\0"
" hle\0"
+ " avx2\0"
+ " bmi2\0"
" rtm\0"
- " dsp\0"
- " dspr2\0"
+ " avx512f\0"
+ " avx512dq\0"
+ " rdseed\0"
+ " avx512ifma\0"
+ " avx512pf\0"
+ " avx512er\0"
+ " avx512cd\0"
+ " sha\0"
+ " avx512bw\0"
+ " avx512vl\0"
"\0";
-static const int features_indices[] = {
- 0, 1, 7, 13, 19, 26, 34, 42,
- 47, 53, 58, 63, 68, -1
+static const quint8 features_indices[] = {
+ 0, 6, 12, 5, 5, 5, 5, 5,
+ 5, 24, 5, 5, 31, 36, 5, 5,
+ 5, 5, 5, 48, 56, 5, 64, 71,
+ 5, 79, 5, 5, 84, 89, 95, 5,
+ 5, 5, 5, 103, 108, 113, 5, 5,
+ 119, 5, 5, 125, 5, 5, 5, 5,
+ 130, 139, 149, 5, 5, 157, 5, 5,
+ 5, 5, 169, 179, 189, 199, 204, 214
};
+#else
+static const char features_string[] = "";
+static const int features_indices[] = { };
+#endif
// end generated
-static const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]);
+static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]);
// record what CPU features were enabled by default in this Qt build
-static const uint minFeature = qCompilerCpuFeatures;
+static const quint64 minFeature = qCompilerCpuFeatures;
#ifdef Q_OS_WIN
#if defined(Q_CC_GNU)
-# define ffs __builtin_ffs
+# define ffsll __builtin_ffsll
#else
-int ffs(int i)
+int ffsll(quint64 i)
{
-#ifndef Q_OS_WINCE
+#if defined(Q_OS_WIN64)
unsigned long result;
- return _BitScanForward(&result, i) ? result : 0;
+ return _BitScanForward64(&result, i) ? result : 0;
+#elif !defined(Q_OS_WINCE)
+ unsigned long result;
+ return _BitScanForward(&result, i) ? result :
+ _BitScanForward(&result, i >> 32) ? result + 32 : 0;
#else
return 0;
#endif
}
#endif
-#elif defined(Q_OS_ANDROID)
-# define ffs __builtin_ffs
+#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX)
+# define ffsll __builtin_ffsll
#endif
-QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0);
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) };
+#else
+Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };
+#endif
void qDetectCpuFeatures()
{
@@ -545,17 +666,17 @@ void qDetectCpuFeatures()
// contains all the features that the code required. Qt 4 ran for years
// like that, so it shouldn't be a problem.
- qt_cpu_features.store(minFeature | QSimdInitialized);
+ qt_cpu_features.store(minFeature | quint32(QSimdInitialized));
return;
# endif
#endif
- uint f = detectProcessorFeatures();
+ quint64 f = detectProcessorFeatures();
QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
if (!disable.isEmpty()) {
disable.prepend(' ');
for (int i = 0; i < features_count; ++i) {
if (disable.contains(features_string + features_indices[i]))
- f &= ~(1 << i);
+ f &= ~(Q_UINT64_C(1) << i);
}
}
@@ -565,29 +686,32 @@ void qDetectCpuFeatures()
bool runningOnValgrind = false;
#endif
if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) {
- uint missing = minFeature & ~f;
+ quint64 missing = minFeature & ~f;
fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n ");
for (int i = 0; i < features_count; ++i) {
- if (missing & (1 << i))
+ if (missing & (Q_UINT64_C(1) << i))
fprintf(stderr, "%s", features_string + features_indices[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
- qFatal("Aborted. Incompatible processor: missing feature 0x%x -%s.", missing,
- features_string + features_indices[ffs(missing) - 1]);
+ qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing,
+ features_string + features_indices[ffsll(missing) - 1]);
}
- qt_cpu_features.store(f | QSimdInitialized);
+ qt_cpu_features[0].store(f | quint32(QSimdInitialized));
+#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
+ qt_cpu_features[1].store(f >> 32);
+#endif
}
void qDumpCPUFeatures()
{
- uint features = qCpuFeatures();
+ quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized);
printf("Processor features: ");
for (int i = 0; i < features_count; ++i) {
- if (features & (1 << i))
+ if (features & (Q_UINT64_C(1) << i))
printf("%s%s", features_string + features_indices[i],
- minFeature & (1 << i) ? "[required]" : "");
+ minFeature & (Q_UINT64_C(1) << i) ? "[required]" : "");
}
puts("");
}
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index dd93b4fd26..1e8b3420cf 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -149,7 +149,7 @@
# define QT_FUNCTION_TARGET(x)
# endif
#else
-# define QT_COMPILER_SUPPORTS_HERE(x) defined(__ ## x ## __)
+# define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __)
# define QT_FUNCTION_TARGET(x)
#endif
@@ -217,6 +217,23 @@
# endif
#endif
+#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f"
+#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd"
+#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er"
+#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf"
+#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw"
+#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq"
+#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl"
+#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma"
+#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi"
+
+#define QT_FUNCTION_TARGET_STRING_F16C "f16c"
+#define QT_FUNCTION_TARGET_STRING_RDRAND "rdrnd"
+#define QT_FUNCTION_TARGET_STRING_BMI "bmi"
+#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2"
+#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
+#define QT_FUNCTION_TARGET_STRING_SHA "sha"
+
// other x86 intrinsics
#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \
|| (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \
@@ -244,74 +261,170 @@ QT_BEGIN_NAMESPACE
enum CPUFeatures {
- NEON = 0x2, ARM_NEON = NEON,
- SSE2 = 0x4,
- SSE3 = 0x8,
- SSSE3 = 0x10,
- SSE4_1 = 0x20,
- SSE4_2 = 0x40,
- AVX = 0x80,
- AVX2 = 0x100,
- HLE = 0x200,
- RTM = 0x400,
- DSP = 0x800,
- DSPR2 = 0x1000,
+#if defined(Q_PROCESSOR_ARM)
+ CpuFeatureNEON = 0,
+ CpuFeatureARM_NEON = CpuFeatureNEON,
+#elif defined(Q_PROCESSOR_MIPS)
+ CpuFeatureDSP = 0,
+ CpuFeatureDSPR2 = 1,
+#elif defined(Q_PROCESSOR_X86)
+ // The order of the flags is jumbled so it matches most closely the bits in CPUID
+ // Out of order:
+ CpuFeatureSSE2 = 1, // uses the bit for PCLMULQDQ
+ // in level 1, ECX
+ CpuFeatureSSE3 = (0 + 0),
+ CpuFeatureSSSE3 = (0 + 9),
+ CpuFeatureSSE4_1 = (0 + 19),
+ CpuFeatureSSE4_2 = (0 + 20),
+ CpuFeatureMOVBE = (0 + 22),
+ CpuFeaturePOPCNT = (0 + 23),
+ CpuFeatureAES = (0 + 25),
+ CpuFeatureAVX = (0 + 28),
+ CpuFeatureF16C = (0 + 29),
+ CpuFeatureRDRAND = (0 + 30),
+ // 31 is always zero and we've used it for the QSimdInitialized
+
+ // in level 7, leaf 0, EBX
+ CpuFeatureBMI = (32 + 3),
+ CpuFeatureHLE = (32 + 4),
+ CpuFeatureAVX2 = (32 + 5),
+ CpuFeatureBMI2 = (32 + 8),
+ CpuFeatureRTM = (32 + 11),
+ CpuFeatureAVX512F = (32 + 16),
+ CpuFeatureAVX512DQ = (32 + 17),
+ CpuFeatureRDSEED = (32 + 18),
+ CpuFeatureAVX512IFMA = (32 + 21),
+ CpuFeatureAVX512PF = (32 + 26),
+ CpuFeatureAVX512ER = (32 + 27),
+ CpuFeatureAVX512CD = (32 + 28),
+ CpuFeatureSHA = (32 + 29),
+ CpuFeatureAVX512BW = (32 + 30),
+ CpuFeatureAVX512VL = (32 + 31),
+
+ // in level 7, leaf 0, ECX (out of order, for now)
+ CpuFeatureAVX512VBMI = 2, // uses the bit for DTES64
+#endif
// used only to indicate that the CPU detection was initialised
QSimdInitialized = 0x80000000
};
-static const uint qCompilerCpuFeatures = 0
+static const quint64 qCompilerCpuFeatures = 0
+#if defined __SHA__
+ | (Q_UINT64_C(1) << CpuFeatureSHA)
+#endif
+#if defined __AES__
+ | (Q_UINT64_C(1) << CpuFeatureAES)
+#endif
#if defined __RTM__
- | RTM
+ | (Q_UINT64_C(1) << CpuFeatureRTM)
+#endif
+#ifdef __RDRND__
+ | (Q_UINT64_C(1) << CpuFeatureRDRAND)
+#endif
+#ifdef __RDSEED__
+ | (Q_UINT64_C(1) << CpuFeatureRDSEED)
+#endif
+#if defined __BMI__
+ | (Q_UINT64_C(1) << CpuFeatureBMI)
+#endif
+#if defined __BMI2__
+ | (Q_UINT64_C(1) << CpuFeatureBMI2)
+#endif
+#if defined __F16C__
+ | (Q_UINT64_C(1) << CpuFeatureF16C)
+#endif
+#if defined __POPCNT__
+ | (Q_UINT64_C(1) << CpuFeaturePOPCNT)
+#endif
+#if defined __MOVBE__ // GCC and Clang don't seem to define this
+ | (Q_UINT64_C(1) << CpuFeatureMOVBE)
+#endif
+#if defined __AVX512F__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512F)
+#endif
+#if defined __AVX512CD__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512CD)
+#endif
+#if defined __AVX512ER__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512ER)
+#endif
+#if defined __AVX512PF__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512PF)
+#endif
+#if defined __AVX512BW__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512BW)
+#endif
+#if defined __AVX512DQ__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512DQ)
+#endif
+#if defined __AVX512VL__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512VL)
+#endif
+#if defined __AVX512IFMA__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA)
+#endif
+#if defined __AVX512VBMI__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI)
#endif
#if defined __AVX2__
- | AVX2
+ | (Q_UINT64_C(1) << CpuFeatureAVX2)
#endif
#if defined __AVX__
- | AVX
+ | (Q_UINT64_C(1) << CpuFeatureAVX)
#endif
#if defined __SSE4_2__
- | SSE4_2
+ | (Q_UINT64_C(1) << CpuFeatureSSE4_2)
#endif
#if defined __SSE4_1__
- | SSE4_1
+ | (Q_UINT64_C(1) << CpuFeatureSSE4_1)
#endif
#if defined __SSSE3__
- | SSSE3
+ | (Q_UINT64_C(1) << CpuFeatureSSSE3)
#endif
#if defined __SSE3__
- | SSE3
+ | (Q_UINT64_C(1) << CpuFeatureSSE3)
#endif
#if defined __SSE2__
- | SSE2
+ | (Q_UINT64_C(1) << CpuFeatureSSE2)
#endif
#if defined __ARM_NEON__
- | NEON
+ | (Q_UINT64_C(1) << CpuFeatureNEON)
#endif
#if defined __mips_dsp
- | DSP
+ | (Q_UINT64_C(1) << CpuFeatureDSP)
#endif
#if defined __mips_dspr2
- | DSPR2
+ | (Q_UINT64_C(1) << CpuFeatureDSPR2)
#endif
;
-extern Q_CORE_EXPORT QBasicAtomicInt qt_cpu_features;
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1];
+#else
+extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2];
+#endif
Q_CORE_EXPORT void qDetectCpuFeatures();
-static inline uint qCpuFeatures()
+static inline quint64 qCpuFeatures()
{
- int features = qt_cpu_features.load();
+ quint64 features = qt_cpu_features[0].load();
+#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
+ features |= quint64(qt_cpu_features[1].load()) << 32;
+#endif
if (Q_UNLIKELY(features == 0)) {
qDetectCpuFeatures();
- features = qt_cpu_features.load();
+ features = qt_cpu_features[0].load();
+#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
+ features |= quint64(qt_cpu_features[1].load()) << 32;
+#endif
Q_ASSUME(features != 0);
}
- return uint(features);
+ return features;
}
-#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature)))
+#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (Q_UINT64_C(1) << CpuFeature ## feature)) \
+ || (qCpuFeatures() & (Q_UINT64_C(1) << CpuFeature ## feature)))
#ifdef Q_PROCESSOR_X86
// Bit scan functions for x86
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..cb72316c32 100644
--- a/src/corelib/tools/qstack.h
+++ b/src/corelib/tools/qstack.h
@@ -43,9 +43,8 @@ template<class T>
class QStack : public QVector<T>
{
public:
- inline QStack() {}
- inline ~QStack() {}
- inline void swap(QStack<T> &other) { QVector<T>::swap(other); } // prevent QVector<->QStack swaps
+ // compiler-generated special member functions are fine!
+ inline void swap(QStack<T> &other) Q_DECL_NOTHROW { QVector<T>::swap(other); } // prevent QVector<->QStack swaps
inline void push(const T &t) { QVector<T>::append(t); }
T pop();
T &top();
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index b623c62043..39e0f6825e 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()
@@ -1448,7 +1509,7 @@ QString::QString(const QChar *unicode, int size)
} else {
if (size < 0) {
size = 0;
- while (unicode[size] != 0)
+ while (!unicode[size].isNull())
++size;
}
if (!size) {
@@ -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.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
- Returns the number of occurrences of character \a ch in the string.
+ \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 &section = 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 &reg, 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()]);
+ }
+ 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;
}
- result += uc[i++];
}
+
return result;
}
@@ -8024,14 +8222,25 @@ QString &QString::setRawData(const QChar *unicode, int size)
\snippet code/src_corelib_tools_qstring.cpp 6
+ \note If the function you're calling with a QLatin1String
+ argument isn't actually overloaded to take QLatin1String, the
+ implicit conversion to QString will trigger a memory allocation,
+ which is usually what you want to avoid by using QLatin1String
+ in the first place. In those cases, using QStringLiteral may be
+ the better option.
+
\sa QString, QLatin1Char, {QStringLiteral()}{QStringLiteral}
*/
+/*! \fn QLatin1String::QLatin1String()
+ \since 5.6
+
+ Constructs a QLatin1String object that stores a nullptr.
+*/
+
/*! \fn QLatin1String::QLatin1String(const char *str)
- Constructs a QLatin1String object that stores \a str. Note that if
- \a str is 0, an empty string is created; this case is handled by
- QString.
+ Constructs a QLatin1String object that stores \a str.
The string data is \e not copied. The caller must be able to
guarantee that \a str will not be deleted or modified as long as
@@ -8043,8 +8252,6 @@ QString &QString::setRawData(const QChar *unicode, int size)
/*! \fn QLatin1String::QLatin1String(const char *str, int size)
Constructs a QLatin1String object that stores \a str with \a size.
- Note that if \a str is 0, an empty string is created; this case
- is handled by QString.
The string data is \e not copied. The caller must be able to
guarantee that \a str will not be deleted or modified as long as
@@ -9125,8 +9332,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 +9350,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 +9371,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 +9389,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 +9475,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 d44a5baf2a..d21708efb9 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
@@ -82,20 +83,21 @@ template <typename T> class QVector;
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 const char *latin1() const { return m_data; }
- inline int size() const { return m_size; }
- inline const char *data() const { return m_data; }
-
- inline bool operator==(const QString &s) const;
- inline bool operator!=(const QString &s) const;
- inline bool operator>(const QString &s) const;
- inline bool operator<(const QString &s) const;
- inline bool operator>=(const QString &s) const;
- inline bool operator<=(const QString &s) const;
+ Q_DECL_CONSTEXPR inline QLatin1String() Q_DECL_NOTHROW : m_size(0), m_data(Q_NULLPTR) {}
+ Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) Q_DECL_NOTHROW : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
+ Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) Q_DECL_NOTHROW : m_size(sz), m_data(s) {}
+ inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(s.size()), m_data(s.constData()) {}
+
+ Q_DECL_CONSTEXPR const char *latin1() const Q_DECL_NOTHROW { return m_data; }
+ Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; }
+ Q_DECL_CONSTEXPR const char *data() const Q_DECL_NOTHROW { return m_data; }
+
+ inline bool operator==(const QString &s) const Q_DECL_NOTHROW;
+ inline bool operator!=(const QString &s) const Q_DECL_NOTHROW;
+ inline bool operator>(const QString &s) const Q_DECL_NOTHROW;
+ inline bool operator<(const QString &s) const Q_DECL_NOTHROW;
+ inline bool operator>=(const QString &s) const Q_DECL_NOTHROW;
+ inline bool operator<=(const QString &s) const Q_DECL_NOTHROW;
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
inline QT_ASCII_CAST_WARN bool operator==(const char *s) const;
@@ -420,6 +422,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 +430,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 +539,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 +596,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 +655,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 +673,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 +717,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;
@@ -1114,34 +1131,34 @@ inline bool operator!=(QString::Null, QString::Null) { return false; }
inline bool operator!=(QString::Null, const QString &s) { return !s.isNull(); }
inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); }
-inline bool operator==(QLatin1String s1, QLatin1String s2)
+inline bool operator==(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
{ return (s1.size() == s2.size() && !memcmp(s1.latin1(), s2.latin1(), s1.size())); }
-inline bool operator!=(QLatin1String s1, QLatin1String s2)
+inline bool operator!=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
{ return (s1.size() != s2.size() || memcmp(s1.latin1(), s2.latin1(), s1.size())); }
-inline bool operator<(QLatin1String s1, QLatin1String s2)
+inline bool operator<(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size()));
return (r < 0) || (r == 0 && s1.size() < s2.size()); }
-inline bool operator<=(QLatin1String s1, QLatin1String s2)
+inline bool operator<=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size()));
return (r < 0) || (r == 0 && s1.size() <= s2.size()); }
-inline bool operator>(QLatin1String s1, QLatin1String s2)
+inline bool operator>(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size()));
return (r > 0) || (r == 0 && s1.size() > s2.size()); }
-inline bool operator>=(QLatin1String s1, QLatin1String s2)
+inline bool operator>=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size()));
return (r > 0) || (r == 0 && s1.size() >= s2.size()); }
-inline bool QLatin1String::operator==(const QString &s) const
+inline bool QLatin1String::operator==(const QString &s) const Q_DECL_NOTHROW
{ return s == *this; }
-inline bool QLatin1String::operator!=(const QString &s) const
+inline bool QLatin1String::operator!=(const QString &s) const Q_DECL_NOTHROW
{ return s != *this; }
-inline bool QLatin1String::operator>(const QString &s) const
+inline bool QLatin1String::operator>(const QString &s) const Q_DECL_NOTHROW
{ return s < *this; }
-inline bool QLatin1String::operator<(const QString &s) const
+inline bool QLatin1String::operator<(const QString &s) const Q_DECL_NOTHROW
{ return s > *this; }
-inline bool QLatin1String::operator>=(const QString &s) const
+inline bool QLatin1String::operator>=(const QString &s) const Q_DECL_NOTHROW
{ return s <= *this; }
-inline bool QLatin1String::operator<=(const QString &s) const
+inline bool QLatin1String::operator<=(const QString &s) const Q_DECL_NOTHROW
{ return s >= *this; }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
@@ -1211,30 +1228,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 +1360,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 +1413,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 +1448,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 +1484,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 +1599,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/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 1dbc005bca..3d41aeee18 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -421,7 +421,7 @@ QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
a.reserve(len);
QChar *it = a.data() + a.size();
QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
- a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
+ a.resize(int(it - a.constData())); //may be smaller than len if there was conversion from utf8
return a;
}
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..f432820252 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
@@ -192,10 +202,21 @@ QT_BEGIN_NAMESPACE
Returns an equivalent version number but with all trailing zeros removed.
To check if two numbers are equivalent, use normalized() on both version
- numbers before perforing the compare.
+ numbers before performing the compare.
\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 \