forked from ondra/server-sdk
114 lines
2.7 KiB
C++
114 lines
2.7 KiB
C++
#include "compression.h"
|
|
|
|
#include <QFileInfo>
|
|
#include <QDir>
|
|
|
|
#include <zlib.h> // gzip decompress
|
|
|
|
|
|
namespace core {
|
|
|
|
/**
|
|
* @brief Decompress gzip data
|
|
* @param compressed gzip data
|
|
* @return decompressed data
|
|
*/
|
|
QByteArray Compression::decompress(const QByteArray &compressed)
|
|
{
|
|
if (compressed.size() <= 4) {
|
|
qWarning("gUncompress: Input data is truncated");
|
|
return QByteArray();
|
|
}
|
|
|
|
QByteArray result;
|
|
|
|
int ret;
|
|
z_stream strm;
|
|
static const int CHUNK_SIZE = 1024;
|
|
char out[CHUNK_SIZE];
|
|
|
|
/* allocate inflate state */
|
|
strm.zalloc = Z_NULL;
|
|
strm.zfree = Z_NULL;
|
|
strm.opaque = Z_NULL;
|
|
strm.avail_in = compressed.size();
|
|
strm.next_in = (Bytef*)(compressed.data());
|
|
|
|
ret = inflateInit2(&strm, 15 + 32); // gzip decoding
|
|
if (ret != Z_OK)
|
|
return QByteArray();
|
|
|
|
// run inflate()
|
|
do {
|
|
strm.avail_out = CHUNK_SIZE;
|
|
strm.next_out = (Bytef*)(out);
|
|
|
|
ret = inflate(&strm, Z_NO_FLUSH);
|
|
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
|
|
|
switch (ret) {
|
|
case Z_NEED_DICT:
|
|
return QByteArray();
|
|
case Z_DATA_ERROR:
|
|
case Z_MEM_ERROR:
|
|
(void)inflateEnd(&strm);
|
|
return QByteArray();
|
|
}
|
|
|
|
result.append(out, CHUNK_SIZE - strm.avail_out);
|
|
} while (strm.avail_out == 0);
|
|
|
|
// clean up and return
|
|
inflateEnd(&strm);
|
|
|
|
// Calculate compression ratio
|
|
// original :200
|
|
// compressed :100
|
|
// ratio = 0.5
|
|
float ratio = (float)compressed.count() / (float)result.count();
|
|
float compression = ratio * 100.0;
|
|
|
|
qCInfo(sdkcompress) << "compress data:" << compressed.count()
|
|
<< "uncompressed data:" << result.count()
|
|
<< "compression:" << compression;
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Return path to source directory
|
|
* @param subpath ( e.g. test/data )
|
|
* @return absolute path to desired subpath in source folder
|
|
*/
|
|
QString Compression::sourcePath(const QString &subpath)
|
|
{
|
|
QDir dir(__FILE__);
|
|
dir.cdUp();
|
|
dir.cdUp();
|
|
dir.cdUp();
|
|
|
|
return dir.absoluteFilePath(subpath);
|
|
}
|
|
|
|
/**
|
|
* @brief Return data from source directory
|
|
* @param subpath ( e.g. test/data/gizp.src )
|
|
* @return data of file - QByteArray
|
|
*/
|
|
QByteArray Compression::sourceData(const QString &subpath)
|
|
{
|
|
// Get data from file
|
|
QString filePath = sourcePath(subpath);
|
|
if (! QFileInfo::exists(filePath)) {
|
|
qCWarning(sdkcompress) << "path does not exists:" << filePath;
|
|
return QByteArray();
|
|
}
|
|
QFile file(filePath);
|
|
if ( file.open(QIODevice::ReadOnly) )
|
|
return file.readAll();
|
|
return QByteArray();
|
|
}
|
|
|
|
|
|
} // namespace core
|