diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index cd8c393d51..5aa9d54843 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -38,6 +38,7 @@ #include "qcache.h" #include "qdatastream.h" #include "qdebug.h" +#include "qhashfunctions.h" #include "qlist.h" #include "qmap.h" #include "qmutex.h" @@ -882,6 +883,15 @@ static bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key && key1.cs == key2.cs; } +static uint qHash(const QRegExpEngineKey &key, uint seed = 0) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.pattern); + seed = hash(seed, key.patternSyntax); + seed = hash(seed, key.cs); + return seed; +} + class QRegExpEngine; //Q_DECLARE_TYPEINFO(QVector, Q_MOVABLE_TYPE); @@ -3807,11 +3817,6 @@ struct QRegExpPrivate }; #if !defined(QT_NO_REGEXP_OPTIM) -uint qHash(const QRegExpEngineKey &key, uint seed = 0) Q_DECL_NOTHROW -{ - return qHash(key.pattern, seed); -} - typedef QCache EngineCache; Q_GLOBAL_STATIC(EngineCache, globalEngineCache) static QBasicMutex globalEngineCacheMutex; @@ -4032,6 +4037,21 @@ bool QRegExp::operator==(const QRegExp &rx) const return priv->engineKey == rx.priv->engineKey && priv->minimal == rx.priv->minimal; } +/*! + \since 5.6 + \relates QRegExp + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.priv->engineKey); + seed = hash(seed, key.priv->minimal); + return seed; +} + /*! \fn bool QRegExp::operator!=(const QRegExp &rx) const diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index b08a8bd282..f384e6c51f 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -45,6 +45,9 @@ QT_BEGIN_NAMESPACE struct QRegExpPrivate; class QStringList; +class QRegExp; + +Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed = 0) Q_DECL_NOTHROW; class Q_CORE_EXPORT QRegExp { @@ -104,6 +107,8 @@ public: static QString escape(const QString &str); + friend Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW; + private: QRegExpPrivate *priv; }; diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 9950b90720..18dd2d12c2 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -38,6 +38,7 @@ #ifndef QT_NO_REGULAREXPRESSION #include +#include #include #include #include @@ -1837,6 +1838,21 @@ bool QRegularExpression::operator==(const QRegularExpression &re) const \sa operator==() */ +/*! + \since 5.6 + \relates QRegularExpression + + Returns the hash value for \a key, using + \a seed to seed the calculation. +*/ +uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.d->pattern); + seed = hash(seed, key.d->patternOptions); + return seed; +} + /*! Escapes all characters of \a str so that they no longer have any special meaning when used as a regular expression pattern string, and returns diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index d2abfc7701..2bca6a211b 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -49,6 +49,9 @@ QT_BEGIN_NAMESPACE class QRegularExpressionMatch; class QRegularExpressionMatchIterator; struct QRegularExpressionPrivate; +class QRegularExpression; + +Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed = 0) Q_DECL_NOTHROW; class Q_CORE_EXPORT QRegularExpression { @@ -139,6 +142,7 @@ private: friend class QRegularExpressionMatch; friend struct QRegularExpressionMatchPrivate; friend class QRegularExpressionMatchIterator; + friend Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW; QRegularExpression(QRegularExpressionPrivate &dd); QExplicitlySharedDataPointer d; diff --git a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp b/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp index fefdec7496..b9a3fc13c5 100644 --- a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp +++ b/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp @@ -1224,6 +1224,9 @@ void tst_QRegExp::operator_eq() for (int j = 0; j < I * J * K * ELL; ++j) { QCOMPARE(rxtable[i] == rxtable[j], i / ELL == j / ELL); QCOMPARE(rxtable[i] != rxtable[j], i / ELL != j / ELL); + // this just happens to have no hash collisions. If at some point + // we get collisions, restrict the test to only equal elements: + QCOMPARE(qHash(rxtable[i]) == qHash(rxtable[j]), i / ELL == j / ELL); } } } diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 99f6a31267..6b7614b7b9 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -1424,6 +1424,7 @@ static void verifyEquality(const QRegularExpression &re1, const QRegularExpressi { QVERIFY(re1 == re2); QVERIFY(re2 == re1); + QCOMPARE(qHash(re1), qHash(re2)); QVERIFY(!(re1 != re2)); QVERIFY(!(re2 != re1)); @@ -1431,22 +1432,26 @@ static void verifyEquality(const QRegularExpression &re1, const QRegularExpressi QVERIFY(re1 == re3); QVERIFY(re3 == re1); + QCOMPARE(qHash(re1), qHash(re3)); QVERIFY(!(re1 != re3)); QVERIFY(!(re3 != re1)); QVERIFY(re2 == re3); QVERIFY(re3 == re2); + QCOMPARE(qHash(re2), qHash(re3)); QVERIFY(!(re2 != re3)); QVERIFY(!(re3 != re2)); re3 = re2; QVERIFY(re1 == re3); QVERIFY(re3 == re1); + QCOMPARE(qHash(re1), qHash(re3)); QVERIFY(!(re1 != re3)); QVERIFY(!(re3 != re1)); QVERIFY(re2 == re3); QVERIFY(re3 == re2); + QCOMPARE(qHash(re2), qHash(re3)); QVERIFY(!(re2 != re3)); QVERIFY(!(re3 != re2)); }