mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-23 10:22:55 +00:00
reimplement qCompress() and qUncompress() via libdeflate
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
f365a2d30e
commit
cec95847e6
21 changed files with 128 additions and 212 deletions
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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
4
README
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
31
cmake/modules/FindDeflate.cmake
Normal file
31
cmake/modules/FindDeflate.cmake
Normal 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)
|
|
@ -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)
|
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "qdrawhelper_p.h"
|
||||
#include "qguicommon_p.h"
|
||||
|
||||
#include <zlib.h>
|
||||
#include <png.h>
|
||||
#include <pngconf.h>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue