diff --git a/README b/README index faf0aff4d..f748f3fec 100644 --- a/README +++ b/README @@ -58,7 +58,7 @@ There are several things you should be aware before considering Katie: - Unicode v5.0+ characters and partial scripts support - support for AArch64 architecture - support for locale aliases - - qCompress() and qUncompress() use libdeflate which is much faster + - SVG document handler use libdeflate which is much faster - stack backtrace on assert, crash or warning via execinfo - brief manual pages for all command-line tools - desktop files, Shell profile and dynamic linker/loader config diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 033398532..b5ff2a995 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -2,7 +2,6 @@ set(EXTRA_CORE_LIBS ${ICU_LIBRARIES} ${JANSSON_LIBRARIES} - ${DEFLATE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} # libm should be present by default becaue this is C++ m @@ -89,7 +88,6 @@ include_directories( ${CMAKE_BINARY_DIR}/include/QtCore ${ICU_INCLUDES} ${JANSSON_INCLUDES} - ${DEFLATE_INCLUDES} ) set(CORE_HEADERS diff --git a/src/core/tools/qbytearray.cpp b/src/core/tools/qbytearray.cpp index 125d83945..4214b6cc7 100644 --- a/src/core/tools/qbytearray.cpp +++ b/src/core/tools/qbytearray.cpp @@ -271,156 +271,6 @@ QByteArray qRandomUuid() return QByteArray(uuidbuf, sizeof(uuidbuf)); } -/*! - \relates QByteArray - - Compresses the \a data byte array and returns the compressed data - in a new byte array. - - The \a compressionLevel parameter specifies how much compression - should be used. Valid values are between 0 and 9, with 9 - corresponding to the greatest compression (i.e. smaller compressed - data) at the cost of using a slower algorithm. Smaller values (8, - 7, ..., 1) provide successively less compression at slightly - faster speeds. The value 0 corresponds to no compression at all. - The default value is 1, which results in good trade-off between - compression ratio and speed. - - \sa qUncompress() -*/ - -/*! \relates QByteArray - - \overload - - Compresses the first \a nbytes of \a data and returns the - compressed data in a new byte array. -*/ -QByteArray qCompress(const char* data, int nbytes, int compressionLevel) -{ -#ifndef QT_BOOTSTRAPPED - if (Q_UNLIKELY(!data)) { - qWarning("qCompress: Data is null"); - return QByteArray(); - } else if (Q_UNLIKELY(nbytes <= 0)) { - qWarning("qCompress: Data size is negative or zero"); - return QByteArray(); - } - - struct libdeflate_compressor* comp = libdeflate_alloc_compressor(compressionLevel); - if (Q_UNLIKELY(!comp)) { - qWarning("qCompress: Could not allocate compressor"); - return QByteArray(); - } - - const size_t boundresult = libdeflate_gzip_compress_bound(comp, nbytes); - if (Q_UNLIKELY(boundresult <= 0)) { - qWarning("qCompress: Compression boundary is negative or zero"); - libdeflate_free_compressor(comp); - return QByteArray(); - } - - QByteArray result(boundresult, Qt::Uninitialized); - const size_t compresult = libdeflate_gzip_compress(comp, data, nbytes, result.data(), result.size()); - libdeflate_free_compressor(comp); - - if (Q_UNLIKELY(compresult <= 0)) { - qWarning("qCompress: Could not compress data"); - return QByteArray(); - } - - result.resize(compresult); - return result; -#else - Q_UNUSED(data); - Q_UNUSED(nbytes); - Q_UNUSED(compressionLevel); - Q_ASSERT_X(false, "qCompress", "internal error"); - return QByteArray(); -#endif -} - -/*! - \fn QByteArray qUncompress(const QByteArray &data) - - \relates QByteArray - - Uncompresses the \a data byte array and returns a new byte array - with the uncompressed data. - - Returns an empty QByteArray if the input data was corrupt. - - This function will uncompress data compressed with qCompress(). - - \sa qCompress() -*/ - -/*! \relates QByteArray - - \overload - - Uncompresses the first \a nbytes of \a data and returns a new byte - array with the uncompressed data. -*/ -QByteArray qUncompress(const char* data, int nbytes) -{ -#ifndef QT_BOOTSTRAPPED - if (Q_UNLIKELY(!data)) { - qWarning("qUncompress: Data is null"); - return QByteArray(); - } else if (Q_UNLIKELY(nbytes <= 0)) { - qWarning("qUncompress: Data size is negative or zero"); - return QByteArray(); - } - - struct libdeflate_decompressor* decomp = libdeflate_alloc_decompressor(); - if (Q_UNLIKELY(!decomp)) { - qWarning("qUncompress: Could not allocate decompressor"); - return QByteArray(); - } - - size_t speculativesize = (nbytes * 2); - QByteArray result(speculativesize, Qt::Uninitialized); - libdeflate_result decompresult = LIBDEFLATE_INSUFFICIENT_SPACE; - while (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { - decompresult = libdeflate_gzip_decompress( - decomp, - data, nbytes, - result.data(), result.size(), - &speculativesize - ); - - if (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { - speculativesize = (speculativesize + QT_BUFFSIZE); - result.resize(speculativesize); - } - - if (speculativesize >= QBYTEARRAY_MAX) { - break; - } - } - libdeflate_free_decompressor(decomp); - - switch (decompresult) { - case LIBDEFLATE_SUCCESS: { - result.resize(speculativesize); - break; - } - default: { - qWarning("qUncompress: Could not decompress data"); - result.clear(); - break; - } - } - return result; -#else - Q_UNUSED(data); - Q_UNUSED(nbytes); - Q_ASSERT_X(false, "qUncompress", "internal error"); - return QByteArray(); -#endif -} - QByteArray::Data QByteArray::shared_null = { QAtomicInt(1), 0, 0, shared_null.array, {0} }; diff --git a/src/core/tools/qbytearray.h b/src/core/tools/qbytearray.h index 156fca230..3f7b3ef7e 100644 --- a/src/core/tools/qbytearray.h +++ b/src/core/tools/qbytearray.h @@ -479,13 +479,6 @@ Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &); Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &); #endif -Q_CORE_EXPORT QByteArray qCompress(const char* data, int nbytes, int compressionLevel = 1); -Q_CORE_EXPORT QByteArray qUncompress(const char* data, int nbytes); -inline QByteArray qCompress(const QByteArray& data, int compressionLevel = 1) -{ return qCompress(data.constData(), data.size(), compressionLevel); } -inline QByteArray qUncompress(const QByteArray& data) -{ return qUncompress(data.constData(), data.size()); } - Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE); static inline int qstrcmp(const char *str1, const QByteArray &str2) diff --git a/src/svg/CMakeLists.txt b/src/svg/CMakeLists.txt index ebfb0621d..601558314 100644 --- a/src/svg/CMakeLists.txt +++ b/src/svg/CMakeLists.txt @@ -1,6 +1,7 @@ # add_definitions() set(EXTRA_SVG_LIBS KtCore KtXml KtGui + ${DEFLATE_LIBRARIES} ) set(SVG_PUBLIC_HEADERS @@ -14,6 +15,7 @@ include_directories( ${CMAKE_BINARY_DIR}/include/QtXml ${CMAKE_BINARY_DIR}/include/QtGui ${CMAKE_BINARY_DIR}/include/QtSvg + ${DEFLATE_INCLUDES} ) set(SVG_HEADERS diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index b1aa97e29..06e093426 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -32,8 +32,58 @@ #include "qdebug.h" #include "qcorecommon_p.h" +#include + QT_BEGIN_NAMESPACE +static QByteArray qt_uncompress(const char* data, const int nbytes) +{ + if (Q_UNLIKELY(nbytes <= 0)) { + return QByteArray(); + } + + struct libdeflate_decompressor* decomp = libdeflate_alloc_decompressor(); + if (Q_UNLIKELY(!decomp)) { + qWarning("Could not allocate SVG decompressor"); + return QByteArray(); + } + + size_t speculativesize = (nbytes * 2); + QByteArray result(speculativesize, Qt::Uninitialized); + libdeflate_result decompresult = LIBDEFLATE_INSUFFICIENT_SPACE; + while (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + decompresult = libdeflate_gzip_decompress( + decomp, + data, nbytes, + result.data(), result.size(), + &speculativesize + ); + + if (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + speculativesize = (speculativesize + QT_BUFFSIZE); + result.resize(speculativesize); + } + + if (speculativesize >= QBYTEARRAY_MAX) { + break; + } + } + libdeflate_free_decompressor(decomp); + + switch (decompresult) { + case LIBDEFLATE_SUCCESS: { + result.resize(speculativesize); + break; + } + default: { + qWarning("Could not decompress SVG data"); + result.clear(); + break; + } + } + return result; +} + QSvgTinyDocument::QSvgTinyDocument() : QSvgStructureNode(0) { @@ -57,9 +107,9 @@ QSvgTinyDocument * QSvgTinyDocument::load(const QString &fileName) QSvgTinyDocument * QSvgTinyDocument::load(const QByteArray &contents) { - // Check for gzip magic number and inflate if appropriate + // Check for gzip magic number and decompress if appropriate if (contents.startsWith("\x1f\x8b")) { - return load(qUncompress(contents.constData(), contents.size())); + return load(qt_uncompress(contents.constData(), contents.size())); } QSvgHandler handler(contents); diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h index ce0c9aa25..e656d71ac 100644 --- a/src/svg/qsvgtinydocument_p.h +++ b/src/svg/qsvgtinydocument_p.h @@ -51,10 +51,10 @@ class QSvgFont; class QSvgTinyDocument : public QSvgStructureNode { public: - static QSvgTinyDocument * load(const QString &file); - static QSvgTinyDocument * load(const QByteArray &contents); - static QSvgTinyDocument * load(QXmlStreamReader *contents); -public: + static QSvgTinyDocument* load(const QString &file); + static QSvgTinyDocument* load(const QByteArray &contents); + static QSvgTinyDocument* load(QXmlStreamReader *contents); + QSvgTinyDocument(); ~QSvgTinyDocument(); Type type() const; diff --git a/tests/benchmarks/core/tools/qbytearray/main.cpp b/tests/benchmarks/core/tools/qbytearray/main.cpp index 174087e2c..fec532491 100644 --- a/tests/benchmarks/core/tools/qbytearray/main.cpp +++ b/tests/benchmarks/core/tools/qbytearray/main.cpp @@ -32,8 +32,6 @@ class tst_qbytearray : public QObject private slots: void append(); void append_data(); - void compress_uncompress_data(); - void compress_uncompress(); void to_from_base64(); void to_from_hex(); void bench_qstrcmp(); @@ -67,33 +65,6 @@ void tst_qbytearray::append() } } -void tst_qbytearray::compress_uncompress_data() -{ - QTest::addColumn("level"); - QTest::newRow("0") << int(0); - QTest::newRow("1") << int(1); - QTest::newRow("2") << int(2); - QTest::newRow("3") << int(3); - QTest::newRow("4") << int(4); - QTest::newRow("5") << int(5); - QTest::newRow("6") << int(6); - QTest::newRow("7") << int(7); - QTest::newRow("8") << int(8); - QTest::newRow("9") << int(9); -} - -void tst_qbytearray::compress_uncompress() -{ - QFETCH(int, level); - - QBENCHMARK { - QByteArray compressed = qCompress(lorem, level); - QVERIFY(!compressed.isEmpty()); - QByteArray decompressed = qUncompress(compressed); - QVERIFY(decompressed == lorem); - } -} - void tst_qbytearray::to_from_base64() { QBENCHMARK {