122 lines
2.7 KiB
C++
122 lines
2.7 KiB
C++
#ifndef NO_ZLIB
|
|
|
|
#include "leveldb/zlib_compressor.h"
|
|
|
|
#include <zlib.h>
|
|
#include <algorithm>
|
|
|
|
namespace leveldb {
|
|
|
|
void ZlibCompressorBase::compressImpl(const char* input, size_t length, ::std::string& buffer) const
|
|
{
|
|
const size_t BUFSIZE = 128 * 1024;
|
|
unsigned char temp_buffer[BUFSIZE];
|
|
|
|
//reserve enough memory to not reallocate on the fly
|
|
buffer.reserve(buffer.size() + compressBound(length));
|
|
|
|
z_stream strm;
|
|
strm.zalloc = 0;
|
|
strm.zfree = 0;
|
|
strm.next_in = (unsigned char *)(input);
|
|
strm.avail_in = (uint32_t)length;
|
|
strm.next_out = temp_buffer;
|
|
strm.avail_out = BUFSIZE;
|
|
|
|
auto res = deflateInit2(&strm, compressionLevel, Z_DEFLATED, _window(), 8, Z_DEFAULT_STRATEGY);
|
|
assert(res == Z_OK);
|
|
|
|
int deflate_res = Z_OK;
|
|
while (strm.avail_in != 0)
|
|
{
|
|
int res = deflate(&strm, Z_NO_FLUSH);
|
|
assert(res == Z_OK);
|
|
if (strm.avail_out == 0)
|
|
{
|
|
buffer.append(temp_buffer, temp_buffer + BUFSIZE);
|
|
strm.next_out = temp_buffer;
|
|
strm.avail_out = BUFSIZE;
|
|
}
|
|
}
|
|
|
|
while (deflate_res == Z_OK)
|
|
{
|
|
if (strm.avail_out == 0)
|
|
{
|
|
buffer.append(temp_buffer, temp_buffer + BUFSIZE);
|
|
strm.next_out = temp_buffer;
|
|
strm.avail_out = BUFSIZE;
|
|
}
|
|
deflate_res = deflate(&strm, Z_FINISH);
|
|
}
|
|
|
|
assert(deflate_res == Z_STREAM_END);
|
|
buffer.append(temp_buffer, temp_buffer + BUFSIZE - strm.avail_out);
|
|
deflateEnd(&strm);
|
|
}
|
|
|
|
int ZlibCompressorBase::inflate(const char* input, size_t length, ::std::string &output) const {
|
|
const int CHUNK = 64 * 1024;
|
|
|
|
int ret;
|
|
size_t have;
|
|
z_stream strm;
|
|
unsigned char out[CHUNK];
|
|
|
|
/* allocate inflate state */
|
|
strm.zalloc = Z_NULL;
|
|
strm.zfree = Z_NULL;
|
|
strm.opaque = Z_NULL;
|
|
strm.avail_in = (uint32_t)length;
|
|
strm.next_in = (Bytef*)input;
|
|
|
|
ret = inflateInit2(&strm, _window());
|
|
|
|
if (ret != Z_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
/* decompress until deflate stream ends or end of file */
|
|
do {
|
|
/* run inflate() on input until output buffer not full */
|
|
do {
|
|
|
|
strm.avail_out = CHUNK;
|
|
strm.next_out = out;
|
|
|
|
ret = ::inflate(&strm, Z_NO_FLUSH);
|
|
|
|
if (ret == Z_NEED_DICT) {
|
|
ret = Z_DATA_ERROR;
|
|
}
|
|
if (ret < 0) {
|
|
(void)inflateEnd(&strm);
|
|
return ret;
|
|
}
|
|
|
|
have = CHUNK - strm.avail_out;
|
|
|
|
output.append((char*)out, have);
|
|
|
|
} while (strm.avail_out == 0);
|
|
|
|
/* done when inflate() says it's done */
|
|
} while (ret != Z_STREAM_END);
|
|
|
|
/* clean up and return */
|
|
(void)inflateEnd(&strm);
|
|
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
|
|
}
|
|
|
|
bool ZlibCompressorBase::decompress(const char* input, size_t length, ::std::string &output) const {
|
|
return inflate(input, length, output) == Z_OK;
|
|
}
|
|
|
|
int ZlibCompressorBase::_window() const {
|
|
return raw ? -15 : 15;
|
|
}
|
|
|
|
}
|
|
|
|
#endif |