Skip to content

Commit

Permalink
Add qHash(QRegExp) and qHash(QRegularExpression)
Browse files Browse the repository at this point in the history
QReg*Exp*s can be compared for equality,
so qHash should be overloaded, too.

There was a (poor) private implementation of qHash(QRegExpEngineKey)
already, which has now been replaced with a better one (the old one
didn't take into account all the fields that make up equality,
producing unnecessary collisions).

[ChangeLog][QtCore][QRegExp] Added qHash(QRegExp).
[ChangeLog][QtCore][QRegularExpression] Added qHash(QRegularExpression).

Change-Id: I1d22fbcc0508018a3f94b4c24571b13ba6e07df2
Reviewed-by: Giuseppe D'Angelo <[email protected]>
  • Loading branch information
marc-kdab committed May 5, 2015
1 parent 85d9403 commit 87155a8
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 5 deletions.
30 changes: 25 additions & 5 deletions src/corelib/tools/qregexp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<int>, Q_MOVABLE_TYPE);
Expand Down Expand Up @@ -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<QRegExpEngineKey, QRegExpEngine> EngineCache;
Q_GLOBAL_STATIC(EngineCache, globalEngineCache)
static QBasicMutex globalEngineCacheMutex;
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/corelib/tools/qregexp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -104,6 +107,8 @@ class Q_CORE_EXPORT QRegExp

static QString escape(const QString &str);

friend Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW;

private:
QRegExpPrivate *priv;
};
Expand Down
16 changes: 16 additions & 0 deletions src/corelib/tools/qregularexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#ifndef QT_NO_REGULAREXPRESSION

#include <QtCore/qcoreapplication.h>
#include <QtCore/qhashfunctions.h>
#include <QtCore/qmutex.h>
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/corelib/tools/qregularexpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -139,6 +142,7 @@ class Q_CORE_EXPORT QRegularExpression
friend class QRegularExpressionMatch;
friend struct QRegularExpressionMatchPrivate;
friend class QRegularExpressionMatchIterator;
friend Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW;

QRegularExpression(QRegularExpressionPrivate &dd);
QExplicitlySharedDataPointer<QRegularExpressionPrivate> d;
Expand Down
3 changes: 3 additions & 0 deletions tests/auto/corelib/tools/qregexp/tst_qregexp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1424,29 +1424,34 @@ 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));

QRegularExpression re3(re1);

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));
}
Expand Down

0 comments on commit 87155a8

Please sign in to comment.