use libdeflate_crc32() for hashing

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-04-27 03:05:03 +03:00
parent d27075599e
commit facd387374
10 changed files with 22 additions and 126 deletions

View file

@ -11,7 +11,6 @@ set(unifdef_arguments
-UQT_BOOTSTRAPPED -UQT_BOOTSTRAPPED
# not supported # not supported
-UQT_NO_QOBJECT -UQT_NO_QOBJECT
-UQT_NO_COMPRESS
-UQT_NO_THREAD -UQT_NO_THREAD
-UQT_NO_PROCESS -UQT_NO_PROCESS
-UQT_NO_DATASTREAM -UQT_NO_DATASTREAM

View file

@ -46,7 +46,6 @@
// Not supported, used to bootstrap // Not supported, used to bootstrap
#cmakedefine QT_NO_QOBJECT #cmakedefine QT_NO_QOBJECT
#cmakedefine QT_NO_COMPRESS
#cmakedefine QT_NO_THREAD #cmakedefine QT_NO_THREAD
#cmakedefine QT_NO_PROCESS #cmakedefine QT_NO_PROCESS
#cmakedefine QT_NO_DATASTREAM #cmakedefine QT_NO_DATASTREAM

View file

@ -150,7 +150,7 @@ static inline QByteArray normalizeTypeInternal(const char *t, const char *e, boo
{ {
const int len = e - t; const int len = e - t;
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
const uint cachekey = qHash(QByteArray::fromRawData(t, len)); const uint cachekey = qHash(t, len);
QMutexLocker lock(qGlobalNormalizedTypeMutex()); QMutexLocker lock(qGlobalNormalizedTypeMutex());
QByteArray cached = qGlobalNormalizedTypeHash()->value(cachekey); QByteArray cached = qGlobalNormalizedTypeHash()->value(cachekey);
if (!cached.isEmpty()) { if (!cached.isEmpty()) {

View file

@ -35,9 +35,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef QT_NO_COMPRESS
#include <libdeflate.h> #include <libdeflate.h>
#endif // QT_NO_COMPRESS
#define IS_RAW_DATA(d) ((d)->data != (d)->array) #define IS_RAW_DATA(d) ((d)->data != (d)->array)
@ -223,21 +221,6 @@ char* qstrncpy(char *dst, const char *src, uint len)
\sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons} \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons}
*/ */
/*!
\relates QByteArray
Returns the CRC-32 checksum of the first \a len bytes of \a data.
*/
quint32 qChecksum(const char *data, uint len)
{
#ifndef QT_NO_COMPRESS
return libdeflate_crc32(0, data, len);
#else
Q_ASSERT_X(false, "qChecksum", "internal error");
return 0;
#endif
}
/*! /*!
\relates QByteArray \relates QByteArray
@ -286,10 +269,7 @@ QByteArray qRandomUuid()
return QByteArray(uuidbuf, sizeof(uuidbuf)); return QByteArray(uuidbuf, sizeof(uuidbuf));
} }
#ifndef QT_NO_COMPRESS
/*! /*!
\fn QByteArray qCompress(const QByteArray& data, int compressionLevel)
\relates QByteArray \relates QByteArray
Compresses the \a data byte array and returns the compressed data Compresses the \a data byte array and returns the compressed data
@ -423,7 +403,6 @@ QByteArray qUncompress(const char* data, int nbytes)
} }
return result; return result;
} }
#endif // QT_NO_COMPRESS
QByteArray::Data QByteArray::shared_null = { QAtomicInt(1), QByteArray::Data QByteArray::shared_null = { QAtomicInt(1),
0, 0, shared_null.array, {0} }; 0, 0, shared_null.array, {0} };

View file

@ -43,7 +43,7 @@ inline uint qstrnlen(const char *str, uint maxlen)
{ return str ? uint(strnlen(str, maxlen)) : 0; } { return str ? uint(strnlen(str, maxlen)) : 0; }
Q_CORE_EXPORT char* qstrcpy(char *dst, const char *src); Q_CORE_EXPORT char* qstrcpy(char *dst, const char *src);
Q_CORE_EXPORT char* qstrncpy(char *dst, const char *src, uint len); Q_CORE_EXPORT char* qstrncpy(char *dst, const char *src, const uint len);
inline int qstrcmp(const char *str1, const char *str2) inline int qstrcmp(const char *str1, const char *str2)
{ {
@ -51,7 +51,7 @@ inline int qstrcmp(const char *str1, const char *str2)
: (str1 ? 1 : (str2 ? -1 : 0)); : (str1 ? 1 : (str2 ? -1 : 0));
} }
inline int qstrncmp(const char *str1, const char *str2, uint len) inline int qstrncmp(const char *str1, const char *str2, const uint len)
{ {
return (str1 && str2) ? strncmp(str1, str2, len) return (str1 && str2) ? strncmp(str1, str2, len)
: (str1 ? 1 : (str2 ? -1 : 0)); : (str1 ? 1 : (str2 ? -1 : 0));
@ -62,14 +62,12 @@ inline int qstricmp(const char *str1, const char *str2)
: (str1 ? 1 : (str2 ? -1 : 0)); : (str1 ? 1 : (str2 ? -1 : 0));
} }
inline int qstrnicmp(const char *str1, const char *str2, uint len) inline int qstrnicmp(const char *str1, const char *str2, const uint len)
{ {
return (str1 && str2) ? strncasecmp(str1, str2, len) return (str1 && str2) ? strncasecmp(str1, str2, len)
: (str1 ? 1 : (str2 ? -1 : 0)); : (str1 ? 1 : (str2 ? -1 : 0));
} }
Q_CORE_EXPORT quint32 qChecksum(const char *s, uint len);
Q_CORE_EXPORT QByteArray qRandomUuid(); Q_CORE_EXPORT QByteArray qRandomUuid();
class QByteRef; class QByteRef;
@ -481,14 +479,12 @@ Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &); Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);
#endif #endif
#ifndef QT_NO_COMPRESS
Q_CORE_EXPORT QByteArray qCompress(const char* data, int nbytes, int compressionLevel = 1); Q_CORE_EXPORT QByteArray qCompress(const char* data, int nbytes, int compressionLevel = 1);
Q_CORE_EXPORT QByteArray qUncompress(const char* data, int nbytes); Q_CORE_EXPORT QByteArray qUncompress(const char* data, int nbytes);
inline QByteArray qCompress(const QByteArray& data, int compressionLevel = 1) inline QByteArray qCompress(const QByteArray& data, int compressionLevel = 1)
{ return qCompress(data.constData(), data.size(), compressionLevel); } { return qCompress(data.constData(), data.size(), compressionLevel); }
inline QByteArray qUncompress(const QByteArray& data) inline QByteArray qUncompress(const QByteArray& data)
{ return qUncompress(data.constData(), data.size()); } { return qUncompress(data.constData(), data.size()); }
#endif
Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE);

View file

@ -23,63 +23,19 @@
#include "qbitarray.h" #include "qbitarray.h"
#include "qstring.h" #include "qstring.h"
#include <libdeflate.h>
#include <stdlib.h> #include <stdlib.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
uint qHash(const char *key, const uint len)
// ### Qt 5: see tests/benchmarks/corelib/tools/qhash/qhash_string.cpp
// Hashing of the whole string is a waste of cycles.
/*
These functions are based on Peter J. Weinberger's hash function
(from the Dragon Book). The constant 24 in the original function
was replaced with 23 to produce fewer collisions on input such as
"a", "aa", "aaa", "aaaa", ...
*/
static inline uint hash(const uchar *p, int n)
{ {
uint h = 0; return libdeflate_crc32(23, key, len);
while (n--) {
h = (h << 4) + *p++;
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
static inline uint hash(const QChar *p, int n)
{
uint h = 0;
while (n--) {
h = (h << 4) + (*p++).unicode();
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
uint qHash(const QByteArray &key)
{
return hash(reinterpret_cast<const uchar *>(key.constData()), key.size());
}
uint qHash(const QString &key)
{
return hash(key.unicode(), key.size());
}
uint qHash(const QStringRef &key)
{
return hash(key.unicode(), key.size());
} }
uint qHash(const QBitArray &bitArray) uint qHash(const QBitArray &bitArray)
{ {
return hash(reinterpret_cast<const uchar *>(bitArray.d.constData()), bitArray.d.size()); return qHash(bitArray.d.constData(), bitArray.d.size());
} }
/* /*

View file

@ -34,6 +34,9 @@ class QByteArray;
class QString; class QString;
class QStringRef; class QStringRef;
Q_CORE_EXPORT uint qHash(const char *key, const uint len);
Q_CORE_EXPORT uint qHash(const QBitArray &key);
inline uint qHash(const char key) { return uint(key); } inline uint qHash(const char key) { return uint(key); }
inline uint qHash(const uchar key) { return uint(key); } inline uint qHash(const uchar key) { return uint(key); }
inline uint qHash(const signed char key) { return uint(key); } inline uint qHash(const signed char key) { return uint(key); }
@ -60,11 +63,15 @@ inline uint qHash(const quint64 key)
} }
inline uint qHash(const qint64 key) { return qHash(quint64(key)); } inline uint qHash(const qint64 key) { return qHash(quint64(key)); }
inline uint qHash(const QChar key) { return qHash(key.unicode()); } inline uint qHash(const QChar key) { return qHash(key.unicode()); }
Q_CORE_EXPORT uint qHash(const QByteArray &key); inline uint qHash(const QByteArray &key) { return qHash(key.constData(), key.size()); }
Q_CORE_EXPORT uint qHash(const QString &key); inline uint qHash(const QString &key)
Q_CORE_EXPORT uint qHash(const QStringRef &key); {
Q_CORE_EXPORT uint qHash(const QBitArray &key); return qHash(reinterpret_cast<const char *>(key.unicode()), key.size() * sizeof(QChar));
}
inline uint qHash(const QStringRef &key)
{
return qHash(reinterpret_cast<const char *>(key.unicode()), key.size() * sizeof(QChar));
}
template <class T> inline uint qHash(const T *key) template <class T> inline uint qHash(const T *key)
{ {
return qHash(reinterpret_cast<quintptr>(key)); return qHash(reinterpret_cast<quintptr>(key));

View file

@ -11,6 +11,7 @@ include_directories(
${CMAKE_BINARY_DIR}/include/QtCore ${CMAKE_BINARY_DIR}/include/QtCore
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${ICU_INCLUDES} ${ICU_INCLUDES}
${DEFLATE_INCLUDES}
) )
set(MOC_SOURCES set(MOC_SOURCES
@ -34,7 +35,6 @@ set(BOOTSTRAP_DEFINITIONS
-DQT_NO_THREAD -DQT_NO_THREAD
-DQT_NO_PROCESS -DQT_NO_PROCESS
-DQT_NO_USING_NAMESPACE -DQT_NO_USING_NAMESPACE
-DQT_NO_COMPRESS
-DQT_NO_EXCEPTIONS -DQT_NO_EXCEPTIONS
-DQT_NO_REGEXP -DQT_NO_REGEXP
-DQT_NO_TEXTCODEC -DQT_NO_TEXTCODEC
@ -81,7 +81,7 @@ set(BOOTSTRAP_SOURCES
add_executable(bootstrap_moc ${BOOTSTRAP_SOURCES} ${MOC_SOURCES}) add_executable(bootstrap_moc ${BOOTSTRAP_SOURCES} ${MOC_SOURCES})
target_compile_definitions(bootstrap_moc PRIVATE ${BOOTSTRAP_DEFINITIONS}) target_compile_definitions(bootstrap_moc PRIVATE ${BOOTSTRAP_DEFINITIONS})
target_link_libraries(bootstrap_moc ${ICU_LIBRARIES}) target_link_libraries(bootstrap_moc ${ICU_LIBRARIES} ${DEFLATE_LIBRARIES})
add_executable(moc ${MOC_SOURCES}) add_executable(moc ${MOC_SOURCES})
target_link_libraries(moc ${EXTRA_MOC_LIBS}) target_link_libraries(moc ${EXTRA_MOC_LIBS})

View file

@ -38,7 +38,6 @@ private slots:
void to_from_hex(); void to_from_hex();
void bench_qstrcmp(); void bench_qstrcmp();
void bench_qstrncmp(); void bench_qstrncmp();
void bench_qchecksum();
}; };
@ -134,17 +133,6 @@ void tst_qbytearray::bench_qstrncmp()
} }
} }
void tst_qbytearray::bench_qchecksum()
{
static const int loremsize = lorem.size();
static const char* const loremdata = lorem.constData();
QBENCHMARK {
const int result = qChecksum(loremdata, loremsize);
Q_UNUSED(result);
}
}
QTEST_MAIN(tst_qbytearray) QTEST_MAIN(tst_qbytearray)
#include "moc_main.cpp" #include "moc_main.cpp"

View file

@ -64,9 +64,6 @@ private slots:
void qhash_simple(); void qhash_simple();
void qhash_simple_reserve(); void qhash_simple_reserve();
void qhash_vs_qchecksum_data();
void qhash_vs_qchecksum();
private: private:
QString data(); QString data();
}; };
@ -131,31 +128,6 @@ void tst_QHash::qhash_simple_reserve()
} }
} }
void tst_QHash::qhash_vs_qchecksum_data()
{
QTest::addColumn<bool>("qhash");
QTest::newRow("qHash") << true;
QTest::newRow("qChecksum") << false;
}
void tst_QHash::qhash_vs_qchecksum()
{
QFETCH(bool, qhash);
const QByteArray asciidata = data().toAscii();
if (qhash) {
QBENCHMARK {
(void)qHash(asciidata);
}
} else {
QBENCHMARK {
(void)qChecksum(asciidata.constData(), asciidata.size());
}
}
}
QTEST_MAIN(tst_QHash) QTEST_MAIN(tst_QHash)
#include "moc_qhash_string.cpp" #include "moc_qhash_string.cpp"