diff options
Diffstat (limited to 'src/corelib/tools')
30 files changed, 897 insertions, 398 deletions
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index f0cc56e899..a642fb9b39 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -159,6 +159,7 @@ struct QTypedArrayData inline iterator &operator-=(int j) { i-=j; return *this; } inline iterator operator+(int j) const { return iterator(i+j); } inline iterator operator-(int j) const { return iterator(i-j); } + friend inline iterator operator+(int j, iterator k) { return k + j; } inline int operator-(iterator j) const { return i - j.i; } inline operator T*() const { return i; } }; @@ -194,6 +195,7 @@ struct QTypedArrayData inline const_iterator &operator-=(int j) { i-=j; return *this; } inline const_iterator operator+(int j) const { return const_iterator(i+j); } inline const_iterator operator-(int j) const { return const_iterator(i-j); } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } inline int operator-(const_iterator j) const { return i - j.i; } inline operator const T*() const { return i; } }; diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 7c601e1336..3468580bf1 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -950,7 +950,7 @@ QByteArray qUncompress(const uchar* data, int nbytes) $LC_CTYPE is set, most Unix systems do "the right thing".) Functions that this affects include contains(), indexOf(), lastIndexOf(), operator<(), operator<=(), operator>(), - operator>=(), toLower() and toUpper(). + operator>=(), isLower(), isUpper(), toLower() and toUpper(). This issue does not apply to \l{QString}s since they represent characters using Unicode. @@ -2941,6 +2941,78 @@ bool QByteArray::endsWith(const char *str) const return qstrncmp(d->data() + d->size - len, str, len) == 0; } +/*! + Returns true if \a c is an uppercase Latin1 letter. + \note The multiplication sign 0xD7 and the sz ligature 0xDF are not + treated as uppercase Latin1. + */ +static inline bool isUpperCaseLatin1(char c) +{ + if (c >= 'A' && c <= 'Z') + return true; + + return (uchar(c) >= 0xC0 && uchar(c) <= 0xDE && uchar(c) != 0xD7); +} + +/*! + Returns \c true if this byte array contains only uppercase letters, + otherwise returns \c false. The byte array is interpreted as a Latin-1 + encoded string. + \since 5.12 + + \sa isLower(), toUpper() +*/ +bool QByteArray::isUpper() const +{ + if (isEmpty()) + return false; + + const char *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!isUpperCaseLatin1(d[i])) + return false; + } + + return true; +} + +/*! + Returns true if \a c is an lowercase Latin1 letter. + \note The division sign 0xF7 is not treated as lowercase Latin1, + but the small y dieresis 0xFF is. + */ +static inline bool isLowerCaseLatin1(char c) +{ + if (c >= 'a' && c <= 'z') + return true; + + return (uchar(c) >= 0xD0 && uchar(c) != 0xF7); +} + +/*! + Returns \c true if this byte array contains only lowercase letters, + otherwise returns \c false. The byte array is interpreted as a Latin-1 + encoded string. + \since 5.12 + + \sa isUpper(), toLower() + */ +bool QByteArray::isLower() const +{ + if (isEmpty()) + return false; + + const char *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!isLowerCaseLatin1(d[i])) + return false; + } + + return true; +} + /*! \overload Returns \c true if this byte array ends with character \a ch; @@ -3052,7 +3124,7 @@ QByteArray QByteArray::mid(int pos, int len) const Example: \snippet code/src_corelib_tools_qbytearray.cpp 30 - \sa toUpper(), {8-bit Character Comparisons} + \sa isLower(), toUpper(), {8-bit Character Comparisons} */ // prevent the compiler from inlining the function in each of @@ -3106,7 +3178,7 @@ QByteArray QByteArray::toLower_helper(QByteArray &a) Example: \snippet code/src_corelib_tools_qbytearray.cpp 31 - \sa toLower(), {8-bit Character Comparisons} + \sa isUpper(), toLower(), {8-bit Character Comparisons} */ QByteArray QByteArray::toUpper_helper(const QByteArray &a) diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 300f795469..bed710c597 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -245,6 +245,9 @@ public: bool endsWith(char c) const; bool endsWith(const char *c) const; + bool isUpper() const; + bool isLower() const; + void truncate(int pos); void chop(int n); diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 18facf7e42..faa7263d6b 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -211,6 +211,7 @@ void QContiguousCache<T>::detach_helper() template <typename T> void QContiguousCache<T>::setCapacity(int asize) { + Q_ASSERT(asize >= 0); if (asize == d->alloc) return; detach(); @@ -285,6 +286,7 @@ inline QContiguousCacheData *QContiguousCache<T>::allocateData(int aalloc) template <typename T> QContiguousCache<T>::QContiguousCache(int cap) { + Q_ASSERT(cap >= 0); d = allocateData(cap); d->ref.store(1); d->alloc = cap; diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index a1b121f1ee..3c79bb797d 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -544,6 +544,46 @@ QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method) return hash.result(); } +/*! + Returns the size of the output of the selected hash \a method in bytes. + + \since 5.12 +*/ +int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method) +{ + switch (method) { + case QCryptographicHash::Sha1: + return 20; +#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 + case QCryptographicHash::Md4: + return 16; + case QCryptographicHash::Md5: + return 16; + case QCryptographicHash::Sha224: + return SHA224HashSize; + case QCryptographicHash::Sha256: + return SHA256HashSize; + case QCryptographicHash::Sha384: + return SHA384HashSize; + case QCryptographicHash::Sha512: + return SHA512HashSize; + case QCryptographicHash::RealSha3_224: + case QCryptographicHash::Keccak_224: + return 224 / 8; + case QCryptographicHash::RealSha3_256: + case QCryptographicHash::Keccak_256: + return 256 / 8; + case QCryptographicHash::RealSha3_384: + case QCryptographicHash::Keccak_384: + return 384 / 8; + case QCryptographicHash::RealSha3_512: + case QCryptographicHash::Keccak_512: + return 512 / 8; +#endif + } + return 0; +} + QT_END_NAMESPACE #ifndef QT_NO_QOBJECT diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h index 2f74d42405..ad1de7c756 100644 --- a/src/corelib/tools/qcryptographichash.h +++ b/src/corelib/tools/qcryptographichash.h @@ -101,6 +101,7 @@ public: QByteArray result() const; static QByteArray hash(const QByteArray &data, Algorithm method); + static int hashLength(Algorithm method); private: Q_DISABLE_COPY(QCryptographicHash) QCryptographicHashPrivate *d; diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index ce663ce2ca..a586ca5671 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -348,6 +348,7 @@ public: inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { return *this = *this + j; } inline iterator &operator-=(int j) { return *this = *this - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } #ifndef QT_STRICT_ITERATORS public: @@ -413,6 +414,7 @@ public: inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { return *this = *this + j; } inline const_iterator &operator-=(int j) { return *this = *this - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } // ### Qt 5: not sure this is necessary anymore #ifdef QT_STRICT_ITERATORS diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index c8f3f4c8c3..1e6d4df474 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -159,6 +159,7 @@ public: inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { return *this = *this + j; } inline iterator &operator-=(int j) { return *this = *this - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } }; friend class iterator; @@ -193,6 +194,7 @@ public: inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { return *this = *this + j; } inline const_iterator &operator-=(int j) { return *this = *this - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } }; friend class const_iterator; diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index af7659e995..c00220ad3a 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -269,6 +269,7 @@ public: inline iterator &operator-=(difference_type j) { i-=j; return *this; } inline iterator operator+(difference_type j) const { return iterator(i+j); } inline iterator operator-(difference_type j) const { return iterator(i-j); } + friend inline iterator operator+(difference_type j, iterator k) { return k + j; } inline int operator-(iterator j) const { return int(i - j.i); } }; friend class iterator; @@ -312,6 +313,7 @@ public: inline const_iterator &operator-=(difference_type j) { i-=j; return *this; } inline const_iterator operator+(difference_type j) const { return const_iterator(i+j); } inline const_iterator operator-(difference_type j) const { return const_iterator(i-j); } + friend inline const_iterator operator+(difference_type j, const_iterator k) { return k + j; } inline int operator-(const_iterator j) const { return int(i - j.i); } }; friend class const_iterator; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 09b148ea9e..9c1e78ee61 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -233,14 +233,6 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const if (addLikelySubtags(id)) return id; } - // language_script - if (country_id) { - QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0); - if (addLikelySubtags(id)) { - id.country_id = country_id; - return id; - } - } // language_region if (script_id) { QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id); @@ -249,6 +241,14 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const return id; } } + // language_script + if (country_id) { + QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0); + if (addLikelySubtags(id)) { + id.country_id = country_id; + return id; + } + } // language if (script_id && country_id) { QLocaleId id = QLocaleId::fromIds(language_id, 0, 0); @@ -258,6 +258,14 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const return id; } } + // und_script + if (language_id) { + QLocaleId id = QLocaleId::fromIds(0, script_id, 0); + if (addLikelySubtags(id)) { + id.language_id = language_id; + return id; + } + } return *this; } @@ -382,6 +390,13 @@ const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLoca QList<QLocaleId> tried; tried.push_back(likelyId); + // No match; try again with raw data: + if (!tried.contains(localeId)) { + if (const QLocaleData *const data = findLocaleDataById(localeId)) + return data; + tried.push_back(localeId); + } + // No match; try again with likely country if (country != QLocale::AnyCountry && (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) { diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index a5b9096835..1cf9299e26 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -449,6 +449,7 @@ public: inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { return *this = *this + j; } inline iterator &operator-=(int j) { return *this = *this - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } #ifndef QT_STRICT_ITERATORS public: @@ -512,6 +513,7 @@ public: inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { return *this = *this + j; } inline const_iterator &operator-=(int j) { return *this = *this - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } #ifdef QT_STRICT_ITERATORS private: diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 96ddca56af..87b30c952e 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -3813,50 +3813,57 @@ struct QRegExpPrivate }; #if !defined(QT_NO_REGEXP_OPTIM) -typedef QCache<QRegExpEngineKey, QRegExpEngine> EngineCache; -Q_GLOBAL_STATIC(EngineCache, globalEngineCache) -static QBasicMutex globalEngineCacheMutex; +struct QRECache +{ + typedef QHash<QRegExpEngineKey, QRegExpEngine *> EngineCache; + typedef QCache<QRegExpEngineKey, QRegExpEngine> UnusedEngineCache; + EngineCache usedEngines; + UnusedEngineCache unusedEngines; +}; +Q_GLOBAL_STATIC(QRECache, engineCache) +static QBasicMutex engineCacheMutex; #endif // QT_NO_REGEXP_OPTIM static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key) { - if (!eng->ref.deref()) { #if !defined(QT_NO_REGEXP_OPTIM) - if (globalEngineCache()) { - QMutexLocker locker(&globalEngineCacheMutex); - QT_TRY { - globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4); - } QT_CATCH(const std::bad_alloc &) { - // in case of an exception (e.g. oom), just delete the engine - delete eng; - } + QMutexLocker locker(&engineCacheMutex); + if (!eng->ref.deref()) { + if (QRECache *c = engineCache()) { + c->unusedEngines.insert(key, eng, 4 + key.pattern.length() / 4); + c->usedEngines.remove(key); } else { delete eng; } + } #else - Q_UNUSED(key); + Q_UNUSED(key); + if (!eng->ref.deref()) delete eng; #endif - } } static void prepareEngine_helper(QRegExpPrivate *priv) { - bool initMatchState = !priv->eng; + Q_ASSERT(!priv->eng); + #if !defined(QT_NO_REGEXP_OPTIM) - if (!priv->eng && globalEngineCache()) { - QMutexLocker locker(&globalEngineCacheMutex); - priv->eng = globalEngineCache()->take(priv->engineKey); - if (priv->eng != 0) + QMutexLocker locker(&engineCacheMutex); + if (QRECache *c = engineCache()) { + priv->eng = c->unusedEngines.take(priv->engineKey); + if (!priv->eng) + priv->eng = c->usedEngines.value(priv->engineKey); + if (!priv->eng) + priv->eng = new QRegExpEngine(priv->engineKey); + else priv->eng->ref.ref(); + + c->usedEngines.insert(priv->engineKey, priv->eng); + return; } #endif // QT_NO_REGEXP_OPTIM - if (!priv->eng) - priv->eng = new QRegExpEngine(priv->engineKey); - - if (initMatchState) - priv->matchState.prepareForMatch(priv->eng); + priv->eng = new QRegExpEngine(priv->engineKey); } inline static void prepareEngine(QRegExpPrivate *priv) @@ -3864,6 +3871,7 @@ inline static void prepareEngine(QRegExpPrivate *priv) if (priv->eng) return; prepareEngine_helper(priv); + priv->matchState.prepareForMatch(priv->eng); } static void prepareEngineForMatch(QRegExpPrivate *priv, const QString &str) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 13eff07c04..29ad578013 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -798,6 +798,83 @@ Q_AUTOTEST_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count = static const unsigned int qt_qregularexpression_optimize_after_use_count = 10; #endif // QT_BUILD_INTERNAL + +namespace QtPrivate { +/*! + internal +*/ +QString wildcardToRegularExpression(const QString &wildcardString) +{ + const int wclen = wildcardString.length(); + QString rx; + int i = 0; + bool hasNegativeBracket = false; + const QChar *wc = wildcardString.unicode(); + + while (i < wclen) { + const QChar c = wc[i++]; + switch (c.unicode()) { + case '*': + rx += QLatin1String(".*"); + break; + case '?': + rx += QLatin1Char('.'); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '^': + case '{': + case '|': + case '}': + rx += QLatin1Char('\\'); + rx += c; + break; + case '[': + // Support for the [!abc] or [!a-c] syntax + // Implements a negative look-behind for one char. + if (wc[i] == QLatin1Char(']')) { + rx += c; + rx += wc[i++]; + } else if (wc[i] == QLatin1Char('!')) { + rx += QLatin1String(".(?<"); + rx += wc[i++]; + rx += c; + hasNegativeBracket = true; + } else { + rx += c; + } + + if (i < wclen) { + if (rx[i] == QLatin1Char(']')) + rx += wc[i++]; + while (i < wclen && wc[i] != QLatin1Char(']')) { + if (wc[i] == QLatin1Char('\\')) + rx += QLatin1Char('\\'); + rx += wc[i++]; + } + } + break; + case ']': + rx += c; + // Closes the negative look-behind expression. + if (hasNegativeBracket) { + rx += QLatin1Char(')'); + hasNegativeBracket = false; + } + break; + default: + rx += c; + break; + } + } + + return rx; +} +} + /*! \internal */ @@ -1554,6 +1631,47 @@ void QRegularExpression::setPattern(const QString &pattern) } /*! + \since 5.12 + + Sets the pattern string of the regular expression to \a wildcard pattern. + The pattern options are left unchanged. + + \warning Unlike QRegExp, this implementation follows closely the definition + of wildcard for glob patterns: + \table + \row \li \b{c} + \li Any character represents itself apart from those mentioned + below. Thus \b{c} matches the character \e c. + \row \li \b{?} + \li Matches any single character. It is the same as + \b{.} in full regexps. + \row \li \b{*} + \li Matches zero or more of any characters. It is the + same as \b{.*} in full regexps. + \row \li \b{[abc]} + \li Matches one character given in the bracket. + \row \li \b{[a-c]} + \li Matches one character from the range given in the bracket. + \row \li \b{[!abc]} + \li Matches one character that is not given in the bracket. + \row \li \b{[!a-c]} + \li matches one character that is not from the range given in the + bracket. + \endtable + + \note This function generates a regular expression that will act following + the wildcard pattern given. However the content of the regular expression + will not be the same as the one set. + + \sa pattern(), setPattern() +*/ +void QRegularExpression::setWildcardPattern(const QString &pattern) +{ + setPattern(QtPrivate::wildcardToRegularExpression(pattern)); +} + + +/*! Returns the pattern options for the regular expression. \sa setPatternOptions(), pattern() diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index 398fc9ec9c..f26f52d427 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -96,6 +96,7 @@ public: QString pattern() const; void setPattern(const QString &pattern); + void setWildcardPattern(const QString &pattern); bool isValid() const; int patternErrorOffset() const; diff --git a/src/corelib/tools/qregularexpression_p.h b/src/corelib/tools/qregularexpression_p.h new file mode 100644 index 0000000000..f5455de853 --- /dev/null +++ b/src/corelib/tools/qregularexpression_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Samuel Gaist <samuel.gaist@edeltech.ch> +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QREGULAREXPRESSION_P_H +#define QREGULAREXPRESSION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qglobal_p.h> + +#include <qregularexpression.h> +#include <qstring.h> + +QT_REQUIRE_CONFIG(regularexpression); + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { +QString wildcardToRegularExpression(const QString &expression); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp index eb7bdfe95c..59650ed2f7 100644 --- a/src/corelib/tools/qringbuffer.cpp +++ b/src/corelib/tools/qringbuffer.cpp @@ -312,12 +312,14 @@ qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const Q_ASSERT(maxLength >= 0 && pos >= 0); qint64 readSoFar = 0; - for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) { - qint64 blockLength = buffers[i].size(); + for (const QRingChunk &chunk : buffers) { + if (readSoFar == maxLength) + break; + qint64 blockLength = chunk.size(); if (pos < blockLength) { blockLength = qMin(blockLength - pos, maxLength - readSoFar); - memcpy(data + readSoFar, buffers[i].data() + pos, blockLength); + memcpy(data + readSoFar, chunk.data() + pos, blockLength); readSoFar += blockLength; pos = 0; } else { diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 7ded120ab7..6640c8486d 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -131,6 +131,7 @@ public: inline iterator operator--(int) { iterator r = *this; --i; return r; } inline iterator operator+(int j) const { return i + j; } inline iterator operator-(int j) const { return i - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } inline iterator &operator+=(int j) { i += j; return *this; } inline iterator &operator-=(int j) { i -= j; return *this; } }; @@ -165,6 +166,7 @@ public: inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; } inline const_iterator operator+(int j) const { return i + j; } inline const_iterator operator-(int j) const { return i - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } inline const_iterator &operator+=(int j) { i += j; return *this; } inline const_iterator &operator-=(int j) { i -= j; return *this; } }; diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 780f2331a8..3ef134a99d 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -136,6 +136,18 @@ private: T *d; }; +template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2) +{ + Q_UNUSED(p1); + return !p2; +} + +template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2) +{ + Q_UNUSED(p2); + return !p1; +} + template <class T> class QExplicitlySharedDataPointer { public: @@ -271,6 +283,18 @@ Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer( : d(adata) { if (d) d->ref.ref(); } +template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2) +{ + Q_UNUSED(p1); + return !p2; +} + +template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2) +{ + Q_UNUSED(p2); + return !p1; +} + template <class T> Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) { p1.swap(p2); } diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 25340f2d02..fd9c6a7079 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -80,6 +80,43 @@ QT_BEGIN_NAMESPACE +/* + * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note + * we remove the terminating -1 that the script adds. + */ + +// begin generated +#if defined(Q_PROCESSOR_ARM) +/* Data: + neon + crc32 + */ +static const char features_string[] = + " neon\0" + " crc32\0" + "\0"; +static const int features_indices[] = { 0, 6 }; +#elif defined(Q_PROCESSOR_MIPS) +/* Data: + dsp + dspr2 +*/ +static const char features_string[] = + " dsp\0" + " dspr2\0" + "\0"; + +static const int features_indices[] = { + 0, 5 +}; +#elif defined(Q_PROCESSOR_X86) +# include "qsimd_x86.cpp" // generated by util/x86simdgen +#else +static const char features_string[] = ""; +static const int features_indices[] = { }; +#endif +// end generated + #if defined (Q_OS_NACL) static inline uint detectProcessorFeatures() { @@ -222,29 +259,32 @@ static void cpuidFeatures01(uint &ecx, uint &edx) inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));} #endif -static void cpuidFeatures07_00(uint &ebx, uint &ecx) +static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx) { #if defined(Q_CC_GNU) qregisteruint rbx; // in case it's 64-bit qregisteruint rcx = 0; + qregisteruint rdx = 0; asm ("xchg " PICreg", %0\n" "cpuid\n" "xchg " PICreg", %0\n" - : "=&r" (rbx), "+&c" (rcx) - : "a" (7) - : "%edx"); + : "=&r" (rbx), "+&c" (rcx), "+&d" (rdx) + : "a" (7)); ebx = rbx; ecx = rcx; + edx = rdx; #elif defined(Q_OS_WIN) int info[4]; __cpuidex(info, 7, 0); ebx = info[1]; ecx = info[2]; + edx = info[3]; #elif defined(Q_CC_GHS) unsigned int info[4]; __CPUIDEX(7, 0, info); ebx = info[1]; ecx = info[2]; + edx = info[3]; #endif } @@ -285,8 +325,11 @@ static quint64 detectProcessorFeatures() static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) | (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) | (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) | - (Q_UINT64_C(1) << CpuFeatureAVX512VL) | - (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI); + (Q_UINT64_C(1) << CpuFeatureAVX512VL) | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | + (Q_UINT64_C(1) << CpuFeatureAVX512VBMI) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI2) | + (Q_UINT64_C(1) << CpuFeatureAVX512VNNI) | (Q_UINT64_C(1) << CpuFeatureAVX512BITALG) | + (Q_UINT64_C(1) << CpuFeatureAVX512VPOPCNTDQ) | + (Q_UINT64_C(1) << CpuFeatureAVX5124NNIW) | (Q_UINT64_C(1) << CpuFeatureAVX5124FMAPS); static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512; static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2; @@ -299,52 +342,33 @@ static quint64 detectProcessorFeatures() Q_ASSERT(cpuidLevel >= 1); #endif - uint cpuid01ECX = 0, cpuid01EDX = 0; - cpuidFeatures01(cpuid01ECX, cpuid01EDX); - - // the low 32-bits of features is cpuid01ECX - // note: we need to check OS support for saving the AVX register state - features = cpuid01ECX; - -#if defined(Q_PROCESSOR_X86_32) - // x86 might not have SSE2 support - if (cpuid01EDX & (1u << 26)) - features |= Q_UINT64_C(1) << CpuFeatureSSE2; - else - features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2); - // we should verify that the OS enabled saving of the SSE state... -#else - // x86-64 or x32 - features |= Q_UINT64_C(1) << CpuFeatureSSE2; -#endif + uint results[X86CpuidMaxLeaf] = {}; + cpuidFeatures01(results[Leaf1ECX], results[Leaf1EDX]); + if (cpuidLevel >= 7) + cpuidFeatures07_00(results[Leaf7_0EBX], results[Leaf7_0ECX], results[Leaf7_0EDX]); + + // populate our feature list + for (uint i = 0; i < sizeof(x86_locators) / sizeof(x86_locators[0]); ++i) { + uint word = x86_locators[i] / 32; + uint bit = 1U << (x86_locators[i] % 32); + quint64 feature = Q_UINT64_C(1) << (i + 1); + if (results[word] & bit) + features |= feature; + } + // now check the AVX state uint xgetbvA = 0, xgetbvD = 0; - if (cpuid01ECX & (1u << 27)) { + if (results[Leaf1ECX] & (1u << 27)) { // XGETBV enabled xgetbv(0, xgetbvA, xgetbvD); } - uint cpuid0700EBX = 0; - uint cpuid0700ECX = 0; - if (cpuidLevel >= 7) { - cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX); - - // the high 32-bits of features is cpuid0700EBX - features |= quint64(cpuid0700EBX) << 32; - } - if ((xgetbvA & AVXState) != AVXState) { // support for YMM registers is disabled, disable all AVX features &= ~AllAVX; } else if ((xgetbvA & AVX512State) != AVX512State) { // support for ZMM registers or mask registers is disabled, disable all AVX512 features &= ~AllAVX512; - } else { - // this feature is out of order - if (cpuid0700ECX & (1u << 1)) - features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI; - else - features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI); } return features; @@ -493,162 +517,12 @@ static inline uint detectProcessorFeatures() } #endif -/* - * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note - * that the x86 version has a lot of blanks that must be kept and that the - * offset table's type is changed to make the table smaller. We also remove the - * terminating -1 that the script adds. - */ - -// begin generated -#if defined(Q_PROCESSOR_ARM) -/* Data: - neon - crc32 - */ -static const char features_string[] = - " neon\0" - " crc32\0" - "\0"; -static const int features_indices[] = { 0, 6 }; -#elif defined(Q_PROCESSOR_MIPS) -/* Data: - dsp - dspr2 -*/ -static const char features_string[] = - " dsp\0" - " dspr2\0" - "\0"; - -static const int features_indices[] = { - 0, 5 -}; -#elif defined(Q_PROCESSOR_X86) -/* Data: - sse3 - sse2 - avx512vbmi - - - - - - - ssse3 - - - fma - cmpxchg16b - - - - - - sse4.1 - sse4.2 - - movbe - popcnt - - aes - - - avx - f16c - rdrand - - - - - bmi - hle - avx2 - - - bmi2 - - - rtm - - - - - avx512f - avx512dq - rdseed - - - avx512ifma - - - - - avx512pf - avx512er - avx512cd - sha - avx512bw - avx512vl - */ -static const char features_string[] = - " sse3\0" - " sse2\0" - " avx512vbmi\0" - " ssse3\0" - " fma\0" - " cmpxchg16b\0" - " sse4.1\0" - " sse4.2\0" - " movbe\0" - " popcnt\0" - " aes\0" - " avx\0" - " f16c\0" - " rdrand\0" - " bmi\0" - " hle\0" - " avx2\0" - " bmi2\0" - " rtm\0" - " avx512f\0" - " avx512dq\0" - " rdseed\0" - " avx512ifma\0" - " avx512pf\0" - " avx512er\0" - " avx512cd\0" - " sha\0" - " avx512bw\0" - " avx512vl\0" - "\0"; - -static const quint8 features_indices[] = { - 0, 6, 12, 5, 5, 5, 5, 5, - 5, 24, 5, 5, 31, 36, 5, 5, - 5, 5, 5, 48, 56, 5, 64, 71, - 5, 79, 5, 5, 84, 89, 95, 5, - 5, 5, 5, 103, 108, 113, 5, 5, - 119, 5, 5, 125, 5, 5, 5, 5, - 130, 139, 149, 5, 5, 157, 5, 5, - 5, 5, 169, 179, 189, 199, 204, 214 -}; -#else -static const char features_string[] = ""; -static const int features_indices[] = { }; -#endif -// end generated - static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]); // record what CPU features were enabled by default in this Qt build static const quint64 minFeature = qCompilerCpuFeatures; -#ifdef Q_ATOMIC_INT64_IS_SUPPORTED Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; -#else -Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) }; -#endif void qDetectCpuFeatures() { @@ -681,9 +555,6 @@ void qDetectCpuFeatures() } qt_cpu_features[0].store(f | quint32(QSimdInitialized)); -#ifndef Q_ATOMIC_INT64_IS_SUPPORTED - qt_cpu_features[1].store(f >> 32); -#endif } void qDumpCPUFeatures() diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 18684caefb..1b7ed57fa8 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -179,6 +179,7 @@ #ifdef Q_PROCESSOR_X86 /* -- x86 intrinsic support -- */ +# include "qsimd_x86_p.h" # if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2) // MSVC doesn't define __SSE2__, so do it ourselves @@ -232,33 +233,6 @@ # define __RDRND__ 1 # endif -#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2" -#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3" -#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3" -#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1" -#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2" -#define QT_FUNCTION_TARGET_STRING_AVX "avx" -#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2" -#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f" -#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd" -#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er" -#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf" -#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw" -#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq" -#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl" -#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma" -#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi" - -#define QT_FUNCTION_TARGET_STRING_AES "aes,sse4.2" -#define QT_FUNCTION_TARGET_STRING_PCLMUL "pclmul,sse4.2" -#define QT_FUNCTION_TARGET_STRING_POPCNT "popcnt" -#define QT_FUNCTION_TARGET_STRING_F16C "f16c,avx" -#define QT_FUNCTION_TARGET_STRING_RDRND "rdrnd" -#define QT_FUNCTION_TARGET_STRING_BMI "bmi" -#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2" -#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed" -#define QT_FUNCTION_TARGET_STRING_SHA "sha" - #endif /* Q_PROCESSOR_X86 */ // Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html @@ -292,6 +266,7 @@ QT_BEGIN_NAMESPACE +#ifndef Q_PROCESSOR_X86 enum CPUFeatures { #if defined(Q_PROCESSOR_ARM) CpuFeatureNEON = 0, @@ -300,42 +275,6 @@ enum CPUFeatures { #elif defined(Q_PROCESSOR_MIPS) CpuFeatureDSP = 0, CpuFeatureDSPR2 = 1, -#elif defined(Q_PROCESSOR_X86) - // The order of the flags is jumbled so it matches most closely the bits in CPUID - // Out of order: - CpuFeatureSSE2 = 1, // uses the bit for PCLMULQDQ - // in level 1, ECX - CpuFeatureSSE3 = (0 + 0), - CpuFeatureSSSE3 = (0 + 9), - CpuFeatureSSE4_1 = (0 + 19), - CpuFeatureSSE4_2 = (0 + 20), - CpuFeatureMOVBE = (0 + 22), - CpuFeaturePOPCNT = (0 + 23), - CpuFeatureAES = (0 + 25), - CpuFeatureAVX = (0 + 28), - CpuFeatureF16C = (0 + 29), - CpuFeatureRDRND = (0 + 30), - // 31 is always zero and we've used it for the QSimdInitialized - - // in level 7, leaf 0, EBX - CpuFeatureBMI = (32 + 3), - CpuFeatureHLE = (32 + 4), - CpuFeatureAVX2 = (32 + 5), - CpuFeatureBMI2 = (32 + 8), - CpuFeatureRTM = (32 + 11), - CpuFeatureAVX512F = (32 + 16), - CpuFeatureAVX512DQ = (32 + 17), - CpuFeatureRDSEED = (32 + 18), - CpuFeatureAVX512IFMA = (32 + 21), - CpuFeatureAVX512PF = (32 + 26), - CpuFeatureAVX512ER = (32 + 27), - CpuFeatureAVX512CD = (32 + 28), - CpuFeatureSHA = (32 + 29), - CpuFeatureAVX512BW = (32 + 30), - CpuFeatureAVX512VL = (32 + 31), - - // in level 7, leaf 0, ECX (out of order, for now) - CpuFeatureAVX512VBMI = 2, // uses the bit for DTES64 #endif // used only to indicate that the CPU detection was initialised @@ -343,84 +282,6 @@ enum CPUFeatures { }; static const quint64 qCompilerCpuFeatures = 0 -#if defined __SHA__ - | (Q_UINT64_C(1) << CpuFeatureSHA) -#endif -#if defined __AES__ - | (Q_UINT64_C(1) << CpuFeatureAES) -#endif -#if defined __RTM__ - | (Q_UINT64_C(1) << CpuFeatureRTM) -#endif -#ifdef __RDRND__ - | (Q_UINT64_C(1) << CpuFeatureRDRND) -#endif -#ifdef __RDSEED__ - | (Q_UINT64_C(1) << CpuFeatureRDSEED) -#endif -#if defined __BMI__ - | (Q_UINT64_C(1) << CpuFeatureBMI) -#endif -#if defined __BMI2__ - | (Q_UINT64_C(1) << CpuFeatureBMI2) -#endif -#if defined __F16C__ - | (Q_UINT64_C(1) << CpuFeatureF16C) -#endif -#if defined __POPCNT__ - | (Q_UINT64_C(1) << CpuFeaturePOPCNT) -#endif -#if defined __MOVBE__ // GCC and Clang don't seem to define this - | (Q_UINT64_C(1) << CpuFeatureMOVBE) -#endif -#if defined __AVX512F__ - | (Q_UINT64_C(1) << CpuFeatureAVX512F) -#endif -#if defined __AVX512CD__ - | (Q_UINT64_C(1) << CpuFeatureAVX512CD) -#endif -#if defined __AVX512ER__ - | (Q_UINT64_C(1) << CpuFeatureAVX512ER) -#endif -#if defined __AVX512PF__ - | (Q_UINT64_C(1) << CpuFeatureAVX512PF) -#endif -#if defined __AVX512BW__ - | (Q_UINT64_C(1) << CpuFeatureAVX512BW) -#endif -#if defined __AVX512DQ__ - | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) -#endif -#if defined __AVX512VL__ - | (Q_UINT64_C(1) << CpuFeatureAVX512VL) -#endif -#if defined __AVX512IFMA__ - | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) -#endif -#if defined __AVX512VBMI__ - | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI) -#endif -#if defined __AVX2__ - | (Q_UINT64_C(1) << CpuFeatureAVX2) -#endif -#if defined __AVX__ - | (Q_UINT64_C(1) << CpuFeatureAVX) -#endif -#if defined __SSE4_2__ - | (Q_UINT64_C(1) << CpuFeatureSSE4_2) -#endif -#if defined __SSE4_1__ - | (Q_UINT64_C(1) << CpuFeatureSSE4_1) -#endif -#if defined __SSSE3__ - | (Q_UINT64_C(1) << CpuFeatureSSSE3) -#endif -#if defined __SSE3__ - | (Q_UINT64_C(1) << CpuFeatureSSE3) -#endif -#if defined __SSE2__ - | (Q_UINT64_C(1) << CpuFeatureSSE2) -#endif #if defined __ARM_NEON__ | (Q_UINT64_C(1) << CpuFeatureNEON) #endif @@ -434,30 +295,28 @@ static const quint64 qCompilerCpuFeatures = 0 | (Q_UINT64_C(1) << CpuFeatureDSPR2) #endif ; +#endif -#ifdef Q_ATOMIC_INT64_IS_SUPPORTED -extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1]; +#ifdef QT_BOOTSTRAPPED +static inline quint64 qCpuFeatures() +{ + return QSimdInitialized; +} #else -extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2]; -#endif +extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1]; Q_CORE_EXPORT void qDetectCpuFeatures(); static inline quint64 qCpuFeatures() { quint64 features = qt_cpu_features[0].load(); -#ifndef Q_ATOMIC_INT64_IS_SUPPORTED - features |= quint64(qt_cpu_features[1].load()) << 32; -#endif if (Q_UNLIKELY(features == 0)) { qDetectCpuFeatures(); features = qt_cpu_features[0].load(); -#ifndef Q_ATOMIC_INT64_IS_SUPPORTED - features |= quint64(qt_cpu_features[1].load()) << 32; -#endif Q_ASSUME(features != 0); } return features; } +#endif #define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (Q_UINT64_C(1) << CpuFeature ## feature)) \ || (qCpuFeatures() & (Q_UINT64_C(1) << CpuFeature ## feature))) diff --git a/src/corelib/tools/qsimd_x86.cpp b/src/corelib/tools/qsimd_x86.cpp new file mode 100644 index 0000000000..8275f964d8 --- /dev/null +++ b/src/corelib/tools/qsimd_x86.cpp @@ -0,0 +1,98 @@ +// This is a generated file. DO NOT EDIT. +// Please see util/x86simdgen/generate.pl +#include <qglobal.h> + +static const char features_string[] = + " sse2\0" + " sse3\0" + " ssse3\0" + " fma\0" + " sse4.1\0" + " sse4.2\0" + " movbe\0" + " popcnt\0" + " aes\0" + " avx\0" + " f16c\0" + " rdrnd\0" + " bmi\0" + " hle\0" + " avx2\0" + " bmi2\0" + " rtm\0" + " avx512f\0" + " avx512dq\0" + " rdseed\0" + " avx512ifma\0" + " avx512pf\0" + " avx512er\0" + " avx512cd\0" + " sha\0" + " avx512bw\0" + " avx512vl\0" + " avx512vbmi\0" + " avx512vbmi2\0" + " gfni\0" + " vaes\0" + " avx512vnni\0" + " avx512bitalg\0" + " avx512vpopcntdq\0" + " avx5124nniw\0" + " avx5124fmaps\0" + "\0"; + +static const quint16 features_indices[] = { + 306, 0, 6, 12, 19, 24, 32, 40, + 47, 55, 60, 65, 71, 78, 83, 88, + 94, 100, 105, 114, 124, 132, 144, 154, + 164, 174, 179, 189, 199, 211, 224, 230, + 236, 248, 262, 279, 292 +}; + +enum X86CpuidLeaves { + Leaf1ECX, + Leaf1EDX, + Leaf7_0EBX, + Leaf7_0ECX, + Leaf7_0EDX, + X86CpuidMaxLeaf +}; + +static const quint8 x86_locators[] = { + Leaf1EDX*32 + 26, // sse2 + Leaf1ECX*32 + 0, // sse3 + Leaf1ECX*32 + 9, // ssse3 + Leaf1ECX*32 + 12, // fma + Leaf1ECX*32 + 19, // sse4.1 + Leaf1ECX*32 + 20, // sse4.2 + Leaf1ECX*32 + 22, // movbe + Leaf1ECX*32 + 23, // popcnt + Leaf1ECX*32 + 25, // aes + Leaf1ECX*32 + 28, // avx + Leaf1ECX*32 + 29, // f16c + Leaf1ECX*32 + 30, // rdrnd + Leaf7_0EBX*32 + 3, // bmi + Leaf7_0EBX*32 + 4, // hle + Leaf7_0EBX*32 + 5, // avx2 + Leaf7_0EBX*32 + 8, // bmi2 + Leaf7_0EBX*32 + 11, // rtm + Leaf7_0EBX*32 + 16, // avx512f + Leaf7_0EBX*32 + 17, // avx512dq + Leaf7_0EBX*32 + 18, // rdseed + Leaf7_0EBX*32 + 21, // avx512ifma + Leaf7_0EBX*32 + 26, // avx512pf + Leaf7_0EBX*32 + 27, // avx512er + Leaf7_0EBX*32 + 28, // avx512cd + Leaf7_0EBX*32 + 29, // sha + Leaf7_0EBX*32 + 30, // avx512bw + Leaf7_0EBX*32 + 31, // avx512vl + Leaf7_0ECX*32 + 1, // avx512vbmi + Leaf7_0ECX*32 + 6, // avx512vbmi2 + Leaf7_0ECX*32 + 8, // gfni + Leaf7_0ECX*32 + 9, // vaes + Leaf7_0ECX*32 + 11, // avx512vnni + Leaf7_0ECX*32 + 12, // avx512bitalg + Leaf7_0ECX*32 + 14, // avx512vpopcntdq + Leaf7_0EDX*32 + 2, // avx5124nniw + Leaf7_0EDX*32 + 3 // avx5124fmaps +}; diff --git a/src/corelib/tools/qsimd_x86_p.h b/src/corelib/tools/qsimd_x86_p.h new file mode 100644 index 0000000000..45d5f2895f --- /dev/null +++ b/src/corelib/tools/qsimd_x86_p.h @@ -0,0 +1,227 @@ +// This is a generated file. DO NOT EDIT. +// Please see util/x86simdgen/generate.pl +#ifndef QSIMD_P_H +# error "Please include <private/qsimd_p.h> instead" +#endif +#ifndef QSIMD_X86_P_H +#define QSIMD_X86_P_H + +#include "qsimd_p.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +// Macros for QT_FUNCTION_TARGET (for Clang and GCC) +#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2" +#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3" +#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3" +#define QT_FUNCTION_TARGET_STRING_FMA "fma" +#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1" +#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2" +#define QT_FUNCTION_TARGET_STRING_MOVBE "movbe" +#define QT_FUNCTION_TARGET_STRING_POPCNT "popcnt" +#define QT_FUNCTION_TARGET_STRING_AES "aes,sse4.2" +#define QT_FUNCTION_TARGET_STRING_AVX "avx" +#define QT_FUNCTION_TARGET_STRING_F16C "f16c" +#define QT_FUNCTION_TARGET_STRING_RDRND "rdrnd" +#define QT_FUNCTION_TARGET_STRING_BMI "bmi" +#define QT_FUNCTION_TARGET_STRING_HLE "hle" +#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2" +#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2" +#define QT_FUNCTION_TARGET_STRING_RTM "rtm" +#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f" +#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq" +#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed" +#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma" +#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf" +#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er" +#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd" +#define QT_FUNCTION_TARGET_STRING_SHA "sha" +#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw" +#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl" +#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi" +#define QT_FUNCTION_TARGET_STRING_AVX512VBMI2 "avx512vbmi2" +#define QT_FUNCTION_TARGET_STRING_GFNI "gfni" +#define QT_FUNCTION_TARGET_STRING_VAES "vaes" +#define QT_FUNCTION_TARGET_STRING_AVX512VNNI "avx512vnni" +#define QT_FUNCTION_TARGET_STRING_AVX512BITALG "avx512bitalg" +#define QT_FUNCTION_TARGET_STRING_AVX512VPOPCNTDQ "avx512vpopcntdq" +#define QT_FUNCTION_TARGET_STRING_AVX5124NNIW "avx5124nniw" +#define QT_FUNCTION_TARGET_STRING_AVX5124FMAPS "avx5124fmaps" + +enum CPUFeatures { + // in CPUID Leaf 1, EDX: + CpuFeatureSSE2 = 1, + + // in CPUID Leaf 1, ECX: + CpuFeatureSSE3 = 2, + CpuFeatureSSSE3 = 3, + CpuFeatureFMA = 4, + CpuFeatureSSE4_1 = 5, + CpuFeatureSSE4_2 = 6, + CpuFeatureMOVBE = 7, + CpuFeaturePOPCNT = 8, + CpuFeatureAES = 9, + CpuFeatureAVX = 10, + CpuFeatureF16C = 11, + CpuFeatureRDRND = 12, + + // in CPUID Leaf 7, Sub-leaf 0, EBX: + CpuFeatureBMI = 13, + CpuFeatureHLE = 14, + CpuFeatureAVX2 = 15, + CpuFeatureBMI2 = 16, + CpuFeatureRTM = 17, + CpuFeatureAVX512F = 18, + CpuFeatureAVX512DQ = 19, + CpuFeatureRDSEED = 20, + CpuFeatureAVX512IFMA = 21, + CpuFeatureAVX512PF = 22, + CpuFeatureAVX512ER = 23, + CpuFeatureAVX512CD = 24, + CpuFeatureSHA = 25, + CpuFeatureAVX512BW = 26, + CpuFeatureAVX512VL = 27, + + // in CPUID Leaf 7, Sub-leaf 0, ECX: + CpuFeatureAVX512VBMI = 28, + CpuFeatureAVX512VBMI2 = 29, + CpuFeatureGFNI = 30, + CpuFeatureVAES = 31, + CpuFeatureAVX512VNNI = 32, + CpuFeatureAVX512BITALG = 33, + CpuFeatureAVX512VPOPCNTDQ = 34, + + // in CPUID Leaf 7, Sub-leaf 0, EDX: + CpuFeatureAVX5124NNIW = 35, + CpuFeatureAVX5124FMAPS = 36, + + // used only to indicate that the CPU detection was initialized + QSimdInitialized = 1 +}; + +static const quint64 qCompilerCpuFeatures = 0 +#ifdef __SSE2__ + | (Q_UINT64_C(1) << CpuFeatureSSE2) +#endif +#ifdef __SSE3__ + | (Q_UINT64_C(1) << CpuFeatureSSE3) +#endif +#ifdef __SSSE3__ + | (Q_UINT64_C(1) << CpuFeatureSSSE3) +#endif +#ifdef __FMA__ + | (Q_UINT64_C(1) << CpuFeatureFMA) +#endif +#ifdef __SSE4_1__ + | (Q_UINT64_C(1) << CpuFeatureSSE4_1) +#endif +#ifdef __SSE4_2__ + | (Q_UINT64_C(1) << CpuFeatureSSE4_2) +#endif +#ifdef __MOVBE__ + | (Q_UINT64_C(1) << CpuFeatureMOVBE) +#endif +#ifdef __POPCNT__ + | (Q_UINT64_C(1) << CpuFeaturePOPCNT) +#endif +#ifdef __AES__ + | (Q_UINT64_C(1) << CpuFeatureAES) +#endif +#ifdef __AVX__ + | (Q_UINT64_C(1) << CpuFeatureAVX) +#endif +#ifdef __F16C__ + | (Q_UINT64_C(1) << CpuFeatureF16C) +#endif +#ifdef __RDRND__ + | (Q_UINT64_C(1) << CpuFeatureRDRND) +#endif +#ifdef __BMI__ + | (Q_UINT64_C(1) << CpuFeatureBMI) +#endif +#ifdef __HLE__ + | (Q_UINT64_C(1) << CpuFeatureHLE) +#endif +#ifdef __AVX2__ + | (Q_UINT64_C(1) << CpuFeatureAVX2) +#endif +#ifdef __BMI2__ + | (Q_UINT64_C(1) << CpuFeatureBMI2) +#endif +#ifdef __RTM__ + | (Q_UINT64_C(1) << CpuFeatureRTM) +#endif +#ifdef __AVX512F__ + | (Q_UINT64_C(1) << CpuFeatureAVX512F) +#endif +#ifdef __AVX512DQ__ + | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) +#endif +#ifdef __RDSEED__ + | (Q_UINT64_C(1) << CpuFeatureRDSEED) +#endif +#ifdef __AVX512IFMA__ + | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) +#endif +#ifdef __AVX512PF__ + | (Q_UINT64_C(1) << CpuFeatureAVX512PF) +#endif +#ifdef __AVX512ER__ + | (Q_UINT64_C(1) << CpuFeatureAVX512ER) +#endif +#ifdef __AVX512CD__ + | (Q_UINT64_C(1) << CpuFeatureAVX512CD) +#endif +#ifdef __SHA__ + | (Q_UINT64_C(1) << CpuFeatureSHA) +#endif +#ifdef __AVX512BW__ + | (Q_UINT64_C(1) << CpuFeatureAVX512BW) +#endif +#ifdef __AVX512VL__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VL) +#endif +#ifdef __AVX512VBMI__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI) +#endif +#ifdef __AVX512VBMI2__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI2) +#endif +#ifdef __GFNI__ + | (Q_UINT64_C(1) << CpuFeatureGFNI) +#endif +#ifdef __VAES__ + | (Q_UINT64_C(1) << CpuFeatureVAES) +#endif +#ifdef __AVX512VNNI__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VNNI) +#endif +#ifdef __AVX512BITALG__ + | (Q_UINT64_C(1) << CpuFeatureAVX512BITALG) +#endif +#ifdef __AVX512VPOPCNTDQ__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VPOPCNTDQ) +#endif +#ifdef __AVX5124NNIW__ + | (Q_UINT64_C(1) << CpuFeatureAVX5124NNIW) +#endif +#ifdef __AVX5124FMAPS__ + | (Q_UINT64_C(1) << CpuFeatureAVX5124FMAPS) +#endif + ; + +QT_END_NAMESPACE + +#endif // QSIMD_X86_P_H + diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b2dcb6d8da..51bc8359a0 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -4883,6 +4883,50 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const return qt_ends_with(*this, c, cs); } +/*! + Returns \c true if the string only contains uppercase letters, + otherwise returns \c false. + \since 5.12 + + \sa QChar::isUpper(), isLower() +*/ +bool QString::isUpper() const +{ + if (isEmpty()) + return false; + + const QChar *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!d[i].isUpper()) + return false; + } + + return true; +} + +/*! + Returns \c true if the string only contains lowercase letters, + otherwise returns \c false. + \since 5.12 + + \sa QChar::isLower(), isUpper() + */ +bool QString::isLower() const +{ + if (isEmpty()) + return false; + + const QChar *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!d[i].isLower()) + return false; + } + + return true; +} + static QByteArray qt_convert_to_latin1(QStringView string); QByteArray QString::toLatin1_helper(const QString &string) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index f27f7efa2b..447f000486 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -409,6 +409,9 @@ public: bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool isUpper() const; + bool isLower() const; + Q_REQUIRED_RESULT 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; diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index daa7dc1531..db6be581ec 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -66,11 +66,10 @@ static QTimeZonePrivate *newBackendTimeZone() return new QAndroidTimeZonePrivate(); #elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED) return new QTzTimeZonePrivate(); - // Registry based timezone backend not available on WinRT -#elif defined Q_OS_WIN - return new QWinTimeZonePrivate(); #elif QT_CONFIG(icu) return new QIcuTimeZonePrivate(); +#elif defined Q_OS_WIN + return new QWinTimeZonePrivate(); #else return new QUtcTimeZonePrivate(); #endif // System Locales @@ -93,11 +92,10 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId) return new QAndroidTimeZonePrivate(ianaId); #elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED) return new QTzTimeZonePrivate(ianaId); - // Registry based timezone backend not available on WinRT -#elif defined Q_OS_WIN - return new QWinTimeZonePrivate(ianaId); #elif QT_CONFIG(icu) return new QIcuTimeZonePrivate(ianaId); +#elif defined Q_OS_WIN + return new QWinTimeZonePrivate(ianaId); #else return new QUtcTimeZonePrivate(ianaId); #endif // System Locales @@ -822,8 +820,8 @@ bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId) // IDs as availableTimeZoneIds() may be slow if (!QTimeZonePrivate::isValidId(ianaId)) return false; - const QList<QByteArray> tzIds = availableTimeZoneIds(); - return std::binary_search(tzIds.begin(), tzIds.end(), ianaId); + return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) || + global_tz->backend->isTimeZoneIdAvailable(ianaId); } static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByteArray> &l2) diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 1a5135f103..2b6c2ea6a5 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -486,6 +486,13 @@ QByteArray QTimeZonePrivate::systemTimeZoneId() const return QByteArray(); } +bool QTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const +{ + // Fall-back implementation, can be made faster in subclasses + const QList<QByteArray> tzIds = availableTimeZoneIds(); + return std::binary_search(tzIds.begin(), tzIds.end(), ianaId); +} + QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const { return QList<QByteArray>(); @@ -864,6 +871,17 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const return utcQByteArray(); } +bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const +{ + for (int i = 0; i < utcDataTableSize; ++i) { + const QUtcData *data = utcData(i); + if (utcId(data) == ianaId) { + return true; + } + } + return false; +} + QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const { QList<QByteArray> result; diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index 4d357111f2..c9a5726216 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -128,6 +128,7 @@ public: virtual QByteArray systemTimeZoneId() const; + virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const; virtual QList<QByteArray> availableTimeZoneIds() const; virtual QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const; virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const; @@ -204,6 +205,7 @@ public: QByteArray systemTimeZoneId() const override; + bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override; QList<QByteArray> availableTimeZoneIds() const override; QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; QList<QByteArray> availableTimeZoneIds(int utcOffset) const override; @@ -323,6 +325,7 @@ public: QByteArray systemTimeZoneId() const override; + bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override; QList<QByteArray> availableTimeZoneIds() const override; QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 6a5df6272a..f1735a80e7 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -1098,6 +1098,11 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const return ianaId; } +bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const +{ + return tzZones->contains(ianaId); +} + QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const { QList<QByteArray> result = tzZones->keys(); diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp index 8bde07c710..ec91b7e8a8 100644 --- a/src/corelib/tools/qtimezoneprivate_win.cpp +++ b/src/corelib/tools/qtimezoneprivate_win.cpp @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE #ifndef Q_OS_WINRT +// The registry-based timezone backend is not available on WinRT, which falls back to equivalent APIs. #define QT_USE_REGISTRY_TIMEZONE 1 #endif diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 72224f280d..30f7edb5f2 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -159,16 +159,18 @@ qtConfig(timezone) { SOURCES += \ tools/qtimezone.cpp \ tools/qtimezoneprivate.cpp - !nacl:darwin: \ + !nacl:darwin: { SOURCES += tools/qtimezoneprivate_mac.mm - else: android:!android-embedded: \ + } else: android:!android-embedded: { SOURCES += tools/qtimezoneprivate_android.cpp - else: unix: \ + } else: unix: { SOURCES += tools/qtimezoneprivate_tz.cpp - else: win32: \ - SOURCES += tools/qtimezoneprivate_win.cpp - qtConfig(icu): \ + qtConfig(icu): SOURCES += tools/qtimezoneprivate_icu.cpp + } else: qtConfig(icu): { SOURCES += tools/qtimezoneprivate_icu.cpp + } else: win32: { + SOURCES += tools/qtimezoneprivate_win.cpp + } } qtConfig(datetimeparser) { @@ -179,7 +181,9 @@ qtConfig(datetimeparser) { qtConfig(regularexpression) { QMAKE_USE_PRIVATE += pcre2 - HEADERS += tools/qregularexpression.h + HEADERS += \ + tools/qregularexpression.h \ + tools/qregularexpression_p.h SOURCES += tools/qregularexpression.cpp } |