reimplement qCompress() and qUncompress() via libdeflate

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-02-05 02:52:02 +02:00
parent f365a2d30e
commit cec95847e6
21 changed files with 128 additions and 212 deletions

View file

@ -29,7 +29,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qq libpcre3-dev libssl-dev zlib1g-dev libzstd-dev libjansson-dev libc6-dev libpng-dev libcups2-dev libfreetype6-dev libfontconfig1-dev libdbus-1-dev libicu-dev xorg-dev
sudo apt-get install -qq libpcre3-dev libssl-dev libdeflate-dev libjansson-dev libc6-dev libpng-dev libcups2-dev libfreetype6-dev libfontconfig1-dev libdbus-1-dev libicu-dev xorg-dev
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View file

@ -165,11 +165,11 @@ option(KATIE_UTILS "Build maintainance utilities" OFF)
add_feature_info(utils KATIE_UTILS "build maintainance utilities")
# v0.4+ required for inflateInit2() but that is pre-release
find_package(ZLIB)
set_package_properties(ZLIB PROPERTIES
PURPOSE "Required for compression support"
DESCRIPTION "A Massively Spiffy Yet Delicately Unobtrusive Compression Library"
URL "https://zlib.net"
find_package(Deflate)
set_package_properties(Deflate PROPERTIES
PURPOSE "Required for compression and decompression support"
DESCRIPTION "Heavily optimized library for DEFLATE/zlib/gzip compression and decompression"
URL "https://github.com/ebiggers/libdeflate"
TYPE REQUIRED
)
@ -182,15 +182,6 @@ set_package_properties(ICU PROPERTIES
TYPE REQUIRED
)
# v1.1.3+ required for exported ZSTD_getErrorString() and ZSTD_getErrorCode()
find_package(ZSTD 1.1.3)
set_package_properties(ZSTD PROPERTIES
PURPOSE "Required for compression support"
DESCRIPTION "Fast real-time compression algorithm"
URL "https://github.com/facebook/zstd"
TYPE REQUIRED
)
# v2.8+ required for JSON_PARSER_MAX_DEPTH
find_package(Jansson 2.8)
set_package_properties(Jansson PROPERTIES

4
README
View file

@ -12,7 +12,7 @@ There are several things you should be aware before considering Katie:
- some things have changed:
- QMake build system replaced with CMake
- zlib, zstd, Jansson, OpenSSL, PCRE, Freetype, ICU, X11 and libpng are
- libdeflate, Jansson, OpenSSL, PCRE, Freetype, ICU, X11 and libpng are
required for building
- OpenSSL, D-Bus and CUPS must be linked to during build
- QtUiTools is build as shared library by default
@ -61,7 +61,7 @@ There are several things you should be aware before considering Katie:
- support for locale aliases
- support for generating SHA-256 and SHA-512 hash sums (SHA-2)
- verification section for plugins build with Clang
- qCompress() and qUncompress() use ZSTD which is much faster
- qCompress() and qUncompress() 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

View file

@ -12,7 +12,7 @@ build_script:
sudo apt-get update -qq
sudo apt-get install -qq libpcre3-dev libssl-dev zlib1g-dev libzstd-dev \
sudo apt-get install -qq libpcre3-dev libssl-dev libdeflate-dev \
libc6-dev libpng-dev libcups2-dev libfreetype6-dev libfontconfig1-dev \
libdbus-1-dev libicu-dev xorg-dev dbus-x11 libjansson-dev ccache \
fonts-freefont-ttf

View file

@ -0,0 +1,31 @@
# - Try to find libdeflate
# Once done this will define
#
# DEFLATE_FOUND - system has libdeflate
# DEFLATE_INCLUDES - the libdeflate include directory
# DEFLATE_LIBRARIES - the libraries needed to use libdeflate
#
# Copyright (C) 2022, Ivailo Monev, <xakepa10@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# libdeflate does not provide pkg-config files
include(FindPkgConfig)
include(FindPackageHandleStandardArgs)
find_path(DEFLATE_INCLUDES
NAMES libdeflate.h
HINTS $ENV{DEFLATEDIR}/include
)
find_library(DEFLATE_LIBRARIES
NAMES deflate
HINTS $ENV{DEFLATEDIR}/lib
)
find_package_handle_standard_args(Deflate
REQUIRED_VARS DEFLATE_LIBRARIES DEFLATE_INCLUDES
)
mark_as_advanced(DEFLATE_INCLUDES DEFLATE_LIBRARIES)

View file

@ -1,32 +0,0 @@
# - Try to find ZSTD
# Once done this will define
#
# ZSTD_FOUND - system has ZSTD
# ZSTD_INCLUDES - the ZSTD include directory
# ZSTD_LIBRARIES - the libraries needed to use ZSTD
#
# Copyright (C) 2015, Ivailo Monev, <xakepa10@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
include(FindPkgConfig)
include(FindPackageHandleStandardArgs)
pkg_check_modules(PC_ZSTD QUIET libzstd)
find_path(ZSTD_INCLUDES
NAMES zstd.h
HINTS $ENV{ZSTDDIR}/include ${PC_ZSTD_INCLUDEDIR}
)
find_library(ZSTD_LIBRARIES
NAMES zstd
HINTS $ENV{ZSTDDIR}/lib ${PC_ZSTD_LIBDIR}
)
find_package_handle_standard_args(ZSTD
VERSION_VAR PC_ZSTD_VERSION
REQUIRED_VARS ZSTD_LIBRARIES ZSTD_INCLUDES
)
mark_as_advanced(ZSTD_INCLUDES ZSTD_LIBRARIES)

View file

@ -11,7 +11,7 @@ arch=('i486' 'i686' 'pentium4' 'x86_64' 'arm')
url='https://github.com/fluxer/katie'
license=('LGPL' 'BSD')
depends=('libsm' 'libxcursor' 'libxinerama' 'libxrandr' 'fontconfig'
'icu' 'jansson' 'libcups' 'xdg-utils')
'icu' 'jansson' 'libcups' 'xdg-utils' 'libdeflate')
makedepends=('cmake' 'git' 'unifdef')
optdepends=('gnu-free-fonts: last resort font')
source=("git+https://github.com/fluxer/katie")

View file

@ -5,7 +5,7 @@ Homepage: https://github.com/fluxer/katie
Vcs-Git: git://github.com/fluxer/katie.git
Vcs-browser: https://github.com/fluxer/katie
Standards-Version: 4.12.0
Build-Depends: debhelper (>= 9~), libssl-dev, zlib1g-dev, libzstd-dev,
Build-Depends: debhelper (>= 9~), libssl-dev, libdeflate-dev,
libc6-dev, libjansson-dev, libpng-dev, libcups2-dev, libfreetype6-dev,
libfontconfig1-dev, libpcre3-dev, libdbus-1-dev, libicu-dev, cmake,
git, xserver-xorg-dev, libxinerama-dev, libxrandr-dev, libxrender-dev,

View file

@ -7,7 +7,7 @@ Summary: C++ toolkit derived from the Qt 4.8 framework
License: BSD and LGPLv2+
URL: https://github.com/fluxer/katie
BuildRequires: gcc-c++ cmake libicu-devel libzstd-devel jansson-devel zlib-devel libpng-devel freetype-devel pcre-devel openssl-devel libX11-devel libXinerama-devel libXrandr-devel libXrender-devel libXfixes-devel libXcursor-devel libSM-devel libICE-devel dbus-devel fontconfig-devel cups-devel unifdef
BuildRequires: gcc-c++ cmake libicu-devel libdeflate-devel jansson-devel libpng-devel freetype-devel pcre-devel openssl-devel libX11-devel libXinerama-devel libXrandr-devel libXrender-devel libXfixes-devel libXcursor-devel libSM-devel libICE-devel dbus-devel fontconfig-devel cups-devel unifdef
Requires: xdg-utils gnu-free-fonts
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig

View file

@ -18,7 +18,7 @@ USE_XORG = x11 xinerama xrandr xrender xfixes xcursor xext sm ice
USE_LDCONFIG = yes
RUN_DEPENDS = xdg-open:devel/xdg-utils \
${LOCALBASE}/share/fonts/freefont-ttf/FreeSans.ttf:x11-fonts/freefont-ttf
LIB_DEPENDS = libzstd.so:archivers/zstd libicuuc.so:devel/icu \
LIB_DEPENDS = libdeflate.so:archivers/libdeflate libicuuc.so:devel/icu \
libicui18n.so:devel/icu libjansson.so:devel/jansson \
libpcre.so:devel/pcre libpng.so:graphics/png \
libfreetype.so:print/freetype2 libfontconfig.so:x11-fonts/fontconfig \

View file

@ -26,11 +26,10 @@ DEPENDS += freefont-ttf-[0-9]*:../../fonts/freefont-ttf
BUILD_DEPENDS = unifdef-[0-9]*:../../devel/unifdef
.include "../../sysutils/desktop-file-utils/desktopdb.mk"
.include "../../archivers/zstd/buildlink3.mk"
.include "../../archivers/libdeflate_is_not_available/buildlink3.mk"
.include "../../textproc/jansson/buildlink3.mk"
.include "../../textproc/icu/buildlink3.mk"
.include "../../devel/pcre/buildlink3.mk"
.include "../../devel/zlib/buildlink3.mk"
.include "../../security/openssl/buildlink3.mk"
.include "../../x11/libXinerama/buildlink3.mk"
.include "../../x11/libXcursor/buildlink3.mk"

View file

@ -21,10 +21,10 @@ COMPILER = base-clang ports-gcc
MODULES = devel/cmake
BUILD_DEPENDS = devel/gettext,-tools
RUN_DEPENDS = devel/desktop-file-utils devel/xdg-utils fonts/freefont-ttf
LIB_DEPENDS = archivers/zstd textproc/icu4c devel/jansson devel/pcre \
LIB_DEPENDS = archivers/libdeflate_is_not_available textproc/icu4c devel/jansson devel/pcre \
graphics/png x11/dbus print/cups,-libs devel/gettext,-runtime
WANTLIB = ${COMPILER_LIBCXX} ICE SM X11 Xcursor Xext Xfixes Xinerama Xrandr \
Xrender fontconfig freetype zstd icui18n icuuc pcre png \
Xrender fontconfig freetype deflate icui18n icuuc pcre png \
dbus-1 cups intl ssl z c crypto m
SEPARATE_BUILD = Yes
CONFIGURE_ARGS = -DKATIE_TOOLS_SUFFIX="-katie" -Wno-dev

View file

@ -1,7 +1,7 @@
# add_definitions()
set(EXTRA_CORE_LIBS
${ICU_LIBRARIES}
${ZSTD_LIBRARIES}
${DEFLATE_LIBRARIES}
${JANSSON_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
# libm should be present by default becaue this is C++
@ -108,7 +108,7 @@ include_directories(
${CMAKE_BINARY_DIR}/privateinclude
${CMAKE_BINARY_DIR}/include/QtCore
${ICU_INCLUDES}
${ZSTD_INCLUDES}
${DEFLATE_INCLUDES}
${JANSSON_INCLUDES}
)

View file

@ -28,6 +28,7 @@
#include "qlocale_tools_p.h"
#include "qscopedpointer.h"
#include "qdatastream.h"
#include "qplatformdefs.h"
#include "qcorecommon_p.h"
#include <ctype.h>
@ -36,8 +37,7 @@
#include <stdlib.h>
#ifndef QT_NO_COMPRESS
#include <zstd.h>
#include <zstd_errors.h>
#include <libdeflate.h>
#endif // QT_NO_COMPRESS
#define IS_RAW_DATA(d) ((d)->data != (d)->array)
@ -330,20 +330,29 @@ QByteArray qCompress(const char* data, int nbytes, int compressionLevel)
return QByteArray();
}
const size_t bndresult = ZSTD_compressBound(nbytes);
if (Q_UNLIKELY(bndresult <= 0)) {
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");
return QByteArray();
}
QSTACKARRAY(char, cmpbuffer, bndresult);
const size_t cmpresult = ZSTD_compress(cmpbuffer, bndresult, data, nbytes, compressionLevel);
if (Q_UNLIKELY(ZSTD_isError(cmpresult))) {
qWarning("qCompress: Could not compress data (%s)", ZSTD_getErrorString(ZSTD_getErrorCode(cmpresult)));
QSTACKARRAY(char, compbuffer, boundresult);
const size_t compresult = libdeflate_gzip_compress(comp, data, nbytes, compbuffer, boundresult);
libdeflate_free_compressor(comp);
if (compresult <= 0) {
qWarning("qUncompress: Could not compress data");
return QByteArray();
}
return QByteArray(cmpbuffer, cmpresult);
return QByteArray(compbuffer, compresult);
}
/*!
@ -378,20 +387,47 @@ QByteArray qUncompress(const char* data, int nbytes)
return QByteArray();
}
const unsigned long long uncompressedsize = ZSTD_getDecompressedSize(data, nbytes);
if (Q_UNLIKELY(uncompressedsize <= 0)) {
qWarning("qUncompress: Uncompressed size is negative or zero");
struct libdeflate_decompressor* decomp = libdeflate_alloc_decompressor();
if (Q_UNLIKELY(!decomp)) {
qWarning("qUncompress: Could not allocate decompressor");
return QByteArray();
}
QSTACKARRAY(char, decbuffer, uncompressedsize);
const size_t decresult = ZSTD_decompress(decbuffer, uncompressedsize, data, nbytes);
if (Q_UNLIKELY(ZSTD_isError(decresult))) {
qWarning("qUncompress: Could not uncompress data (%s)", ZSTD_getErrorString(ZSTD_getErrorCode(decresult)));
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;
}
}
return QByteArray(decbuffer, uncompressedsize);
switch (decompresult) {
case LIBDEFLATE_SUCCESS: {
result.resize(speculativesize);
break;
}
default: {
qWarning("qUncompress: Could not decompress data");
result.clear();
break;
}
}
libdeflate_free_decompressor(decomp);
return result;
}
#endif // QT_NO_COMPRESS

View file

@ -26,7 +26,6 @@
#include "qdrawhelper_p.h"
#include "qguicommon_p.h"
#include <zlib.h>
#include <png.h>
#include <pngconf.h>

View file

@ -2,7 +2,7 @@
set(EXTRA_NETWORK_LIBS
KtCore
${OPENSSL_LIBRARIES}
${ZLIB_LIBRARIES}
${DEFLATE_LIBRARIES}
)
set(NETWORK_PUBLIC_HEADERS
@ -44,7 +44,7 @@ include_directories(
${CMAKE_BINARY_DIR}/include/QtCore
${CMAKE_BINARY_DIR}/include/QtNetwork
${OPENSSL_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS}
${DEFLATE_INCLUDES}
)
set(NETWORK_HEADERS

View file

@ -614,20 +614,16 @@ bool QHttpNetworkConnectionChannel::expand(bool dataComplete)
Q_ASSERT(reply);
qint64 total = reply->d_func()->compressedData.size();
if (total >= QT_BUFFSIZE || dataComplete) {
if (total >= 0 && dataComplete) {
// uncompress the data
QByteArray content, inflated;
content = reply->d_func()->compressedData;
QByteArray inflated;
QByteArray content = reply->d_func()->compressedData;
reply->d_func()->compressedData.clear();
int ret = Z_OK;
bool ret = true;
if (content.size())
ret = reply->d_func()->gunzipBodyPartially(content, inflated);
if (ret >= Z_OK) {
if (dataComplete && ret == Z_OK && !reply->d_func()->streamEnd) {
reply->d_func()->gunzipBodyPartiallyEnd();
reply->d_func()->streamEnd = true;
}
ret = reply->d_func()->gunzipBody(content, inflated);
if (ret) {
if (inflated.size()) {
reply->d_func()->totalProgress += inflated.size();
reply->d_func()->appendUncompressedReplyData(inflated);
@ -651,7 +647,7 @@ void QHttpNetworkConnectionChannel::allDone()
{
Q_ASSERT(reply);
// expand the whole data.
if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) {
if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress) {
bool expandResult = expand(true);
// If expand() failed we can just return, it had already called connection->emitReplyError()
if (!expandResult)

View file

@ -249,7 +249,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
connectionCloseEnabled(true),
forceConnectionCloseEnabled(false),
lastChunkRead(false),
currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0), connection(0), initInflate(false),
currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0), connection(0),
autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), downstreamLimited(false)
,userProvidedDownloadBuffer(0)
@ -271,10 +271,6 @@ void QHttpNetworkReplyPrivate::clearHttpLayerInformation()
currentChunkRead = 0;
lastChunkRead = false;
connectionCloseEnabled = true;
if (initInflate)
inflateEnd(&inflateStrm);
initInflate = false;
streamEnd = false;
fields.clear();
}
@ -380,7 +376,7 @@ bool QHttpNetworkReplyPrivate::gzipCheckHeader(QByteArray &content, int &pos)
method = body[pos];
if (pos++ <= maxPos)
flags = body[pos];
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
if (method != 8 || (flags & RESERVED) != 0) {
return ret;
}
@ -410,69 +406,22 @@ bool QHttpNetworkReplyPrivate::gzipCheckHeader(QByteArray &content, int &pos)
return ret;
}
int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated)
bool QHttpNetworkReplyPrivate::gunzipBody(QByteArray &compressed, QByteArray &inflated)
{
int ret = Z_DATA_ERROR;
unsigned have;
QSTACKARRAY(unsigned char, out, QT_BUFFSIZE);
int pos = -1;
if (!initInflate) {
// check the header
if (!gzipCheckHeader(compressed, pos))
return ret;
// allocate inflate state
inflateStrm.zalloc = Z_NULL;
inflateStrm.zfree = Z_NULL;
inflateStrm.opaque = Z_NULL;
inflateStrm.avail_in = 0;
inflateStrm.next_in = Z_NULL;
ret = inflateInit2(&inflateStrm, -MAX_WBITS);
if (ret != Z_OK)
return ret;
initInflate = true;
streamEnd = false;
// check the header
if (!gzipCheckHeader(compressed, pos)) {
return false;
}
//remove the header.
compressed.remove(0, pos+1);
// expand until deflate stream ends
inflateStrm.next_in = (unsigned char *)compressed.data();
inflateStrm.avail_in = compressed.size();
do {
inflateStrm.avail_out = sizeof(out);
inflateStrm.next_out = out;
ret = inflate(&inflateStrm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
// and fall through
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&inflateStrm);
initInflate = false;
return ret;
}
have = sizeof(out) - inflateStrm.avail_out;
inflated.append(QByteArray((const char *)out, have));
} while (inflateStrm.avail_out == 0 && inflateStrm.avail_in > 0);
// clean up and return
if (ret <= Z_ERRNO || ret == Z_STREAM_END) {
gunzipBodyPartiallyEnd();
}
streamEnd = (ret == Z_STREAM_END);
return ret;
inflated = qUncompress(compressed.constData(), compressed.size());
return !inflated.isEmpty();
}
void QHttpNetworkReplyPrivate::gunzipBodyPartiallyEnd()
{
if (initInflate) {
inflateEnd(&inflateStrm);
initInflate = false;
}
}
qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
{
if (fragment.isEmpty()) {

View file

@ -35,7 +35,7 @@
#include <qplatformdefs.h>
#ifndef QT_NO_HTTP
#include <zlib.h>
#include <libdeflate.h>
static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header
// gzip flag byte
#define HEAD_CRC 0x02 // bit 1 set: header CRC present
@ -182,8 +182,7 @@ public:
bool isConnectionCloseEnabled();
bool isGzipped();
bool gzipCheckHeader(QByteArray &content, int &pos);
int gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated);
void gunzipBodyPartiallyEnd();
bool gunzipBody(QByteArray &compressed, QByteArray &inflated);
void removeAutoDecompressHeader();
enum ReplyState {
@ -214,9 +213,6 @@ public:
qint64 readBufferMaxSize;
QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel;
bool initInflate;
bool streamEnd;
z_stream inflateStrm;
bool autoDecompress;
QByteDataBuffer responseData; // uncompressed body

View file

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

View file

@ -35,7 +35,7 @@
#include "qdebug.h"
#include "qcorecommon_p.h"
#include <zlib.h>
#include <libdeflate.h>
QT_BEGIN_NAMESPACE
@ -57,60 +57,11 @@ Q_AUTOTEST_EXPORT QByteArray qt_inflateGZipDataFrom(const QByteArray &contents)
static QByteArray qt_inflateGZipDataFrom(const QByteArray &contents)
#endif
{
QSTACKARRAY(char, source, contents.size());
::memcpy(source, contents.constData(), contents.size() * sizeof(char));
QByteArray destination;
// Initialize zlib stream struct
z_stream zlibStream;
zlibStream.next_in = Z_NULL;
zlibStream.avail_in = 0;
zlibStream.avail_out = 0;
zlibStream.zalloc = Z_NULL;
zlibStream.zfree = Z_NULL;
zlibStream.opaque = Z_NULL;
// Adding 16 to the window size gives us gzip decoding
if (inflateInit2(&zlibStream, MAX_WBITS + 16) != Z_OK) {
qWarning("Cannot initialize zlib, because: %s",
(zlibStream.msg != NULL ? zlibStream.msg : "Unknown error"));
if (contents.isEmpty()) {
return QByteArray();
}
zlibStream.avail_in = contents.size();
zlibStream.next_in = reinterpret_cast<Bytef*>(source);
do {
// Prepare the destination buffer
int oldSize = destination.size();
destination.resize(oldSize + QT_BUFFSIZE);
zlibStream.next_out = reinterpret_cast<Bytef*>(
destination.data() + oldSize - zlibStream.avail_out);
zlibStream.avail_out += QT_BUFFSIZE;
int zlibResult = inflate(&zlibStream, Z_NO_FLUSH);
switch (zlibResult) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_STREAM_ERROR:
case Z_MEM_ERROR: {
inflateEnd(&zlibStream);
qWarning("Error while inflating gzip file: %s",
(zlibStream.msg != NULL ? zlibStream.msg : "Unknown error"));
destination.chop(zlibStream.avail_out);
return destination;
}
}
// If the output buffer still has more room after calling inflate
// it means we have to provide more data, so exit the loop here
} while (!zlibStream.avail_out);
// Chop off trailing space in the buffer
destination.chop(zlibStream.avail_out);
inflateEnd(&zlibStream);
return destination;
return qUncompress(contents.constData(), contents.size());
}
QSvgTinyDocument * QSvgTinyDocument::load(const QString &fileName)