GH-1227 add GZip compress function and a unit test fo GZip

This commit is contained in:
Petr Mrázek
2015-09-14 02:25:47 +02:00
parent cfd5976471
commit e38cc1d480
4 changed files with 119 additions and 14 deletions

View File

@ -2,12 +2,6 @@
#include <zlib.h>
#include <QByteArray>
// HACK: workaround for terrible macro crap on Windows
int wrap_inflate (z_streamp strm, int flush)
{
return inflate(strm, flush);
}
bool GZip::decompress(const QByteArray &compressedBytes, QByteArray &uncompressedBytes)
{
if (compressedBytes.size() == 0)
@ -17,16 +11,13 @@ bool GZip::decompress(const QByteArray &compressedBytes, QByteArray &uncompresse
}
unsigned uncompLength = compressedBytes.size();
unsigned half_length = compressedBytes.size() / 2;
uncompressedBytes.clear();
uncompressedBytes.resize(uncompLength);
z_stream strm;
memset(&strm, 0, sizeof(strm));
strm.next_in = (Bytef *)compressedBytes.data();
strm.avail_in = compressedBytes.size();
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
bool done = false;
@ -35,20 +26,22 @@ bool GZip::decompress(const QByteArray &compressedBytes, QByteArray &uncompresse
return false;
}
int err = Z_OK;
while (!done)
{
// If our output buffer is too small
if (strm.total_out >= uncompLength)
{
uncompressedBytes.resize(uncompLength + half_length);
uncompLength += half_length;
uncompressedBytes.resize(uncompLength * 2);
uncompLength *= 2;
}
strm.next_out = (Bytef *)(uncompressedBytes.data() + strm.total_out);
strm.avail_out = uncompLength - strm.total_out;
// Inflate another chunk.
int err = wrap_inflate(&strm, Z_SYNC_FLUSH);
err = inflate(&strm, Z_SYNC_FLUSH);
if (err == Z_STREAM_END)
done = true;
else if (err != Z_OK)
@ -57,7 +50,7 @@ bool GZip::decompress(const QByteArray &compressedBytes, QByteArray &uncompresse
}
}
if (inflateEnd(&strm) != Z_OK)
if (inflateEnd(&strm) != Z_OK || !done)
{
return false;
}
@ -65,3 +58,58 @@ bool GZip::decompress(const QByteArray &compressedBytes, QByteArray &uncompresse
uncompressedBytes.resize(strm.total_out);
return true;
}
bool GZip::compress(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
{
if (uncompressedBytes.size() == 0)
{
compressedBytes = uncompressedBytes;
return true;
}
unsigned compLength = std::min(uncompressedBytes.size(), 16);
compressedBytes.clear();
compressedBytes.resize(compLength);
z_stream zs;
memset(&zs, 0, sizeof(zs));
if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK)
{
return false;
}
zs.next_in = (Bytef*)uncompressedBytes.data();
zs.avail_in = uncompressedBytes.size();
int ret;
compressedBytes.resize(uncompressedBytes.size());
unsigned offset = 0;
unsigned temp = 0;
do
{
auto remaining = compressedBytes.size() - offset;
if(remaining < 1)
{
compressedBytes.resize(compressedBytes.size() * 2);
}
zs.next_out = (Bytef *) (compressedBytes.data() + offset);
temp = zs.avail_out = compressedBytes.size() - offset;
ret = deflate(&zs, Z_FINISH);
offset += temp - zs.avail_out;
} while (ret == Z_OK);
compressedBytes.resize(offset);
if (deflateEnd(&zs) != Z_OK)
{
return false;
}
if (ret != Z_STREAM_END)
{
return false;
}
return true;
}

View File

@ -7,5 +7,6 @@ class MULTIMC_LOGIC_EXPORT GZip
{
public:
static bool decompress(const QByteArray &compressedBytes, QByteArray &uncompressedBytes);
static bool compress(const QByteArray &uncompressedBytes, QByteArray &compressedBytes);
};