goldendict-ng/src/decompress.cc
2023-04-17 17:17:36 -04:00

178 lines
3.8 KiB
C++

#include "decompress.hh"
#include "zlib.h"
#include "bzlib.h"
#ifdef MAKE_ZIM_SUPPORT
#include "lzma.h"
#include "zstd.h"
#endif
#define CHUNK_SIZE 2048
QByteArray zlibDecompress( const char * bufptr, unsigned length )
{
z_stream zs;
char buf[CHUNK_SIZE];
QByteArray str;
int res;
memset( &zs, 0, sizeof(zs) );
zs.next_in = (Bytef *)bufptr;
zs.avail_in = length;
while( 1 )
{
res = inflateInit( &zs );
if( res != Z_OK )
break;
while( res != Z_STREAM_END )
{
zs.next_out = (Bytef *)buf;
zs.avail_out = CHUNK_SIZE;
res = inflate( &zs, Z_SYNC_FLUSH );
str.append( buf, CHUNK_SIZE - zs.avail_out );
if( res != Z_OK && res != Z_STREAM_END )
break;
}
break;
}
inflateEnd( &zs );
if( res != Z_STREAM_END )
str.clear();
return str;
}
string decompressZlib( const char * bufptr, unsigned length )
{
QByteArray b = zlibDecompress( bufptr, length );
return string( b.constData(), b.size() );
}
string decompressBzip2( const char * bufptr, unsigned length )
{
bz_stream zs;
char buf[CHUNK_SIZE];
string str;
int res;
memset( &zs, 0, sizeof(zs) );
zs.next_in = (char *)bufptr;
zs.avail_in = length;
zs.total_in_lo32 = length;
while( 1 )
{
res = BZ2_bzDecompressInit( &zs, 0, 0 );
if( res != BZ_OK )
break;
while( res != BZ_STREAM_END )
{
zs.next_out = buf;
zs.avail_out = CHUNK_SIZE;
zs.total_out_lo32 = length;
res = BZ2_bzDecompress( &zs );
str.append( buf, CHUNK_SIZE - zs.avail_out );
if( res != BZ_OK && res != BZ_STREAM_END )
break;
}
break;
}
BZ2_bzDecompressEnd( &zs );
if( res != BZ_STREAM_END )
str.clear();
return str;
}
#ifdef MAKE_ZIM_SUPPORT
string decompressLzma2( const char * bufptr, unsigned length,
bool raw_decoder )
{
string str;
lzma_ret res;
char buf[CHUNK_SIZE];
lzma_stream strm = LZMA_STREAM_INIT;
strm.next_in = reinterpret_cast< const uint8_t * >( bufptr );
strm.avail_in = length;
lzma_options_lzma opt;
lzma_filter filters[ 2 ];
if( raw_decoder )
{
lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT);
filters[ 0 ].id = LZMA_FILTER_LZMA2;
filters[ 0 ].options = &opt;
filters[ 1 ].id = LZMA_VLI_UNKNOWN;
}
while( 1 )
{
if( raw_decoder )
res = lzma_raw_decoder( &strm, filters );
else
res = lzma_stream_decoder( &strm, UINT64_MAX, 0 );
if( res != LZMA_OK )
break;
while ( res != LZMA_STREAM_END )
{
strm.next_out = reinterpret_cast< uint8_t * >( buf );
strm.avail_out = CHUNK_SIZE;
res = lzma_code( &strm, LZMA_RUN );
str.append( buf, CHUNK_SIZE - strm.avail_out );
if( res != LZMA_OK && res != LZMA_STREAM_END )
break;
}
lzma_end( &strm );
if( res != LZMA_STREAM_END )
str.clear();
break;
}
return str;
}
string decompressZstd( const char *bufptr, unsigned length )
{
string str;
char buf[CHUNK_SIZE];
size_t res;
// string err;
ZSTD_DStream *zds;
ZSTD_inBuffer in_buf = { bufptr, length, 0 };
ZSTD_outBuffer out_buf = { buf, CHUNK_SIZE, 0 };
zds = ZSTD_createDStream();
if( !zds )
return str;
res = ZSTD_initDStream( zds );
if( ZSTD_isError( res ) )
{
// err = string( ZSTD_getErrorName( res ) );
ZSTD_freeDStream( zds );
return str;
}
do
{
out_buf.pos = 0;
res = ZSTD_decompressStream( zds, &out_buf, &in_buf );
if( ZSTD_isError( res ) )
{
// err = string( ZSTD_getErrorName( res ) );
ZSTD_freeDStream( zds );
return string();
}
str.append( buf, out_buf.pos );
}
while( out_buf.pos >= out_buf.size );
ZSTD_freeDStream( zds );
return str;
}
#endif