From 860b2d098d33a6e6ff1c01238c43fb3c0c30971f Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Mon, 17 Oct 2022 16:36:39 +0300 Subject: [PATCH] kdecore: new KCompressor and KDecompressor classes replacing KFilterDev Signed-off-by: Ivailo Monev --- CMakeLists.txt | 8 +- cmake/modules/FindLibDeflate.cmake | 31 ++ includes/CMakeLists.txt | 4 +- includes/KCompressor | 1 + includes/KDecompressor | 1 + includes/KFilterBase | 1 - includes/KFilterDev | 1 - kdecore/CMakeLists.txt | 15 +- kdecore/compression/ConfigureChecks.cmake | 4 - .../compression/config-compression.h.cmake | 3 - kdecore/compression/kbzip2filter.cpp | 205 --------- kdecore/compression/kbzip2filter.h | 58 --- kdecore/compression/kcompressor.cpp | 290 +++++++++++++ kdecore/compression/kcompressor.h | 60 +++ kdecore/compression/kdecompressor.cpp | 323 +++++++++++++++ kdecore/compression/kdecompressor.h | 58 +++ kdecore/compression/kfilterbase.cpp | 176 -------- kdecore/compression/kfilterbase.h | 123 ------ kdecore/compression/kfilterdev.cpp | 368 ----------------- kdecore/compression/kfilterdev.h | 151 ------- kdecore/compression/kgzipfilter.cpp | 390 ------------------ kdecore/compression/kgzipfilter.h | 73 ---- kdecore/compression/kxzfilter.cpp | 184 --------- kdecore/compression/kxzfilter.h | 61 --- kdecore/localization/kcharsets.cpp | 2 - kdecore/tests/CMakeLists.txt | 6 - kdecore/tests/kfiltertest.cpp | 369 ----------------- kdecore/tests/kfiltertest.h | 61 --- 28 files changed, 776 insertions(+), 2251 deletions(-) create mode 100644 cmake/modules/FindLibDeflate.cmake create mode 100644 includes/KCompressor create mode 100644 includes/KDecompressor delete mode 100644 includes/KFilterBase delete mode 100644 includes/KFilterDev delete mode 100644 kdecore/compression/kbzip2filter.cpp delete mode 100644 kdecore/compression/kbzip2filter.h create mode 100644 kdecore/compression/kcompressor.cpp create mode 100644 kdecore/compression/kcompressor.h create mode 100644 kdecore/compression/kdecompressor.cpp create mode 100644 kdecore/compression/kdecompressor.h delete mode 100644 kdecore/compression/kfilterbase.cpp delete mode 100644 kdecore/compression/kfilterbase.h delete mode 100644 kdecore/compression/kfilterdev.cpp delete mode 100644 kdecore/compression/kfilterdev.h delete mode 100644 kdecore/compression/kgzipfilter.cpp delete mode 100644 kdecore/compression/kgzipfilter.h delete mode 100644 kdecore/compression/kxzfilter.cpp delete mode 100644 kdecore/compression/kxzfilter.h delete mode 100644 kdecore/tests/kfiltertest.cpp delete mode 100644 kdecore/tests/kfiltertest.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9239b777..b5c02e70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,12 +55,12 @@ if(ENABLE_TESTING) endif() # required features -find_package(ZLIB) +find_package(LibDeflate) set_package_properties(ZLIB PROPERTIES - DESCRIPTION "Support for gzip compressed files and data streams" - URL "http://www.zlib.net" + DESCRIPTION "Heavily optimized library for DEFLATE/zlib/gzip compression and decompression" + URL "https://github.com/ebiggers/libdeflate" TYPE REQUIRED - PURPOSE "Required by the core KDE libraries and some critical kioslaves" + PURPOSE "Compression and decompression of DEFLATE/zlib/gzip format" ) find_package(SharedMimeInfo 0.91) diff --git a/cmake/modules/FindLibDeflate.cmake b/cmake/modules/FindLibDeflate.cmake new file mode 100644 index 00000000..b0c0f245 --- /dev/null +++ b/cmake/modules/FindLibDeflate.cmake @@ -0,0 +1,31 @@ +# Try to find libdeflate, once done this will define: +# +# LIBDEFLATE_FOUND - system has libdeflate +# LIBDEFLATE_INCLUDES - the libdeflate include directory +# LIBDEFLATE_LIBRARIES - the libraries needed to use libdeflate +# +# Copyright (c) 2022 Ivailo Monev +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +# libdeflate does not provide pkg-config files + +find_package(PkgConfig REQUIRED) +include(FindPackageHandleStandardArgs) + +find_path(LIBDEFLATE_INCLUDES + NAMES libdeflate.h + HINTS $ENV{LIBDEFLATEDIR}/include +) + +find_library(LIBDEFLATE_LIBRARIES + NAMES deflate + HINTS $ENV{LIBDEFLATEDIR}/lib +) + +find_package_handle_standard_args(LibDeflate + REQUIRED_VARS LIBDEFLATE_LIBRARIES LIBDEFLATE_INCLUDES +) + +mark_as_advanced(LIBDEFLATE_INCLUDES LIBDEFLATE_LIBRARIES) diff --git a/includes/CMakeLists.txt b/includes/CMakeLists.txt index 38a455d2..d3288974 100644 --- a/includes/CMakeLists.txt +++ b/includes/CMakeLists.txt @@ -132,8 +132,8 @@ install( KFileMetaInfoItem KFilePlacesModel KFileTreeView - KFilterBase - KFilterDev + KCompressor + KDecompressor KFind KFindDialog KFloatValidator diff --git a/includes/KCompressor b/includes/KCompressor new file mode 100644 index 00000000..ed9acae9 --- /dev/null +++ b/includes/KCompressor @@ -0,0 +1 @@ +#include "../kcompressor.h" diff --git a/includes/KDecompressor b/includes/KDecompressor new file mode 100644 index 00000000..b3674c5d --- /dev/null +++ b/includes/KDecompressor @@ -0,0 +1 @@ +#include "../kdecompressor.h" diff --git a/includes/KFilterBase b/includes/KFilterBase deleted file mode 100644 index b82dfef0..00000000 --- a/includes/KFilterBase +++ /dev/null @@ -1 +0,0 @@ -#include "../kfilterbase.h" diff --git a/includes/KFilterDev b/includes/KFilterDev deleted file mode 100644 index beda0dbb..00000000 --- a/includes/KFilterDev +++ /dev/null @@ -1 +0,0 @@ -#include "../kfilterdev.h" diff --git a/kdecore/CMakeLists.txt b/kdecore/CMakeLists.txt index 1f7b889c..64dc1b22 100644 --- a/kdecore/CMakeLists.txt +++ b/kdecore/CMakeLists.txt @@ -31,7 +31,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/compression) include_directories( ${KDE4_KDECORE_INCLUDES} ${KDE4_KDEUI_INCLUDES} - ${ZLIB_INCLUDE_DIR} + ${LIBDEFLATE_INCLUDES} ${QT_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR}/auth ${CMAKE_CURRENT_SOURCE_DIR}/sonnet @@ -49,14 +49,12 @@ add_definitions(-DQT_NO_CAST_FROM_ASCII) # compile bzip2 support if available if(BZIP2_FOUND) include_directories(${BZIP2_INCLUDE_DIR}) - set(kdecore_OPTIONAL_SRCS ${kdecore_OPTIONAL_SRCS} compression/kbzip2filter.cpp) set(kdecore_OPTIONAL_LIBS ${kdecore_OPTIONAL_LIBS} ${BZIP2_LIBRARIES}) endif(BZIP2_FOUND) # compile lzma support if available if(LIBLZMA_FOUND) include_directories(${LIBLZMA_INCLUDE_DIRS}) - set(kdecore_OPTIONAL_SRCS ${kdecore_OPTIONAL_SRCS} compression/kxzfilter.cpp) set(kdecore_OPTIONAL_LIBS ${kdecore_OPTIONAL_LIBS} ${LIBLZMA_LIBRARIES}) endif(LIBLZMA_FOUND) @@ -89,9 +87,8 @@ endif() ########### next target ############### set(kdecore_LIB_SRCS - compression/kgzipfilter.cpp - compression/kfilterbase.cpp - compression/kfilterdev.cpp + compression/kcompressor.cpp + compression/kdecompressor.cpp config/kconfig.cpp config/kconfigbase.cpp config/kconfigdata.cpp @@ -219,7 +216,7 @@ endif() add_library(kdecore ${LIBRARY_TYPE} ${kdecore_LIB_SRCS}) target_link_libraries(kdecore PRIVATE - ${ZLIB_LIBRARY} + ${LIBDEFLATE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${kdecore_OPTIONAL_LIBS} ) @@ -277,8 +274,8 @@ install( install( FILES ${CMAKE_CURRENT_BINARY_DIR}/kdecore_export.h - compression/kfilterbase.h - compression/kfilterdev.h + compression/kcompressor.h + compression/kdecompressor.h config/kconfig.h config/kconfigbase.h config/kconfiggroup.h diff --git a/kdecore/compression/ConfigureChecks.cmake b/kdecore/compression/ConfigureChecks.cmake index 0440f99e..53b2f821 100644 --- a/kdecore/compression/ConfigureChecks.cmake +++ b/kdecore/compression/ConfigureChecks.cmake @@ -1,6 +1,2 @@ kde4_bool_to_01(BZIP2_FOUND HAVE_BZIP2_SUPPORT) -if(BZIP2_FOUND AND BZIP2_NEED_PREFIX) - set(NEED_BZ2_PREFIX 1) -endif() - kde4_bool_to_01(LIBLZMA_FOUND HAVE_XZ_SUPPORT) diff --git a/kdecore/compression/config-compression.h.cmake b/kdecore/compression/config-compression.h.cmake index dce2ec19..3067c891 100644 --- a/kdecore/compression/config-compression.h.cmake +++ b/kdecore/compression/config-compression.h.cmake @@ -1,8 +1,5 @@ #cmakedefine01 HAVE_BZIP2_SUPPORT -/* Set to 1 if the libbz2 functions need the BZ2_ prefix */ -#cmakedefine01 NEED_BZ2_PREFIX - /* Set to 1 if you have xz */ #cmakedefine01 HAVE_XZ_SUPPORT diff --git a/kdecore/compression/kbzip2filter.cpp b/kdecore/compression/kbzip2filter.cpp deleted file mode 100644 index 061a4d8b..00000000 --- a/kdecore/compression/kbzip2filter.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000-2005 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbzip2filter.h" - -#include - -#if HAVE_BZIP2_SUPPORT - -// we don't need that -#define BZ_NO_STDIO -extern "C" { - #include -} - -#if NEED_BZ2_PREFIX - #define bzDecompressInit(x,y,z) BZ2_bzDecompressInit(x,y,z) - #define bzDecompressEnd(x) BZ2_bzDecompressEnd(x) - #define bzCompressEnd(x) BZ2_bzCompressEnd(x) - #define bzDecompress(x) BZ2_bzDecompress(x) - #define bzCompress(x,y) BZ2_bzCompress(x, y) - #define bzCompressInit(x,y,z,a) BZ2_bzCompressInit(x, y, z, a); -#endif - -#include - -#include - - - -// For docu on this, see /usr/doc/bzip2-0.9.5d/bzip2-0.9.5d/manual_3.html - -class KBzip2Filter::Private -{ -public: - Private() - : isInitialized(false) - { - memset(&zStream, 0, sizeof(zStream)); - mode = 0; - } - - bz_stream zStream; - int mode; - bool isInitialized; -}; - -KBzip2Filter::KBzip2Filter() - :d(new Private) -{ -} - - -KBzip2Filter::~KBzip2Filter() -{ - delete d; -} - -bool KBzip2Filter::init( int mode ) -{ - if (d->isInitialized) { - terminate(); - } - - d->zStream.next_in = 0; - d->zStream.avail_in = 0; - if ( mode == QIODevice::ReadOnly ) - { - const int result = bzDecompressInit(&d->zStream, 0, 0); - if (result != BZ_OK) { - kDebug(7118) << "bzDecompressInit returned " << result; - return false; - } - } else if ( mode == QIODevice::WriteOnly ) { - const int result = bzCompressInit(&d->zStream, 5, 0, 0); - if (result != BZ_OK) { - kDebug(7118) << "bzDecompressInit returned " << result; - return false; - } - } else { - kWarning(7118) << "Unsupported mode " << mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported"; - return false; - } - d->mode = mode; - d->isInitialized = true; - return true; -} - -int KBzip2Filter::mode() const -{ - return d->mode; -} - -bool KBzip2Filter::terminate() -{ - if (d->mode == QIODevice::ReadOnly) { - const int result = bzDecompressEnd(&d->zStream); - if (result != BZ_OK) { - kDebug(7118) << "bzDecompressEnd returned " << result; - return false; - } - } else if (d->mode == QIODevice::WriteOnly) { - const int result = bzCompressEnd(&d->zStream); - if (result != BZ_OK) { - kDebug(7118) << "bzDecompressEnd returned " << result; - return false; - } - } else { - kWarning(7118) << "Unsupported mode " << d->mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported"; - return false; - } - d->isInitialized = false; - return true; -} - - -bool KBzip2Filter::reset() -{ - // bzip2 doesn't seem to have a reset call... - if (!terminate()) { - return false; - } - if (!init( d->mode )) { - return false; - } - return true; -} - -void KBzip2Filter::setOutBuffer( char * data, uint maxlen ) -{ - d->zStream.avail_out = maxlen; - d->zStream.next_out = data; -} - -void KBzip2Filter::setInBuffer( const char *data, unsigned int size ) -{ - d->zStream.avail_in = size; - d->zStream.next_in = const_cast(data); -} - -int KBzip2Filter::inBufferAvailable() const -{ - return d->zStream.avail_in; -} - -int KBzip2Filter::outBufferAvailable() const -{ - return d->zStream.avail_out; -} - -KBzip2Filter::Result KBzip2Filter::uncompress() -{ - //qDebug() << "Calling bzDecompress with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable(); - int result = bzDecompress(&d->zStream); - if ( result < BZ_OK ) { - kWarning(7118) << "bzDecompress returned" << result; - } - - switch (result) { - case BZ_OK: - return KFilterBase::Ok; - case BZ_STREAM_END: - return KFilterBase::End; - default: - return KFilterBase::Error; - } -} - -KBzip2Filter::Result KBzip2Filter::compress( bool finish ) -{ - //qDebug() << "Calling bzCompress with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable(); - int result = bzCompress(&d->zStream, finish ? BZ_FINISH : BZ_RUN ); - - switch (result) { - case BZ_OK: - case BZ_FLUSH_OK: - case BZ_RUN_OK: - case BZ_FINISH_OK: - return KFilterBase::Ok; - case BZ_STREAM_END: - //qDebug() << " bzCompress returned " << result; - return KFilterBase::End; - default: - //qDebug() << " bzCompress returned " << result; - return KFilterBase::Error; - } -} - -#endif /* HAVE_BZIP2_SUPPORT */ diff --git a/kdecore/compression/kbzip2filter.h b/kdecore/compression/kbzip2filter.h deleted file mode 100644 index 469bfa41..00000000 --- a/kdecore/compression/kbzip2filter.h +++ /dev/null @@ -1,58 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KBZIP2FILTER_H -#define KBZIP2FILTER_H - -#include - -#if HAVE_BZIP2_SUPPORT - -#include "kfilterbase.h" - -/** - * Internal class used by KFilterDev - * @internal - */ -class KBzip2Filter : public KFilterBase -{ -public: - KBzip2Filter(); - virtual ~KBzip2Filter(); - - virtual bool init( int ); - virtual int mode() const; - virtual bool terminate(); - virtual bool reset(); - virtual bool readHeader() { return true; } // bzip2 handles it by itself ! Cool ! - virtual bool writeHeader( const QByteArray & ) { return true; } - virtual void setOutBuffer( char * data, uint maxlen ); - virtual void setInBuffer( const char * data, uint size ); - virtual int inBufferAvailable() const; - virtual int outBufferAvailable() const; - virtual Result uncompress(); - virtual Result compress( bool finish ); -private: - class Private; - Private* const d; -}; - -#endif - -#endif diff --git a/kdecore/compression/kcompressor.cpp b/kdecore/compression/kcompressor.cpp new file mode 100644 index 00000000..21808b53 --- /dev/null +++ b/kdecore/compression/kcompressor.cpp @@ -0,0 +1,290 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config-compression.h" +#include "kcompressor.h" +#include "klocale.h" +#include "kmimetype.h" +#include "kdebug.h" +#include + +#include + +#if defined(HAVE_BZIP2_SUPPORT) +# include +#endif + +#if defined(HAVE_XZ_SUPPORT) +# include +#endif + +// for reference: +// http://linux.math.tifr.res.in/manuals/html/manual_3.html + +class KCompressorPrivate +{ +public: + KCompressorPrivate(); + + KCompressor::KCompressorType m_type; + int m_level; + QByteArray m_result; + QString m_errorstring; +}; + +KCompressorPrivate::KCompressorPrivate() + : m_type(KCompressor::TypeUnknown), + m_level(1) +{ +} + + +KCompressor::KCompressor() + : d(new KCompressorPrivate()) +{ +} + +KCompressor::~KCompressor() +{ + delete d; +} + +KCompressor::KCompressorType KCompressor::type() const +{ + return d->m_type; +} + +bool KCompressor::setType(const KCompressorType type) +{ + if (type == KCompressor::TypeUnknown) { + return false; + } + d->m_type = type; + return true; +} + +int KCompressor::level() const +{ + return d->m_level; +} + +bool KCompressor::setLevel(const int level) +{ + d->m_errorstring.clear(); + if (level < 0 || level > 9) { + d->m_errorstring = i18n("Compression level not in the 0-9 range: %1", level); + return false; + } + d->m_level = level; + return true; +} + +bool KCompressor::process(const QByteArray &data) +{ + d->m_errorstring.clear(); + d->m_result.clear(); + + switch (d->m_type) { + case KCompressor::TypeUnknown: { + return false; + } + case KCompressor::TypeDeflate: { + struct libdeflate_compressor* comp = libdeflate_alloc_compressor(d->m_level); + if (Q_UNLIKELY(!comp)) { + d->m_errorstring = i18n("Could not allocate compressor"); + return false; + } + + const size_t boundresult = libdeflate_deflate_compress_bound(comp, data.size()); + if (Q_UNLIKELY(boundresult <= 0)) { + d->m_errorstring = i18n("Compression boundary is negative or zero"); + libdeflate_free_compressor(comp); + return false; + } + + d->m_result.resize(boundresult); + const size_t compresult = libdeflate_deflate_compress( + comp, + data.constData(), data.size(), + d->m_result.data(), d->m_result.size() + ); + libdeflate_free_compressor(comp); + + if (Q_UNLIKELY(compresult <= 0)) { + d->m_errorstring = i18n("Could not compress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(compresult); + return true; + } + case KCompressor::TypeZlib: { + struct libdeflate_compressor* comp = libdeflate_alloc_compressor(d->m_level); + if (Q_UNLIKELY(!comp)) { + d->m_errorstring = i18n("Could not allocate compressor"); + return false; + } + + const size_t boundresult = libdeflate_zlib_compress_bound(comp, data.size()); + if (Q_UNLIKELY(boundresult <= 0)) { + d->m_errorstring = i18n("Compression boundary is negative or zero"); + libdeflate_free_compressor(comp); + return false; + } + + d->m_result.resize(boundresult); + const size_t compresult = libdeflate_zlib_compress( + comp, + data.constData(), data.size(), + d->m_result.data(), d->m_result.size() + ); + libdeflate_free_compressor(comp); + + if (Q_UNLIKELY(compresult <= 0)) { + d->m_errorstring = i18n("Could not compress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(compresult); + return true; + } + case KCompressor::TypeGZip: { + struct libdeflate_compressor* comp = libdeflate_alloc_compressor(d->m_level); + if (Q_UNLIKELY(!comp)) { + d->m_errorstring = i18n("Could not allocate compressor"); + return false; + } + + const size_t boundresult = libdeflate_gzip_compress_bound(comp, data.size()); + if (Q_UNLIKELY(boundresult <= 0)) { + d->m_errorstring = i18n("Compression boundary is negative or zero"); + libdeflate_free_compressor(comp); + return false; + } + + d->m_result.resize(boundresult); + const size_t compresult = libdeflate_gzip_compress( + comp, + data.constData(), data.size(), + d->m_result.data(), d->m_result.size() + ); + libdeflate_free_compressor(comp); + + if (Q_UNLIKELY(compresult <= 0)) { + d->m_errorstring = i18n("Could not compress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(compresult); + return true; + } +#if defined(HAVE_BZIP2_SUPPORT) + case KCompressor::TypeBZip2: { + d->m_result.resize(data.size() + QT_BUFFSIZE); + uint compsize = d->m_result.size(); + + int compresult = compresult = BZ2_bzBuffToBuffCompress( + d->m_result.data(), &compsize, + (char*)data.constData(), data.size(), + d->m_level, 0, 0 + ); + + if (Q_UNLIKELY(compresult < BZ_OK || compresult > BZ_STREAM_END)) { + d->m_errorstring = i18n("Could not compress data"); + return false; + } + + d->m_result.resize(compsize); + return true; + } +#endif // HAVE_BZIP2_SUPPORT +#if defined(HAVE_XZ_SUPPORT) + case KCompressor::TypeXZ: { + d->m_result.resize(data.size() + QT_BUFFSIZE); + size_t compsize = d->m_result.size(); + + lzma_stream comp = LZMA_STREAM_INIT; + comp.next_in = (const uint8_t*)data.constData(); + comp.avail_in = data.size(); + comp.next_out = (uint8_t*)d->m_result.data(); + comp.avail_out = compsize; + + lzma_ret compresult = lzma_easy_encoder(&comp, d->m_level, LZMA_CHECK_CRC32); + if (Q_UNLIKELY(compresult != LZMA_OK)) { + d->m_errorstring = i18n("Could not initialize compressor"); + d->m_result.clear(); + return false; + } + + compresult = lzma_code(&comp, LZMA_FINISH); + if (Q_UNLIKELY(compresult != LZMA_OK && compresult != LZMA_STREAM_END)) { + d->m_errorstring = i18n("Could not compress data"); + d->m_result.clear(); + return false; + } + compsize = comp.total_out; + lzma_end(&comp); + + d->m_result.resize(compsize); + return true; + } +#endif // HAVE_XZ_SUPPORT + default: { + kWarning() << "Unsupported type" << d->m_type; + return false; + } + } + Q_UNREACHABLE(); +} + +QByteArray KCompressor::result() const +{ + return d->m_result; +} + +QString KCompressor::errorString() const +{ + return d->m_errorstring; +} + +KCompressor::KCompressorType KCompressor::typeForMime(const QString &mime) +{ + const KMimeType::Ptr kmimetype = KMimeType::mimeType(mime); + if (kmimetype) { + if (kmimetype->is(QString::fromLatin1("application/x-gzip"))) { + return KCompressor::TypeGZip; + } else if (kmimetype->is(QString::fromLatin1("application/x-bzip"))) { + return KCompressor::TypeBZip2; + } else if (kmimetype->is(QString::fromLatin1("application/x-xz"))) { + return KCompressor::TypeXZ; + } + } + return KCompressor::TypeUnknown; +} + +KCompressor::KCompressorType KCompressor::typeForFile(const QString &filepath) +{ + const KMimeType::Ptr kmimetype = KMimeType::findByPath(filepath); + if (kmimetype) { + return KCompressor::typeForMime(kmimetype->name()); + } + return KCompressor::TypeUnknown; +} diff --git a/kdecore/compression/kcompressor.h b/kdecore/compression/kcompressor.h new file mode 100644 index 00000000..3861bc7c --- /dev/null +++ b/kdecore/compression/kcompressor.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KCOMPRESSOR_H +#define KCOMPRESSOR_H + +#include + +#include + +class KCompressorPrivate; + +class KDECORE_EXPORT KCompressor +{ +public: + enum KCompressorType { + TypeUnknown = 0, + TypeDeflate = 1, + TypeZlib = 2, + TypeGZip = 3, + TypeBZip2 = 4, + TypeXZ = 5 + }; + + KCompressor(); + ~KCompressor(); + + KCompressorType type() const; + bool setType(const KCompressorType type); + int level() const; + bool setLevel(const int level); + + bool process(const QByteArray &data); + QByteArray result() const; + + QString errorString() const; + + static KCompressorType typeForMime(const QString &mime); + static KCompressorType typeForFile(const QString &filepath); + +private: + KCompressorPrivate* d; +}; + +#endif // KCOMPRESSOR_H diff --git a/kdecore/compression/kdecompressor.cpp b/kdecore/compression/kdecompressor.cpp new file mode 100644 index 00000000..c4bc0b56 --- /dev/null +++ b/kdecore/compression/kdecompressor.cpp @@ -0,0 +1,323 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config-compression.h" +#include "kdecompressor.h" +#include "klocale.h" +#include "kmimetype.h" +#include "kdebug.h" +#include + +#include +#include + +#if defined(HAVE_BZIP2_SUPPORT) +# include +#endif + +#if defined(HAVE_XZ_SUPPORT) +# include +#endif + +// for reference: +// http://linux.math.tifr.res.in/manuals/html/manual_3.html + +class KDecompressorPrivate +{ +public: + KDecompressorPrivate(); + + KDecompressor::KDecompressorType m_type; + QByteArray m_result; + QString m_errorstring; +}; + +KDecompressorPrivate::KDecompressorPrivate() + : m_type(KDecompressor::TypeUnknown) +{ +} + + +KDecompressor::KDecompressor() + : d(new KDecompressorPrivate()) +{ +} + +KDecompressor::~KDecompressor() +{ + delete d; +} + +KDecompressor::KDecompressorType KDecompressor::type() const +{ + return d->m_type; +} + +bool KDecompressor::setType(const KDecompressorType type) +{ + if (type == KDecompressor::TypeUnknown) { + return false; + } + d->m_type = type; + return true; +} + +bool KDecompressor::process(const QByteArray &data) +{ + d->m_errorstring.clear(); + d->m_result.clear(); + + switch (d->m_type) { + case KDecompressor::TypeUnknown: { + return false; + } + case KDecompressor::TypeDeflate: { + struct libdeflate_decompressor* decomp = libdeflate_alloc_decompressor(); + if (Q_UNLIKELY(!decomp)) { + d->m_errorstring = i18n("Could not allocate decompressor"); + return false; + } + + size_t speculativesize = (data.size() * 2); + d->m_result.resize(speculativesize); + + libdeflate_result decompresult = LIBDEFLATE_INSUFFICIENT_SPACE; + while (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + decompresult = libdeflate_deflate_decompress( + decomp, + data.constData(), data.size(), + d->m_result.data(), d->m_result.size(), + &speculativesize + ); + + if (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + speculativesize = (speculativesize + QT_BUFFSIZE); + d->m_result.resize(speculativesize); + } + + if (speculativesize >= INT_MAX) { + break; + } + } + libdeflate_free_decompressor(decomp); + + if (decompresult != LIBDEFLATE_SUCCESS) { + d->m_errorstring = i18n("Could not decompress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(speculativesize); + return true; + } + case KDecompressor::TypeZlib: { + struct libdeflate_decompressor* decomp = libdeflate_alloc_decompressor(); + if (Q_UNLIKELY(!decomp)) { + d->m_errorstring = i18n("Could not allocate decompressor"); + return false; + } + + size_t speculativesize = (data.size() * 2); + d->m_result.resize(speculativesize); + + libdeflate_result decompresult = LIBDEFLATE_INSUFFICIENT_SPACE; + while (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + decompresult = libdeflate_zlib_decompress( + decomp, + data.constData(), data.size(), + d->m_result.data(), d->m_result.size(), + &speculativesize + ); + + if (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + speculativesize = (speculativesize + QT_BUFFSIZE); + d->m_result.resize(speculativesize); + } + + if (speculativesize >= INT_MAX) { + break; + } + } + libdeflate_free_decompressor(decomp); + + if (decompresult != LIBDEFLATE_SUCCESS) { + d->m_errorstring = i18n("Could not decompress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(speculativesize); + return true; + } + case KDecompressor::TypeGZip: { + struct libdeflate_decompressor* decomp = libdeflate_alloc_decompressor(); + if (Q_UNLIKELY(!decomp)) { + d->m_errorstring = i18n("Could not allocate decompressor"); + return false; + } + + size_t speculativesize = (data.size() * 2); + d->m_result.resize(speculativesize); + + libdeflate_result decompresult = LIBDEFLATE_INSUFFICIENT_SPACE; + while (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + decompresult = libdeflate_gzip_decompress( + decomp, + data.constData(), data.size(), + d->m_result.data(), d->m_result.size(), + &speculativesize + ); + + if (decompresult == LIBDEFLATE_INSUFFICIENT_SPACE) { + speculativesize = (speculativesize + QT_BUFFSIZE); + d->m_result.resize(speculativesize); + } + + if (speculativesize >= INT_MAX) { + break; + } + } + libdeflate_free_decompressor(decomp); + + if (decompresult != LIBDEFLATE_SUCCESS) { + d->m_errorstring = i18n("Could not decompress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(speculativesize); + return true; + } +#if defined(HAVE_BZIP2_SUPPORT) + case KDecompressor::TypeBZip2: { + uint speculativesize = (data.size() * 2); + d->m_result.resize(speculativesize); + int decompresult = BZ_OUTBUFF_FULL; + while (decompresult == BZ_OUTBUFF_FULL) { + decompresult = BZ2_bzBuffToBuffDecompress( + d->m_result.data(), &speculativesize, + (char*)data.constData(), data.size(), + 0, 0 + ); + + if (decompresult == BZ_OUTBUFF_FULL) { + speculativesize = (speculativesize + QT_BUFFSIZE); + d->m_result.resize(speculativesize); + } + + if (speculativesize >= INT_MAX) { + break; + } + } + + if (Q_UNLIKELY(decompresult < BZ_OK || decompresult > BZ_STREAM_END)) { + d->m_errorstring = i18n("Could not decompress data"); + d->m_result.clear(); + return false; + } + + d->m_result.resize(speculativesize); + return true; + } +#endif // HAVE_BZIP2_SUPPORT +#if defined(HAVE_XZ_SUPPORT) + case KDecompressor::TypeXZ: { + size_t speculativesize = (data.size() * 2); + d->m_result.resize(speculativesize); + + lzma_stream decomp = LZMA_STREAM_INIT; + decomp.next_in = (const uint8_t*)data.constData(); + decomp.avail_in = data.size(); + decomp.next_out = (uint8_t*)d->m_result.data(); + decomp.avail_out = speculativesize; + + lzma_ret decompresult = lzma_auto_decoder(&decomp, UINT64_MAX, 0); + if (Q_UNLIKELY(decompresult != LZMA_OK)) { + d->m_errorstring = i18n("Could not initialize decompressor"); + d->m_result.clear(); + return false; + } + + decompresult = LZMA_MEM_ERROR; + while (decompresult == LZMA_MEM_ERROR) { + decompresult = lzma_code(&decomp, LZMA_FINISH); + + if (decompresult == LZMA_MEM_ERROR) { + speculativesize = (speculativesize + QT_BUFFSIZE); + d->m_result.resize(speculativesize); + } + + if (speculativesize >= INT_MAX) { + break; + } + } + + if (Q_UNLIKELY(decompresult != LZMA_OK && decompresult != LZMA_STREAM_END)) { + d->m_errorstring = i18n("Could not decompress data"); + d->m_result.clear(); + return false; + } + speculativesize = decomp.total_out; + lzma_end(&decomp); + + d->m_result.resize(speculativesize); + return true; + } + +#endif // HAVE_XZ_SUPPORT + default: { + kWarning() << "Unsupported type" << d->m_type; + return false; + } + } + Q_UNREACHABLE(); +} + +QByteArray KDecompressor::result() const +{ + return d->m_result; +} + +QString KDecompressor::errorString() const +{ + return d->m_errorstring; +} + +KDecompressor::KDecompressorType KDecompressor::typeForMime(const QString &mime) +{ + const KMimeType::Ptr kmimetype = KMimeType::mimeType(mime); + if (kmimetype) { + if (kmimetype->is(QString::fromLatin1("application/x-gzip"))) { + return KDecompressor::TypeGZip; + } else if (kmimetype->is(QString::fromLatin1("application/x-bzip"))) { + return KDecompressor::TypeBZip2; + } else if (kmimetype->is(QString::fromLatin1("application/x-xz"))) { + return KDecompressor::TypeXZ; + } + } + return KDecompressor::TypeUnknown; +} + +KDecompressor::KDecompressorType KDecompressor::typeForFile(const QString &filepath) +{ + const KMimeType::Ptr kmimetype = KMimeType::findByPath(filepath); + if (kmimetype) { + return KDecompressor::typeForMime(kmimetype->name()); + } + return KDecompressor::TypeUnknown; +} diff --git a/kdecore/compression/kdecompressor.h b/kdecore/compression/kdecompressor.h new file mode 100644 index 00000000..b157e3f6 --- /dev/null +++ b/kdecore/compression/kdecompressor.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KDECOMPRESSOR_H +#define KDECOMPRESSOR_H + +#include + +#include + +class KDecompressorPrivate; + +class KDECORE_EXPORT KDecompressor +{ +public: + enum KDecompressorType { + TypeUnknown = 0, + TypeDeflate = 1, + TypeZlib = 2, + TypeGZip = 3, + TypeBZip2 = 4, + TypeXZ = 5 + }; + + KDecompressor(); + ~KDecompressor(); + + KDecompressorType type() const; + bool setType(const KDecompressorType type); + + bool process(const QByteArray &data); + QByteArray result() const; + + QString errorString() const; + + static KDecompressorType typeForMime(const QString &mime); + static KDecompressorType typeForFile(const QString &filepath); + +private: + KDecompressorPrivate* d; +}; + +#endif // KDECOMPRESSOR_H diff --git a/kdecore/compression/kfilterbase.cpp b/kdecore/compression/kfilterbase.cpp deleted file mode 100644 index f0620285..00000000 --- a/kdecore/compression/kfilterbase.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000-2005 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kfilterbase.h" -#include - -#include -#include -#include "kgzipfilter.h" -#if HAVE_BZIP2_SUPPORT -#include "kbzip2filter.h" -#endif -#if HAVE_XZ_SUPPORT -#include "kxzfilter.h" -#endif - -class KFilterBasePrivate -{ -public: - KFilterBasePrivate(); - - QIODevice * m_dev; - bool m_bAutoDel; - KFilterBase::FilterFlags m_flags; -}; - -KFilterBasePrivate::KFilterBasePrivate() - : m_dev( 0L ), - m_bAutoDel( false ), - m_flags(KFilterBase::WithHeaders) -{ -} - -KFilterBase::KFilterBase() - : d(new KFilterBasePrivate()) -{ -} - -KFilterBase::~KFilterBase() -{ - if ( d->m_bAutoDel ) - delete d->m_dev; - delete d; -} - -void KFilterBase::setDevice( QIODevice * dev, bool autodelete ) -{ - d->m_dev = dev; - d->m_bAutoDel = autodelete; -} - -QIODevice * KFilterBase::device() -{ - return d->m_dev; -} - -bool KFilterBase::inBufferEmpty() const -{ - return inBufferAvailable() == 0; -} - -bool KFilterBase::outBufferFull() const -{ - return outBufferAvailable() == 0; -} - -KFilterBase * KFilterBase::findFilterByFileName( const QString & fileName ) -{ - if ( fileName.endsWith( QLatin1String(".gz"), Qt::CaseInsensitive ) ) - { - return new KGzipFilter; - } -#if HAVE_BZIP2_SUPPORT - if ( fileName.endsWith( QLatin1String(".bz2"), Qt::CaseInsensitive ) ) - { - return new KBzip2Filter; - } -#endif -#if HAVE_XZ_SUPPORT - if ( fileName.endsWith( QLatin1String(".lzma"), Qt::CaseInsensitive ) || fileName.endsWith( QLatin1String(".xz"), Qt::CaseInsensitive ) ) - { - return new KXzFilter; - } -#endif - else - { - // not a warning, since this is called often with other mimetypes (see #88574)... - // maybe we can avoid that though? - //qDebug() << "KFilterBase::findFilterByFileName : no filter found for " << fileName; - } - - return 0; -} - -KFilterBase * KFilterBase::findFilterByMimeType( const QString & mimeType ) -{ - if (mimeType == QLatin1String("application/x-gzip")) { - return new KGzipFilter; - } -#if HAVE_BZIP2_SUPPORT - if (mimeType == QLatin1String("application/x-bzip") - || mimeType == QLatin1String("application/x-bzip2") // old name, kept for compatibility - ) { - return new KBzip2Filter; - } -#endif -#if HAVE_XZ_SUPPORT - if ( mimeType == QLatin1String( "application/x-lzma" ) // legacy name, still used - || mimeType == QLatin1String( "application/x-xz" ) // current naming - ) { - return new KXzFilter; - } -#endif - const KMimeType::Ptr mime = KMimeType::mimeType(mimeType); - if (mime) { - if (mime->is(QString::fromLatin1("application/x-gzip"))) { - return new KGzipFilter; - } -#if HAVE_BZIP2_SUPPORT - if (mime->is(QString::fromLatin1("application/x-bzip"))) { - return new KBzip2Filter; - } -#endif -#if HAVE_XZ_SUPPORT - if (mime->is(QString::fromLatin1("application/x-lzma"))) { - return new KXzFilter; - } - - if (mime->is(QString::fromLatin1("application/x-xz"))) { - return new KXzFilter; - } -#endif - } - - // not a warning, since this is called often with other mimetypes (see #88574)... - // maybe we can avoid that though? - //qDebug() << "no filter found for" << mimeType; - return 0; -} - -bool KFilterBase::terminate() -{ - return false; -} - -bool KFilterBase::reset() -{ - return false; -} - -void KFilterBase::setFilterFlags(FilterFlags flags) -{ - d->m_flags = flags; -} - -KFilterBase::FilterFlags KFilterBase::filterFlags() const -{ - return d->m_flags; -} - diff --git a/kdecore/compression/kfilterbase.h b/kdecore/compression/kfilterbase.h deleted file mode 100644 index 191a63d0..00000000 --- a/kdecore/compression/kfilterbase.h +++ /dev/null @@ -1,123 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KFILTERBASE_H -#define KFILTERBASE_H - -#include - -#include - -class KFilterBasePrivate; - -/** - * This is the base class for compression filters - * such as gzip and bzip2. It's pretty much internal. - * Don't use directly, use KFilterDev instead. - * @internal - */ -class KDECORE_EXPORT KFilterBase -{ -public: - KFilterBase(); - virtual ~KFilterBase(); - - /** - * Sets the device on which the filter will work - * @param dev the device on which the filter will work - * @param autodelete if true, @p dev is deleted when the filter is deleted - */ - void setDevice( QIODevice * dev, bool autodelete = false ); - // Note that this isn't in the constructor, because of KPluginFactory::create, - // but it should be called before using the filterbase ! - - /** - * Returns the device on which the filter will work. - * @returns the device on which the filter will work - */ - QIODevice * device(); - /** \internal */ - virtual bool init( int mode ) = 0; - /** \internal */ - virtual int mode() const = 0; - /** \internal */ - virtual bool terminate(); - /** \internal */ - virtual bool reset(); - /** \internal */ - virtual bool readHeader() = 0; - /** \internal */ - virtual bool writeHeader( const QByteArray & filename ) = 0; - /** \internal */ - virtual void setOutBuffer( char * data, uint maxlen ) = 0; - /** \internal */ - virtual void setInBuffer( const char * data, uint size ) = 0; - /** \internal */ - virtual bool inBufferEmpty() const; - /** \internal */ - virtual int inBufferAvailable() const = 0; - /** \internal */ - virtual bool outBufferFull() const; - /** \internal */ - virtual int outBufferAvailable() const = 0; - - /** \internal */ - enum Result { Ok, End, Error }; - /** \internal */ - virtual Result uncompress() = 0; - /** \internal */ - virtual Result compress( bool finish ) = 0; - - /** - * \internal - * \since 4.3 - */ - enum FilterFlags { - NoHeaders = 0, - WithHeaders = 1 - }; - /** - * \internal - * \since 4.3 - */ - void setFilterFlags(FilterFlags flags); - FilterFlags filterFlags() const; - - /** - * Call this to create the appropriate filter for the file - * named @p fileName. - * @param fileName the name of the file to filter - * @return the filter for the @p fileName, or 0 if not found - */ - static KFilterBase * findFilterByFileName( const QString & fileName ); - - /** - * Call this to create the appropriate filter for the mimetype - * @p mimeType. For instance application/x-gzip. - * @param mimeType the mime type of the file to filter - * @return the filter for the @p mimeType, or 0 if not found - */ - static KFilterBase * findFilterByMimeType( const QString & mimeType ); - -private: - Q_DISABLE_COPY( KFilterBase ) - KFilterBasePrivate * const d; -}; - -#endif diff --git a/kdecore/compression/kfilterdev.cpp b/kdecore/compression/kfilterdev.cpp deleted file mode 100644 index fa0d95cc..00000000 --- a/kdecore/compression/kfilterdev.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000, 2006 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kfilterdev.h" -#include "kfilterbase.h" - -#include // for EOF -#include -#include - -#include -#include - -#define BUFFER_SIZE 8*1024 - -class KFilterDev::Private -{ -public: - Private() : bNeedHeader(true), bSkipHeaders(false), - autoDeleteFilterBase(false), bOpenedUnderlyingDevice(false), - bIgnoreData(false){} - bool bNeedHeader; - bool bSkipHeaders; - bool autoDeleteFilterBase; - bool bOpenedUnderlyingDevice; - bool bIgnoreData; - QByteArray buffer; // Used as 'input buffer' when reading, as 'output buffer' when writing - QByteArray origFileName; - KFilterBase::Result result; - KFilterBase *filter; -}; - -KFilterDev::KFilterDev( KFilterBase * _filter, bool autoDeleteFilterBase ) - : d(new Private) -{ - assert(_filter); - d->filter = _filter; - d->autoDeleteFilterBase = autoDeleteFilterBase; -} - -KFilterDev::~KFilterDev() -{ - if ( isOpen() ) - close(); - if ( d->autoDeleteFilterBase ) - delete d->filter; - delete d; -} - -//static -QIODevice * KFilterDev::deviceForFile( const QString & fileName, const QString & mimetype, - bool forceFilter ) -{ - QFile * f = new QFile( fileName ); - KFilterBase * base = mimetype.isEmpty() ? KFilterBase::findFilterByFileName( fileName ) - : KFilterBase::findFilterByMimeType( mimetype ); - if ( base ) - { - base->setDevice(f, true); - return new KFilterDev(base, true); - } - if(!forceFilter) - return f; - else - { - delete f; - return 0L; - } -} - -QIODevice * KFilterDev::device( QIODevice* inDevice, const QString & mimetype, bool autoDeleteInDevice ) -{ - if (inDevice==0) - return 0; - KFilterBase * base = KFilterBase::findFilterByMimeType(mimetype); - if ( base ) - { - base->setDevice(inDevice, autoDeleteInDevice); - return new KFilterDev(base, true /* auto-delete "base" */); - } - return 0; -} - -bool KFilterDev::open( QIODevice::OpenMode mode ) -{ - if (isOpen()) { - qWarning() << "KFilterDev::open: device is already open"; - return true; // QFile returns false, but well, the device -is- open... - } - //kDebug(7005) << mode; - if ( mode == QIODevice::ReadOnly ) - { - d->buffer.resize(0); - } - else - { - d->buffer.resize( BUFFER_SIZE ); - d->filter->setOutBuffer( d->buffer.data(), d->buffer.size() ); - } - d->bNeedHeader = !d->bSkipHeaders; - d->filter->setFilterFlags(d->bSkipHeaders ? KFilterBase::NoHeaders : KFilterBase::WithHeaders); - d->filter->init( mode ); - d->bOpenedUnderlyingDevice = !d->filter->device()->isOpen(); - bool ret = d->bOpenedUnderlyingDevice ? d->filter->device()->open( mode ) : true; - d->result = KFilterBase::Ok; - - if ( !ret ) - qWarning() << "KFilterDev::open: Couldn't open underlying device"; - else - setOpenMode( mode ); - - return ret; -} - -void KFilterDev::close() -{ - if ( !isOpen() ) - return; - if ( d->filter->mode() == QIODevice::WriteOnly ) - write( 0L, 0 ); // finish writing - //kDebug(7005) << "Calling terminate()."; - - d->filter->terminate(); - if ( d->bOpenedUnderlyingDevice ) - d->filter->device()->close(); - setOpenMode( QIODevice::NotOpen ); -} - -bool KFilterDev::seek( qint64 pos ) -{ - qint64 ioIndex = this->pos(); // current position - if ( ioIndex == pos ) - return true; - - //kDebug(7005) << "seek(" << pos << ") called"; - - Q_ASSERT ( d->filter->mode() == QIODevice::ReadOnly ); - - if ( pos == 0 ) - { - // We can forget about the cached data - d->bNeedHeader = !d->bSkipHeaders; - d->result = KFilterBase::Ok; - d->filter->setInBuffer(0L,0); - d->filter->reset(); - QIODevice::seek(pos); - return d->filter->device()->reset(); - } - - if ( ioIndex > pos ) // we can start from here - pos = pos - ioIndex; - else - { - // we have to start from 0 ! Ugly and slow, but better than the previous - // solution (KTarGz was allocating everything into memory) - if (!seek(0)) // recursive - return false; - } - - //kDebug(7005) << "reading " << pos << " dummy bytes"; - QByteArray dummy( qMin( pos, (qint64)3*BUFFER_SIZE ), 0 ); - d->bIgnoreData = true; - bool result = ( read( dummy.data(), pos ) == pos ); - d->bIgnoreData = false; - QIODevice::seek(pos); - return result; -} - -bool KFilterDev::atEnd() const -{ - return (d->result == KFilterBase::End) - && QIODevice::atEnd() // take QIODevice's internal buffer into account - && d->filter->device()->atEnd(); -} - -qint64 KFilterDev::readData( char *data, qint64 maxlen ) -{ - Q_ASSERT ( d->filter->mode() == QIODevice::ReadOnly ); - //kDebug(7005) << "maxlen=" << maxlen; - KFilterBase* filter = d->filter; - - uint dataReceived = 0; - - // We came to the end of the stream - if ( d->result == KFilterBase::End ) - return dataReceived; - - // If we had an error, return -1. - if ( d->result != KFilterBase::Ok ) - return -1; - - - qint64 outBufferSize; - if ( d->bIgnoreData ) - { - outBufferSize = qMin( maxlen, (qint64)3*BUFFER_SIZE ); - } - else - { - outBufferSize = maxlen; - } - outBufferSize -= dataReceived; - qint64 availOut = outBufferSize; - filter->setOutBuffer( data, outBufferSize ); - - while ( dataReceived < maxlen ) - { - if (filter->inBufferEmpty()) - { - // Not sure about the best size to set there. - // For sure, it should be bigger than the header size (see comment in readHeader) - d->buffer.resize( BUFFER_SIZE ); - // Request data from underlying device - int size = filter->device()->read( d->buffer.data(), - d->buffer.size() ); - //kDebug(7005) << "got" << size << "bytes from device"; - if (size) { - filter->setInBuffer( d->buffer.data(), size ); - } else { - // Not enough data available in underlying device for now - break; - } - } - if (d->bNeedHeader) - { - (void) filter->readHeader(); - d->bNeedHeader = false; - } - - d->result = filter->uncompress(); - - if (d->result == KFilterBase::Error) - { - qWarning() << "KFilterDev: Error when uncompressing data"; - break; - } - - // We got that much data since the last time we went here - uint outReceived = availOut - filter->outBufferAvailable(); - //kDebug(7005) << "avail_out = " << filter->outBufferAvailable() << " result=" << d->result << " outReceived=" << outReceived; - if( availOut < (uint)filter->outBufferAvailable() ) - qWarning() << " last availOut " << availOut << " smaller than new avail_out=" << filter->outBufferAvailable() << " !"; - - dataReceived += outReceived; - if ( !d->bIgnoreData ) // Move on in the output buffer - { - data += outReceived; - availOut = maxlen - dataReceived; - } - else if ( maxlen - dataReceived < outBufferSize ) - { - availOut = maxlen - dataReceived; - } - if (d->result == KFilterBase::End) - { - //kDebug(7005) << "got END. dataReceived=" << dataReceived; - break; // Finished. - } - filter->setOutBuffer( data, availOut ); - } - - return dataReceived; -} - -qint64 KFilterDev::writeData( const char *data /*0 to finish*/, qint64 len ) -{ - KFilterBase* filter = d->filter; - Q_ASSERT ( filter->mode() == QIODevice::WriteOnly ); - // If we had an error, return 0. - if ( d->result != KFilterBase::Ok ) - return 0; - - bool finish = (data == 0L); - if (!finish) - { - filter->setInBuffer( data, len ); - if (d->bNeedHeader) - { - (void)filter->writeHeader( d->origFileName ); - d->bNeedHeader = false; - } - } - - uint dataWritten = 0; - uint availIn = len; - while ( dataWritten < len || finish ) - { - - d->result = filter->compress( finish ); - - if (d->result == KFilterBase::Error) - { - qWarning() << "KFilterDev: Error when compressing data"; - // What to do ? - break; - } - - // Wrote everything ? - if (filter->inBufferEmpty() || (d->result == KFilterBase::End)) - { - // We got that much data since the last time we went here - uint wrote = availIn - filter->inBufferAvailable(); - - //kDebug(7005) << " Wrote everything for now. avail_in=" << filter->inBufferAvailable() << "result=" << d->result << "wrote=" << wrote; - - // Move on in the input buffer - data += wrote; - dataWritten += wrote; - - availIn = len - dataWritten; - //kDebug(7005) << " availIn=" << availIn << "dataWritten=" << dataWritten << "pos=" << pos(); - if ( availIn > 0 ) - filter->setInBuffer( data, availIn ); - } - - if (filter->outBufferFull() || (d->result == KFilterBase::End) || finish) - { - //kDebug(7005) << " writing to underlying. avail_out=" << filter->outBufferAvailable(); - int towrite = d->buffer.size() - filter->outBufferAvailable(); - if ( towrite > 0 ) - { - // Write compressed data to underlying device - int size = filter->device()->write( d->buffer.data(), towrite ); - if ( size != towrite ) { - qWarning() << "KFilterDev::write. Could only write " << size << " out of " << towrite << " bytes"; - return 0; // indicate an error (happens on disk full) - } - //else - //kDebug(7005) << " wrote " << size << " bytes"; - } - if (d->result == KFilterBase::End) - { - //kDebug(7005) << " END"; - Q_ASSERT(finish); // hopefully we don't get end before finishing - break; - } - d->buffer.resize(BUFFER_SIZE); - filter->setOutBuffer( d->buffer.data(), d->buffer.size() ); - } - } - - return dataWritten; -} - -void KFilterDev::setOrigFileName( const QByteArray & fileName ) -{ - d->origFileName = fileName; -} - -void KFilterDev::setSkipHeaders() -{ - d->bSkipHeaders = true; -} diff --git a/kdecore/compression/kfilterdev.h b/kdecore/compression/kfilterdev.h deleted file mode 100644 index 5da2b3b9..00000000 --- a/kdecore/compression/kfilterdev.h +++ /dev/null @@ -1,151 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -#ifndef KFILTERDEV_H -#define KFILTERDEV_H - -#include -#include - -class KFilterBase; - -/** - * A class for reading and writing compressed data onto a device - * (e.g. file, but other usages are possible, like a buffer or a socket). - * - * To simply read/write compressed files, see deviceForFile. - * - * @author David Faure - */ -class KDECORE_EXPORT KFilterDev : public QIODevice -{ -public: - /** - * Destructs the KFilterDev. - * Calls close() if the filter device is still open. - */ - virtual ~KFilterDev(); - - /** - * Open for reading or writing. - * If the KFilterBase's device is not opened, it will be opened. - */ - virtual bool open( QIODevice::OpenMode mode ); - /** - * Close after reading or writing. - * If the KFilterBase's device was opened by open(), it will be closed. - */ - virtual void close(); - - /** - * For writing gzip compressed files only: - * set the name of the original file, to be used in the gzip header. - * @param fileName the name of the original file - */ - void setOrigFileName( const QByteArray & fileName ); - - /** - * Call this let this device skip the gzip headers when reading/writing. - * This way KFilterDev (with gzip filter) can be used as a direct wrapper - * around zlib - this is used by KZip. - */ - void setSkipHeaders(); - - /** - * That one can be quite slow, when going back. Use with care. - */ - virtual bool seek( qint64 ); - - virtual bool atEnd() const; - - /// Reimplemented to return true. KFilterDev is a sequential QIODevice. - /// Well, not really, since it supports seeking and KZip uses that. - //virtual bool isSequential() const { return true; } - -public: - - - // KDE4 TODO: turn those static methods into constructors - - /** - * Creates an i/o device that is able to read from @p fileName, - * whether it's compressed or not. Available compression filters - * (gzip/bzip2 etc.) will automatically be used. - * - * The compression filter to be used is determined from the @p fileName - * if @p mimetype is empty. Pass "application/x-gzip" or "application/x-bzip" - * to force the corresponding decompression filter, if available. - * - * Warning: application/x-bzip may not be available. - * In that case a QFile opened on the compressed data will be returned ! - * Use KFilterBase::findFilterByMimeType and code similar to what - * deviceForFile is doing, to better control what's happening. - * - * The returned QIODevice has to be deleted after using. - * - * @param fileName the name of the file to filter - * @param mimetype the mime type of the file to filter, or QString() if unknown - * @param forceFilter if true, the function will either find a compression filter, or return 0. - * If false, it will always return a QIODevice. If no - * filter is available it will return a simple QFile. - * This can be useful if the file is usable without a filter. - * @return if a filter has been found, the QIODevice for the filter. If the - * filter does not exist, the return value depends on @p forceFilter. - * The returned QIODevice has to be deleted after using. - */ - static QIODevice * deviceForFile( const QString & fileName, const QString & mimetype = QString(), - bool forceFilter = false ); - - /** - * Creates an i/o device that is able to read from the QIODevice @p inDevice, - * whether the data is compressed or not. Available compression filters - * (gzip/bzip2 etc.) will automatically be used. - * - * The compression filter to be used is determined @p mimetype . - * Pass "application/x-gzip" or "application/x-bzip" - * to use the corresponding decompression filter. - * - * Warning: application/x-bzip may not be available. - * In that case 0 will be returned ! - * - * The returned QIODevice has to be deleted after using. - * @param inDevice input device. Won't be deleted if @p autoDeleteInDevice = false - * @param mimetype the mime type for the filter - * @param autoDeleteInDevice if true, @p inDevice will be deleted automatically - * @return a KFilterDev that filters the original stream. Must be deleted after using - */ - static QIODevice * device( QIODevice* inDevice, const QString & mimetype, bool autoDeleteInDevice = true ); - -protected: - virtual qint64 readData( char *data, qint64 maxlen ); - virtual qint64 writeData( const char *data, qint64 len ); - -private: - /** - * Constructs a KFilterDev for a given filter (e.g. gzip, bzip2 etc.). - * @param filter the KFilterBase to use - * @param autoDeleteFilterBase when true this object will become the - * owner of @p filter. - */ - explicit KFilterDev( KFilterBase * filter, bool autoDeleteFilterBase = false ); -private: - class Private; - Private* const d; -}; - - -#endif diff --git a/kdecore/compression/kgzipfilter.cpp b/kdecore/compression/kgzipfilter.cpp deleted file mode 100644 index 5e82f9d2..00000000 --- a/kdecore/compression/kgzipfilter.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000-2005 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kgzipfilter.h" - -#include - -#include -#include -#include - - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -// #define DEBUG_GZIP - -class KGzipFilter::Private -{ -public: - Private() - : headerWritten(false), footerWritten(false), compressed(false), mode(0), crc(0), isInitialized(false) - { - zStream.zalloc = (alloc_func)0; - zStream.zfree = (free_func)0; - zStream.opaque = (voidpf)0; - } - - z_stream zStream; - bool headerWritten; - bool footerWritten; - bool compressed; - int mode; - ulong crc; - bool isInitialized; -}; - -KGzipFilter::KGzipFilter() - : d(new Private) -{ -} - - -KGzipFilter::~KGzipFilter() -{ - delete d; -} - -bool KGzipFilter::init(int mode) -{ - return init(mode, filterFlags() == WithHeaders ? GZipHeader : RawDeflate); -} - -bool KGzipFilter::init(int mode, Flag flag) -{ - if (d->isInitialized) { - terminate(); - } - d->zStream.next_in = Z_NULL; - d->zStream.avail_in = 0; - if ( mode == QIODevice::ReadOnly ) - { - const int windowBits = (flag == RawDeflate) - ? -MAX_WBITS /*no zlib header*/ - : (flag == GZipHeader) ? - MAX_WBITS + 32 /* auto-detect and eat gzip header */ - : MAX_WBITS /*zlib header*/; - const int result = inflateInit2(&d->zStream, windowBits); - if ( result != Z_OK ) { - kDebug(7110) << "inflateInit2 returned " << result; - return false; - } - } else if ( mode == QIODevice::WriteOnly ) - { - int result = deflateInit2(&d->zStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); // same here - if ( result != Z_OK ) { - kDebug(7110) << "deflateInit returned " << result; - return false; - } - } else { - kWarning(7110) << "KGzipFilter: Unsupported mode " << mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported"; - return false; - } - d->mode = mode; - d->compressed = true; - d->headerWritten = false; - d->footerWritten = false; - d->isInitialized = true; - return true; -} - -int KGzipFilter::mode() const -{ - return d->mode; -} - -bool KGzipFilter::terminate() -{ - if ( d->mode == QIODevice::ReadOnly ) - { - int result = inflateEnd(&d->zStream); - if ( result != Z_OK ) { - kDebug(7110) << "inflateEnd returned " << result; - return false; - } - } else if ( d->mode == QIODevice::WriteOnly ) - { - int result = deflateEnd(&d->zStream); - if ( result != Z_OK ) { - kDebug(7110) << "deflateEnd returned " << result; - return false; - } - } - d->isInitialized = false; - return true; -} - - -bool KGzipFilter::reset() -{ - if ( d->mode == QIODevice::ReadOnly ) - { - int result = inflateReset(&d->zStream); - if ( result != Z_OK ) { - kDebug(7110) << "inflateReset returned " << result; - return false; - } - } else if ( d->mode == QIODevice::WriteOnly ) { - int result = deflateReset(&d->zStream); - if ( result != Z_OK ) { - kDebug(7110) << "deflateReset returned " << result; - return false; - } - d->headerWritten = false; - d->footerWritten = false; - } - return true; -} - -bool KGzipFilter::readHeader() -{ - // We now rely on zlib to read the full header (see the MAX_WBITS + 32 in init). - // We just use this method to check if the data is actually compressed. - -#ifdef DEBUG_GZIP - kDebug(7110) << "avail=" << d->zStream.avail_in; -#endif - // Assume not compressed until we see a gzip header - d->compressed = false; - Bytef *p = d->zStream.next_in; - int i = d->zStream.avail_in; - if ((i -= 10) < 0) return false; // Need at least 10 bytes -#ifdef DEBUG_GZIP - kDebug(7110) << "first byte is " << QString::number(*p,16); -#endif - if (*p++ != 0x1f) return false; // GZip magic -#ifdef DEBUG_GZIP - kDebug(7110) << "second byte is " << QString::number(*p,16); -#endif - if (*p++ != 0x8b) return false; - -#if 0 - int method = *p++; - int flags = *p++; - if ((method != Z_DEFLATED) || (flags & RESERVED) != 0) return false; - p += 6; - if ((flags & EXTRA_FIELD) != 0) // skip extra field - { - if ((i -= 2) < 0) return false; // Need at least 2 bytes - int len = *p++; - len += (*p++) << 8; - if ((i -= len) < 0) return false; // Need at least len bytes - p += len; - } - if ((flags & ORIG_NAME) != 0) // skip original file name - { -#ifdef DEBUG_GZIP - kDebug(7110) << "ORIG_NAME=" << (char*)p; -#endif - while( (i > 0) && (*p)) - { - i--; p++; - } - if (--i <= 0) return false; - p++; - } - if ((flags & COMMENT) != 0) // skip comment - { - while( (i > 0) && (*p)) - { - i--; p++; - } - if (--i <= 0) return false; - p++; - } - if ((flags & HEAD_CRC) != 0) // skip the header crc - { - if ((i-=2) < 0) return false; - p += 2; - } - - d->zStream.avail_in = i; - d->zStream.next_in = p; -#endif - - d->compressed = true; -#ifdef DEBUG_GZIP - kDebug(7110) << "header OK"; -#endif - return true; -} - -/* Output a 16 bit value, lsb first */ -#define put_short(w) \ - *p++ = (uchar) ((w) & 0xff); \ - *p++ = (uchar) ((ushort)(w) >> 8); - -/* Output a 32 bit value to the bit stream, lsb first */ -#define put_long(n) \ - put_short((n) & 0xffff); \ - put_short(((ulong)(n)) >> 16); - -bool KGzipFilter::writeHeader( const QByteArray & fileName ) -{ - Bytef *p = d->zStream.next_out; - int i = d->zStream.avail_out; - *p++ = 0x1f; - *p++ = 0x8b; - *p++ = Z_DEFLATED; - *p++ = ORIG_NAME; - put_long( time( 0L ) ); // Modification time (in unix format) - *p++ = 0; // Extra flags (2=max compress, 4=fastest compress) - *p++ = 3; // Unix - - uint len = fileName.length(); - for ( uint j = 0 ; j < len ; ++j ) - *p++ = fileName[j]; - *p++ = 0; - int headerSize = p - d->zStream.next_out; - i -= headerSize; - Q_ASSERT(i>0); - d->crc = crc32(0L, Z_NULL, 0); - d->zStream.next_out = p; - d->zStream.avail_out = i; - d->headerWritten = true; - return true; -} - -void KGzipFilter::writeFooter() -{ - Q_ASSERT( d->headerWritten ); - Q_ASSERT(!d->footerWritten); - Bytef *p = d->zStream.next_out; - int i = d->zStream.avail_out; - //kDebug(7110) << "avail_out=" << i << "writing CRC=" << QString::number(d->crc, 16) << "at p=" << p; - put_long( d->crc ); - //kDebug(7110) << "writing totalin=" << d->zStream.total_in << "at p=" << p; - put_long( d->zStream.total_in ); - i -= p - d->zStream.next_out; - d->zStream.next_out = p; - d->zStream.avail_out = i; - d->footerWritten = true; -} - -void KGzipFilter::setOutBuffer( char * data, uint maxlen ) -{ - d->zStream.avail_out = maxlen; - d->zStream.next_out = (Bytef *) data; -} -void KGzipFilter::setInBuffer( const char * data, uint size ) -{ -#ifdef DEBUG_GZIP - kDebug(7110) << "avail_in=" << size; -#endif - d->zStream.avail_in = size; - d->zStream.next_in = (Bytef*) data; -} -int KGzipFilter::inBufferAvailable() const -{ - return d->zStream.avail_in; -} -int KGzipFilter::outBufferAvailable() const -{ - return d->zStream.avail_out; -} - -KGzipFilter::Result KGzipFilter::uncompress_noop() -{ - // I'm not sure we really need support for that (uncompressed streams), - // but why not, it can't hurt to have it. One case I can think of is someone - // naming a tar file "blah.tar.gz" :-) - if ( d->zStream.avail_in > 0 ) - { - int n = (d->zStream.avail_in < d->zStream.avail_out) ? d->zStream.avail_in : d->zStream.avail_out; - memcpy( d->zStream.next_out, d->zStream.next_in, n ); - d->zStream.avail_out -= n; - d->zStream.next_in += n; - d->zStream.avail_in -= n; - return KFilterBase::Ok; - } else - return KFilterBase::End; -} - -KGzipFilter::Result KGzipFilter::uncompress() -{ -#ifndef NDEBUG - if (d->mode == 0) { - qWarning() << "mode==0; KGzipFilter::init was not called!"; - return KFilterBase::Error; - } else if (d->mode == QIODevice::WriteOnly) { - qWarning() << "uncompress called but the filter was opened for writing!"; - return KFilterBase::Error; - } - Q_ASSERT ( d->mode == QIODevice::ReadOnly ); -#endif - - if ( d->compressed ) - { -#ifdef DEBUG_GZIP - kDebug(7110) << "Calling inflate with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable(); - kDebug(7110) << " next_in=" << d->zStream.next_in; -#endif - int result = inflate(&d->zStream, Z_SYNC_FLUSH); -#ifdef DEBUG_GZIP - kDebug(7110) << " -> inflate returned " << result; - kDebug(7110) << " now avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable(); - kDebug(7110) << " next_in=" << d->zStream.next_in; -#else - if ( result != Z_OK && result != Z_STREAM_END ) - kDebug(7110) << "Warning: inflate() returned " << result; -#endif - return ( result == Z_OK ? KFilterBase::Ok : ( result == Z_STREAM_END ? KFilterBase::End : KFilterBase::Error ) ); - } else - return uncompress_noop(); -} - -KGzipFilter::Result KGzipFilter::compress( bool finish ) -{ - Q_ASSERT ( d->compressed ); - Q_ASSERT ( d->mode == QIODevice::WriteOnly ); - - Bytef* p = d->zStream.next_in; - ulong len = d->zStream.avail_in; -#ifdef DEBUG_GZIP - kDebug(7110) << " calling deflate with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable(); -#endif - const int result = deflate(&d->zStream, finish ? Z_FINISH : Z_NO_FLUSH); - if ( result != Z_OK && result != Z_STREAM_END ) { - kDebug(7110) << " deflate returned " << result; - } - if ( d->headerWritten ) - { - //kDebug(7110) << "Computing CRC for the next " << len - d->zStream.avail_in << " bytes"; - d->crc = crc32(d->crc, p, len - d->zStream.avail_in); - } - KGzipFilter::Result callerResult = result == Z_OK ? KFilterBase::Ok : (Z_STREAM_END ? KFilterBase::End : KFilterBase::Error); - - if (result == Z_STREAM_END && d->headerWritten && !d->footerWritten) { - if (d->zStream.avail_out >= 8 /*footer size*/) { - //kDebug(7110) << "finished, write footer"; - writeFooter(); - } else { - // No room to write the footer (#157706/#188415), we'll have to do it on the next pass. - //kDebug(7110) << "finished, but no room for footer yet"; - callerResult = KFilterBase::Ok; - } - } - return callerResult; -} diff --git a/kdecore/compression/kgzipfilter.h b/kdecore/compression/kgzipfilter.h deleted file mode 100644 index 6d662d39..00000000 --- a/kdecore/compression/kgzipfilter.h +++ /dev/null @@ -1,73 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000, 2009 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KGZIPFILTER_H -#define KGZIPFILTER_H - -#include "kfilterbase.h" - -/** - * Internal class used by KFilterDev - * - * This header is not installed. - * - * @internal - */ -class KDECORE_EXPORT KGzipFilter : public KFilterBase -{ -public: - KGzipFilter(); - virtual ~KGzipFilter(); - - - virtual bool init(int mode); - - // The top of zlib.h explains it: there are three cases. - // - Raw deflate, no header (e.g. inside a ZIP file) - // - Thin zlib header (1) (which is normally what HTTP calls "deflate" (2)) - // - Gzip header, implemented here by readHeader - // - // (1) as written out by compress()/compress2() - // (2) see http://www.zlib.net/zlib_faq.html#faq39 - enum Flag { - RawDeflate = 0, // raw deflate data - ZlibHeader = 1, // zlib headers (HTTP deflate) - GZipHeader = 2 - }; - bool init(int mode, Flag flag); // for direct users of KGzipFilter - virtual int mode() const; - virtual bool terminate(); - virtual bool reset(); - virtual bool readHeader(); // this is about the GZIP header - virtual bool writeHeader( const QByteArray & fileName ); - void writeFooter(); - virtual void setOutBuffer( char * data, uint maxlen ); - virtual void setInBuffer( const char * data, uint size ); - virtual int inBufferAvailable() const; - virtual int outBufferAvailable() const; - virtual Result uncompress(); - virtual Result compress( bool finish ); - -private: - Result uncompress_noop(); - class Private; - Private* const d; -}; - -#endif diff --git a/kdecore/compression/kxzfilter.cpp b/kdecore/compression/kxzfilter.cpp deleted file mode 100644 index 9bfde4ed..00000000 --- a/kdecore/compression/kxzfilter.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2007-2008 Per Øyvind Karlsen - - Based on kbzip2filter: - Copyright (C) 2000-2005 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kxzfilter.h" - -#include - -#if HAVE_XZ_SUPPORT -extern "C" { - #include -} - -#include - -#include - - -class KXzFilter::Private -{ -public: - Private() - : isInitialized(false) - { - memset(&zStream, 0, sizeof(zStream)); - mode = 0; - } - - lzma_stream zStream; - int mode; - bool isInitialized; -}; - -KXzFilter::KXzFilter() - :d(new Private) -{ -} - - -KXzFilter::~KXzFilter() -{ - delete d; -} - -bool KXzFilter::init( int mode ) -{ - if (d->isInitialized) { - terminate(); - } - - d->zStream.next_in = 0; - d->zStream.avail_in = 0; - if ( mode == QIODevice::ReadOnly ) { - /* We set the memlimit for decompression to 100MiB which should be - * more than enough to be sufficient for level 9 which requires 65 MiB. - */ - const lzma_ret result = lzma_auto_decoder(&d->zStream, 100<<20, 0); - if (result != LZMA_OK) { - kDebug(7131) << "lzma_auto_decoder returned " << result; - return false; - } - } else if ( mode == QIODevice::WriteOnly ) { - const lzma_ret result = lzma_easy_encoder(&d->zStream, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC32); - if (result != LZMA_OK) { - kDebug(7131) << "lzma_easy_encoder returned " << result; - return false; - } - } else { - kWarning(7131) << "Unsupported mode " << mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported"; - return false; - } - d->mode = mode; - d->isInitialized = true; - return true; -} - -int KXzFilter::mode() const -{ - return d->mode; -} - -bool KXzFilter::terminate() -{ - if (d->mode == QIODevice::ReadOnly || d->mode == QIODevice::WriteOnly) { - lzma_end(&d->zStream); - } else { - kWarning(7131) << "Unsupported mode " << d->mode << ". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported"; - return false; - } - d->isInitialized = false; - return true; -} - - -bool KXzFilter::reset() -{ - kDebug(7131) << "KXzFilter::reset"; - // liblzma doesn't have a reset call... - if (!terminate()) { - return false; - } - if (!init( d->mode )) { - return false; - } - return true; -} - -void KXzFilter::setOutBuffer( char * data, uint maxlen ) -{ - d->zStream.avail_out = maxlen; - d->zStream.next_out = (uint8_t *)data; -} - -void KXzFilter::setInBuffer( const char *data, unsigned int size ) -{ - d->zStream.avail_in = size; - d->zStream.next_in = (uint8_t *)const_cast(data); -} - -int KXzFilter::inBufferAvailable() const -{ - return d->zStream.avail_in; -} - -int KXzFilter::outBufferAvailable() const -{ - return d->zStream.avail_out; -} - -KXzFilter::Result KXzFilter::uncompress() -{ - //kDebug(7131) << "Calling lzma_code with avail_in=" << inBufferAvailable() << " avail_out =" << outBufferAvailable(); - lzma_ret result = lzma_code(&d->zStream, LZMA_RUN); - if ( result != LZMA_OK ) { - kDebug(7131) << "lzma_code returned " << result; - kDebug(7131) << "KXzFilter::uncompress " << ( result == LZMA_STREAM_END ? KFilterBase::End : KFilterBase::Error ); - } - - switch (result) { - case LZMA_OK: - return KFilterBase::Ok; - case LZMA_STREAM_END: - return KFilterBase::End; - default: - return KFilterBase::Error; - } -} - -KXzFilter::Result KXzFilter::compress( bool finish ) -{ - //kDebug(7131) << "Calling lzma_code with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable(); - lzma_ret result = lzma_code(&d->zStream, finish ? LZMA_FINISH : LZMA_RUN ); - - switch (result) { - case LZMA_OK: - return KFilterBase::Ok; - case LZMA_STREAM_END: - kDebug(7131) << " lzma_code returned " << result; - return KFilterBase::End; - default: - kDebug(7131) << " lzma_code returned " << result; - return KFilterBase::Error; - } -} - -#endif /* HAVE_XZ_SUPPORT */ diff --git a/kdecore/compression/kxzfilter.h b/kdecore/compression/kxzfilter.h deleted file mode 100644 index 16d0113a..00000000 --- a/kdecore/compression/kxzfilter.h +++ /dev/null @@ -1,61 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2007-2008 Per Øyvind Karlsen - - Based on kbzip2filter: - Copyright (C) 2000 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KXZFILTER_H -#define KXZFILTER_H - -#include - -#if HAVE_XZ_SUPPORT - -#include "kfilterbase.h" - -/** - * Internal class used by KFilterDev - * @internal - */ -class KXzFilter : public KFilterBase -{ -public: - KXzFilter(); - virtual ~KXzFilter(); - - virtual bool init( int ); - virtual int mode() const; - virtual bool terminate(); - virtual bool reset(); - virtual bool readHeader() { return true; } // lzma handles it by itself ! Cool ! - virtual bool writeHeader( const QByteArray & ) { return true; } - virtual void setOutBuffer( char * data, uint maxlen ); - virtual void setInBuffer( const char * data, uint size ); - virtual int inBufferAvailable() const; - virtual int outBufferAvailable() const; - virtual Result uncompress(); - virtual Result compress( bool finish ); -private: - class Private; - Private* const d; -}; - -#endif - -#endif // KXZFILTER_H diff --git a/kdecore/localization/kcharsets.cpp b/kdecore/localization/kcharsets.cpp index b85bf942..ffd4abf0 100644 --- a/kdecore/localization/kcharsets.cpp +++ b/kdecore/localization/kcharsets.cpp @@ -19,8 +19,6 @@ Boston, MA 02110-1301, USA. */ #include "kcharsets.h" - -#include "kfilterdev.h" #include "kentities.cpp" #include "kconfig.h" diff --git a/kdecore/tests/CMakeLists.txt b/kdecore/tests/CMakeLists.txt index fab340a0..1196d1e8 100644 --- a/kdecore/tests/CMakeLists.txt +++ b/kdecore/tests/CMakeLists.txt @@ -104,12 +104,6 @@ set(kmimeglobsfileparsertest_SRCS kmimeglobsfileparsertest.cpp ../services/kmime kde4_add_test(kdecore-kmimeglobsfileparsertest ${kmimeglobsfileparsertest_SRCS}) target_link_libraries(kdecore-kmimeglobsfileparsertest ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY}) -########### kfiltertest ############### - -set(kfiltertest_SRCS kfiltertest.cpp) -kde4_add_test(kdecore-kfiltertest ${kfiltertest_SRCS}) -target_link_libraries(kdecore-kfiltertest ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} ${ZLIB_LIBRARIES}) - ########### module for klibloadertest4 ############### set(klibloadertestmodule4_PART_SRCS klibloadertest4_module.cpp ) diff --git a/kdecore/tests/kfiltertest.cpp b/kdecore/tests/kfiltertest.cpp deleted file mode 100644 index 8cd2580d..00000000 --- a/kdecore/tests/kfiltertest.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (C) 2002-2005 David Faure - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License version 2 as published by the Free Software Foundation; - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "kfiltertest.h" - -#include "qtest_kde.h" - -#include -#include "kfilterdev.h" -#include "kfilterbase.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -QTEST_KDEMAIN_CORE(KFilterTest) - -void KFilterTest::initTestCase() -{ - const QString currentdir = QDir::currentPath(); - pathgz = currentdir + "/test.gz"; - pathbz2 = currentdir + "/test.bz2"; - pathxz = currentdir + "/test.xz"; - - // warning, update the COMPAREs in test_block_write() if changing the test data... - testData = "hello world\n"; -} - -void KFilterTest::test_block_write(const QString & fileName, const QByteArray& data) -{ - QIODevice * dev = KFilterDev::deviceForFile( fileName ); - QVERIFY( dev != 0 ); - bool ok = dev->open( QIODevice::WriteOnly ); - QVERIFY( ok ); - - const int ret = dev->write(data); - QCOMPARE(ret, data.size()); - - dev->close(); - delete dev; - - QVERIFY( QFile::exists( fileName ) ); -} - -void KFilterTest::test_block_write() -{ - kDebug() << " -- test_block_write gzip -- "; - test_block_write(pathgz, testData); - QCOMPARE( QFileInfo( pathgz ).size(), 33LL ); // size of test.gz - -#if HAVE_BZIP2_SUPPORT - kDebug() << " -- test_block_write bzip2 -- "; - test_block_write(pathbz2, testData); - QCOMPARE( QFileInfo( pathbz2 ).size(), 52LL ); // size of test.bz2 -#endif - -#if HAVE_XZ_SUPPORT - kDebug() << " -- test_block_write xz -- "; - test_block_write(pathxz, testData); - QCOMPARE( QFileInfo( pathxz ).size(), 64LL ); // size of test.lzma -#endif -} - -void KFilterTest::test_biggerWrites() -{ - const QString currentdir = QDir::currentPath(); - const QString outFile = currentdir + "/test_big.gz"; - // Find the out-of-bounds from #157706/#188415 - QByteArray data; - data.reserve(10000); - // Prepare test data - for (int i = 0; i < 8170; ++i) - data.append(static_cast(KRandom::randomMax(256))); - QCOMPARE(data.size(), 8170); - // 8170 random bytes compress to 8194 bytes due to the gzip header/footer. - // Now we can go one by one until we pass 8192. - // On 32 bit systems it crashed with data.size()=8173, before the "no room for footer yet" fix. - int compressedSize = 0; - while (compressedSize < 8200) { - test_block_write(outFile, data); - compressedSize = QFileInfo(outFile).size(); - kDebug() << data.size() << "compressed into" << compressedSize; - // Test data is valid - test_readall(outFile, QString::fromLatin1("application/x-gzip"), data); - - - data.append(static_cast(KRandom::randomMax(256))); - } -} - -void KFilterTest::test_block_read( const QString & fileName ) -{ - QIODevice * dev = KFilterDev::deviceForFile( fileName ); - QVERIFY( dev != 0 ); - bool ok = dev->open( QIODevice::ReadOnly ); - QVERIFY( ok ); - - QByteArray array(1024,'\0'); - QByteArray read; - int n; - while ( ( n = dev->read( array.data(), array.size() ) ) ) - { - QVERIFY( n > 0 ); - read += QByteArray( array, n ); - //kDebug() << "read returned " << n; - //kDebug() << "read='" << read << "'"; - - // pos() has no real meaning on sequential devices - // Ah, but kzip uses kfilterdev as a non-sequential device... - - QCOMPARE( (int)dev->pos(), (int)read.size() ); - //kDebug() << "dev.at = " << dev->at(); - } - QCOMPARE( read, testData ); - - // Test seeking back - ok = dev->seek(0); - // test readAll - read = dev->readAll(); - QCOMPARE( read.size(), testData.size() ); - QCOMPARE( read, testData ); - - dev->close(); - delete dev; -} - -void KFilterTest::test_block_read() -{ - kDebug() << " -- test_block_read gzip -- "; - test_block_read(pathgz); -#if HAVE_BZIP2_SUPPORT - kDebug() << " -- test_block_read bzip2 -- "; - test_block_read(pathbz2); -#endif -#if HAVE_XZ_SUPPORT - kDebug() << " -- test_block_read lzma -- "; - test_block_read(pathxz); -#endif -} - -void KFilterTest::test_getch( const QString & fileName ) -{ - QIODevice * dev = KFilterDev::deviceForFile( fileName ); - QVERIFY( dev != 0 ); - bool ok = dev->open( QIODevice::ReadOnly ); - QVERIFY( ok ); - QByteArray read; - char ch; - while ( dev->getChar(&ch) ) { - //printf("%c",ch); - read += ch; - } - dev->close(); - delete dev; - QCOMPARE( read, testData ); -} - -void KFilterTest::test_getch() -{ - kDebug() << " -- test_getch gzip -- "; - test_getch(pathgz); -#if HAVE_BZIP2_SUPPORT - kDebug() << " -- test_getch bzip2 -- "; - test_getch(pathbz2); -#endif -#if HAVE_XZ_SUPPORT - kDebug() << " -- test_getch lzma -- "; - test_getch(pathxz); -#endif -} - -void KFilterTest::test_textstream( const QString & fileName ) -{ - QIODevice * dev = KFilterDev::deviceForFile( fileName ); - QVERIFY( dev != 0 ); - bool ok = dev->open( QIODevice::ReadOnly ); - QVERIFY( ok ); - QTextStream ts( dev ); - QString readStr = ts.readAll(); - dev->close(); - delete dev; - - QByteArray read = readStr.toLatin1(); - QCOMPARE( read, testData ); -} - -void KFilterTest::test_textstream() -{ - kDebug() << " -- test_textstream gzip -- "; - test_textstream(pathgz); -#if HAVE_BZIP2_SUPPORT - kDebug() << " -- test_textstream bzip2 -- "; - test_textstream(pathbz2); -#endif -#if HAVE_XZ_SUPPORT - kDebug() << " -- test_textstream lzma -- "; - test_textstream(pathxz); -#endif -} - -void KFilterTest::test_readall(const QString & fileName, const QString& mimeType, const QByteArray& expectedData) -{ - QFile file(fileName); - QIODevice *flt = KFilterDev::device(&file, mimeType, false); - QVERIFY(flt); - bool ok = flt->open( QIODevice::ReadOnly ); - QVERIFY(ok); - const QByteArray read = flt->readAll(); - QCOMPARE(read.size(), expectedData.size()); - QCOMPARE(read, expectedData); - delete flt; -} - -void KFilterTest::test_readall() -{ - kDebug() << " -- test_readall gzip -- "; - test_readall(pathgz, QString::fromLatin1("application/x-gzip"), testData); -#if HAVE_BZIP2_SUPPORT - kDebug() << " -- test_readall bzip2 -- "; - test_readall(pathbz2, QString::fromLatin1("application/x-bzip"), testData); -#endif -#if HAVE_XZ_SUPPORT - kDebug() << " -- test_readall lzma -- "; - test_readall(pathxz, QString::fromLatin1("application/x-xz"), testData); -#endif - kDebug() << " -- test_readall gzip-derived -- "; - test_readall(pathgz, QString::fromLatin1("image/svg+xml-compressed"), testData); -} - -void KFilterTest::test_uncompressed() -{ - // Can KFilterDev handle uncompressed data even when using gzip decompression? - kDebug() << " -- test_uncompressed -- "; - QBuffer buffer(&testData); - buffer.open(QIODevice::ReadOnly); - QIODevice *flt = KFilterDev::device(&buffer, QString::fromLatin1("application/x-gzip"), false); - bool ok = flt->open( QIODevice::ReadOnly ); - QVERIFY(ok); - QByteArray read = flt->readAll(); - QCOMPARE( read.size(), testData.size() ); - QCOMPARE( read, testData ); - delete flt; -} - -void KFilterTest::test_findFilterByMimeType_data() -{ - QTest::addColumn("mimeType"); - QTest::addColumn("valid"); - - // direct mimetype name - QTest::newRow("application/x-gzip") << QString::fromLatin1("application/x-gzip") << true; -#if HAVE_BZIP2_SUPPORT - QTest::newRow("application/x-bzip") << QString::fromLatin1("application/x-bzip") << true; - QTest::newRow("application/x-bzip2") << QString::fromLatin1("application/x-bzip2") << true; -#else - QTest::newRow("application/x-bzip") << QString::fromLatin1("application/x-bzip") << false; - QTest::newRow("application/x-bzip2") << QString::fromLatin1("application/x-bzip2") << false; -#endif - // indirect compressed mimetypes - QTest::newRow("application/x-gzdvi") << QString::fromLatin1("application/x-gzdvi") << true; - - // non-compressed mimetypes - QTest::newRow("text/plain") << QString::fromLatin1("text/plain") << false; - QTest::newRow("application/x-tar") << QString::fromLatin1("application/x-tar") << false; -} - -void KFilterTest::test_findFilterByMimeType() -{ - QFETCH(QString, mimeType); - QFETCH(bool, valid); - - KFilterBase *filter = KFilterBase::findFilterByMimeType(mimeType); - QCOMPARE(filter != 0, valid); - - delete filter; -} - -static void getCompressedData(QByteArray& data, QByteArray& compressedData) -{ - data = "Hello world, this is a test for deflate, from bug 114830 / 117683"; - compressedData.resize(long(data.size()*1.1f) + 12L); // requirements of zlib::compress2 - unsigned long out_bufferlen = compressedData.size(); - const int ret = compress2((Bytef*)compressedData.data(), &out_bufferlen, (const Bytef*)data.constData(), data.size(), 1); - QCOMPARE(ret, Z_OK); - compressedData.resize(out_bufferlen); -} - -void KFilterTest::test_deflateWithZlibHeader() -{ - QByteArray data, deflatedData; - getCompressedData(data, deflatedData); - -#if 0 // Can't use KFilterDev for this, we need to call KGzipFilter::init(QIODevice::ReadOnly, KGzipFilter::ZlibHeader); - QBuffer buffer(&deflatedData); - QIODevice *flt = KFilterDev::device(&buffer, "application/x-gzip", false); - static_cast(flt)->setSkipHeaders(); - bool ok = flt->open( QIODevice::ReadOnly ); - QVERIFY(ok); - const QByteArray read = flt->readAll(); -#else - KGzipFilter* mFilterDevice = new KGzipFilter; - mFilterDevice->init(QIODevice::ReadOnly, KGzipFilter::ZlibHeader); - - mFilterDevice->setInBuffer(deflatedData.constData(), deflatedData.size()); - char buf[8192]; - mFilterDevice->setOutBuffer(buf, sizeof(buf)); - KFilterBase::Result result = mFilterDevice->uncompress(); - QCOMPARE(result, KFilterBase::End); - const int bytesOut = sizeof(buf) - mFilterDevice->outBufferAvailable(); - QVERIFY(bytesOut); - QByteArray read(buf, bytesOut); - mFilterDevice->terminate(); - delete mFilterDevice; -#endif - QCOMPARE(QString::fromLatin1(read), QString::fromLatin1(data)); // more readable output than the line below - QCOMPARE(read, data); -} - -void KFilterTest::test_pushData() // ### UNFINISHED -{ - QFile file(pathgz); - QVERIFY(file.open(QIODevice::ReadOnly)); - const QByteArray compressed = file.readAll(); - const int firstChunkSize = compressed.size() / 2; - QByteArray firstData(compressed, firstChunkSize); - QBuffer inBuffer(&firstData); - QVERIFY(inBuffer.open(QIODevice::ReadWrite)); - QIODevice *flt = KFilterDev::device(&inBuffer, "application/x-gzip", false); - QVERIFY(flt->open(QIODevice::ReadOnly)); - QByteArray read = flt->readAll(); - qDebug() << QString::fromLatin1(read); - - // And later... - inBuffer.write(QByteArray(compressed.data() + firstChunkSize, compressed.size() - firstChunkSize)); - QCOMPARE(inBuffer.data().size(), compressed.size()); - read += flt->readAll(); - qDebug() << QString::fromLatin1(read); - delete flt; -} - -void KFilterTest::slotFilterOutput(const QByteArray& data) -{ - m_filterOutput += data; -} - -#include "moc_kfiltertest.cpp" diff --git a/kdecore/tests/kfiltertest.h b/kdecore/tests/kfiltertest.h deleted file mode 100644 index 2b63b8fd..00000000 --- a/kdecore/tests/kfiltertest.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2002-2005 David Faure - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License version 2 as published by the Free Software Foundation; - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#ifndef KFILTERTEST_H -#define KFILTERTEST_H - -#include - - -class KFilterTest : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void initTestCase(); - void test_block_write(); - void test_block_read(); - void test_biggerWrites(); - void test_getch(); - void test_textstream(); - void test_readall(); - void test_uncompressed(); - void test_findFilterByMimeType_data(); - void test_findFilterByMimeType(); - void test_deflateWithZlibHeader(); - void test_pushData(); - -private: - void test_block_write(const QString & fileName, const QByteArray& data); - void test_block_read( const QString & fileName ); - void test_getch( const QString & fileName ); - void test_textstream( const QString & fileName ); - void test_readall(const QString & fileName, const QString& mimeType, const QByteArray& expectedData); - -protected Q_SLOTS: - void slotFilterOutput(const QByteArray& data); - -private: - QString pathgz; - QString pathbz2; - QString pathxz; - QByteArray testData; - QByteArray m_filterOutput; -}; - - -#endif