|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
#include "webcc/zlib_wrapper.h"
|
|
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <utility> // std::move
|
|
|
|
|
|
|
|
|
|
#include "zlib.h"
|
|
|
|
@ -8,11 +9,61 @@
|
|
|
|
|
|
|
|
|
|
namespace webcc {
|
|
|
|
|
|
|
|
|
|
bool Compress(const std::string& input, std::string* output) {
|
|
|
|
|
output->clear();
|
|
|
|
|
|
|
|
|
|
if (input.empty()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
z_stream stream;
|
|
|
|
|
stream.next_in = (Bytef*)input.data();
|
|
|
|
|
stream.avail_in = (uInt)input.size();
|
|
|
|
|
stream.zalloc = Z_NULL;
|
|
|
|
|
stream.zfree = Z_NULL;
|
|
|
|
|
stream.opaque = Z_NULL;
|
|
|
|
|
|
|
|
|
|
int ret = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
|
|
|
|
|
MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY);
|
|
|
|
|
if (ret != Z_OK) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string buf;
|
|
|
|
|
buf.resize(input.size() / 2); // TODO
|
|
|
|
|
|
|
|
|
|
// Run deflate() on input until output buffer is not full.
|
|
|
|
|
do {
|
|
|
|
|
stream.avail_out = (uInt)buf.size();
|
|
|
|
|
stream.next_out = (Bytef*)buf.data();
|
|
|
|
|
|
|
|
|
|
int err = deflate(&stream, Z_FINISH);
|
|
|
|
|
|
|
|
|
|
assert(err != Z_STREAM_ERROR);
|
|
|
|
|
|
|
|
|
|
if (err != Z_OK) {
|
|
|
|
|
deflateEnd(&stream);
|
|
|
|
|
if (stream.msg != nullptr) {
|
|
|
|
|
LOG_ERRO("zlib deflate error: %s", stream.msg);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::size_t size = buf.size() - stream.avail_out;
|
|
|
|
|
output->insert(output->end(), buf.data(), buf.data() + size);
|
|
|
|
|
} while (stream.avail_out == 0);
|
|
|
|
|
|
|
|
|
|
if (deflateEnd(&stream) != Z_OK) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Modified from:
|
|
|
|
|
// http://windrealm.org/tutorials/decompress-gzip-stream.php
|
|
|
|
|
|
|
|
|
|
bool Decompress(const std::string& input, std::string& output) {
|
|
|
|
|
output.clear();
|
|
|
|
|
bool Decompress(const std::string& input, std::string* output) {
|
|
|
|
|
output->clear();
|
|
|
|
|
|
|
|
|
|
if (input.empty()) {
|
|
|
|
|
return true;
|
|
|
|
@ -22,12 +73,12 @@ bool Decompress(const std::string& input, std::string& output) {
|
|
|
|
|
std::string buf;
|
|
|
|
|
buf.resize(input.size());
|
|
|
|
|
|
|
|
|
|
z_stream strm;
|
|
|
|
|
strm.next_in = (Bytef*)input.c_str();
|
|
|
|
|
strm.avail_in = (uInt)input.size();
|
|
|
|
|
strm.total_out = 0;
|
|
|
|
|
strm.zalloc = Z_NULL;
|
|
|
|
|
strm.zfree = Z_NULL;
|
|
|
|
|
z_stream stream;
|
|
|
|
|
stream.next_in = (Bytef*)input.data();
|
|
|
|
|
stream.avail_in = (uInt)input.size();
|
|
|
|
|
stream.total_out = 0;
|
|
|
|
|
stream.zalloc = Z_NULL;
|
|
|
|
|
stream.zfree = Z_NULL;
|
|
|
|
|
|
|
|
|
|
// About the windowBits paramter:
|
|
|
|
|
// (https://stackoverflow.com/a/1838702)
|
|
|
|
@ -35,45 +86,41 @@ bool Decompress(const std::string& input, std::string& output) {
|
|
|
|
|
// windowBits can also be greater than 15 for optional gzip decoding. Add 32
|
|
|
|
|
// to windowBits to enable zlib and gzip decoding with automatic header
|
|
|
|
|
// detection, or add 16 to decode only the gzip format (the zlib format will
|
|
|
|
|
// return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
|
|
|
|
|
// a crc32 instead of an adler32.
|
|
|
|
|
if (inflateInit2(&strm, (32 + MAX_WBITS)) != Z_OK) {
|
|
|
|
|
// return a Z_DATA_ERROR).
|
|
|
|
|
if (inflateInit2(&stream, MAX_WBITS + 32) != Z_OK) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
// Enlarge the output buffer if it's too small.
|
|
|
|
|
if (strm.total_out >= buf.size()) {
|
|
|
|
|
if (stream.total_out >= buf.size()) {
|
|
|
|
|
buf.resize(buf.size() + input.size() / 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strm.next_out = (Bytef*)(buf.c_str() + strm.total_out);
|
|
|
|
|
strm.avail_out = (uInt)buf.size() - strm.total_out;
|
|
|
|
|
stream.next_out = (Bytef*)(buf.data() + stream.total_out);
|
|
|
|
|
stream.avail_out = (uInt)buf.size() - stream.total_out;
|
|
|
|
|
|
|
|
|
|
// Inflate another chunk.
|
|
|
|
|
//int err = inflate(&strm, Z_SYNC_FLUSH);
|
|
|
|
|
int err = inflate(&strm, Z_FULL_FLUSH);
|
|
|
|
|
int err = inflate(&stream, Z_SYNC_FLUSH);
|
|
|
|
|
|
|
|
|
|
if (err == Z_STREAM_END) {
|
|
|
|
|
break;
|
|
|
|
|
} else if (err != Z_OK) {
|
|
|
|
|
inflateEnd(&strm);
|
|
|
|
|
if (strm.msg != nullptr) {
|
|
|
|
|
LOG_ERRO("zlib inflate error: %s", strm.msg);
|
|
|
|
|
inflateEnd(&stream);
|
|
|
|
|
if (stream.msg != nullptr) {
|
|
|
|
|
LOG_ERRO("zlib inflate error: %s", stream.msg);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inflateEnd(&strm) != Z_OK) {
|
|
|
|
|
if (inflateEnd(&stream) != Z_OK) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove the unused buffer.
|
|
|
|
|
buf.erase(strm.total_out);
|
|
|
|
|
|
|
|
|
|
// Move the buffer to the output.
|
|
|
|
|
output = std::move(buf);
|
|
|
|
|
// Remove the unused part then move to the output
|
|
|
|
|
buf.erase(stream.total_out);
|
|
|
|
|
*output = std::move(buf);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|