diff options
Diffstat (limited to 'src/corelib/tools')
36 files changed, 1852 insertions, 899 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 98c484c1dd..dc419c3758 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -85,8 +85,20 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, headerSize += (alignment - Q_ALIGNOF(QArrayData)); // Allocate additional space if array is growing - if (options & Grow) - capacity = qAllocMore(int(objectSize * capacity), int(headerSize)) / int(objectSize); + if (options & Grow) { + + // Guard against integer overflow when multiplying. + if (capacity > std::numeric_limits<size_t>::max() / objectSize) + return 0; + + size_t alloc = objectSize * capacity; + + // Make sure qAllocMore won't overflow. + if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize) + return 0; + + capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize); + } size_t allocSize = headerSize + objectSize * capacity; @@ -118,7 +130,8 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize, return; #endif - Q_ASSERT_X(!data->ref.isStatic(), "QArrayData::deallocate", "Static data can not be deleted"); + Q_ASSERT_X(data == 0 || !data->ref.isStatic(), "QArrayData::deallocate", + "Static data can not be deleted"); ::free(data); } diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index f2cd3ec983..aef38bc20b 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -169,8 +169,10 @@ public: private: Data *clone(QArrayData::AllocationOptions options) const Q_REQUIRED_RESULT { - QArrayDataPointer copy(Data::allocate(d->detachCapacity(d->size), - options)); + Data *x = Data::allocate(d->detachCapacity(d->size), options); + Q_CHECK_PTR(x); + QArrayDataPointer copy(x); + if (d->size) copy->copyAppend(d->begin(), d->end()); diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 6ac442d27b..92c2188caa 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Intel Corporation. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -38,6 +39,7 @@ #include "qlist.h" #include "qlocale.h" #include "qlocale_p.h" +#include "qstringalgorithms_p.h" #include "qscopedpointer.h" #include <qdatastream.h> #include <qmath.h> @@ -54,6 +56,64 @@ QT_BEGIN_NAMESPACE +// Latin 1 case system, used by QByteArray::to{Upper,Lower}() and qstr(n)icmp(): +/* +#!/usr/bin/perl -l +use feature "unicode_strings"; +for (0..255) { + $up = uc(chr($_)); + $up = chr($_) if ord($up) > 0x100 || length $up > 1; + printf "0x%02x,", ord($up); + print "" if ($_ & 0xf) == 0xf; +} +*/ +static const uchar latin1_uppercased[256] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, + 0x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x7b,0x7c,0x7d,0x7e,0x7f, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, + 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, + 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, + 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, + 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, + 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, + 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xf7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xff +}; + +/* +#!/usr/bin/perl -l +use feature "unicode_strings"; +for (0..255) { + $up = lc(chr($_)); + $up = chr($_) if ord($up) > 0x100 || length $up > 1; + printf "0x%02x,", ord($up); + print "" if ($_ & 0xf) == 0xf; +} +*/ +static const uchar latin1_lowercased[256] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, + 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, + 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, + 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xd7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xdf, + 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff +}; int qFindByteArray( const char *haystack0, int haystackLen, int from, @@ -63,7 +123,7 @@ int qFindByteArray( int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW { Q_ASSERT(alloc >= 0 && extra >= 0); - Q_ASSERT_X(alloc < (1 << 30) - extra, "qAllocMore", "Requested size is too large!"); + Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!"); unsigned nalloc = qNextPowerOfTwo(alloc + extra); @@ -248,7 +308,7 @@ int qstricmp(const char *str1, const char *str2) uchar c; if (!s1 || !s2) return s1 ? 1 : (s2 ? -1 : 0); - for (; !(res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)); s1++, s2++) + for (; !(res = (c = latin1_lowercased[*s1]) - latin1_lowercased[*s2]); s1++, s2++) if (!c) // strings are equal break; return res; @@ -283,7 +343,7 @@ int qstrnicmp(const char *str1, const char *str2, uint len) if (!s1 || !s2) return s1 ? 1 : (s2 ? -1 : 0); for (; len--; s1++, s2++) { - if ((res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2))) + if ((res = (c = latin1_lowercased[*s1]) - latin1_lowercased[*s2])) return res; if (!c) // strings are equal break; @@ -1485,8 +1545,11 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { - if (options & Data::Grow) + if (options & Data::Grow) { + if (alloc > uint(MaxAllocSize) - uint(sizeof(Data))) + qBadAlloc(); alloc = qAllocMore(alloc, sizeof(Data)); + } Data *x = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc)); Q_CHECK_PTR(x); x->alloc = alloc; @@ -2677,6 +2740,8 @@ QByteArray QByteArray::mid(int pos, int len) const } /*! + \fn QByteArray QByteArray::toLower() const + Returns a lowercase copy of the byte array. The bytearray is interpreted as a Latin-1 encoded string. @@ -2685,21 +2750,56 @@ QByteArray QByteArray::mid(int pos, int len) const \sa toUpper(), {8-bit Character Comparisons} */ -QByteArray QByteArray::toLower() const + +// noinline so that the compiler won't inline the function in each of +// toLower and toUpper when the only difference is the table being used +// (even with constant propagation, there's no gain in performance). +template <typename T> +#ifdef Q_CC_MSVC +__declspec(noinline) +#elif defined(Q_CC_GNU) +__attribute__((noinline)) +#endif +static QByteArray toCase_template(T &input, const uchar * table) { - QByteArray s(*this); - uchar *p = reinterpret_cast<uchar *>(s.data()); - uchar *e = reinterpret_cast<uchar *>(s.end()); - if (p) { - while (p != e) { - *p = QChar::toLower((ushort)*p); - p++; - } + // find the first bad character in input + const char *orig_begin = input.constBegin(); + const char *firstBad = orig_begin; + const char *e = input.constEnd(); + for ( ; firstBad != e ; ++firstBad) { + uchar ch = uchar(*firstBad); + uchar converted = table[ch]; + if (ch != converted) + break; + } + + if (firstBad == e) + return qMove(input); + + // transform the rest + QByteArray s = qMove(input); // will copy if T is const QByteArray + char *b = s.begin(); // will detach if necessary + char *p = b + (firstBad - orig_begin); + e = b + s.size(); + for ( ; p != e; ++p) { + *p = char(uchar(table[uchar(*p)])); } return s; } +QByteArray QByteArray::toLower_helper(const QByteArray &a) +{ + return toCase_template(a, latin1_lowercased); +} + +QByteArray QByteArray::toLower_helper(QByteArray &a) +{ + return toCase_template(a, latin1_lowercased); +} + /*! + \fn QByteArray QByteArray::toUpper() const + Returns an uppercase copy of the byte array. The bytearray is interpreted as a Latin-1 encoded string. @@ -2709,18 +2809,14 @@ QByteArray QByteArray::toLower() const \sa toLower(), {8-bit Character Comparisons} */ -QByteArray QByteArray::toUpper() const +QByteArray QByteArray::toUpper_helper(const QByteArray &a) { - QByteArray s(*this); - uchar *p = reinterpret_cast<uchar *>(s.data()); - uchar *e = reinterpret_cast<uchar *>(s.end()); - if (p) { - while (p != e) { - *p = QChar::toUpper((ushort)*p); - p++; - } - } - return s; + return toCase_template(a, latin1_uppercased); +} + +QByteArray QByteArray::toUpper_helper(QByteArray &a) +{ + return toCase_template(a, latin1_uppercased); } /*! \fn void QByteArray::clear() @@ -3100,6 +3196,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba) */ /*! + \fn QByteArray QByteArray::simplified() const + Returns a byte array that has whitespace removed from the start and the end, and which has each sequence of internal whitespace replaced with a single space. @@ -3114,32 +3212,19 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba) \sa trimmed() */ -QByteArray QByteArray::simplified() const +QByteArray QByteArray::simplified_helper(const QByteArray &a) { - if (d->size == 0) - return *this; - QByteArray result(d->size, Qt::Uninitialized); - const char *from = d->data(); - const char *fromend = from + d->size; - int outc=0; - char *to = result.d->data(); - for (;;) { - while (from!=fromend && ascii_isspace(uchar(*from))) - from++; - while (from!=fromend && !ascii_isspace(uchar(*from))) - to[outc++] = *from++; - if (from!=fromend) - to[outc++] = ' '; - else - break; - } - if (outc > 0 && to[outc-1] == ' ') - outc--; - result.resize(outc); - return result; + return QStringAlgorithms<const QByteArray>::simplified_helper(a); +} + +QByteArray QByteArray::simplified_helper(QByteArray &a) +{ + return QStringAlgorithms<QByteArray>::simplified_helper(a); } /*! + \fn QByteArray QByteArray::trimmed() const + Returns a byte array that has whitespace removed from the start and the end. @@ -3154,29 +3239,17 @@ QByteArray QByteArray::simplified() const \sa simplified() */ -QByteArray QByteArray::trimmed() const +QByteArray QByteArray::trimmed_helper(const QByteArray &a) { - if (d->size == 0) - return *this; - const char *s = d->data(); - if (!ascii_isspace(uchar(*s)) && !ascii_isspace(uchar(s[d->size-1]))) - return *this; - int start = 0; - int end = d->size - 1; - while (start<=end && ascii_isspace(uchar(s[start]))) // skip white space from start - start++; - if (start <= end) { // only white space - while (end && ascii_isspace(uchar(s[end]))) // skip white space from end - end--; - } - int l = end - start + 1; - if (l <= 0) { - QByteArrayDataPtr empty = { Data::allocate(0) }; - return QByteArray(empty); - } - return QByteArray(s+start, l); + return QStringAlgorithms<const QByteArray>::trimmed_helper(a); +} + +QByteArray QByteArray::trimmed_helper(QByteArray &a) +{ + return QStringAlgorithms<QByteArray>::trimmed_helper(a); } + /*! Returns a byte array of size \a width that contains this byte array padded by the \a fill character. @@ -4052,15 +4125,9 @@ QByteArray QByteArray::fromHex(const QByteArray &hexEncoded) bool odd_digit = true; for (int i = hexEncoded.size() - 1; i >= 0; --i) { - int ch = hexEncoded.at(i); - int tmp; - if (ch >= '0' && ch <= '9') - tmp = ch - '0'; - else if (ch >= 'a' && ch <= 'f') - tmp = ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'F') - tmp = ch - 'A' + 10; - else + uchar ch = uchar(hexEncoded.at(i)); + int tmp = QtMiscUtils::fromHex(ch); + if (tmp == -1) continue; if (odd_digit) { --result; @@ -4088,16 +4155,8 @@ QByteArray QByteArray::toHex() const char *hexData = hex.data(); const uchar *data = (const uchar *)d->data(); for (int i = 0; i < d->size; ++i) { - int j = (data[i] >> 4) & 0xf; - if (j <= 9) - hexData[i*2] = (j + '0'); - else - hexData[i*2] = (j + 'a' - 10); - j = data[i] & 0xf; - if (j <= 9) - hexData[i*2+1] = (j + '0'); - else - hexData[i*2+1] = (j + 'a' - 10); + hexData[i*2] = QtMiscUtils::toHexLower(data[i] >> 4); + hexData[i*2+1] = QtMiscUtils::toHexLower(data[i] & 0xf); } return hex; } @@ -4292,12 +4351,6 @@ static inline bool q_strchr(const char str[], char chr) return false; } -static inline char toHexHelper(char c) -{ - static const char hexnumbers[] = "0123456789ABCDEF"; - return hexnumbers[c & 0xf]; -} - static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const char *alsoEncode, char percent) { if (ba->isEmpty()) @@ -4330,8 +4383,8 @@ static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const ch output = ba->data(); } output[length++] = percent; - output[length++] = toHexHelper((c & 0xf0) >> 4); - output[length++] = toHexHelper(c & 0xf); + output[length++] = QtMiscUtils::toHexUpper((c & 0xf0) >> 4); + output[length++] = QtMiscUtils::toHexUpper(c & 0xf); } } if (output) diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index f13b1c16cd..6976124bca 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -256,11 +256,40 @@ public: void truncate(int pos); void chop(int n); +#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) +# 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 + QByteArray toLower() const & Q_REQUIRED_RESULT + { return toLower_helper(*this); } + QByteArray toLower() && Q_REQUIRED_RESULT + { return toLower_helper(*this); } + QByteArray toUpper() const & Q_REQUIRED_RESULT + { return toUpper_helper(*this); } + QByteArray toUpper() && Q_REQUIRED_RESULT + { return toUpper_helper(*this); } + QByteArray trimmed() const & Q_REQUIRED_RESULT + { return trimmed_helper(*this); } + QByteArray trimmed() && Q_REQUIRED_RESULT + { return trimmed_helper(*this); } + QByteArray simplified() const & Q_REQUIRED_RESULT + { return simplified_helper(*this); } + QByteArray simplified() && Q_REQUIRED_RESULT + { return simplified_helper(*this); } +# ifdef Q_REQUIRED_RESULT_pushed +# pragma pop_macro("Q_REQUIRED_RESULT") +# endif +#else QByteArray toLower() const Q_REQUIRED_RESULT; QByteArray toUpper() const Q_REQUIRED_RESULT; - QByteArray trimmed() const Q_REQUIRED_RESULT; QByteArray simplified() const Q_REQUIRED_RESULT; +#endif + QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const Q_REQUIRED_RESULT; QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const Q_REQUIRED_RESULT; @@ -414,6 +443,15 @@ private: void expand(int i); QByteArray nulTerminated() const; + static QByteArray toLower_helper(const QByteArray &a); + static QByteArray toLower_helper(QByteArray &a); + static QByteArray toUpper_helper(const QByteArray &a); + static QByteArray toUpper_helper(QByteArray &a); + static QByteArray trimmed_helper(const QByteArray &a); + static QByteArray trimmed_helper(QByteArray &a); + static QByteArray simplified_helper(const QByteArray &a); + static QByteArray simplified_helper(QByteArray &a); + friend class QByteRef; friend class QString; friend Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes); diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index 4db09e0f82..547c1ffda2 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -83,8 +83,10 @@ public: #ifndef QT_NO_CAST_FROM_ASCII QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) : ucs(uchar(c)) { } +#ifndef QT_RESTRICTED_CAST_FROM_ASCII QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(uchar c) : ucs(c) { } #endif +#endif // Unicode information enum Category @@ -377,68 +379,77 @@ public: inline UnicodeVersion unicodeVersion() const { return QChar::unicodeVersion(ucs); } #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline char toAscii() const { return toLatin1(); } + QT_DEPRECATED Q_DECL_CONSTEXPR inline char toAscii() const { return toLatin1(); } #endif - inline char toLatin1() const; + Q_DECL_CONSTEXPR inline char toLatin1() const; Q_DECL_CONSTEXPR inline ushort unicode() const { return ucs; } inline ushort &unicode() { return ucs; } #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED static inline QChar fromAscii(char c) + QT_DEPRECATED static Q_DECL_CONSTEXPR inline QChar fromAscii(char c) { return fromLatin1(c); } #endif - static inline QChar fromLatin1(char c); + Q_DECL_CONSTEXPR static inline QChar fromLatin1(char c); - inline bool isNull() const { return ucs == 0; } + Q_DECL_CONSTEXPR inline bool isNull() const { return ucs == 0; } inline bool isPrint() const { return QChar::isPrint(ucs); } - inline bool isSpace() const { return QChar::isSpace(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); } - inline bool isLetter() const { return QChar::isLetter(ucs); } - inline bool isNumber() const { return QChar::isNumber(ucs); } - inline bool isLetterOrNumber() const { return QChar::isLetterOrNumber(ucs); } - inline bool isDigit() const { return QChar::isDigit(ucs); } - inline bool isLower() const { return QChar::isLower(ucs); } - inline bool isUpper() const { return QChar::isUpper(ucs); } - inline bool isTitleCase() const { return QChar::isTitleCase(ucs); } - - inline bool isNonCharacter() const { return QChar::isNonCharacter(ucs); } - inline bool isHighSurrogate() const { return QChar::isHighSurrogate(ucs); } - inline bool isLowSurrogate() const { return QChar::isLowSurrogate(ucs); } - inline bool isSurrogate() const { return QChar::isSurrogate(ucs); } - - inline uchar cell() const { return uchar(ucs & 0xff); } - inline uchar row() const { return uchar((ucs>>8)&0xff); } + 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 inline bool isNonCharacter(uint ucs4) { + static Q_DECL_CONSTEXPR inline bool isNonCharacter(uint ucs4) + { return ucs4 >= 0xfdd0 && (ucs4 <= 0xfdef || (ucs4 & 0xfffe) == 0xfffe); } - static inline bool isHighSurrogate(uint ucs4) { + static Q_DECL_CONSTEXPR inline bool isHighSurrogate(uint ucs4) + { return ((ucs4 & 0xfffffc00) == 0xd800); } - static inline bool isLowSurrogate(uint ucs4) { + static Q_DECL_CONSTEXPR inline bool isLowSurrogate(uint ucs4) + { return ((ucs4 & 0xfffffc00) == 0xdc00); } - static inline bool isSurrogate(uint ucs4) { + static Q_DECL_CONSTEXPR inline bool isSurrogate(uint ucs4) + { return (ucs4 - 0xd800u < 2048u); } - static inline bool requiresSurrogates(uint ucs4) { + static Q_DECL_CONSTEXPR inline bool requiresSurrogates(uint ucs4) + { return (ucs4 >= 0x10000); } - static inline uint surrogateToUcs4(ushort high, ushort low) { + static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(ushort high, ushort low) + { return (uint(high)<<10) + low - 0x35fdc00; } - static inline uint surrogateToUcs4(QChar high, QChar low) { - return surrogateToUcs4(high.unicode(), low.unicode()); + static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(QChar high, QChar low) + { + return surrogateToUcs4(high.ucs, low.ucs); } - static inline ushort highSurrogate(uint ucs4) { + static Q_DECL_CONSTEXPR inline ushort highSurrogate(uint ucs4) + { return ushort((ucs4>>10) + 0xd7c0); } - static inline ushort lowSurrogate(uint ucs4) { + static Q_DECL_CONSTEXPR inline ushort lowSurrogate(uint ucs4) + { return ushort(ucs4%0x400 + 0xdc00); } @@ -469,17 +480,17 @@ public: static UnicodeVersion QT_FASTCALL currentUnicodeVersion() Q_DECL_CONST_FUNCTION; static bool QT_FASTCALL isPrint(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isSpace(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 inline bool isLetter(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isNumber(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isLetterOrNumber(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isDigit(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isLower(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isUpper(uint ucs4) Q_DECL_CONST_FUNCTION; - static inline bool isTitleCase(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; private: static bool QT_FASTCALL isSpace_helper(uint ucs4) Q_DECL_CONST_FUNCTION; @@ -491,53 +502,57 @@ private: QChar(char c); QChar(uchar c); #endif + + friend Q_DECL_CONSTEXPR bool operator==(QChar, QChar); + friend Q_DECL_CONSTEXPR bool operator< (QChar, QChar); ushort ucs; }; Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE); -inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } -inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); } +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)); } -inline bool QChar::isSpace(uint ucs4) +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))); } -inline bool QChar::isLetter(uint 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)); } -inline bool QChar::isNumber(uint ucs4) +Q_DECL_CONSTEXPR inline bool QChar::isNumber(uint ucs4) { return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::isNumber_helper(ucs4)); } -inline bool QChar::isLetterOrNumber(uint 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)); } -inline bool QChar::isDigit(uint ucs4) +Q_DECL_CONSTEXPR inline bool QChar::isDigit(uint ucs4) { return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::category(ucs4) == Number_DecimalDigit); } -inline bool QChar::isLower(uint ucs4) +Q_DECL_CONSTEXPR inline bool QChar::isLower(uint ucs4) { return (ucs4 <= 'z' && ucs4 >= 'a') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Lowercase); } -inline bool QChar::isUpper(uint ucs4) +Q_DECL_CONSTEXPR inline bool QChar::isUpper(uint ucs4) { return (ucs4 <= 'Z' && ucs4 >= 'A') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Uppercase); } -inline bool QChar::isTitleCase(uint ucs4) +Q_DECL_CONSTEXPR inline bool QChar::isTitleCase(uint ucs4) { return ucs4 > 127 && QChar::category(ucs4) == Letter_Titlecase; } -inline bool operator==(QChar c1, QChar c2) { return c1.unicode() == c2.unicode(); } -inline bool operator!=(QChar c1, QChar c2) { return c1.unicode() != c2.unicode(); } -inline bool operator<=(QChar c1, QChar c2) { return c1.unicode() <= c2.unicode(); } -inline bool operator>=(QChar c1, QChar c2) { return c1.unicode() >= c2.unicode(); } -inline bool operator<(QChar c1, QChar c2) { return c1.unicode() < c2.unicode(); } -inline bool operator>(QChar c1, QChar c2) { return c1.unicode() > c2.unicode(); } +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) { return !operator==(c1, c2); } +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< (c2, c1); } +Q_DECL_CONSTEXPR inline bool operator<=(QChar c1, QChar c2) { return !operator< (c2, c1); } #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QChar); diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 01772b2ad5..117ce381f1 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -37,6 +37,10 @@ #include <qcoreapplication.h> #include <qhash.h> #include <qvector.h> +#include <qdebug.h> +#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +# include <qt_windows.h> +#endif #include <stdio.h> #include <stdlib.h> @@ -209,7 +213,10 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const platforms. These applications may not use the standard output or error channels since the output is either discarded or not accessible. - For such GUI applications, it is recommended to display help texts and error messages + On Windows, QCommandLineParser uses message boxes to display usage information + and errors if no console window can be obtained. + + For other platforms, it is recommended to display help texts and error messages using a QMessageBox. To preserve the formatting of the help text, rich text with \c <pre> elements should be used: @@ -219,36 +226,20 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const case CommandLineOk: break; case CommandLineError: -#ifdef Q_OS_WIN QMessageBox::warning(0, QGuiApplication::applicationDisplayName(), "<html><head/><body><h2>" + errorMessage + "</h2><pre>" + parser.helpText() + "</pre></body></html>"); -#else - fputs(qPrintable(errorMessage), stderr); - fputs("\n\n", stderr); - fputs(qPrintable(parser.helpText()), stderr); -#endif return 1; case CommandLineVersionRequested: -#ifdef Q_OS_WIN QMessageBox::information(0, QGuiApplication::applicationDisplayName(), QGuiApplication::applicationDisplayName() + ' ' + QCoreApplication::applicationVersion()); -#else - printf("%s %s\n", QGuiApplication::applicationDisplayName(), - qPrintable(QCoreApplication::applicationVersion())); -#endif return 0; case CommandLineHelpRequested: -#ifdef Q_OS_WIN QMessageBox::warning(0, QGuiApplication::applicationDisplayName(), "<html><head/><body><pre>" + parser.helpText() + "</pre></body></html>"); return 0; -#else - parser.showHelp(); - Q_UNREACHABLE(); -#endif } \endcode @@ -491,6 +482,41 @@ QString QCommandLineParser::errorText() const return QString(); } +enum MessageType { UsageMessage, ErrorMessage }; + +#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +// Return whether to use a message box. Use handles if a console can be obtained +// or we are run with redirected handles (for example, by QProcess). +static inline bool displayMessageBox() +{ + if (GetConsoleWindow()) + return false; + STARTUPINFO startupInfo; + startupInfo.cb = sizeof(STARTUPINFO); + GetStartupInfo(&startupInfo); + return !(startupInfo.dwFlags & STARTF_USESTDHANDLES); +} +#endif // Q_OS_WIN && !QT_BOOTSTRAPPED && !Q_OS_WIN && !Q_OS_WINRT + +static void showParserMessage(const QString &message, MessageType type) +{ +#if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) + if (displayMessageBox()) { + const UINT flags = MB_OK | MB_TOPMOST | MB_SETFOREGROUND + | (type == UsageMessage ? MB_ICONINFORMATION : MB_ICONERROR); + QString title; + if (QCoreApplication::instance()) + title = QCoreApplication::instance()->property("applicationDisplayName").toString(); + if (title.isEmpty()) + title = QCoreApplication::applicationName(); + MessageBoxW(0, reinterpret_cast<const wchar_t *>(message.utf16()), + reinterpret_cast<const wchar_t *>(title.utf16()), flags); + return; + } +#endif // Q_OS_WIN && !QT_BOOTSTRAPPED && !Q_OS_WIN && !Q_OS_WINRT + fputs(qPrintable(message), type == UsageMessage ? stdout : stderr); +} + /*! Processes the command line \a arguments. @@ -507,7 +533,7 @@ QString QCommandLineParser::errorText() const void QCommandLineParser::process(const QStringList &arguments) { if (!d->parse(arguments)) { - fprintf(stderr, "%s\n", qPrintable(errorText())); + showParserMessage(errorText() + QLatin1Char('\n'), ErrorMessage); ::exit(EXIT_FAILURE); } @@ -913,7 +939,9 @@ QStringList QCommandLineParser::unknownOptionNames() const */ Q_NORETURN void QCommandLineParser::showVersion() { - fprintf(stdout, "%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion())); + showParserMessage(QCoreApplication::applicationName() + QLatin1Char(' ') + + QCoreApplication::applicationVersion() + QLatin1Char('\n'), + UsageMessage); ::exit(EXIT_SUCCESS); } @@ -930,7 +958,7 @@ Q_NORETURN void QCommandLineParser::showVersion() */ Q_NORETURN void QCommandLineParser::showHelp(int exitCode) { - fprintf(stdout, "%s", qPrintable(d->helpText())); + showParserMessage(d->helpText(), UsageMessage); ::exit(exitCode); } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index f0f6a56755..69d4bd7d99 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -249,7 +249,7 @@ static QString toOffsetString(Qt::DateFormat format, int offset) } // Parse offset in [+-]HH[:]MM format -static int fromOffsetString(const QString &offsetString, bool *valid) +static int fromOffsetString(const QStringRef &offsetString, bool *valid) { *valid = false; @@ -270,15 +270,15 @@ static int fromOffsetString(const QString &offsetString, bool *valid) return 0; // Split the hour and minute parts - QStringList parts = offsetString.mid(1).split(QLatin1Char(':')); + QVector<QStringRef> parts = offsetString.mid(1).split(QLatin1Char(':')); if (parts.count() == 1) { // [+-]HHMM format - parts.append(parts.at(0).mid(2)); - parts[0] = parts.at(0).left(2); + parts.append(parts.first().mid(2)); + parts[0] = parts.first().left(2); } bool ok = false; - const int hour = parts.at(0).toInt(&ok); + const int hour = parts.first().toInt(&ok); if (!ok) return 0; @@ -898,18 +898,18 @@ QString QDate::toString(Qt::DateFormat format) const #ifndef QT_NO_TEXTDATE case Qt::TextDate: getDateFromJulianDay(jd, &y, &m, &d); - return QString::fromUtf8("%1 %2 %3 %4").arg(shortDayName(dayOfWeek())) - .arg(shortMonthName(m)) - .arg(d) - .arg(y); + return QString::fromLatin1("%1 %2 %3 %4").arg(shortDayName(dayOfWeek())) + .arg(shortMonthName(m)) + .arg(d) + .arg(y); #endif case Qt::ISODate: getDateFromJulianDay(jd, &y, &m, &d); if (y < 0 || y > 9999) return QString(); - return QString::fromUtf8("%1-%2-%3").arg(y, 4, 10, QLatin1Char('0')) - .arg(m, 2, 10, QLatin1Char('0')) - .arg(d, 2, 10, QLatin1Char('0')); + return QString::fromLatin1("%1-%2-%3").arg(y, 4, 10, QLatin1Char('0')) + .arg(m, 2, 10, QLatin1Char('0')) + .arg(d, 2, 10, QLatin1Char('0')); } } @@ -1247,12 +1247,12 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format) default: #ifndef QT_NO_TEXTDATE case Qt::TextDate: { - QStringList parts = string.split(QLatin1Char(' '), QString::SkipEmptyParts); + QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts); if (parts.count() != 4) return QDate(); - QString monthName = parts.at(1); + QStringRef monthName = parts.at(1); int month = -1; // Assume that English monthnames are the default for (int i = 0; i < 12; ++i) { @@ -1288,10 +1288,10 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format) || (string.size() > 10 && string.at(10).isDigit())) { return QDate(); } - const int year = string.mid(0, 4).toInt(); + const int year = string.midRef(0, 4).toInt(); if (year <= 0 || year > 9999) return QDate(); - return QDate(year, string.mid(5, 2).toInt(), string.mid(8, 2).toInt()); + return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt()); } } return QDate(); @@ -1649,9 +1649,9 @@ QString QTime::toString(Qt::DateFormat format) const case Qt::ISODate: case Qt::TextDate: default: - return QString::fromUtf8("%1:%2:%3").arg(hour(), 2, 10, QLatin1Char('0')) - .arg(minute(), 2, 10, QLatin1Char('0')) - .arg(second(), 2, 10, QLatin1Char('0')); + return QString::fromLatin1("%1:%2:%3").arg(hour(), 2, 10, QLatin1Char('0')) + .arg(minute(), 2, 10, QLatin1Char('0')) + .arg(second(), 2, 10, QLatin1Char('0')); } } @@ -3596,11 +3596,11 @@ QString QDateTime::toString(Qt::DateFormat format) const QTime tm; d->getDateTime(&dt, &tm); //We cant use date.toString(Qt::TextDate) as we need to insert the time before the year - buf = QString::fromUtf8("%1 %2 %3 %4 %5").arg(dt.shortDayName(dt.dayOfWeek())) - .arg(dt.shortMonthName(dt.month())) - .arg(dt.day()) - .arg(tm.toString(Qt::TextDate)) - .arg(dt.year()); + buf = QString::fromLatin1("%1 %2 %3 %4 %5").arg(dt.shortDayName(dt.dayOfWeek())) + .arg(dt.shortMonthName(dt.month())) + .arg(dt.day()) + .arg(tm.toString(Qt::TextDate)) + .arg(dt.year()); if (timeSpec() != Qt::LocalTime) { buf += QStringLiteral(" GMT"); if (d->m_spec == Qt::OffsetFromUTC) @@ -4197,6 +4197,39 @@ qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW #error "What system is this?" #endif +/*! \fn QDateTime QDateTime::fromCFDate(CFDateRef date) + \since 5.5 + + Constructs a new QDateTime containing a copy of the CFDate \a date. + + \sa toCFDate() +*/ + +/*! \fn CFDateRef QDateTime::toCFDate() const + \since 5.5 + + Creates a CFDate from a QDateTime. The caller owns the CFDate object + and is responsible for releasing it. + + \sa fromCFDate() +*/ + +/*! \fn QDateTime QDateTime::fromNSDate(const NSDate *date) + \since 5.5 + + Constructs a new QDateTime containing a copy of the NSDate \a date. + + \sa toNSDate() +*/ + +/*! \fn NSDate QDateTime::toNSDate() const + \since 5.5 + + Creates an NSDate from a QDateTime. The NSDate object is autoreleased. + + \sa fromNSDate() +*/ + /*! \since 4.2 @@ -4351,7 +4384,7 @@ int QDateTime::utcOffset() const #ifndef QT_NO_DATESTRING -static int fromShortMonthName(const QString &monthName) +static int fromShortMonthName(const QStringRef &monthName) { // Assume that English monthnames are the default for (int i = 0; i < 12; ++i) { @@ -4443,7 +4476,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (found) { bool ok; - offset = fromOffsetString(isoString.mid(signIndex).toString(), &ok); + offset = fromOffsetString(isoString.mid(signIndex), &ok); if (!ok) return QDateTime(); isoString = isoString.left(signIndex); @@ -4463,7 +4496,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) } #if !defined(QT_NO_TEXTDATE) case Qt::TextDate: { - QStringList parts = string.split(QLatin1Char(' '), QString::SkipEmptyParts); + QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts); if ((parts.count() < 5) || (parts.count() > 6)) return QDateTime(); @@ -4482,9 +4515,9 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (!month || !day) { month = fromShortMonthName(parts.at(2)); if (month) { - QString dayStr = parts.at(1); + QStringRef dayStr = parts.at(1); if (dayStr.endsWith(QLatin1Char('.'))) { - dayStr.chop(1); + dayStr = dayStr.left(dayStr.size() - 1); day = dayStr.toInt(); } } @@ -4517,7 +4550,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (!date.isValid()) return QDateTime(); - QStringList timeParts = parts.at(timePart).split(QLatin1Char(':')); + QVector<QStringRef> timeParts = parts.at(timePart).split(QLatin1Char(':')); if (timeParts.count() < 2 || timeParts.count() > 3) return QDateTime(); @@ -4532,7 +4565,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) int second = 0; int millisecond = 0; if (timeParts.count() > 2) { - QStringList secondParts = timeParts.at(2).split(QLatin1Char('.')); + QVector<QStringRef> secondParts = timeParts.at(2).split(QLatin1Char('.')); if (secondParts.size() > 2) { return QDateTime(); } @@ -4557,10 +4590,10 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (parts.count() == 5) return QDateTime(date, time, Qt::LocalTime); - QString tz = parts.at(5); + QStringRef tz = parts.at(5); if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive)) return QDateTime(); - tz.remove(0, 3); + tz = tz.mid(3); if (!tz.isEmpty()) { int offset = fromOffsetString(tz, &ok); if (!ok) @@ -4987,7 +5020,7 @@ QDebug operator<<(QDebug dbg, const QDateTime &date) spec = QStringLiteral(" Qt::UTC"); break; case Qt::OffsetFromUTC: - spec = QString::fromUtf8(" Qt::OffsetFromUTC %1s").arg(date.offsetFromUtc()); + spec = QString::fromLatin1(" Qt::OffsetFromUTC %1s").arg(date.offsetFromUtc()); break; case Qt::TimeZone: #ifndef QT_BOOTSTRAPPED diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index a75d7d9bc8..5bcd01a587 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -40,6 +40,13 @@ #include <limits> +#ifdef Q_OS_MAC +Q_FORWARD_DECLARE_CF_TYPE(CFDate); +# ifdef __OBJC__ +Q_FORWARD_DECLARE_OBJC_CLASS(NSDate); +# endif +#endif + QT_BEGIN_NAMESPACE class QTimeZone; @@ -296,6 +303,15 @@ public: #endif static qint64 currentMSecsSinceEpoch() Q_DECL_NOTHROW; +#if defined(Q_OS_MAC) || defined(Q_QDOC) + static QDateTime fromCFDate(CFDateRef date); + CFDateRef toCFDate() const Q_DECL_CF_RETURNS_RETAINED; +# if defined(__OBJC__) || defined(Q_QDOC) + static QDateTime fromNSDate(const NSDate *date); + NSDate *toNSDate() const Q_DECL_NS_RETURNS_AUTORELEASED; +# endif +#endif + private: friend class QDateTimePrivate; void detach(); diff --git a/src/corelib/tools/qdatetime_mac.mm b/src/corelib/tools/qdatetime_mac.mm new file mode 100644 index 0000000000..c8a1d22928 --- /dev/null +++ b/src/corelib/tools/qdatetime_mac.mm @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Petroules Corporation. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdatetime.h" + +#import <Foundation/Foundation.h> + +QT_BEGIN_NAMESPACE + +QDateTime QDateTime::fromCFDate(CFDateRef date) +{ + if (!date) + return QDateTime(); + return QDateTime::fromMSecsSinceEpoch(static_cast<qint64>((CFDateGetAbsoluteTime(date) + + kCFAbsoluteTimeIntervalSince1970) * 1000)); +} + +CFDateRef QDateTime::toCFDate() const +{ + return CFDateCreate(kCFAllocatorDefault, (static_cast<CFAbsoluteTime>(toMSecsSinceEpoch()) + / 1000) - kCFAbsoluteTimeIntervalSince1970); +} + +QDateTime QDateTime::fromNSDate(const NSDate *date) +{ + if (!date) + return QDateTime(); + return QDateTime::fromMSecsSinceEpoch(static_cast<qint64>([date timeIntervalSince1970] * 1000)); +} + +NSDate *QDateTime::toNSDate() const +{ + return [NSDate + dateWithTimeIntervalSince1970:static_cast<NSTimeInterval>(toMSecsSinceEpoch()) / 1000]; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index 78484f30ed..7c7f7f2a6a 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -111,6 +111,9 @@ public: m_status(other.m_status) {} + // ### XXX: when the tooling situation improves, look at fixing the padding. + // 4 bytes padding + qint64 m_msecs; Qt::TimeSpec m_spec; int m_offsetFromUtc; diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index a3dd4d9a60..e6fb531d7d 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -347,9 +347,7 @@ typedef QVector<TCBPoint> TCBPoints; class QEasingCurveFunction { public: - enum Type { In, Out, InOut, OutIn }; - - QEasingCurveFunction(QEasingCurveFunction::Type type = In, qreal period = 0.3, qreal amplitude = 1.0, + QEasingCurveFunction(QEasingCurve::Type type, qreal period = 0.3, qreal amplitude = 1.0, qreal overshoot = 1.70158) : _t(type), _p(period), _a(amplitude), _o(overshoot) { } @@ -358,7 +356,7 @@ public: virtual QEasingCurveFunction *copy() const; bool operator==(const QEasingCurveFunction &other) const; - Type _t; + QEasingCurve::Type _t; qreal _p; qreal _a; qreal _o; @@ -367,9 +365,12 @@ public: }; +static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve); + qreal QEasingCurveFunction::value(qreal t) { - return t; + QEasingCurve::EasingFunction func = curveToFunc(_t); + return func(t); } QEasingCurveFunction *QEasingCurveFunction::copy() const @@ -430,8 +431,8 @@ struct BezierEase : public QEasingCurveFunction bool _init; bool _valid; - BezierEase() - : QEasingCurveFunction(InOut), _curves(10), _intervals(10), _init(false), _valid(false) + BezierEase(QEasingCurve::Type type = QEasingCurve::BezierSpline) + : QEasingCurveFunction(type), _curves(10), _intervals(10), _init(false), _valid(false) { } void init() @@ -488,7 +489,7 @@ struct BezierEase : public QEasingCurveFunction } } - QEasingCurveFunction *copy() const + QEasingCurveFunction *copy() const Q_DECL_OVERRIDE { BezierEase *rv = new BezierEase(); rv->_t = _t; @@ -524,7 +525,7 @@ struct BezierEase : public QEasingCurveFunction return newT; } - qreal value(qreal x) + qreal value(qreal x) Q_DECL_OVERRIDE { Q_ASSERT(_bezierCurves.count() % 3 == 0); @@ -814,7 +815,11 @@ struct BezierEase : public QEasingCurveFunction struct TCBEase : public BezierEase { - qreal value(qreal x) + TCBEase() + : BezierEase(QEasingCurve::TCBSpline) + { } + + qreal value(qreal x) Q_DECL_OVERRIDE { Q_ASSERT(_bezierCurves.count() % 3 == 0); @@ -830,11 +835,11 @@ struct TCBEase : public BezierEase struct ElasticEase : public QEasingCurveFunction { - ElasticEase(Type type) + ElasticEase(QEasingCurve::Type type) : QEasingCurveFunction(type, qreal(0.3), qreal(1.0)) { } - QEasingCurveFunction *copy() const + QEasingCurveFunction *copy() const Q_DECL_OVERRIDE { ElasticEase *rv = new ElasticEase(_t); rv->_p = _p; @@ -844,18 +849,18 @@ struct ElasticEase : public QEasingCurveFunction return rv; } - qreal value(qreal t) + qreal value(qreal t) Q_DECL_OVERRIDE { qreal p = (_p < 0) ? qreal(0.3) : _p; qreal a = (_a < 0) ? qreal(1.0) : _a; switch(_t) { - case In: + case QEasingCurve::InElastic: return easeInElastic(t, a, p); - case Out: + case QEasingCurve::OutElastic: return easeOutElastic(t, a, p); - case InOut: + case QEasingCurve::InOutElastic: return easeInOutElastic(t, a, p); - case OutIn: + case QEasingCurve::OutInElastic: return easeOutInElastic(t, a, p); default: return t; @@ -865,11 +870,11 @@ struct ElasticEase : public QEasingCurveFunction struct BounceEase : public QEasingCurveFunction { - BounceEase(Type type) + BounceEase(QEasingCurve::Type type) : QEasingCurveFunction(type, qreal(0.3), qreal(1.0)) { } - QEasingCurveFunction *copy() const + QEasingCurveFunction *copy() const Q_DECL_OVERRIDE { BounceEase *rv = new BounceEase(_t); rv->_a = _a; @@ -878,17 +883,17 @@ struct BounceEase : public QEasingCurveFunction return rv; } - qreal value(qreal t) + qreal value(qreal t) Q_DECL_OVERRIDE { qreal a = (_a < 0) ? qreal(1.0) : _a; switch(_t) { - case In: + case QEasingCurve::InBounce: return easeInBounce(t, a); - case Out: + case QEasingCurve::OutBounce: return easeOutBounce(t, a); - case InOut: + case QEasingCurve::InOutBounce: return easeInOutBounce(t, a); - case OutIn: + case QEasingCurve::OutInBounce: return easeOutInBounce(t, a); default: return t; @@ -898,11 +903,11 @@ struct BounceEase : public QEasingCurveFunction struct BackEase : public QEasingCurveFunction { - BackEase(Type type) + BackEase(QEasingCurve::Type type) : QEasingCurveFunction(type, qreal(0.3), qreal(1.0), qreal(1.70158)) { } - QEasingCurveFunction *copy() const + QEasingCurveFunction *copy() const Q_DECL_OVERRIDE { BackEase *rv = new BackEase(_t); rv->_o = _o; @@ -911,17 +916,17 @@ struct BackEase : public QEasingCurveFunction return rv; } - qreal value(qreal t) + qreal value(qreal t) Q_DECL_OVERRIDE { qreal o = (_o < 0) ? qreal(1.70158) : _o; switch(_t) { - case In: + case QEasingCurve::InBack: return easeInBack(t, o); - case Out: + case QEasingCurve::OutBack: return easeOutBack(t, o); - case InOut: + case QEasingCurve::InOutBack: return easeInOutBack(t, o); - case OutIn: + case QEasingCurve::OutInBack: return easeOutInBack(t, o); default: return t; @@ -1006,55 +1011,31 @@ static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve) static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type) { - QEasingCurveFunction *curveFunc = 0; switch(type) { case QEasingCurve::InElastic: - curveFunc = new ElasticEase(ElasticEase::In); - break; case QEasingCurve::OutElastic: - curveFunc = new ElasticEase(ElasticEase::Out); - break; case QEasingCurve::InOutElastic: - curveFunc = new ElasticEase(ElasticEase::InOut); - break; case QEasingCurve::OutInElastic: - curveFunc = new ElasticEase(ElasticEase::OutIn); - break; + return new ElasticEase(type); case QEasingCurve::OutBounce: - curveFunc = new BounceEase(BounceEase::Out); - break; case QEasingCurve::InBounce: - curveFunc = new BounceEase(BounceEase::In); - break; case QEasingCurve::OutInBounce: - curveFunc = new BounceEase(BounceEase::OutIn); - break; case QEasingCurve::InOutBounce: - curveFunc = new BounceEase(BounceEase::InOut); - break; + return new BounceEase(type); case QEasingCurve::InBack: - curveFunc = new BackEase(BackEase::In); - break; case QEasingCurve::OutBack: - curveFunc = new BackEase(BackEase::Out); - break; case QEasingCurve::InOutBack: - curveFunc = new BackEase(BackEase::InOut); - break; case QEasingCurve::OutInBack: - curveFunc = new BackEase(BackEase::OutIn); - break; + return new BackEase(type); case QEasingCurve::BezierSpline: - curveFunc = new BezierEase(); - break; + return new BezierEase; case QEasingCurve::TCBSpline: - curveFunc = new TCBEase(); - break; + return new TCBEase; default: - curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, qreal(0.3), qreal(1.0), qreal(1.70158)); + return new QEasingCurveFunction(type, qreal(0.3), qreal(1.0), qreal(1.70158)); } - return curveFunc; + return 0; } /*! diff --git a/src/corelib/tools/qelapsedtimer_unix.cpp b/src/corelib/tools/qelapsedtimer_unix.cpp index 9dd5df0266..61bd7f1f21 100644 --- a/src/corelib/tools/qelapsedtimer_unix.cpp +++ b/src/corelib/tools/qelapsedtimer_unix.cpp @@ -155,11 +155,6 @@ static int unixCheckClockType() #endif } -static inline qint64 fractionAdjustment() -{ - return 1000*1000ull; -} - bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW { return clockType() == MonotonicClock; @@ -211,7 +206,7 @@ static qint64 elapsedAndRestart(qint64 sec, qint64 frac, do_gettime(nowsec, nowfrac); sec = *nowsec - sec; frac = *nowfrac - frac; - return sec * Q_INT64_C(1000) + frac / fractionAdjustment(); + return (sec * Q_INT64_C(1000000000) + frac) / Q_INT64_C(1000000); } void QElapsedTimer::start() Q_DECL_NOTHROW @@ -235,20 +230,19 @@ qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW { - qint64 sec, frac; - return elapsedAndRestart(t1, t2, &sec, &frac); + return nsecsElapsed() / Q_INT64_C(1000000); } qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW { - return t1 * Q_INT64_C(1000) + t2 / fractionAdjustment(); + return t1 * Q_INT64_C(1000) + t2 / Q_INT64_C(1000000); } qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW { qint64 secs = other.t1 - t1; qint64 fraction = other.t2 - t2; - return secs * Q_INT64_C(1000) + fraction / fractionAdjustment(); + return (secs * Q_INT64_C(1000000000) + fraction) / Q_INT64_C(1000000); } qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index fe8c52d103..0f741a2f7e 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -259,9 +259,7 @@ static uint qt_create_qhash_seed() quintptr seedPtr = reinterpret_cast<quintptr>(&seed); seed ^= seedPtr; -#if QT_POINTER_SIZE == 8 - seed ^= (seedPtr >> 32); -#endif + seed ^= (qulonglong(seedPtr) >> 32); // no-op on 32-bit platforms #endif // QT_BOOTSTRAPPED return seed; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index fe5e0f33b4..b91fd38a5f 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -55,6 +55,8 @@ const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0 static int grow(int size) { + if (size_t(size) > (MaxAllocSize - QListData::DataHeaderSize) / sizeof(void *)) + qBadAlloc(); // dear compiler: don't optimize me out. volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *); return x; diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index e33be9a2f1..533f1d6dbc 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -628,9 +628,7 @@ inline void QList<T>::swap(int i, int j) Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), "QList<T>::swap", "index out of range"); detach(); - void *t = d->array[d->begin + i]; - d->array[d->begin + i] = d->array[d->begin + j]; - d->array[d->begin + j] = t; + std::swap(d->array[d->begin + i], d->array[d->begin + j]); } template <typename T> @@ -773,11 +771,10 @@ Q_OUTOFLINE_TEMPLATE bool QList<T>::operator==(const QList<T> &l) const return true; if (p.size() != l.p.size()) return false; - Node *i = reinterpret_cast<Node *>(p.end()); - Node *b = reinterpret_cast<Node *>(p.begin()); - Node *li = reinterpret_cast<Node *>(l.p.end()); - while (i != b) { - --i; --li; + Node *i = reinterpret_cast<Node *>(p.begin()); + Node *e = reinterpret_cast<Node *>(p.end()); + Node *li = reinterpret_cast<Node *>(l.p.begin()); + for (; i != e; ++i, ++li) { if (!(i->t() == li->t())) return false; } @@ -925,9 +922,9 @@ Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const template <typename T> Q_OUTOFLINE_TEMPLATE bool QList<T>::contains(const T &t) const { - Node *b = reinterpret_cast<Node *>(p.begin()); - Node *i = reinterpret_cast<Node *>(p.end()); - while (i-- != b) + Node *e = reinterpret_cast<Node *>(p.end()); + Node *i = reinterpret_cast<Node *>(p.begin()); + for (; i != e; ++i) if (i->t() == t) return true; return false; @@ -937,9 +934,9 @@ template <typename T> Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const { int c = 0; - Node *b = reinterpret_cast<Node *>(p.begin()); - Node *i = reinterpret_cast<Node *>(p.end()); - while (i-- != b) + Node *e = reinterpret_cast<Node *>(p.end()); + Node *i = reinterpret_cast<Node *>(p.begin()); + for (; i != e; ++i) if (i->t() == t) ++c; return c; diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h index 33a2766345..400f0f76df 100644 --- a/src/corelib/tools/qmargins.h +++ b/src/corelib/tools/qmargins.h @@ -55,19 +55,19 @@ public: Q_DECL_CONSTEXPR int right() const; Q_DECL_CONSTEXPR int bottom() const; - void setLeft(int left); - void setTop(int top); - void setRight(int right); - void setBottom(int bottom); - - QMargins &operator+=(const QMargins &margins); - QMargins &operator-=(const QMargins &margins); - QMargins &operator+=(int); - QMargins &operator-=(int); - QMargins &operator*=(int); - QMargins &operator/=(int); - QMargins &operator*=(qreal); - QMargins &operator/=(qreal); + Q_DECL_RELAXED_CONSTEXPR void setLeft(int left); + Q_DECL_RELAXED_CONSTEXPR void setTop(int top); + Q_DECL_RELAXED_CONSTEXPR void setRight(int right); + Q_DECL_RELAXED_CONSTEXPR void setBottom(int bottom); + + Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(const QMargins &margins); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(const QMargins &margins); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(int); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(int); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(int); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator/=(int); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(qreal); + Q_DECL_RELAXED_CONSTEXPR QMargins &operator/=(qreal); private: int m_left; @@ -114,16 +114,16 @@ Q_DECL_CONSTEXPR inline int QMargins::bottom() const { return m_bottom; } -inline void QMargins::setLeft(int aleft) +Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setLeft(int aleft) { m_left = aleft; } -inline void QMargins::setTop(int atop) +Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setTop(int atop) { m_top = atop; } -inline void QMargins::setRight(int aright) +Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setRight(int aright) { m_right = aright; } -inline void QMargins::setBottom(int abottom) +Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setBottom(int abottom) { m_bottom = abottom; } Q_DECL_CONSTEXPR inline bool operator==(const QMargins &m1, const QMargins &m2) @@ -210,17 +210,17 @@ Q_DECL_CONSTEXPR inline QMargins operator/(const QMargins &margins, qreal diviso qRound(margins.right() / divisor), qRound(margins.bottom() / divisor)); } -inline QMargins &QMargins::operator+=(const QMargins &margins) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(const QMargins &margins) { return *this = *this + margins; } -inline QMargins &QMargins::operator-=(const QMargins &margins) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(const QMargins &margins) { return *this = *this - margins; } -inline QMargins &QMargins::operator+=(int margin) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(int margin) { m_left += margin; m_top += margin; @@ -229,7 +229,7 @@ inline QMargins &QMargins::operator+=(int margin) return *this; } -inline QMargins &QMargins::operator-=(int margin) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(int margin) { m_left -= margin; m_top -= margin; @@ -238,22 +238,22 @@ inline QMargins &QMargins::operator-=(int margin) return *this; } -inline QMargins &QMargins::operator*=(int factor) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(int factor) { return *this = *this * factor; } -inline QMargins &QMargins::operator/=(int divisor) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator/=(int divisor) { return *this = *this / divisor; } -inline QMargins &QMargins::operator*=(qreal factor) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(qreal factor) { return *this = *this * factor; } -inline QMargins &QMargins::operator/=(qreal divisor) +Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator/=(qreal divisor) { return *this = *this / divisor; } @@ -290,17 +290,17 @@ public: Q_DECL_CONSTEXPR qreal right() const; Q_DECL_CONSTEXPR qreal bottom() const; - void setLeft(qreal left); - void setTop(qreal top); - void setRight(qreal right); - void setBottom(qreal bottom); + Q_DECL_RELAXED_CONSTEXPR void setLeft(qreal left); + Q_DECL_RELAXED_CONSTEXPR void setTop(qreal top); + Q_DECL_RELAXED_CONSTEXPR void setRight(qreal right); + Q_DECL_RELAXED_CONSTEXPR void setBottom(qreal bottom); - QMarginsF &operator+=(const QMarginsF &margins); - QMarginsF &operator-=(const QMarginsF &margins); - QMarginsF &operator+=(qreal addend); - QMarginsF &operator-=(qreal subtrahend); - QMarginsF &operator*=(qreal factor); - QMarginsF &operator/=(qreal divisor); + Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(const QMarginsF &margins); + Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(const QMarginsF &margins); + Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(qreal addend); + Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(qreal subtrahend); + Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator*=(qreal factor); + Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator/=(qreal divisor); Q_DECL_CONSTEXPR inline QMargins toMargins() const; @@ -350,16 +350,16 @@ Q_DECL_CONSTEXPR inline qreal QMarginsF::bottom() const { return m_bottom; } -inline void QMarginsF::setLeft(qreal aleft) +Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setLeft(qreal aleft) { m_left = aleft; } -inline void QMarginsF::setTop(qreal atop) +Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setTop(qreal atop) { m_top = atop; } -inline void QMarginsF::setRight(qreal aright) +Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setRight(qreal aright) { m_right = aright; } -inline void QMarginsF::setBottom(qreal abottom) +Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setBottom(qreal abottom) { m_bottom = abottom; } Q_DECL_CONSTEXPR inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) @@ -423,17 +423,17 @@ Q_DECL_CONSTEXPR inline QMarginsF operator/(const QMarginsF &lhs, qreal divisor) lhs.right() / divisor, lhs.bottom() / divisor); } -inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) +Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) { return *this = *this + margins; } -inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) +Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) { return *this = *this - margins; } -inline QMarginsF &QMarginsF::operator+=(qreal addend) +Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(qreal addend) { m_left += addend; m_top += addend; @@ -442,7 +442,7 @@ inline QMarginsF &QMarginsF::operator+=(qreal addend) return *this; } -inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) +Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) { m_left -= subtrahend; m_top -= subtrahend; @@ -451,12 +451,12 @@ inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) return *this; } -inline QMarginsF &QMarginsF::operator*=(qreal factor) +Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator*=(qreal factor) { return *this = *this * factor; } -inline QMarginsF &QMarginsF::operator/=(qreal divisor) +Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator/=(qreal divisor) { return *this = *this / divisor; } diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index b2217e4dd0..ae33d598d4 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -52,13 +52,13 @@ struct QPair template <typename TT1, typename TT2> Q_DECL_CONSTEXPR QPair(const QPair<TT1, TT2> &p) : first(p.first), second(p.second) {} template <typename TT1, typename TT2> - QPair &operator=(const QPair<TT1, TT2> &p) + Q_DECL_RELAXED_CONSTEXPR QPair &operator=(const QPair<TT1, TT2> &p) { first = p.first; second = p.second; return *this; } #ifdef Q_COMPILER_RVALUE_REFS template <typename TT1, typename TT2> Q_DECL_CONSTEXPR QPair(QPair<TT1, TT2> &&p) : first(std::move(p.first)), second(std::move(p.second)) {} template <typename TT1, typename TT2> - QPair &operator=(QPair<TT1, TT2> &&p) + Q_DECL_RELAXED_CONSTEXPR QPair &operator=(QPair<TT1, TT2> &&p) { first = std::move(p.first); second = std::move(p.second); return *this; } #endif diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h index 5cf97b9052..70474b6d59 100644 --- a/src/corelib/tools/qpoint.h +++ b/src/corelib/tools/qpoint.h @@ -49,22 +49,22 @@ public: Q_DECL_CONSTEXPR inline int x() const; Q_DECL_CONSTEXPR inline int y() const; - inline void setX(int x); - inline void setY(int y); + Q_DECL_RELAXED_CONSTEXPR inline void setX(int x); + Q_DECL_RELAXED_CONSTEXPR inline void setY(int y); Q_DECL_CONSTEXPR inline int manhattanLength() const; - inline int &rx(); - inline int &ry(); + Q_DECL_RELAXED_CONSTEXPR inline int &rx(); + Q_DECL_RELAXED_CONSTEXPR inline int &ry(); - inline QPoint &operator+=(const QPoint &p); - inline QPoint &operator-=(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline QPoint &operator+=(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline QPoint &operator-=(const QPoint &p); - inline QPoint &operator*=(float factor); - inline QPoint &operator*=(double factor); - inline QPoint &operator*=(int factor); + Q_DECL_RELAXED_CONSTEXPR inline QPoint &operator*=(float factor); + Q_DECL_RELAXED_CONSTEXPR inline QPoint &operator*=(double factor); + Q_DECL_RELAXED_CONSTEXPR inline QPoint &operator*=(int factor); - inline QPoint &operator/=(qreal divisor); + Q_DECL_RELAXED_CONSTEXPR inline QPoint &operator/=(qreal divisor); Q_DECL_CONSTEXPR static inline int dotProduct(const QPoint &p1, const QPoint &p2) { return p1.xp * p2.xp + p1.yp * p2.yp; } @@ -116,34 +116,34 @@ Q_DECL_CONSTEXPR inline int QPoint::x() const Q_DECL_CONSTEXPR inline int QPoint::y() const { return yp; } -inline void QPoint::setX(int xpos) +Q_DECL_RELAXED_CONSTEXPR inline void QPoint::setX(int xpos) { xp = xpos; } -inline void QPoint::setY(int ypos) +Q_DECL_RELAXED_CONSTEXPR inline void QPoint::setY(int ypos) { yp = ypos; } inline int Q_DECL_CONSTEXPR QPoint::manhattanLength() const { return qAbs(x())+qAbs(y()); } -inline int &QPoint::rx() +Q_DECL_RELAXED_CONSTEXPR inline int &QPoint::rx() { return xp; } -inline int &QPoint::ry() +Q_DECL_RELAXED_CONSTEXPR inline int &QPoint::ry() { return yp; } -inline QPoint &QPoint::operator+=(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline QPoint &QPoint::operator+=(const QPoint &p) { xp+=p.xp; yp+=p.yp; return *this; } -inline QPoint &QPoint::operator-=(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline QPoint &QPoint::operator-=(const QPoint &p) { xp-=p.xp; yp-=p.yp; return *this; } -inline QPoint &QPoint::operator*=(float factor) +Q_DECL_RELAXED_CONSTEXPR inline QPoint &QPoint::operator*=(float factor) { xp = qRound(xp*factor); yp = qRound(yp*factor); return *this; } -inline QPoint &QPoint::operator*=(double factor) +Q_DECL_RELAXED_CONSTEXPR inline QPoint &QPoint::operator*=(double factor) { xp = qRound(xp*factor); yp = qRound(yp*factor); return *this; } -inline QPoint &QPoint::operator*=(int factor) +Q_DECL_RELAXED_CONSTEXPR inline QPoint &QPoint::operator*=(int factor) { xp = xp*factor; yp = yp*factor; return *this; } Q_DECL_CONSTEXPR inline bool operator==(const QPoint &p1, const QPoint &p2) @@ -182,7 +182,7 @@ Q_DECL_CONSTEXPR inline const QPoint operator+(const QPoint &p) Q_DECL_CONSTEXPR inline const QPoint operator-(const QPoint &p) { return QPoint(-p.xp, -p.yp); } -inline QPoint &QPoint::operator/=(qreal c) +Q_DECL_RELAXED_CONSTEXPR inline QPoint &QPoint::operator/=(qreal c) { xp = qRound(xp/c); yp = qRound(yp/c); @@ -215,16 +215,16 @@ public: Q_DECL_CONSTEXPR inline qreal x() const; Q_DECL_CONSTEXPR inline qreal y() const; - inline void setX(qreal x); - inline void setY(qreal y); + Q_DECL_RELAXED_CONSTEXPR inline void setX(qreal x); + Q_DECL_RELAXED_CONSTEXPR inline void setY(qreal y); - inline qreal &rx(); - inline qreal &ry(); + Q_DECL_RELAXED_CONSTEXPR inline qreal &rx(); + Q_DECL_RELAXED_CONSTEXPR inline qreal &ry(); - inline QPointF &operator+=(const QPointF &p); - inline QPointF &operator-=(const QPointF &p); - inline QPointF &operator*=(qreal c); - inline QPointF &operator/=(qreal c); + Q_DECL_RELAXED_CONSTEXPR inline QPointF &operator+=(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline QPointF &operator-=(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline QPointF &operator*=(qreal c); + Q_DECL_RELAXED_CONSTEXPR inline QPointF &operator/=(qreal c); Q_DECL_CONSTEXPR static inline qreal dotProduct(const QPointF &p1, const QPointF &p2) { return p1.xp * p2.xp + p1.yp * p2.yp; } @@ -289,39 +289,39 @@ Q_DECL_CONSTEXPR inline qreal QPointF::y() const return yp; } -inline void QPointF::setX(qreal xpos) +Q_DECL_RELAXED_CONSTEXPR inline void QPointF::setX(qreal xpos) { xp = xpos; } -inline void QPointF::setY(qreal ypos) +Q_DECL_RELAXED_CONSTEXPR inline void QPointF::setY(qreal ypos) { yp = ypos; } -inline qreal &QPointF::rx() +Q_DECL_RELAXED_CONSTEXPR inline qreal &QPointF::rx() { return xp; } -inline qreal &QPointF::ry() +Q_DECL_RELAXED_CONSTEXPR inline qreal &QPointF::ry() { return yp; } -inline QPointF &QPointF::operator+=(const QPointF &p) +Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator+=(const QPointF &p) { xp+=p.xp; yp+=p.yp; return *this; } -inline QPointF &QPointF::operator-=(const QPointF &p) +Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator-=(const QPointF &p) { xp-=p.xp; yp-=p.yp; return *this; } -inline QPointF &QPointF::operator*=(qreal c) +Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator*=(qreal c) { xp*=c; yp*=c; return *this; } @@ -366,7 +366,7 @@ Q_DECL_CONSTEXPR inline const QPointF operator-(const QPointF &p) return QPointF(-p.xp, -p.yp); } -inline QPointF &QPointF::operator/=(qreal divisor) +Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator/=(qreal divisor) { xp/=divisor; yp/=divisor; diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index b5be5724af..9b86a9f8fc 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -64,17 +64,17 @@ public: Q_DECL_CONSTEXPR inline int x() const; Q_DECL_CONSTEXPR inline int y() const; - inline void setLeft(int pos); - inline void setTop(int pos); - inline void setRight(int pos); - inline void setBottom(int pos); - inline void setX(int x); - inline void setY(int y); - - inline void setTopLeft(const QPoint &p); - inline void setBottomRight(const QPoint &p); - inline void setTopRight(const QPoint &p); - inline void setBottomLeft(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void setLeft(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void setTop(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void setRight(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void setBottom(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void setX(int x); + Q_DECL_RELAXED_CONSTEXPR inline void setY(int y); + + Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPoint &p); Q_DECL_CONSTEXPR inline QPoint topLeft() const; Q_DECL_CONSTEXPR inline QPoint bottomRight() const; @@ -82,39 +82,39 @@ public: Q_DECL_CONSTEXPR inline QPoint bottomLeft() const; Q_DECL_CONSTEXPR inline QPoint center() const; - inline void moveLeft(int pos); - inline void moveTop(int pos); - inline void moveRight(int pos); - inline void moveBottom(int pos); - inline void moveTopLeft(const QPoint &p); - inline void moveBottomRight(const QPoint &p); - inline void moveTopRight(const QPoint &p); - inline void moveBottomLeft(const QPoint &p); - inline void moveCenter(const QPoint &p); - - inline void translate(int dx, int dy); - inline void translate(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveTop(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveRight(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(int pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPoint &p); + + Q_DECL_RELAXED_CONSTEXPR inline void translate(int dx, int dy); + Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPoint &p); Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const Q_REQUIRED_RESULT; Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const Q_REQUIRED_RESULT; - inline void moveTo(int x, int t); - inline void moveTo(const QPoint &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveTo(int x, int t); + Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPoint &p); - inline void setRect(int x, int y, int w, int h); - inline void getRect(int *x, int *y, int *w, int *h) const; + Q_DECL_RELAXED_CONSTEXPR inline void setRect(int x, int y, int w, int h); + Q_DECL_RELAXED_CONSTEXPR inline void getRect(int *x, int *y, int *w, int *h) const; - inline void setCoords(int x1, int y1, int x2, int y2); - inline void getCoords(int *x1, int *y1, int *x2, int *y2) const; + Q_DECL_RELAXED_CONSTEXPR inline void setCoords(int x1, int y1, int x2, int y2); + Q_DECL_RELAXED_CONSTEXPR inline void getCoords(int *x1, int *y1, int *x2, int *y2) const; - inline void adjust(int x1, int y1, int x2, int y2); + Q_DECL_RELAXED_CONSTEXPR inline void adjust(int x1, int y1, int x2, int y2); Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const Q_REQUIRED_RESULT; Q_DECL_CONSTEXPR inline QSize size() const; Q_DECL_CONSTEXPR inline int width() const; Q_DECL_CONSTEXPR inline int height() const; - inline void setWidth(int w); - inline void setHeight(int h); - inline void setSize(const QSize &s); + Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w); + Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h); + Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSize &s); QRect operator|(const QRect &r) const; QRect operator&(const QRect &r) const; @@ -131,8 +131,8 @@ public: Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const; Q_DECL_CONSTEXPR inline QRect marginsRemoved(const QMargins &margins) const; - inline QRect &operator+=(const QMargins &margins); - inline QRect &operator-=(const QMargins &margins); + Q_DECL_RELAXED_CONSTEXPR inline QRect &operator+=(const QMargins &margins); + Q_DECL_RELAXED_CONSTEXPR inline QRect &operator-=(const QMargins &margins); #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED QRect unite(const QRect &r) const Q_REQUIRED_RESULT { return united(r); } @@ -202,34 +202,34 @@ Q_DECL_CONSTEXPR inline int QRect::x() const Q_DECL_CONSTEXPR inline int QRect::y() const { return y1; } -inline void QRect::setLeft(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setLeft(int pos) { x1 = pos; } -inline void QRect::setTop(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTop(int pos) { y1 = pos; } -inline void QRect::setRight(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRight(int pos) { x2 = pos; } -inline void QRect::setBottom(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottom(int pos) { y2 = pos; } -inline void QRect::setTopLeft(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopLeft(const QPoint &p) { x1 = p.x(); y1 = p.y(); } -inline void QRect::setBottomRight(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomRight(const QPoint &p) { x2 = p.x(); y2 = p.y(); } -inline void QRect::setTopRight(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopRight(const QPoint &p) { x2 = p.x(); y1 = p.y(); } -inline void QRect::setBottomLeft(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomLeft(const QPoint &p) { x1 = p.x(); y2 = p.y(); } -inline void QRect::setX(int ax) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setX(int ax) { x1 = ax; } -inline void QRect::setY(int ay) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setY(int ay) { y1 = ay; } Q_DECL_CONSTEXPR inline QPoint QRect::topLeft() const @@ -256,7 +256,7 @@ Q_DECL_CONSTEXPR inline int QRect::height() const Q_DECL_CONSTEXPR inline QSize QRect::size() const { return QSize(width(), height()); } -inline void QRect::translate(int dx, int dy) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(int dx, int dy) { x1 += dx; y1 += dy; @@ -264,7 +264,7 @@ inline void QRect::translate(int dx, int dy) y2 += dy; } -inline void QRect::translate(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(const QPoint &p) { x1 += p.x(); y1 += p.y(); @@ -278,7 +278,7 @@ Q_DECL_CONSTEXPR inline QRect QRect::translated(int dx, int dy) const Q_DECL_CONSTEXPR inline QRect QRect::translated(const QPoint &p) const { return QRect(QPoint(x1 + p.x(), y1 + p.y()), QPoint(x2 + p.x(), y2 + p.y())); } -inline void QRect::moveTo(int ax, int ay) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(int ax, int ay) { x2 += ax - x1; y2 += ay - y1; @@ -286,7 +286,7 @@ inline void QRect::moveTo(int ax, int ay) y1 = ay; } -inline void QRect::moveTo(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(const QPoint &p) { x2 += p.x() - x1; y2 += p.y() - y1; @@ -294,49 +294,49 @@ inline void QRect::moveTo(const QPoint &p) y1 = p.y(); } -inline void QRect::moveLeft(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveLeft(int pos) { x2 += (pos - x1); x1 = pos; } -inline void QRect::moveTop(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTop(int pos) { y2 += (pos - y1); y1 = pos; } -inline void QRect::moveRight(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveRight(int pos) { x1 += (pos - x2); x2 = pos; } -inline void QRect::moveBottom(int pos) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottom(int pos) { y1 += (pos - y2); y2 = pos; } -inline void QRect::moveTopLeft(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopLeft(const QPoint &p) { moveLeft(p.x()); moveTop(p.y()); } -inline void QRect::moveBottomRight(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomRight(const QPoint &p) { moveRight(p.x()); moveBottom(p.y()); } -inline void QRect::moveTopRight(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopRight(const QPoint &p) { moveRight(p.x()); moveTop(p.y()); } -inline void QRect::moveBottomLeft(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomLeft(const QPoint &p) { moveLeft(p.x()); moveBottom(p.y()); } -inline void QRect::moveCenter(const QPoint &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveCenter(const QPoint &p) { int w = x2 - x1; int h = y2 - y1; @@ -346,7 +346,7 @@ inline void QRect::moveCenter(const QPoint &p) y2 = y1 + h; } -inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const +Q_DECL_RELAXED_CONSTEXPR inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const { *ax = x1; *ay = y1; @@ -354,7 +354,7 @@ inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const *ah = y2 - y1 + 1; } -inline void QRect::setRect(int ax, int ay, int aw, int ah) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRect(int ax, int ay, int aw, int ah) { x1 = ax; y1 = ay; @@ -362,7 +362,7 @@ inline void QRect::setRect(int ax, int ay, int aw, int ah) y2 = (ay + ah - 1); } -inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const +Q_DECL_RELAXED_CONSTEXPR inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const { *xp1 = x1; *yp1 = y1; @@ -370,7 +370,7 @@ inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const *yp2 = y2; } -inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) { x1 = xp1; y1 = yp1; @@ -381,7 +381,7 @@ inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) Q_DECL_CONSTEXPR inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const { return QRect(QPoint(x1 + xp1, y1 + yp1), QPoint(x2 + xp2, y2 + yp2)); } -inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) { x1 += dx1; y1 += dy1; @@ -389,13 +389,13 @@ inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) y2 += dy2; } -inline void QRect::setWidth(int w) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setWidth(int w) { x2 = (x1 + w - 1); } -inline void QRect::setHeight(int h) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setHeight(int h) { y2 = (y1 + h - 1); } -inline void QRect::setSize(const QSize &s) +Q_DECL_RELAXED_CONSTEXPR inline void QRect::setSize(const QSize &s) { x2 = (s.width() + x1 - 1); y2 = (s.height() + y1 - 1); @@ -473,13 +473,13 @@ Q_DECL_CONSTEXPR inline QRect QRect::marginsRemoved(const QMargins &margins) con QPoint(x2 - margins.right(), y2 - margins.bottom())); } -inline QRect &QRect::operator+=(const QMargins &margins) +Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator+=(const QMargins &margins) { *this = marginsAdded(margins); return *this; } -inline QRect &QRect::operator-=(const QMargins &margins) +Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator-=(const QMargins &margins) { *this = marginsRemoved(margins); return *this; @@ -511,12 +511,12 @@ public: Q_DECL_CONSTEXPR inline qreal x() const; Q_DECL_CONSTEXPR inline qreal y() const; - inline void setLeft(qreal pos); - inline void setTop(qreal pos); - inline void setRight(qreal pos); - inline void setBottom(qreal pos); - inline void setX(qreal pos) { setLeft(pos); } - inline void setY(qreal pos) { setTop(pos); } + Q_DECL_RELAXED_CONSTEXPR inline void setLeft(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void setTop(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void setRight(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void setBottom(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void setX(qreal pos) { setLeft(pos); } + Q_DECL_RELAXED_CONSTEXPR inline void setY(qreal pos) { setTop(pos); } Q_DECL_CONSTEXPR inline QPointF topLeft() const { return QPointF(xp, yp); } Q_DECL_CONSTEXPR inline QPointF bottomRight() const { return QPointF(xp+w, yp+h); } @@ -524,45 +524,45 @@ public: Q_DECL_CONSTEXPR inline QPointF bottomLeft() const { return QPointF(xp, yp+h); } Q_DECL_CONSTEXPR inline QPointF center() const; - inline void setTopLeft(const QPointF &p); - inline void setBottomRight(const QPointF &p); - inline void setTopRight(const QPointF &p); - inline void setBottomLeft(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPointF &p); - inline void moveLeft(qreal pos); - inline void moveTop(qreal pos); - inline void moveRight(qreal pos); - inline void moveBottom(qreal pos); - inline void moveTopLeft(const QPointF &p); - inline void moveBottomRight(const QPointF &p); - inline void moveTopRight(const QPointF &p); - inline void moveBottomLeft(const QPointF &p); - inline void moveCenter(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveTop(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveRight(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(qreal pos); + Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPointF &p); - inline void translate(qreal dx, qreal dy); - inline void translate(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void translate(qreal dx, qreal dy); + Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPointF &p); Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const Q_REQUIRED_RESULT; Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const Q_REQUIRED_RESULT; - inline void moveTo(qreal x, qreal y); - inline void moveTo(const QPointF &p); + Q_DECL_RELAXED_CONSTEXPR inline void moveTo(qreal x, qreal y); + Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPointF &p); - inline void setRect(qreal x, qreal y, qreal w, qreal h); - inline void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const; + Q_DECL_RELAXED_CONSTEXPR inline void setRect(qreal x, qreal y, qreal w, qreal h); + Q_DECL_RELAXED_CONSTEXPR inline void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const; - inline void setCoords(qreal x1, qreal y1, qreal x2, qreal y2); - inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const; + Q_DECL_RELAXED_CONSTEXPR inline void setCoords(qreal x1, qreal y1, qreal x2, qreal y2); + Q_DECL_RELAXED_CONSTEXPR inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const; - inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2); + Q_DECL_RELAXED_CONSTEXPR inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2); Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const Q_REQUIRED_RESULT; Q_DECL_CONSTEXPR inline QSizeF size() const; Q_DECL_CONSTEXPR inline qreal width() const; Q_DECL_CONSTEXPR inline qreal height() const; - inline void setWidth(qreal w); - inline void setHeight(qreal h); - inline void setSize(const QSizeF &s); + Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w); + Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h); + Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSizeF &s); QRectF operator|(const QRectF &r) const; QRectF operator&(const QRectF &r) const; @@ -578,8 +578,8 @@ public: Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const; Q_DECL_CONSTEXPR inline QRectF marginsRemoved(const QMarginsF &margins) const; - inline QRectF &operator+=(const QMarginsF &margins); - inline QRectF &operator-=(const QMarginsF &margins); + Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator+=(const QMarginsF &margins); + Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator-=(const QMarginsF &margins); #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED QRectF unite(const QRectF &r) const Q_REQUIRED_RESULT { return united(r); } @@ -652,42 +652,42 @@ Q_DECL_CONSTEXPR inline qreal QRectF::x() const Q_DECL_CONSTEXPR inline qreal QRectF::y() const { return yp; } -inline void QRectF::setLeft(qreal pos) { qreal diff = pos - xp; xp += diff; w -= diff; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setLeft(qreal pos) { qreal diff = pos - xp; xp += diff; w -= diff; } -inline void QRectF::setRight(qreal pos) { w = pos - xp; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRight(qreal pos) { w = pos - xp; } -inline void QRectF::setTop(qreal pos) { qreal diff = pos - yp; yp += diff; h -= diff; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTop(qreal pos) { qreal diff = pos - yp; yp += diff; h -= diff; } -inline void QRectF::setBottom(qreal pos) { h = pos - yp; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottom(qreal pos) { h = pos - yp; } -inline void QRectF::setTopLeft(const QPointF &p) { setLeft(p.x()); setTop(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopLeft(const QPointF &p) { setLeft(p.x()); setTop(p.y()); } -inline void QRectF::setTopRight(const QPointF &p) { setRight(p.x()); setTop(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopRight(const QPointF &p) { setRight(p.x()); setTop(p.y()); } -inline void QRectF::setBottomLeft(const QPointF &p) { setLeft(p.x()); setBottom(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomLeft(const QPointF &p) { setLeft(p.x()); setBottom(p.y()); } -inline void QRectF::setBottomRight(const QPointF &p) { setRight(p.x()); setBottom(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomRight(const QPointF &p) { setRight(p.x()); setBottom(p.y()); } Q_DECL_CONSTEXPR inline QPointF QRectF::center() const { return QPointF(xp + w/2, yp + h/2); } -inline void QRectF::moveLeft(qreal pos) { xp = pos; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveLeft(qreal pos) { xp = pos; } -inline void QRectF::moveTop(qreal pos) { yp = pos; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTop(qreal pos) { yp = pos; } -inline void QRectF::moveRight(qreal pos) { xp = pos - w; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveRight(qreal pos) { xp = pos - w; } -inline void QRectF::moveBottom(qreal pos) { yp = pos - h; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottom(qreal pos) { yp = pos - h; } -inline void QRectF::moveTopLeft(const QPointF &p) { moveLeft(p.x()); moveTop(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopLeft(const QPointF &p) { moveLeft(p.x()); moveTop(p.y()); } -inline void QRectF::moveTopRight(const QPointF &p) { moveRight(p.x()); moveTop(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopRight(const QPointF &p) { moveRight(p.x()); moveTop(p.y()); } -inline void QRectF::moveBottomLeft(const QPointF &p) { moveLeft(p.x()); moveBottom(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomLeft(const QPointF &p) { moveLeft(p.x()); moveBottom(p.y()); } -inline void QRectF::moveBottomRight(const QPointF &p) { moveRight(p.x()); moveBottom(p.y()); } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomRight(const QPointF &p) { moveRight(p.x()); moveBottom(p.y()); } -inline void QRectF::moveCenter(const QPointF &p) { xp = p.x() - w/2; yp = p.y() - h/2; } +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveCenter(const QPointF &p) { xp = p.x() - w/2; yp = p.y() - h/2; } Q_DECL_CONSTEXPR inline qreal QRectF::width() const { return w; } @@ -698,25 +698,25 @@ Q_DECL_CONSTEXPR inline qreal QRectF::height() const Q_DECL_CONSTEXPR inline QSizeF QRectF::size() const { return QSizeF(w, h); } -inline void QRectF::translate(qreal dx, qreal dy) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(qreal dx, qreal dy) { xp += dx; yp += dy; } -inline void QRectF::translate(const QPointF &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(const QPointF &p) { xp += p.x(); yp += p.y(); } -inline void QRectF::moveTo(qreal ax, qreal ay) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(qreal ax, qreal ay) { xp = ax; yp = ay; } -inline void QRectF::moveTo(const QPointF &p) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(const QPointF &p) { xp = p.x(); yp = p.y(); @@ -728,7 +728,7 @@ Q_DECL_CONSTEXPR inline QRectF QRectF::translated(qreal dx, qreal dy) const Q_DECL_CONSTEXPR inline QRectF QRectF::translated(const QPointF &p) const { return QRectF(xp + p.x(), yp + p.y(), w, h); } -inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const { *ax = this->xp; *ay = this->yp; @@ -736,7 +736,7 @@ inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const *aah = this->h; } -inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) { this->xp = ax; this->yp = ay; @@ -744,7 +744,7 @@ inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) this->h = aah; } -inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) const +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) const { *xp1 = xp; *yp1 = yp; @@ -752,7 +752,7 @@ inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) co *yp2 = yp + h; } -inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) { xp = xp1; yp = yp1; @@ -760,19 +760,19 @@ inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) h = yp2 - yp1; } -inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) { xp += xp1; yp += yp1; w += xp2 - xp1; h += yp2 - yp1; } Q_DECL_CONSTEXPR inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const { return QRectF(xp + xp1, yp + yp1, w + xp2 - xp1, h + yp2 - yp1); } -inline void QRectF::setWidth(qreal aw) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setWidth(qreal aw) { this->w = aw; } -inline void QRectF::setHeight(qreal ah) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setHeight(qreal ah) { this->h = ah; } -inline void QRectF::setSize(const QSizeF &s) +Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setSize(const QSizeF &s) { w = s.width(); h = s.height(); @@ -852,13 +852,13 @@ Q_DECL_CONSTEXPR inline QRectF QRectF::marginsRemoved(const QMarginsF &margins) QSizeF(w - margins.left() - margins.right(), h - margins.top() - margins.bottom())); } -inline QRectF &QRectF::operator+=(const QMarginsF &margins) +Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator+=(const QMarginsF &margins) { *this = marginsAdded(margins); return *this; } -inline QRectF &QRectF::operator-=(const QMarginsF &margins) +Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator-=(const QMarginsF &margins) { *this = marginsRemoved(margins); return *this; diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 33894927fe..228ee5b842 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -835,6 +835,8 @@ struct QRegularExpressionPrivate : QSharedData }; QRegularExpressionMatchPrivate *doMatch(const QString &subject, + int subjectStartPos, + int subjectLength, int offset, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, @@ -872,6 +874,8 @@ struct QRegularExpressionMatchPrivate : QSharedData { QRegularExpressionMatchPrivate(const QRegularExpression &re, const QString &subject, + int subjectStart, + int subjectLength, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, int capturingCount = 0); @@ -884,6 +888,9 @@ struct QRegularExpressionMatchPrivate : QSharedData // for each captured substring QVector<int> capturedOffsets; + const int subjectStart; + const int subjectLength; + const QRegularExpression::MatchType matchType; const QRegularExpression::MatchOptions matchOptions; @@ -1219,14 +1226,21 @@ static int pcre16SafeExec(const pcre16 *code, const pcre16_extra *extra, /*! \internal - Performs a match of type \a matchType on the given \a subject string with - options \a matchOptions and returns the QRegularExpressionMatchPrivate of - the result. It also advances a match if a previous result is given as \a + Performs a match on the substring of the given \a subject string, + substring which starts from \a subjectStart and up to + (but not including) \a subjectStart + \a subjectLength. The match + will be of type \a matchType and using the options \a matchOptions; + the matching \a offset is relative the substring, + and if negative, it's taken as an offset from the end of the substring. + + It also advances a match if a previous result is given as \a previous. The \a subject string goes a Unicode validity check if \a checkSubjectString is CheckSubjectString and the match options don't include DontCheckSubjectStringMatchOption (PCRE doesn't like illegal UTF-16 sequences). + Returns the QRegularExpressionMatchPrivate of the result. + Advancing a match is a tricky algorithm. If the previous match matched a non-empty string, we just do an ordinary match at the offset position. @@ -1239,6 +1253,8 @@ static int pcre16SafeExec(const pcre16 *code, const pcre16_extra *extra, must advance over it. */ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString &subject, + int subjectStart, + int subjectLength, int offset, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, @@ -1246,21 +1262,22 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString const QRegularExpressionMatchPrivate *previous) const { if (offset < 0) - offset += subject.length(); + offset += subjectLength; QRegularExpression re(*const_cast<QRegularExpressionPrivate *>(this)); - if (offset < 0 || offset > subject.length()) - return new QRegularExpressionMatchPrivate(re, subject, matchType, matchOptions); + if (offset < 0 || offset > subjectLength) + return new QRegularExpressionMatchPrivate(re, subject, subjectStart, subjectLength, matchType, matchOptions); if (!compiledPattern) { qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object"); - return new QRegularExpressionMatchPrivate(re, subject, matchType, matchOptions); + return new QRegularExpressionMatchPrivate(re, subject, subjectStart, subjectLength, matchType, matchOptions); } // skip optimizing and doing the actual matching if NoMatch type was requested if (matchType == QRegularExpression::NoMatch) { QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject, + subjectStart, subjectLength, matchType, matchOptions); priv->isValid = true; return priv; @@ -1268,6 +1285,7 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString // capturingCount doesn't include the implicit "0" capturing group QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject, + subjectStart, subjectLength, matchType, matchOptions, capturingCount + 1); @@ -1307,45 +1325,49 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString int * const captureOffsets = priv->capturedOffsets.data(); const int captureOffsetsCount = priv->capturedOffsets.size(); + int realOffset = offset + subjectStart; + const int realSubjectLength = subjectLength + subjectStart; + const unsigned short * const subjectUtf16 = subject.utf16(); - const int subjectLength = subject.length(); int result; if (!previousMatchWasEmpty) { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, subjectLength, - offset, pcreOptions, + subjectUtf16, realSubjectLength, + realOffset, pcreOptions, captureOffsets, captureOffsetsCount); } else { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, subjectLength, - offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, + subjectUtf16, realSubjectLength, + realOffset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, captureOffsets, captureOffsetsCount); if (result == PCRE_ERROR_NOMATCH) { - ++offset; + ++realOffset; if (usingCrLfNewlines - && offset < subjectLength - && subjectUtf16[offset - 1] == QLatin1Char('\r') - && subjectUtf16[offset] == QLatin1Char('\n')) { - ++offset; - } else if (offset < subjectLength - && QChar::isLowSurrogate(subjectUtf16[offset])) { - ++offset; + && realOffset < realSubjectLength + && subjectUtf16[realOffset - 1] == QLatin1Char('\r') + && subjectUtf16[realOffset] == QLatin1Char('\n')) { + ++realOffset; + } else if (realOffset < realSubjectLength + && QChar::isLowSurrogate(subjectUtf16[realOffset])) { + ++realOffset; } result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, subjectLength, - offset, pcreOptions, + subjectUtf16, realSubjectLength, + realOffset, pcreOptions, captureOffsets, captureOffsetsCount); } } #ifdef QREGULAREXPRESSION_DEBUG qDebug() << "Matching" << pattern << "against" << subject - << offset << matchType << matchOptions << previousMatchWasEmpty + << "starting at" << subjectStart << "len" << subjectLength << "real len" << realSubjectLength + << "offset" << offset << "real offset" << realOffset + << matchType << matchOptions << previousMatchWasEmpty << "result" << result; #endif @@ -1383,10 +1405,13 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString */ QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(const QRegularExpression &re, const QString &subject, + int subjectStart, + int subjectLength, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, int capturingCount) : regularExpression(re), subject(subject), + subjectStart(subjectStart), subjectLength(subjectLength), matchType(matchType), matchOptions(matchOptions), capturedCount(0), hasMatch(false), hasPartialMatch(false), isValid(false) @@ -1412,6 +1437,8 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const // then that subject was already checked at least once (when this object // was created, or when the object that created this one was created, etc.) QRegularExpressionMatchPrivate *nextPrivate = regularExpression.d->doMatch(subject, + subjectStart, + subjectLength, capturedOffsets.at(1), matchType, matchOptions, @@ -1684,7 +1711,33 @@ QRegularExpressionMatch QRegularExpression::match(const QString &subject, { d.data()->compilePattern(); - QRegularExpressionMatchPrivate *priv = d->doMatch(subject, offset, matchType, matchOptions); + QRegularExpressionMatchPrivate *priv = d->doMatch(subject, 0, subject.length(), offset, matchType, matchOptions); + return QRegularExpressionMatch(*priv); +} + +/*! + \since 5.5 + \overload + + Attempts to match the regular expression against the given \a subjectRef + string reference, starting at the position \a offset inside the subject, using a + match of type \a matchType and honoring the given \a matchOptions. + + The returned QRegularExpressionMatch object contains the results of the + match. + + \sa QRegularExpressionMatch, {normal matching} +*/ +QRegularExpressionMatch QRegularExpression::match(const QStringRef &subjectRef, + int offset, + MatchType matchType, + MatchOptions matchOptions) const +{ + d.data()->compilePattern(); + + const QString subject = subjectRef.string() ? *subjectRef.string() : QString(); + + QRegularExpressionMatchPrivate *priv = d->doMatch(subject, subjectRef.position(), subjectRef.length(), offset, matchType, matchOptions); return QRegularExpressionMatch(*priv); } @@ -1714,6 +1767,34 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s } /*! + \since 5.5 + \overload + + Attempts to perform a global match of the regular expression against the + given \a subjectRef string reference, starting at the position \a offset inside the + subject, using a match of type \a matchType and honoring the given \a + matchOptions. + + The returned QRegularExpressionMatchIterator is positioned before the + first match result (if any). + + \sa QRegularExpressionMatchIterator, {global matching} +*/ +QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QStringRef &subjectRef, + int offset, + MatchType matchType, + MatchOptions matchOptions) const +{ + QRegularExpressionMatchIteratorPrivate *priv = + new QRegularExpressionMatchIteratorPrivate(*this, + matchType, + matchOptions, + match(subjectRef, offset, matchType, matchOptions)); + + return QRegularExpressionMatchIterator(*priv); +} + +/*! \since 5.4 Forces an immediate optimization of the pattern, including @@ -1823,6 +1904,8 @@ QString QRegularExpression::escape(const QString &str) QRegularExpressionMatch::QRegularExpressionMatch() : d(new QRegularExpressionMatchPrivate(QRegularExpression(), QString(), + 0, + 0, QRegularExpression::NoMatch, QRegularExpression::NoMatchOption)) { diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index 66538f22b3..f332227094 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -112,11 +112,21 @@ public: MatchType matchType = NormalMatch, MatchOptions matchOptions = NoMatchOption) const; + QRegularExpressionMatch match(const QStringRef &subjectRef, + int offset = 0, + MatchType matchType = NormalMatch, + MatchOptions matchOptions = NoMatchOption) const; + QRegularExpressionMatchIterator globalMatch(const QString &subject, int offset = 0, MatchType matchType = NormalMatch, MatchOptions matchOptions = NoMatchOption) const; + QRegularExpressionMatchIterator globalMatch(const QStringRef &subjectRef, + int offset = 0, + MatchType matchType = NormalMatch, + MatchOptions matchOptions = NoMatchOption) const; + void optimize() const; static QString escape(const QString &str); diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index 2279f1bc2a..58227d6755 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -91,11 +91,20 @@ public: int blockSize = buffers.first().size() - head; if (tailBuffer == 0 || blockSize > bytes) { - bufferSize -= bytes; - if (bufferSize <= 0) - clear(); // try to minify/squeeze us - else + // 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; } @@ -113,7 +122,7 @@ public: // if need buffer reallocation if (tail + bytes > buffers.last().size()) { - if (tail >= basicBlockSize) { + if (tail + bytes > buffers.last().capacity() && tail >= basicBlockSize) { // shrink this buffer to its current size buffers.last().resize(tail); @@ -139,11 +148,20 @@ public: inline void chop(int bytes) { while (bytes > 0) { if (tailBuffer == 0 || tail > bytes) { - bufferSize -= bytes; - if (bufferSize <= 0) - clear(); // try to minify/squeeze us - else + // 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; } @@ -156,7 +174,7 @@ public: } inline bool isEmpty() const { - return tailBuffer == 0 && tail == 0; + return bufferSize == 0; } inline int getChar() { @@ -175,10 +193,14 @@ public: inline void ungetChar(char c) { --head; if (head < 0) { - buffers.prepend(QByteArray()); + if (bufferSize != 0) { + buffers.prepend(QByteArray()); + ++tailBuffer; + } else { + tail = basicBlockSize; + } buffers.first().resize(basicBlockSize); head = basicBlockSize - 1; - ++tailBuffer; } buffers.first()[head] = c; ++bufferSize; diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h index 6b5cf2dd7d..90222ba822 100644 --- a/src/corelib/tools/qsize.h +++ b/src/corelib/tools/qsize.h @@ -51,8 +51,8 @@ public: Q_DECL_CONSTEXPR inline int width() const; Q_DECL_CONSTEXPR inline int height() const; - inline void setWidth(int w); - inline void setHeight(int h); + Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w); + Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h); void transpose(); Q_DECL_CONSTEXPR inline QSize transposed() const; @@ -64,12 +64,12 @@ public: Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const; Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const; - inline int &rwidth(); - inline int &rheight(); + Q_DECL_RELAXED_CONSTEXPR inline int &rwidth(); + Q_DECL_RELAXED_CONSTEXPR inline int &rheight(); - inline QSize &operator+=(const QSize &); - inline QSize &operator-=(const QSize &); - inline QSize &operator*=(qreal c); + Q_DECL_RELAXED_CONSTEXPR inline QSize &operator+=(const QSize &); + Q_DECL_RELAXED_CONSTEXPR inline QSize &operator-=(const QSize &); + Q_DECL_RELAXED_CONSTEXPR inline QSize &operator*=(qreal c); inline QSize &operator/=(qreal c); friend inline Q_DECL_CONSTEXPR bool operator==(const QSize &, const QSize &); @@ -119,10 +119,10 @@ Q_DECL_CONSTEXPR inline int QSize::width() const Q_DECL_CONSTEXPR inline int QSize::height() const { return ht; } -inline void QSize::setWidth(int w) +Q_DECL_RELAXED_CONSTEXPR inline void QSize::setWidth(int w) { wd = w; } -inline void QSize::setHeight(int h) +Q_DECL_RELAXED_CONSTEXPR inline void QSize::setHeight(int h) { ht = h; } Q_DECL_CONSTEXPR inline QSize QSize::transposed() const @@ -137,19 +137,19 @@ inline void QSize::scale(const QSize &s, Qt::AspectRatioMode mode) inline QSize QSize::scaled(int w, int h, Qt::AspectRatioMode mode) const { return scaled(QSize(w, h), mode); } -inline int &QSize::rwidth() +Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rwidth() { return wd; } -inline int &QSize::rheight() +Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rheight() { return ht; } -inline QSize &QSize::operator+=(const QSize &s) +Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator+=(const QSize &s) { wd+=s.wd; ht+=s.ht; return *this; } -inline QSize &QSize::operator-=(const QSize &s) +Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator-=(const QSize &s) { wd-=s.wd; ht-=s.ht; return *this; } -inline QSize &QSize::operator*=(qreal c) +Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator*=(qreal c) { wd = qRound(wd*c); ht = qRound(ht*c); return *this; } Q_DECL_CONSTEXPR inline bool operator==(const QSize &s1, const QSize &s2) @@ -211,8 +211,8 @@ public: Q_DECL_CONSTEXPR inline qreal width() const; Q_DECL_CONSTEXPR inline qreal height() const; - inline void setWidth(qreal w); - inline void setHeight(qreal h); + Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w); + Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h); void transpose(); Q_DECL_CONSTEXPR inline QSizeF transposed() const; @@ -224,12 +224,12 @@ public: Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const; Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const; - inline qreal &rwidth(); - inline qreal &rheight(); + Q_DECL_RELAXED_CONSTEXPR inline qreal &rwidth(); + Q_DECL_RELAXED_CONSTEXPR inline qreal &rheight(); - inline QSizeF &operator+=(const QSizeF &); - inline QSizeF &operator-=(const QSizeF &); - inline QSizeF &operator*=(qreal c); + Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator+=(const QSizeF &); + Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator-=(const QSizeF &); + Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator*=(qreal c); inline QSizeF &operator/=(qreal c); friend Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &, const QSizeF &); @@ -284,10 +284,10 @@ Q_DECL_CONSTEXPR inline qreal QSizeF::width() const Q_DECL_CONSTEXPR inline qreal QSizeF::height() const { return ht; } -inline void QSizeF::setWidth(qreal w) +Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setWidth(qreal w) { wd = w; } -inline void QSizeF::setHeight(qreal h) +Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setHeight(qreal h) { ht = h; } Q_DECL_CONSTEXPR inline QSizeF QSizeF::transposed() const @@ -302,19 +302,19 @@ inline void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode) inline QSizeF QSizeF::scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const { return scaled(QSizeF(w, h), mode); } -inline qreal &QSizeF::rwidth() +Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rwidth() { return wd; } -inline qreal &QSizeF::rheight() +Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rheight() { return ht; } -inline QSizeF &QSizeF::operator+=(const QSizeF &s) +Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator+=(const QSizeF &s) { wd += s.wd; ht += s.ht; return *this; } -inline QSizeF &QSizeF::operator-=(const QSizeF &s) +Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator-=(const QSizeF &s) { wd -= s.wd; ht -= s.ht; return *this; } -inline QSizeF &QSizeF::operator*=(qreal c) +Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator*=(qreal c) { wd *= c; ht *= c; return *this; } Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &s1, const QSizeF &s2) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 9921d5cfbb..e830ed36e5 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -70,6 +70,7 @@ #include "qchar.cpp" #include "qstringmatcher.cpp" #include "qstringiterator_p.h" +#include "qstringalgorithms_p.h" #include "qthreadstorage.h" #ifdef Q_OS_WIN @@ -731,12 +732,30 @@ inline char qToLower(char ch) const QString::Null QString::null = { }; /*! + \macro QT_RESTRICTED_CAST_FROM_ASCII + \relates QString + + Defining this macro disables most automatic conversions from source + literals and 8-bit data to unicode QStrings, but allows the use of + the \c{QChar(char)} and \c{QString(const char (&ch)[N]} constructors, + and the \c{QString::operator=(const char (&ch)[N])} assignment operator + giving most of the type-safety benefits of QT_NO_CAST_FROM_ASCII + but does not require user code to wrap character and string literals + with QLatin1Char, QLatin1String or similar. + + Using this macro together with source strings outside the 7-bit range, + non-literals, or literals with embedded NUL characters is undefined. + + \sa QT_NO_CAST_FROM_ASCII, QT_NO_CAST_TO_ASCII +*/ + +/*! \macro QT_NO_CAST_FROM_ASCII \relates QString Disables automatic conversions from 8-bit strings (char *) to unicode QStrings - \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_BYTEARRAY + \sa QT_NO_CAST_TO_ASCII, QT_RESTRICTED_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY */ /*! @@ -745,7 +764,7 @@ const QString::Null QString::null = { }; disables automatic conversion from QString to 8-bit strings (char *) - \sa QT_NO_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY + \sa QT_NO_CAST_FROM_ASCII, QT_RESTRICTED_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY */ /*! @@ -759,7 +778,7 @@ const QString::Null QString::null = { }; Note: This only works for compilers that support warnings for deprecated API. - \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII + \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII, QT_RESTRICTED_CAST_FROM_ASCII */ /*! @@ -993,6 +1012,9 @@ const QString::Null QString::null = { }; \list \li \c QT_NO_CAST_FROM_ASCII disables automatic conversions from C string literals and pointers to Unicode. + \li \c QT_RESTRICTED_CAST_FROM_ASCII allows automatic conversions + from C characters and character arrays, but disables automatic + conversions from character pointers to Unicode. \li \c QT_NO_CAST_TO_ASCII disables automatic conversion from QString to C strings. \endlist @@ -1310,6 +1332,12 @@ const QString::Null QString::null = { }; can be useful if you want to ensure that all user-visible strings go through QObject::tr(), for example. + \note Defining QT_RESTRICTED_CAST_FROM_ASCII also disables + this constructor, but enables a \c{QString(const char (&ch)[N])} + constructor instead. Using non-literal input, or input with + embedded NUL characters, or non-7-bit characters is undefined + in this case. + \sa fromLatin1(), fromLocal8Bit(), fromUtf8() */ @@ -1656,8 +1684,11 @@ void QString::resize(int size) void QString::reallocData(uint alloc, bool grow) { - if (grow) + if (grow) { + if (alloc > (uint(MaxAllocSize) - sizeof(Data)) / sizeof(QChar)) + qBadAlloc(); alloc = qAllocMore(alloc * sizeof(QChar), sizeof(Data)) / sizeof(QChar); + } if (d->ref.isShared() || IS_RAW_DATA(d)) { Data::AllocationOptions allocOptions(d->capacityReserved ? Data::CapacityReserved : 0); @@ -1748,10 +1779,11 @@ QString &QString::operator=(const QString &other) Assigns \a str to this string. The const char pointer is converted to Unicode using the fromUtf8() function. - You can disable this operator by defining \c - QT_NO_CAST_FROM_ASCII when you compile your applications. This - can be useful if you want to ensure that all user-visible strings + You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII + or \c QT_RESTRICTED_CAST_FROM_ASCII when you compile your applications. + This can be useful if you want to ensure that all user-visible strings go through QObject::tr(), for example. + */ /*! \fn QString &QString::operator=(char ch) @@ -3664,14 +3696,39 @@ int QString::count(const QRegExp& rx) const */ int QString::indexOf(const QRegularExpression& re, int from) const { + return indexOf(re, from, Q_NULLPTR); +} + +/*! + \overload + \since 5.5 + + Returns the index position of the first match of the regular + expression \a re in the string, searching forward from index + position \a from. Returns -1 if \a re didn't match anywhere. + + If the match is successful and \a rmatch is not a null pointer, it also + writes the results of the match into the QRegularExpressionMatch object + pointed to by \a rmatch. + + Example: + + \snippet qstring/main.cpp 97 +*/ +int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const +{ if (!re.isValid()) { qWarning("QString::indexOf: invalid QRegularExpression object"); return -1; } QRegularExpressionMatch match = re.match(*this, from); - if (match.hasMatch()) - return match.capturedStart(); + if (match.hasMatch()) { + const int ret = match.capturedStart(); + if (rmatch) + *rmatch = qMove(match); + return ret; + } return -1; } @@ -3690,22 +3747,45 @@ int QString::indexOf(const QRegularExpression& re, int from) const */ int QString::lastIndexOf(const QRegularExpression &re, int from) const { + return lastIndexOf(re, from, Q_NULLPTR); +} + +/*! + \overload + \since 5.5 + + Returns the index position of the last match of the regular + expression \a re in the string, which starts before the index + position \a from. Returns -1 if \a re didn't match anywhere. + + If the match is successful and \a rmatch is not a null pointer, it also + writes the results of the match into the QRegularExpressionMatch object + pointed to by \a rmatch. + + Example: + + \snippet qstring/main.cpp 98 +*/ +int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const +{ if (!re.isValid()) { qWarning("QString::lastIndexOf: invalid QRegularExpression object"); return -1; } int endpos = (from < 0) ? (size() + from + 1) : (from + 1); - QRegularExpressionMatchIterator iterator = re.globalMatch(*this); int lastIndex = -1; while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); int start = match.capturedStart(); - if (start < endpos) + if (start < endpos) { lastIndex = start; - else + if (rmatch) + *rmatch = qMove(match); + } else { break; + } } return lastIndex; @@ -3719,12 +3799,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from) const */ bool QString::contains(const QRegularExpression &re) const { - if (!re.isValid()) { - qWarning("QString::contains: invalid QRegularExpression object"); - return false; - } - QRegularExpressionMatch match = re.match(*this); - return match.hasMatch(); + return contains(re, Q_NULLPTR); } /*! @@ -3744,13 +3819,13 @@ bool QString::contains(const QRegularExpression &re) const bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *match) const { if (!re.isValid()) { - qWarning("QString::contains: invalid QRegularExpresssion object"); + qWarning("QString::contains: invalid QRegularExpression object"); return false; } QRegularExpressionMatch m = re.match(*this); bool hasMatch = m.hasMatch(); if (hasMatch && match) - *match = m; + *match = qMove(m); return hasMatch; } @@ -3912,12 +3987,14 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl #if !(defined(QT_NO_REGEXP) && defined(QT_NO_REGULAREXPRESSION)) class qt_section_chunk { public: - qt_section_chunk(int l, QString s) { length = l; string = s; } + qt_section_chunk() {} + qt_section_chunk(int l, QString s) : length(l), string(qMove(s)) {} int length; QString string; }; +Q_DECLARE_TYPEINFO(qt_section_chunk, Q_MOVABLE_TYPE); -static QString extractSections(const QList<qt_section_chunk> §ions, +static QString extractSections(const QVector<qt_section_chunk> §ions, int start, int end, QString::SectionFlags flags) @@ -4003,7 +4080,7 @@ QString QString::section(const QRegExp ®, int start, int end, SectionFlags fl sep.setCaseSensitivity((flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive); - QList<qt_section_chunk> sections; + 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))); @@ -4048,7 +4125,7 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti if (flags & SectionCaseInsensitiveSeps) sep.setPatternOptions(sep.patternOptions() | QRegularExpression::CaseInsensitiveOption); - QList<qt_section_chunk> sections; + QVector<qt_section_chunk> sections; int n = length(), m = 0, last_m = 0, last_len = 0; QRegularExpressionMatchIterator iterator = sep.globalMatch(*this); while (iterator.hasNext()) { @@ -4626,6 +4703,8 @@ QString& QString::setUnicode(const QChar *unicode, int size) */ /*! + \fn QString QString::simplified() const + Returns a string that has whitespace removed from the start and the end, and that has each sequence of internal whitespace replaced with a single space. @@ -4640,83 +4719,19 @@ QString& QString::setUnicode(const QChar *unicode, int size) \sa trimmed() */ -QString QString::simplified() const +QString QString::simplified_helper(const QString &str) { - if (d->size == 0) - return *this; - - const QChar * const start = reinterpret_cast<QChar *>(d->data()); - const QChar *from = start; - const QChar *fromEnd = start + d->size; - forever { - QChar ch = *from; - if (!ch.isSpace()) - break; - if (++from == fromEnd) { - // All-whitespace string - QStringDataPtr empty = { Data::allocate(0) }; - return QString(empty); - } - } - // This loop needs no underflow check, as we already determined that - // the string contains non-whitespace. If the string has exactly one - // non-whitespace, it will be checked twice - we can live with that. - while (fromEnd[-1].isSpace()) - fromEnd--; - // The rest of the function depends on the fact that we already know - // that the last character in the source is no whitespace. - const QChar *copyFrom = from; - int copyCount; - forever { - if (++from == fromEnd) { - // Only leading and/or trailing whitespace, if any at all - return mid(copyFrom - start, from - copyFrom); - } - QChar ch = *from; - if (!ch.isSpace()) - continue; - if (ch != QLatin1Char(' ')) { - copyCount = from - copyFrom; - break; - } - ch = *++from; - if (ch.isSpace()) { - copyCount = from - copyFrom - 1; - break; - } - } - // 'from' now points at the non-trailing whitespace which made the - // string not simplified in the first place. 'copyCount' is the number - // of already simplified characters - at least one, obviously - - // without a trailing space. - QString result((fromEnd - from) + copyCount, Qt::Uninitialized); - QChar *to = reinterpret_cast<QChar *>(result.d->data()); - ::memcpy(to, copyFrom, copyCount * 2); - to += copyCount; - fromEnd--; - QChar ch; - forever { - *to++ = QLatin1Char(' '); - do { - ch = *++from; - } while (ch.isSpace()); - if (from == fromEnd) - break; - do { - *to++ = ch; - ch = *++from; - if (from == fromEnd) - goto done; - } while (!ch.isSpace()); + return QStringAlgorithms<const QString>::simplified_helper(str); +} - } - done: - *to++ = ch; - result.truncate(to - reinterpret_cast<QChar *>(result.d->data())); - return result; +QString QString::simplified_helper(QString &str) +{ + return QStringAlgorithms<QString>::simplified_helper(str); } /*! + \fn QString QString::trimmed() const + Returns a string that has whitespace removed from the start and the end. @@ -4732,27 +4747,14 @@ QString QString::simplified() const \sa simplified() */ -QString QString::trimmed() const +QString QString::trimmed_helper(const QString &str) { - if (d->size == 0) - return *this; - const QChar *s = (const QChar*)d->data(); - if (!s->isSpace() && !s[d->size-1].isSpace()) - return *this; - int start = 0; - int end = d->size - 1; - while (start<=end && s[start].isSpace()) // skip white space from start - start++; - if (start <= end) { // only white space - while (end && s[end].isSpace()) // skip white space from end - end--; - } - int l = end - start + 1; - if (l <= 0) { - QStringDataPtr empty = { Data::allocate(0) }; - return QString(empty); - } - return QString(s + start, l); + return QStringAlgorithms<const QString>::trimmed_helper(str); +} + +QString QString::trimmed_helper(QString &str) +{ + return QStringAlgorithms<QString>::trimmed_helper(str); } /*! \fn const QChar QString::at(int position) const @@ -5519,6 +5521,8 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const } /*! + \fn QString QString::toLower() const + Returns a lowercase copy of the string. \snippet qstring/main.cpp 75 @@ -5529,132 +5533,118 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const \sa toUpper(), QLocale::toLower() */ -QString QString::toLower() const +namespace QUnicodeTables { +struct LowercaseTraits { - const ushort *p = d->data(); - if (!p) - return *this; + static signed short caseDiff(const Properties *prop) + { return prop->lowerCaseDiff; } + static bool caseSpecial(const Properties *prop) + { return prop->lowerCaseSpecial; } +}; - const ushort *e = p + d->size; - // this avoids out of bounds check in the loop - while (e != p && QChar::isHighSurrogate(*(e - 1))) - --e; +struct UppercaseTraits +{ + static signed short caseDiff(const Properties *prop) + { return prop->upperCaseDiff; } + static bool caseSpecial(const Properties *prop) + { return prop->upperCaseSpecial; } +}; - const QUnicodeTables::Properties *prop; - while (p != e) { - if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) { - ushort high = *p++; - prop = qGetProp(QChar::surrogateToUcs4(high, *p)); +struct CasefoldTraits +{ + static signed short caseDiff(const Properties *prop) + { return prop->caseFoldDiff; } + static bool caseSpecial(const Properties *prop) + { return prop->caseFoldSpecial; } +}; + +template <typename Traits, typename T> +#ifdef Q_CC_MSVC +__declspec(noinline) +#elif defined(Q_CC_GNU) +__attribute__((noinline)) +#endif +static QString detachAndConvertCase(T &str, QStringIterator it) +{ + QString s = qMove(str); // will copy if T is const QString + QChar *pp = s.begin() + it.index(); // will detach if necessary + uint uc = it.nextUnchecked(); + forever { + const QUnicodeTables::Properties *prop = qGetProp(uc); + signed short caseDiff = Traits::caseDiff(prop); + + if (Q_UNLIKELY(Traits::caseSpecial(prop))) { + // slow path + const ushort *specialCase = specialCaseMap + caseDiff; + ushort length = *specialCase++; + int pos = pp - s.constBegin(); + s.replace(pos, 1, reinterpret_cast<const QChar *>(specialCase), length); + pp = const_cast<QChar *>(s.constBegin()) + pos + length; + } else if (QChar::requiresSurrogates(uc)) { + *pp++ = QChar::highSurrogate(uc + caseDiff); + *pp++ = QChar::lowSurrogate(uc + caseDiff); } else { - prop = qGetProp(*p); + *pp++ = QChar(uc + caseDiff); } - if (prop->lowerCaseDiff) { - if (QChar::isLowSurrogate(*p)) - --p; // safe; diff is 0 for surrogates - QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); - ushort *pp = s.d->data() + (p - d->data()); - while (p != e) { - if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) { - *pp = *p++; - prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p)); - } else { - prop = qGetProp(*p); - } - if (prop->lowerCaseSpecial) { - const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff; - ushort length = *specialCase++; - int pos = pp - s.d->data(); - s.resize(s.d->size + length - 1); - pp = s.d->data() + pos; - while (length--) - *pp++ = *specialCase++; - } else { - *pp++ = *p + prop->lowerCaseDiff; - } - ++p; - } - - // this restores high surrogate parts eaten above, if any - while (e != d->data() + d->size) - *pp++ = *e++; + if (!it.hasNext()) return s; - } - ++p; + + uc = it.nextUnchecked(); } - return *this; } -/*! - Returns the case folded equivalent of the string. For most Unicode - characters this is the same as toLower(). -*/ -QString QString::toCaseFolded() const +template <typename Traits, typename T> +static QString convertCase(T &str) { - const ushort *p = d->data(); - if (!p) - return *this; + const QChar *p = str.constBegin(); + const QChar *e = p + str.size(); - const ushort *e = p + d->size; // this avoids out of bounds check in the loop - while (e != p && QChar::isHighSurrogate(*(e - 1))) + while (e != p && e[-1].isHighSurrogate()) --e; const QUnicodeTables::Properties *prop; - while (p != e) { - if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) { - ushort high = *p++; - prop = qGetProp(QChar::surrogateToUcs4(high, *p)); - } else { - prop = qGetProp(*p); - } - if (prop->caseFoldDiff) { - if (QChar::isLowSurrogate(*p)) - --p; // safe; diff is 0 for surrogates - QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); - ushort *pp = s.d->data() + (p - d->data()); - while (p != e) { - if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) { - *pp = *p++; - prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p)); - } else { - prop = qGetProp(*p); - } - if (prop->caseFoldSpecial) { - const ushort *specialCase = specialCaseMap + prop->caseFoldDiff; - ushort length = *specialCase++; -#if 0 - int pos = pp - s.d->data; - s.resize(s.d->size + length - 1); - pp = s.d->data + pos; - while (length--) - *pp++ = *specialCase++; -#else - //### we currently don't support full case foldings - Q_ASSERT(length == 1); - Q_UNUSED(length) - *pp++ = *specialCase; -#endif - } else { - *pp++ = *p + prop->caseFoldDiff; - } - ++p; - } + QStringIterator it(p, e); + for ( ; it.hasNext(); it.advanceUnchecked()) { + prop = qGetProp(it.peekNextUnchecked()); + if (Traits::caseDiff(prop)) + return detachAndConvertCase<Traits>(str, it); + } + return qMove(str); +} +} // namespace QUnicodeTables - // this restores high surrogate parts eaten above, if any - while (e != d->data() + d->size) - *pp++ = *e++; +QString QString::toLower_helper(const QString &str) +{ + return QUnicodeTables::convertCase<QUnicodeTables::LowercaseTraits>(str); +} - return s; - } - ++p; - } - return *this; +QString QString::toLower_helper(QString &str) +{ + return QUnicodeTables::convertCase<QUnicodeTables::LowercaseTraits>(str); } /*! + \fn QString QString::toCaseFolded() const + + Returns the case folded equivalent of the string. For most Unicode + characters this is the same as toLower(). +*/ + +QString QString::toCaseFolded_helper(const QString &str) +{ + return QUnicodeTables::convertCase<QUnicodeTables::CasefoldTraits>(str); +} + +QString QString::toCaseFolded_helper(QString &str) +{ + return QUnicodeTables::convertCase<QUnicodeTables::CasefoldTraits>(str); +} + +/*! + \fn QString QString::toUpper() const + Returns an uppercase copy of the string. \snippet qstring/main.cpp 81 @@ -5664,63 +5654,18 @@ QString QString::toCaseFolded() const \sa toLower(), QLocale::toLower() */ -QString QString::toUpper() const -{ - const ushort *p = d->data(); - if (!p) - return *this; - const ushort *e = p + d->size; - // this avoids out of bounds check in the loop - while (e != p && QChar::isHighSurrogate(*(e - 1))) - --e; - - const QUnicodeTables::Properties *prop; - while (p != e) { - if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) { - ushort high = *p++; - prop = qGetProp(QChar::surrogateToUcs4(high, *p)); - } else { - prop = qGetProp(*p); - } - if (prop->upperCaseDiff) { - if (QChar::isLowSurrogate(*p)) - --p; // safe; diff is 0 for surrogates - QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); - ushort *pp = s.d->data() + (p - d->data()); - while (p != e) { - if (QChar::isHighSurrogate(*p) && QChar::isLowSurrogate(p[1])) { - *pp = *p++; - prop = qGetProp(QChar::surrogateToUcs4(*pp++, *p)); - } else { - prop = qGetProp(*p); - } - if (prop->upperCaseSpecial) { - const ushort *specialCase = specialCaseMap + prop->upperCaseDiff; - ushort length = *specialCase++; - int pos = pp - s.d->data(); - s.resize(s.d->size + length - 1); - pp = s.d->data() + pos; - while (length--) - *pp++ = *specialCase++; - } else { - *pp++ = *p + prop->upperCaseDiff; - } - ++p; - } - - // this restores high surrogate parts eaten above, if any - while (e != d->data() + d->size) - *pp++ = *e++; +QString QString::toUpper_helper(const QString &str) +{ + return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str); +} - return s; - } - ++p; - } - return *this; +QString QString::toUpper_helper(QString &str) +{ + return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str); } + // ### Qt 6: Consider whether this function shouldn't be removed See task 202871. /*! Safely builds a formatted string from the format string \a cformat @@ -9843,20 +9788,15 @@ QVector<uint> QStringRef::toUcs4() const */ QStringRef QStringRef::trimmed() const { - if (m_size == 0 || m_string == 0) + const QChar *begin = cbegin(); + const QChar *end = cend(); + QStringAlgorithms<const QStringRef>::trimmed_helper_positions(begin, end); + if (begin == cbegin() && end == cend()) return *this; - const QChar *s = m_string->constData() + m_position; - int start = 0; - int end = m_size - 1; - while (start <= end && s[start].isSpace()) // skip white space from start - start++; - if (start <= end) { // only white space - while (end && s[end].isSpace()) // skip white space from end - end--; - } - int l = end - start + 1; - Q_ASSERT(l >= 0); - return QStringRef(m_string, m_position + start, l); + if (begin == end) + return QStringRef(); + int position = m_position + (begin - cbegin()); + return QStringRef(m_string, position, end - begin); } /*! diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a12946e23c..4d51521b12 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -34,6 +34,10 @@ #ifndef QSTRING_H #define QSTRING_H +#if defined(QT_NO_CAST_FROM_ASCII) && defined(QT_RESTRICTED_CAST_FROM_ASCII) +#error QT_NO_CAST_FROM_ASCII and QT_RESTRICTED_CAST_FROM_ASCII must not be defined at the same time +#endif + #include <QtCore/qchar.h> #include <QtCore/qbytearray.h> #include <QtCore/qrefcount.h> @@ -93,7 +97,7 @@ public: inline bool operator>=(const QString &s) const; inline bool operator<=(const QString &s) const; -#ifndef QT_NO_CAST_FROM_ASCII +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline QT_ASCII_CAST_WARN bool operator==(const char *s) const; inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const; inline QT_ASCII_CAST_WARN bool operator<(const char *s) const; @@ -107,7 +111,7 @@ public: inline QT_ASCII_CAST_WARN bool operator>(const QByteArray &s) const; inline QT_ASCII_CAST_WARN bool operator<=(const QByteArray &s) const; inline QT_ASCII_CAST_WARN bool operator>=(const QByteArray &s) const; -#endif // QT_NO_CAST_FROM_ASCII +#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) private: int m_size; @@ -327,7 +331,9 @@ public: #ifndef QT_NO_REGULAREXPRESSION int indexOf(const QRegularExpression &re, int from = 0) const; + int indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads int lastIndexOf(const QRegularExpression &re, int from = -1) const; + int lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads bool contains(const QRegularExpression &re) const; bool contains(const QRegularExpression &re, QRegularExpressionMatch *match) const; // ### Qt 6: merge overloads int count(const QRegularExpression &re) const; @@ -369,12 +375,44 @@ public: QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT; QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT; +#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) +# 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 + QString toLower() const & Q_REQUIRED_RESULT + { return toLower_helper(*this); } + QString toLower() && Q_REQUIRED_RESULT + { return toLower_helper(*this); } + QString toUpper() const & Q_REQUIRED_RESULT + { return toUpper_helper(*this); } + QString toUpper() && Q_REQUIRED_RESULT + { return toUpper_helper(*this); } + QString toCaseFolded() const & Q_REQUIRED_RESULT + { return toCaseFolded_helper(*this); } + QString toCaseFolded() && Q_REQUIRED_RESULT + { return toCaseFolded_helper(*this); } + QString trimmed() const & Q_REQUIRED_RESULT + { return trimmed_helper(*this); } + QString trimmed() && Q_REQUIRED_RESULT + { return trimmed_helper(*this); } + QString simplified() const & Q_REQUIRED_RESULT + { return simplified_helper(*this); } + QString simplified() && Q_REQUIRED_RESULT + { return simplified_helper(*this); } +# ifdef Q_REQUIRED_RESULT_pushed +# pragma pop_macro("Q_REQUIRED_RESULT") +# endif +#else QString toLower() const Q_REQUIRED_RESULT; QString toUpper() const Q_REQUIRED_RESULT; QString toCaseFolded() const Q_REQUIRED_RESULT; - QString trimmed() const Q_REQUIRED_RESULT; QString simplified() const Q_REQUIRED_RESULT; +#endif QString toHtmlEscaped() const Q_REQUIRED_RESULT; QString &insert(int i, QChar c); @@ -596,7 +634,16 @@ public: inline bool operator>=(QLatin1String s) const { return !operator<(s); } // ASCII compatibility -#ifndef QT_NO_CAST_FROM_ASCII +#if defined(QT_RESTRICTED_CAST_FROM_ASCII) + template <int N> + inline QString(const char (&ch)[N]) + : d(fromAscii_helper(ch, N - 1)) + {} + template <int N> + inline QString &operator=(const char (&ch)[N]) + { return (*this = fromLatin1(ch, N - 1)); } +#endif +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline QT_ASCII_CAST_WARN QString(const char *ch) : d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1)) {} @@ -734,6 +781,16 @@ private: Qt::CaseSensitivity cs = Qt::CaseSensitive); static int localeAwareCompare_helper(const QChar *data1, int length1, const QChar *data2, int length2); + static QString toLower_helper(const QString &str); + static QString toLower_helper(QString &str); + static QString toUpper_helper(const QString &str); + static QString toUpper_helper(QString &str); + static QString toCaseFolded_helper(const QString &str); + static QString toCaseFolded_helper(QString &str); + static QString trimmed_helper(const QString &str); + static QString trimmed_helper(QString &str); + static QString simplified_helper(const QString &str); + static QString simplified_helper(QString &str); static Data *fromLatin1_helper(const char *str, int size = -1); static Data *fromAscii_helper(const char *str, int size = -1); static QString fromUtf8_helper(const char *str, int size); @@ -867,11 +924,8 @@ inline QString QString::arg(const QString &a1, const QString &a2, const QString inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const { return section(QString(asep), astart, aend, aflags); } -#ifdef Q_CC_MSVC -// "conditional expression is constant" -#pragma warning(push) -#pragma warning(disable : 4127) -#endif +QT_WARNING_PUSH +QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant" inline int QString::toWCharArray(wchar_t *array) const { @@ -882,9 +936,7 @@ inline int QString::toWCharArray(wchar_t *array) const return toUcs4_helper(d->data(), size(), reinterpret_cast<uint *>(array)); } -#ifdef Q_CC_MSVC -#pragma warning(pop) -#endif +QT_WARNING_POP inline QString QString::fromWCharArray(const wchar_t *string, int size) { @@ -1083,7 +1135,7 @@ inline bool QLatin1String::operator>=(const QString &s) const inline bool QLatin1String::operator<=(const QString &s) const { return s >= *this; } -#ifndef QT_NO_CAST_FROM_ASCII +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline bool QString::operator==(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) == 0; } inline bool QString::operator!=(const char *s) const @@ -1174,7 +1226,7 @@ inline bool QByteArray::operator<=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) <= 0; } inline bool QByteArray::operator>=(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) >= 0; } -#endif // QT_NO_CAST_FROM_ASCII +#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) #ifndef QT_NO_CAST_TO_ASCII inline QByteArray &QByteArray::append(const QString &s) @@ -1202,7 +1254,7 @@ inline const QString operator+(const QString &s1, QChar s2) { QString t(s1); t += s2; return t; } inline const QString operator+(QChar s1, const QString &s2) { QString t(s1); t += s2; return t; } -# ifndef QT_NO_CAST_FROM_ASCII +# if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline QT_ASCII_CAST_WARN const QString operator+(const QString &s1, const char *s2) { QString t(s1); t += QString::fromUtf8(s2); return t; } inline QT_ASCII_CAST_WARN const QString operator+(const char *s1, const QString &s2) @@ -1355,7 +1407,7 @@ public: inline const QChar at(int i) const { Q_ASSERT(uint(i) < uint(size())); return m_string->at(i + m_position); } -#ifndef QT_NO_CAST_FROM_ASCII +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) // ASCII compatibility inline QT_ASCII_CAST_WARN bool operator==(const char *s) const; inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const; @@ -1429,7 +1481,7 @@ inline bool operator<=(const QStringRef &s1, const QStringRef &s2) inline bool operator>=(const QStringRef &s1, const QStringRef &s2) { return !(s1 < s2); } -#ifndef QT_NO_CAST_FROM_ASCII +#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline QT_ASCII_CAST_WARN bool QStringRef::operator==(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) == 0; } inline QT_ASCII_CAST_WARN bool QStringRef::operator!=(const char *s) const @@ -1455,7 +1507,7 @@ inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QStringRef &s2) { return QString::compare_helper(s2.constData(), s2.size(), s1, -1) <= 0; } inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QStringRef &s2) { return QString::compare_helper(s2.constData(), s2.size(), s1, -1) >= 0; } -#endif // QT_NO_CAST_FROM_ASCII +#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const { return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } diff --git a/src/corelib/tools/qstring_compat.cpp b/src/corelib/tools/qstring_compat.cpp index c776092569..d4f21e483a 100644 --- a/src/corelib/tools/qstring_compat.cpp +++ b/src/corelib/tools/qstring_compat.cpp @@ -31,16 +31,42 @@ ** ****************************************************************************/ -#if defined(QSTRING_H) +#if defined(QSTRING_H) || defined(QBYTEARRAY_H) # error "This file cannot be compiled with pre-compiled headers" #endif #define QT_COMPILING_QSTRING_COMPAT_CPP +#include "qbytearray.h" #include "qstring.h" QT_BEGIN_NAMESPACE // all these implementations must be the same as the inline versions in qstring.h +QString QString::trimmed() const +{ + return trimmed_helper(*this); +} + +QString QString::simplified() const +{ + return simplified_helper(*this); +} + +QString QString::toLower() const +{ + return toLower_helper(*this); +} + +QString QString::toCaseFolded() const +{ + return toCaseFolded_helper(*this); +} + +QString QString::toUpper() const +{ + return toUpper_helper(*this); +} + QByteArray QString::toLatin1() const { return toLatin1_helper(*this); @@ -56,4 +82,25 @@ QByteArray QString::toUtf8() const return toUtf8_helper(*this); } +// ditto, for qbytearray.h (because we're lazy) +QByteArray QByteArray::toLower() const +{ + return toLower_helper(*this); +} + +QByteArray QByteArray::toUpper() const +{ + return toUpper_helper(*this); +} + +QByteArray QByteArray::trimmed() const +{ + return trimmed_helper(*this); +} + +QByteArray QByteArray::simplified() const +{ + return simplified_helper(*this); +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h new file mode 100644 index 0000000000..2911055f6a --- /dev/null +++ b/src/corelib/tools/qstringalgorithms_p.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Intel Corporation. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTRINGALGORITHMS_P_H +#define QSTRINGALGORITHMS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "qstring.h" +#include "qlocale_p.h" // for ascii_isspace + +QT_BEGIN_NAMESPACE + +template <typename StringType> struct QStringAlgorithms +{ + typedef typename StringType::value_type Char; + typedef typename StringType::size_type size_type; + typedef typename QtPrivate::remove_cv<StringType>::type NakedStringType; + static const bool isConst = QtPrivate::is_const<StringType>::value; + + static inline bool isSpace(char ch) { return ascii_isspace(ch); } + static inline bool isSpace(QChar ch) { return ch.isSpace(); } + + // Surrogate pairs are not handled in either of the functions below. That is + // not a problem because there are no space characters (Zs, Zl, Zp) outside the + // Basic Multilingual Plane. + + static inline StringType trimmed_helper_inplace(NakedStringType &str, const Char *begin, const Char *end) + { + // in-place trimming: + Char *data = const_cast<Char *>(str.cbegin()); + if (begin != data) + memmove(data, begin, (end - begin) * sizeof(Char)); + str.resize(end - begin); + return qMove(str); + } + + static inline StringType trimmed_helper_inplace(const NakedStringType &, const Char *, const Char *) + { + // can't happen + Q_UNREACHABLE(); + return StringType(); + } + + static inline void trimmed_helper_positions(const Char *&begin, const Char *&end) + { + // skip white space from start + while (begin < end && isSpace(*begin)) + begin++; + // skip white space from end + if (begin < end) { + while (begin < end && isSpace(end[-1])) + end--; + } + } + + static inline StringType trimmed_helper(StringType &str) + { + const Char *begin = str.cbegin(); + const Char *end = str.cend(); + trimmed_helper_positions(begin, end); + + if (begin == str.cbegin() && end == str.cend()) + return str; + if (begin == end) + return StringType(); + if (!isConst && str.isDetached()) + return trimmed_helper_inplace(str, begin, end); + return StringType(begin, end - begin); + } + + static inline StringType simplified_helper(StringType &str) + { + if (str.isEmpty()) + return str; + const Char *src = str.cbegin(); + const Char *end = str.cend(); + NakedStringType result = isConst ? + StringType(str.size(), Qt::Uninitialized) : + qMove(str); + + Char *dst = const_cast<Char *>(result.cbegin()); + Char *ptr = dst; + forever { + while (src != end && isSpace(*src)) + ++src; + while (src != end && !isSpace(*src)) + *ptr++ = *src++; + if (src != end) + *ptr++ = QChar::Space; + else + break; + } + if (ptr != dst && ptr[-1] == QChar::Space) + --ptr; + + int newlen = ptr - dst; + if (isConst && newlen == str.size()) { + // nothing happened, return the original + return str; + } + result.resize(newlen); + return result; + } +}; + +QT_END_NAMESPACE + +#endif // QSTRINGALGORITHMS_P_H diff --git a/src/corelib/tools/qstringiterator_p.h b/src/corelib/tools/qstringiterator_p.h index b80193b790..3f431daf6f 100644 --- a/src/corelib/tools/qstringiterator_p.h +++ b/src/corelib/tools/qstringiterator_p.h @@ -74,6 +74,11 @@ public: return pos; } + inline int index() const + { + return pos - i; + } + inline void setPosition(QString::const_iterator position) { Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds"); diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h index 8e577c2651..c0b245ed8d 100644 --- a/src/corelib/tools/qtimeline.h +++ b/src/corelib/tools/qtimeline.h @@ -137,7 +137,7 @@ Q_SIGNALS: ); protected: - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QTimeLine) diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 8f3db74131..fb5af2bf4a 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -56,6 +56,8 @@ static QTimeZonePrivate *newBackendTimeZone() #else #if defined Q_OS_MAC return new QMacTimeZonePrivate(); +#elif defined Q_OS_ANDROID + return new QAndroidTimeZonePrivate(); #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(); // Registry based timezone backend not available on WinRT @@ -81,6 +83,8 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId) #else #if defined Q_OS_MAC return new QMacTimeZonePrivate(ianaId); +#elif defined Q_OS_ANDROID + return new QAndroidTimeZonePrivate(ianaId); #elif defined Q_OS_UNIX return new QTzTimeZonePrivate(ianaId); // Registry based timezone backend not available on WinRT diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/tools/qtimezoneprivate_android.cpp new file mode 100644 index 0000000000..9d9bfc612d --- /dev/null +++ b/src/corelib/tools/qtimezoneprivate_android.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com> +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QSet> +#include "qtimezone.h" +#include "qtimezoneprivate_p.h" + +QT_BEGIN_NAMESPACE + +/* + Private + + Android implementation +*/ + +// Create the system default time zone +QAndroidTimeZonePrivate::QAndroidTimeZonePrivate() + : QTimeZonePrivate() +{ + // start with system time zone + androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); + init("UTC"); +} + +// Create a named time zone +QAndroidTimeZonePrivate::QAndroidTimeZonePrivate(const QByteArray &ianaId) + : QTimeZonePrivate() +{ + init(ianaId); +} + +QAndroidTimeZonePrivate::QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other) + : QTimeZonePrivate(other) +{ + androidTimeZone = other.androidTimeZone; + m_id = other.id(); +} + +QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate() +{ +} + + +void QAndroidTimeZonePrivate::init(const QByteArray &ianaId) +{ + QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) ); + androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", static_cast<jstring>(jo_ianaId.object()) ); + + if (ianaId.isEmpty()) + m_id = systemTimeZoneId(); + else + m_id = ianaId; +} + +QTimeZonePrivate *QAndroidTimeZonePrivate::clone() +{ + return new QAndroidTimeZonePrivate(*this); +} + + +QString QAndroidTimeZonePrivate::displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, + const QLocale &locale) const +{ + QString name; + + if (androidTimeZone.isValid()) { + jboolean daylightTime = (timeType == QTimeZone::DaylightTime); // treat QTimeZone::GenericTime as QTimeZone::StandardTime + + // treat all NameTypes as java TimeZone style LONG (value 1), except of course QTimeZone::ShortName which is style SHORT (value 0); + jint style = (nameType == QTimeZone::ShortName ? 0 : 1); + + QJNIObjectPrivate jlanguage = QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language())); + QJNIObjectPrivate jcountry = QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country())); + QJNIObjectPrivate jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script())); + QJNIObjectPrivate jlocale("java.util.Locale", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", static_cast<jstring>(jlanguage.object()), static_cast<jstring>(jcountry.object()), static_cast<jstring>(jvariant.object())); + + QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZILjava/util/Locale;)Ljava/lang/String;", daylightTime, style, jlocale.object()); + + name = jname.toString(); + } + + return name; +} + +QString QAndroidTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const +{ + if ( isDaylightTime( atMSecsSinceEpoch ) ) + return displayName(QTimeZone::DaylightTime, QTimeZone::ShortName, QLocale() ); + else + return displayName(QTimeZone::StandardTime, QTimeZone::ShortName, QLocale() ); +} + +int QAndroidTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const +{ + // offsetFromUtc( ) is invoked when androidTimeZone may not yet be set at startup, + // so a validity test is needed here + if ( androidTimeZone.isValid() ) + // the java method getOffset() returns milliseconds, but QTimeZone returns seconds + return androidTimeZone.callMethod<jint>( "getOffset", "(J)I", static_cast<jlong>(atMSecsSinceEpoch) ) / 1000; + else + return 0; +} + +int QAndroidTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const +{ + // the java method does not use a reference time + Q_UNUSED( atMSecsSinceEpoch ); + if ( androidTimeZone.isValid() ) + // the java method getRawOffset() returns milliseconds, but QTimeZone returns seconds + return androidTimeZone.callMethod<jint>( "getRawOffset" ) / 1000; + else + return 0; +} + +int QAndroidTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const +{ + return ( offsetFromUtc(atMSecsSinceEpoch) - standardTimeOffset(atMSecsSinceEpoch) ); +} + +bool QAndroidTimeZonePrivate::hasDaylightTime() const +{ + if ( androidTimeZone.isValid() ) + /* note: the Java function only tests for future daylight transtions, not past */ + return androidTimeZone.callMethod<jboolean>("useDaylightTime" ); + else + return false; +} + +bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const +{ + if ( androidTimeZone.isValid() ) { + QJNIObjectPrivate jDate( "java/util/Date", "(J)V", static_cast<jlong>(atMSecsSinceEpoch) ); + return androidTimeZone.callMethod<jboolean>("inDaylightTime", "(Ljava/util/Date;)Z", jDate.object() ); + } + else + return false; +} + +QTimeZonePrivate::Data QAndroidTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const +{ + if (androidTimeZone.isValid()) { + Data data; + data.atMSecsSinceEpoch = forMSecsSinceEpoch; + data.standardTimeOffset = standardTimeOffset(forMSecsSinceEpoch); + data.offsetFromUtc = offsetFromUtc(forMSecsSinceEpoch); + data.daylightTimeOffset = data.offsetFromUtc - data.standardTimeOffset; + data.abbreviation = abbreviation(forMSecsSinceEpoch); + return data; + } else { + return invalidData(); + } +} + +bool QAndroidTimeZonePrivate::hasTransitions() const +{ + // java.util.TimeZone does not directly provide transitions + return false; +} + +QTimeZonePrivate::Data QAndroidTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const +{ + // transitions not available on Android, so return an invalid data object + Q_UNUSED( afterMSecsSinceEpoch ); + return invalidData(); +} + +QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const +{ + // transitions not available on Android, so return an invalid data object + Q_UNUSED( beforeMSecsSinceEpoch ); + return invalidData(); +} + +// Since Android does not provide an API to access transitions, +// dataForLocalTime needs to be reimplemented without direct use of transitions +QTimeZonePrivate::Data QAndroidTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) const +{ + if (!androidTimeZone.isValid()) { + return invalidData(); + } else { + qint64 UTCepochMSecs; + + // compare the UTC time with standard offset against normal daylight offset of one hour + qint64 standardUTCMSecs(forLocalMSecs - (standardTimeOffset(forLocalMSecs) * 1000)); + qint64 daylightUTCMsecs; + + // Check if daylight time does apply, + // checking also for daylight time boundaries + if (isDaylightTime(standardUTCMSecs)) { + // If daylight does apply, then standardUTCMSecs will be an hour or so ahead of the real epoch time + // so check that time + daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(standardUTCMSecs)*1000; + if (isDaylightTime(daylightUTCMsecs)) { + // daylight time confirmed + UTCepochMSecs = daylightUTCMsecs; + } else { + // daylight time has just finished + UTCepochMSecs = standardUTCMSecs; + } + } else { + // Standard time indicated, but check for a false negative. + // Would a standard one-hour daylight offset indicate daylight time? + daylightUTCMsecs = standardUTCMSecs - 3600000; // 3600000 MSECS_PER_HOUR + if (isDaylightTime(daylightUTCMsecs)) { + // daylight time may have just started, + // but double check against timezone's own daylight offset + // (don't necessarily assume a one-hour offset) + daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(daylightUTCMsecs)*1000; + if (isDaylightTime(daylightUTCMsecs)) { + // daylight time confirmed + UTCepochMSecs = daylightUTCMsecs; + } else { + // false positive, apply standard time after all + UTCepochMSecs = standardUTCMSecs; + } + } else { + // confirmed standard time + UTCepochMSecs = standardUTCMSecs; + } + } + + return data(UTCepochMSecs); + } +} + +QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const +{ + QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); + QJNIObjectPrivate systemTZIdAndroid = androidSystemTimeZone.callObjectMethod<jstring>("getID"); + QByteArray systemTZid = systemTZIdAndroid.toString().toUtf8(); + + return systemTZid; +} + +QSet<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const +{ + QSet<QByteArray> availableTimeZoneIdList; + QJNIObjectPrivate androidAvailableIdList = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getAvailableIDs", "()[Ljava/lang/String;"); + + QJNIEnvironmentPrivate jniEnv; + int androidTZcount = jniEnv->GetArrayLength( static_cast<jarray>(androidAvailableIdList.object()) ); + + // need separate jobject and QAndroidJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject + // (or else the JNI reference table fills after 512 entries from GetObjectArrayElement) + jobject androidTZobject; + QJNIObjectPrivate androidTZ; + for (int i=0; i<androidTZcount; i++ ) { + androidTZobject = jniEnv->GetObjectArrayElement( static_cast<jobjectArray>( androidAvailableIdList.object() ), i ); + androidTZ = androidTZobject; + availableTimeZoneIdList.insert( androidTZ.toString().toUtf8() ); + jniEnv->DeleteLocalRef(androidTZobject); + } + + return availableTimeZoneIdList; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index 5ba42de560..6494ffe148 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -65,6 +65,10 @@ class NSTimeZone; #include <qt_windows.h> #endif // Q_OS_WIN +#ifdef Q_OS_ANDROID +#include <QtCore/private/qjni_p.h> +#endif + QT_BEGIN_NAMESPACE class Q_CORE_EXPORT QTimeZonePrivate : public QSharedData @@ -256,7 +260,7 @@ private: }; #endif // QT_USE_ICU -#if defined Q_OS_UNIX && !defined Q_OS_MAC +#if defined Q_OS_UNIX && !defined Q_OS_MAC && !defined Q_OS_ANDROID class Q_AUTOTEST_EXPORT QTzTimeZonePrivate Q_DECL_FINAL : public QTimeZonePrivate { public: @@ -424,6 +428,50 @@ private: }; #endif // Q_OS_WIN +#ifdef Q_OS_ANDROID +class QAndroidTimeZonePrivate Q_DECL_FINAL : public QTimeZonePrivate +{ +public: + // Create default time zone + QAndroidTimeZonePrivate(); + // Create named time zone + QAndroidTimeZonePrivate(const QByteArray &ianaId); + QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other); + ~QAndroidTimeZonePrivate(); + + QTimeZonePrivate *clone(); + + QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, + const QLocale &locale) const Q_DECL_OVERRIDE; + QString abbreviation(qint64 atMSecsSinceEpoch) const Q_DECL_OVERRIDE; + + int offsetFromUtc(qint64 atMSecsSinceEpoch) const Q_DECL_OVERRIDE; + int standardTimeOffset(qint64 atMSecsSinceEpoch) const Q_DECL_OVERRIDE; + int daylightTimeOffset(qint64 atMSecsSinceEpoch) const Q_DECL_OVERRIDE; + + bool hasDaylightTime() const Q_DECL_OVERRIDE; + bool isDaylightTime(qint64 atMSecsSinceEpoch) const Q_DECL_OVERRIDE; + + Data data(qint64 forMSecsSinceEpoch) const Q_DECL_OVERRIDE; + + bool hasTransitions() const Q_DECL_OVERRIDE; + Data nextTransition(qint64 afterMSecsSinceEpoch) const Q_DECL_OVERRIDE; + Data previousTransition(qint64 beforeMSecsSinceEpoch) const Q_DECL_OVERRIDE; + + Data dataForLocalTime(qint64 forLocalMSecs) const Q_DECL_OVERRIDE; + + QByteArray systemTimeZoneId() const Q_DECL_OVERRIDE; + + QSet<QByteArray> availableTimeZoneIds() const Q_DECL_OVERRIDE; + +private: + void init(const QByteArray &zoneId); + + QJNIObjectPrivate androidTimeZone; + +}; +#endif // Q_OS_ANDROID + QT_END_NAMESPACE #endif // QTIMEZONEPRIVATE_P_H diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index 3876d3822c..53d5228c3b 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -46,9 +46,40 @@ // #include "QtCore/qglobal.h" +#include <limits> QT_BEGIN_NAMESPACE +namespace QtMiscUtils { +inline char toHexUpper(uint value) +{ + static const char hexdigits[] = "0123456789ABCDEF"; + return hexdigits[value & 0xF]; +} + +inline char toHexLower(uint value) +{ + static const char hexdigits[] = "0123456789abcdef"; + return hexdigits[value & 0xF]; +} + +inline int fromHex(uint c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + return -1; +} +} + +// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. +enum { + MaxAllocSize = (1 << (std::numeric_limits<int>::digits - 1)) - 1 +}; + // implemented in qbytearray.cpp int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW; diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index 99e1db1cab..50c90ad746 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -463,6 +463,18 @@ \sa operator<<(), prepend(), insert() */ +/*! \fn void QVector::append(const QVector<T> &value) + + \overload + + \since 5.5 + + Appends the items of the \a value vector to this vector. + + \sa operator<<(), operator+=() +*/ + + /*! \fn void QVector::prepend(const T &value) Inserts \a value at the beginning of the vector. diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 07c66bc393..c00bd07a72 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -128,6 +128,7 @@ public: T &operator[](int i); const T &operator[](int i) const; void append(const T &t); + inline void append(const QVector<T> &l) { *this += l; } void prepend(const T &t); void insert(int i, const T &t); void insert(int i, int n, const T &t); @@ -327,9 +328,11 @@ inline QVector<T>::QVector(const QVector<T> &v) } else { if (v.d->capacityReserved) { d = Data::allocate(v.d->alloc); + Q_CHECK_PTR(d); d->capacityReserved = true; } else { d = Data::allocate(v.d->size); + Q_CHECK_PTR(d); } if (d->alloc) { copyConstruct(v.d->begin(), v.d->end(), d->begin()); @@ -439,6 +442,7 @@ QVector<T>::QVector(int asize) Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0."); if (Q_LIKELY(asize > 0)) { d = Data::allocate(asize); + Q_CHECK_PTR(d); d->size = asize; defaultConstruct(d->begin(), d->end()); } else { @@ -452,6 +456,7 @@ QVector<T>::QVector(int asize, const T &t) Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0."); if (asize > 0) { d = Data::allocate(asize); + Q_CHECK_PTR(d); d->size = asize; T* i = d->end(); while (i != d->begin()) @@ -467,6 +472,7 @@ QVector<T>::QVector(std::initializer_list<T> args) { if (args.size() > 0) { d = Data::allocate(args.size()); + Q_CHECK_PTR(d); // std::initializer_list<T>::iterator is guaranteed to be // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct copyConstruct(args.begin(), args.end(), d->begin()); @@ -707,13 +713,10 @@ bool QVector<T>::operator==(const QVector<T> &v) const return true; if (d->size != v.d->size) return false; - T* b = d->begin(); - T* i = b + d->size; - T* j = v.d->end(); - while (i != b) - if (!(*--i == *--j)) - return false; - return true; + const T *vb = v.d->begin(); + const T *b = d->begin(); + const T *e = d->end(); + return std::equal(b, e, vb); } template <typename T> @@ -791,12 +794,9 @@ int QVector<T>::lastIndexOf(const T &t, int from) const template <typename T> bool QVector<T>::contains(const T &t) const { - T* b = d->begin(); - T* i = d->end(); - while (i != b) - if (*--i == t) - return true; - return false; + const T *b = d->begin(); + const T *e = d->end(); + return std::find(b, e, t) != e; } template <typename T> diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index cef802fa76..01b514d329 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -57,6 +57,7 @@ HEADERS += \ tools/qsize.h \ tools/qstack.h \ tools/qstring.h \ + tools/qstringalgorithms_p.h \ tools/qstringbuilder.h \ tools/qstringiterator_p.h \ tools/qstringlist.h \ @@ -128,13 +129,19 @@ false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator OBJECTIVE_SOURCES += tools/qlocale_mac.mm \ tools/qtimezoneprivate_mac.mm \ tools/qstring_mac.mm \ - tools/qbytearray_mac.mm + tools/qbytearray_mac.mm \ + tools/qdatetime_mac.mm } else:blackberry { SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_blackberry.cpp tools/qtimezoneprivate_tz.cpp HEADERS += tools/qlocale_blackberry.h } -else:unix:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp +else:android { + SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_android.cpp +} +else:unix { + SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp +} else:win32 { SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp !winrt: SOURCES += tools/qtimezoneprivate_win.cpp |