aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-02-11 10:29:25 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-02-11 10:56:12 +0100
commit76f05314f5eb2ab3a13656647e99e20575471bed (patch)
tree98fd86936b2cb24df633afc3233929ff59475235 /src
parent082cc7de37a4f728607cc4a669a2daa511e1216f (diff)
QHashedString(Ref): Use QStringView internally
We cannot store a QStringView internally, as that would increase the size of our objects (QHashedString(Ref) does not support strings with sizes that do not fit into 32bit, thus it can store the hash and the size in one 64 bit block). What we can however do is to construct a QStringView on demand (which is cheap), and use its methods. The benefits are twofold: We get rid of some accidental complexity in qtdeclarative; and the code in QStringView is actually SIMD optimized. Change-Id: I2445a2d5a16b253f4971d7f3be0e1b274326eacb Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp81
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h44
-rw-r--r--src/qml/qml/ftw/qstringhash_p.h2
3 files changed, 28 insertions, 99 deletions
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp
index 4553fa9359..b822e1b120 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -41,60 +41,6 @@
QT_BEGIN_NAMESPACE
-// Copy of QString's qMemCompare
-bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
-{
- Q_ASSERT((lhs && rhs) || !length);
- const quint16 *a = (const quint16 *)lhs;
- const quint16 *b = (const quint16 *)rhs;
-
- if (a == b || !length)
- return true;
-
- union {
- const quint16 *w;
- const quint32 *d;
- quintptr value;
- } sa, sb;
- sa.w = a;
- sb.w = b;
-
- // check alignment
- if ((sa.value & 2) == (sb.value & 2)) {
- // both addresses have the same alignment
- if (sa.value & 2) {
- // both addresses are not aligned to 4-bytes boundaries
- // compare the first character
- if (*sa.w != *sb.w)
- return false;
- --length;
- ++sa.w;
- ++sb.w;
-
- // now both addresses are 4-bytes aligned
- }
-
- // both addresses are 4-bytes aligned
- // do a fast 32-bit comparison
- const quint32 *e = sa.d + (length >> 1);
- for ( ; sa.d != e; ++sa.d, ++sb.d) {
- if (*sa.d != *sb.d)
- return false;
- }
-
- // do we have a tail?
- return (length & 1) ? *sa.w == *sb.w : true;
- } else {
- // one of the addresses isn't 4-byte aligned but the other is
- const quint16 *e = sa.w + length;
- for ( ; sa.w != e; ++sa.w, ++sb.w) {
- if (*sa.w != *sb.w)
- return false;
- }
- }
- return true;
-}
-
QHashedStringRef QHashedStringRef::mid(int offset, int length) const
{
Q_ASSERT(offset < m_length);
@@ -123,35 +69,20 @@ QVector<QHashedStringRef> QHashedStringRef::split(const QChar sep) const
bool QHashedStringRef::endsWith(const QString &s) const
{
- return s.length() < m_length &&
- QHashedString::compare(s.constData(), m_data + m_length - s.length(), s.length());
+ QStringView view {m_data, m_length};
+ return view.endsWith(s);
}
bool QHashedStringRef::startsWith(const QString &s) const
{
- return s.length() < m_length &&
- QHashedString::compare(s.constData(), m_data, s.length());
-}
-
-static int findChar(const QChar *str, int len, QChar ch, int from)
-{
- const ushort *s = (const ushort *)str;
- ushort c = ch.unicode();
- if (from < 0)
- from = qMax(from + len, 0);
- if (from < len) {
- const ushort *n = s + from - 1;
- const ushort *e = s + len;
- while (++n != e)
- if (*n == c)
- return n - s;
- }
- return -1;
+ QStringView view {m_data, m_length};
+ return view.startsWith(s);
}
int QHashedStringRef::indexOf(const QChar &c, int from) const
{
- return findChar(m_data, m_length, c, from);
+ QStringView view {m_data, m_length};
+ return view.indexOf(c, from);
}
QString QHashedStringRef::toString() const
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index c5353acdb1..8f0bd74c53 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -79,7 +79,6 @@ public:
inline quint32 hash() const;
inline quint32 existingHash() const;
- static bool compare(const QChar *lhs, const QChar *rhs, int length);
static inline bool compare(const QChar *lhs, const char *rhs, int length);
static inline bool compare(const char *lhs, const char *rhs, int length);
@@ -217,9 +216,10 @@ bool QHashedString::operator==(const QHashedString &string) const
bool QHashedString::operator==(const QHashedStringRef &string) const
{
- return length() == string.m_length &&
- (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
- QHashedString::compare(constData(), string.m_data, string.m_length);
+ if (m_hash && string.m_hash && m_hash != string.m_hash)
+ return false;
+ QStringView otherView {string.m_data, string.m_length};
+ return static_cast<const QString &>(*this) == otherView;
}
quint32 QHashedString::hash() const
@@ -277,22 +277,26 @@ QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o)
bool QHashedStringRef::operator==(const QString &string) const
{
- return m_length == string.length() &&
- QHashedString::compare(string.constData(), m_data, m_length);
+ QStringView view {m_data, m_length};
+ return view == string;
}
bool QHashedStringRef::operator==(const QHashedString &string) const
{
- return m_length == string.length() &&
- (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
- QHashedString::compare(string.constData(), m_data, m_length);
+ if (m_hash && string.m_hash && m_hash != string.m_hash)
+ return false;
+ QStringView view {m_data, m_length};
+ QStringView otherView {string.constData(), string.length()};
+ return view == otherView;
}
bool QHashedStringRef::operator==(const QHashedStringRef &string) const
{
- return m_length == string.m_length &&
- (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
- QHashedString::compare(string.m_data, m_data, m_length);
+ if (m_hash && string.m_hash && m_hash != string.m_hash)
+ return false;
+ QStringView view {m_data, m_length};
+ QStringView otherView {string.m_data, string.m_length};
+ return view == otherView;
}
bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
@@ -304,29 +308,22 @@ bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
bool QHashedStringRef::operator!=(const QString &string) const
{
- return m_length != string.length() ||
- !QHashedString::compare(string.constData(), m_data, m_length);
+ return !(*this == string);
}
bool QHashedStringRef::operator!=(const QHashedString &string) const
{
- return m_length != string.length() ||
- (m_hash != string.m_hash && m_hash && string.m_hash) ||
- !QHashedString::compare(string.constData(), m_data, m_length);
+ return !(*this == string);
}
bool QHashedStringRef::operator!=(const QHashedStringRef &string) const
{
- return m_length != string.m_length ||
- (m_hash != string.m_hash && m_hash && string.m_hash) ||
- QHashedString::compare(string.m_data, m_data, m_length);
+ return !(*this == string);
}
bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const
{
- return m_length != string.m_length ||
- (m_hash != string.m_hash && m_hash && string.m_hash) ||
- QHashedString::compare(m_data, string.m_data, m_length);
+ return !(*this == string);
}
QChar *QHashedStringRef::data()
@@ -452,6 +449,7 @@ bool QHashedString::compare(const char *lhs, const char *rhs, int length)
return 0 == ::memcmp(lhs, rhs, length);
}
+
quint32 QHashedString::stringHash(const QChar *data, int length)
{
return QV4::String::createHashValue(data, length, nullptr);
diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h
index c4411b4814..25d66f81d1 100644
--- a/src/qml/qml/ftw/qstringhash_p.h
+++ b/src/qml/qml/ftw/qstringhash_p.h
@@ -164,7 +164,7 @@ public:
inline bool equals(const QHashedStringRef &string) const {
return length == string.length() &&
hash == string.hash() &&
- (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length):
+ (isQString()? string == QStringView {utf16Data(), length}:
QHashedString::compare(string.constData(), cStrData(), length));
}