From 66ff3f7fa4cd157d9b79e2fb7fe8cce98c913e08 Mon Sep 17 00:00:00 2001
From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Date: Sat, 27 Apr 2013 01:02:06 +0200
Subject: [PATCH] Add qt_hash(QStringRef) overload

This enables fixing a performance regression compared to Qt 4.
Also, add some qt_hash tests.

Change-Id: Id830e17dec99fb67e5930c80029ac2233b2f427e
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
---
 src/corelib/tools/qhash.cpp                  | 25 ++++++++++++++++----
 src/corelib/tools/qhash.h                    |  1 +
 tests/auto/corelib/tools/qhash/tst_qhash.cpp | 22 +++++++++++++++++
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index ed756cbeb60..59e7a979dcd 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -235,17 +235,16 @@ static void qt_initialize_qhash_seed()
     \internal
 
     Private copy of the implementation of the Qt 4 qHash algorithm for strings,
+    (that is, QChar-based arrays, so all QString-like classes),
     to be used wherever the result is somehow stored or reused across multiple
     Qt versions. The public qHash implementation can change at any time,
     therefore one must not rely on the fact that it will always give the same
     results.
 
-    This function must *never* change its results.
+    The qt_hash functions must *never* change their results.
 */
-uint qt_hash(const QString &key) Q_DECL_NOTHROW
+static uint qt_hash(const QChar *p, int n) Q_DECL_NOTHROW
 {
-    const QChar *p = key.unicode();
-    int n = key.size();
     uint h = 0;
 
     while (n--) {
@@ -256,6 +255,24 @@ uint qt_hash(const QString &key) Q_DECL_NOTHROW
     return h;
 }
 
+/*!
+    \internal
+    \overload
+*/
+uint qt_hash(const QString &key) Q_DECL_NOTHROW
+{
+    return qt_hash(key.unicode(), key.size());
+}
+
+/*!
+    \internal
+    \overload
+*/
+uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW
+{
+    return qt_hash(key.unicode(), key.size());
+}
+
 /*
     The prime_deltas array is a table of selected prime values, even
     though it doesn't look like one. The primes we are using are 1,
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 5d9238f4538..e99a67d1e3a 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -92,6 +92,7 @@ Q_CORE_EXPORT uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
 Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
 Q_CORE_EXPORT uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
 Q_CORE_EXPORT uint qt_hash(const QString &key) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
 
 #if defined(Q_CC_MSVC)
 #pragma warning( push )
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 1cbf1812860..71428310b83 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -75,6 +75,9 @@ private slots:
     void const_shared_null();
     void twoArguments_qHash();
     void initializerList();
+
+    void qthash_data();
+    void qthash();
 };
 
 struct Foo {
@@ -1330,5 +1333,24 @@ void tst_QHash::initializerList()
 #endif
 }
 
+void tst_QHash::qthash_data()
+{
+    QTest::addColumn<QString>("key");
+    QTest::addColumn<uint>("hash");
+
+    QTest::newRow("null") << QString() << 0u;
+    QTest::newRow("empty") << QStringLiteral("") << 0u;
+    QTest::newRow("abcdef") << QStringLiteral("abcdef") << 108567222u;
+    QTest::newRow("tqbfjotld") << QStringLiteral("The quick brown fox jumps over the lazy dog") << 140865879u;
+    QTest::newRow("42") << QStringLiteral("42") << 882u;
+}
+
+void tst_QHash::qthash()
+{
+    QFETCH(QString, key);
+    const uint result = qt_hash(key);
+    QTEST(result, "hash");
+}
+
 QTEST_APPLESS_MAIN(tst_QHash)
 #include "tst_qhash.moc"
-- 
GitLab