drop the qCompress() and qUncompress() functions

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-06-03 22:03:22 +03:00
parent bffd6e4405
commit b7f2401784
8 changed files with 59 additions and 195 deletions

2
README
View file

@ -58,7 +58,7 @@ There are several things you should be aware before considering Katie:
- Unicode v5.0+ characters and partial scripts support - Unicode v5.0+ characters and partial scripts support
- support for AArch64 architecture - support for AArch64 architecture
- support for locale aliases - 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 - stack backtrace on assert, crash or warning via execinfo
- brief manual pages for all command-line tools - brief manual pages for all command-line tools
- desktop files, Shell profile and dynamic linker/loader config - desktop files, Shell profile and dynamic linker/loader config

View file

@ -2,7 +2,6 @@
set(EXTRA_CORE_LIBS set(EXTRA_CORE_LIBS
${ICU_LIBRARIES} ${ICU_LIBRARIES}
${JANSSON_LIBRARIES} ${JANSSON_LIBRARIES}
${DEFLATE_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
# libm should be present by default becaue this is C++ # libm should be present by default becaue this is C++
m m
@ -89,7 +88,6 @@ include_directories(
${CMAKE_BINARY_DIR}/include/QtCore ${CMAKE_BINARY_DIR}/include/QtCore
${ICU_INCLUDES} ${ICU_INCLUDES}
${JANSSON_INCLUDES} ${JANSSON_INCLUDES}
${DEFLATE_INCLUDES}
) )
set(CORE_HEADERS set(CORE_HEADERS

View file

@ -271,156 +271,6 @@ QByteArray qRandomUuid()
return QByteArray(uuidbuf, sizeof(uuidbuf)); 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 = { QByteArray::Data QByteArray::shared_null = {
QAtomicInt(1), 0, 0, shared_null.array, {0} QAtomicInt(1), 0, 0, shared_null.array, {0}
}; };

View file

@ -479,13 +479,6 @@ Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &); Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &);
#endif #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); Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE);
static inline int qstrcmp(const char *str1, const QByteArray &str2) static inline int qstrcmp(const char *str1, const QByteArray &str2)

View file

@ -1,6 +1,7 @@
# add_definitions() # add_definitions()
set(EXTRA_SVG_LIBS set(EXTRA_SVG_LIBS
KtCore KtXml KtGui KtCore KtXml KtGui
${DEFLATE_LIBRARIES}
) )
set(SVG_PUBLIC_HEADERS set(SVG_PUBLIC_HEADERS
@ -14,6 +15,7 @@ include_directories(
${CMAKE_BINARY_DIR}/include/QtXml ${CMAKE_BINARY_DIR}/include/QtXml
${CMAKE_BINARY_DIR}/include/QtGui ${CMAKE_BINARY_DIR}/include/QtGui
${CMAKE_BINARY_DIR}/include/QtSvg ${CMAKE_BINARY_DIR}/include/QtSvg
${DEFLATE_INCLUDES}
) )
set(SVG_HEADERS set(SVG_HEADERS

View file

@ -32,8 +32,58 @@
#include "qdebug.h" #include "qdebug.h"
#include "qcorecommon_p.h" #include "qcorecommon_p.h"
#include <libdeflate.h>
QT_BEGIN_NAMESPACE 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() QSvgTinyDocument::QSvgTinyDocument()
: QSvgStructureNode(0) : QSvgStructureNode(0)
{ {
@ -57,9 +107,9 @@ QSvgTinyDocument * QSvgTinyDocument::load(const QString &fileName)
QSvgTinyDocument * QSvgTinyDocument::load(const QByteArray &contents) 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")) { if (contents.startsWith("\x1f\x8b")) {
return load(qUncompress(contents.constData(), contents.size())); return load(qt_uncompress(contents.constData(), contents.size()));
} }
QSvgHandler handler(contents); QSvgHandler handler(contents);

View file

@ -51,10 +51,10 @@ class QSvgFont;
class QSvgTinyDocument : public QSvgStructureNode class QSvgTinyDocument : public QSvgStructureNode
{ {
public: public:
static QSvgTinyDocument * load(const QString &file); static QSvgTinyDocument* load(const QString &file);
static QSvgTinyDocument * load(const QByteArray &contents); static QSvgTinyDocument* load(const QByteArray &contents);
static QSvgTinyDocument * load(QXmlStreamReader *contents); static QSvgTinyDocument* load(QXmlStreamReader *contents);
public:
QSvgTinyDocument(); QSvgTinyDocument();
~QSvgTinyDocument(); ~QSvgTinyDocument();
Type type() const; Type type() const;

View file

@ -32,8 +32,6 @@ class tst_qbytearray : public QObject
private slots: private slots:
void append(); void append();
void append_data(); void append_data();
void compress_uncompress_data();
void compress_uncompress();
void to_from_base64(); void to_from_base64();
void to_from_hex(); void to_from_hex();
void bench_qstrcmp(); void bench_qstrcmp();
@ -67,33 +65,6 @@ void tst_qbytearray::append()
} }
} }
void tst_qbytearray::compress_uncompress_data()
{
QTest::addColumn<int>("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() void tst_qbytearray::to_from_base64()
{ {
QBENCHMARK { QBENCHMARK {