blob: e9dab9d327f269192e6f746383479bdeb855f95d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* License); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "gzip_compressor.h"
using namespace common;
using namespace error_info;
namespace storage {
GzipCompressor::GzipCompressor() : compressed_buf() { zstream_valid_ = false; }
GzipCompressor::~GzipCompressor() { end_zstream(); }
int GzipCompressor::reset() {
int ret = E_CODE::E_OK;
if (RET_FAIL(end_zstream())) {
} else if (RET_FAIL(init_zstream())) {
}
return ret;
}
int GzipCompressor::init_zstream() {
if (zstream_valid_) {
return E_OK;
}
compress_stream_.zalloc = (alloc_func)0; // Z_NULL
compress_stream_.zfree = (free_func)0;
compress_stream_.opaque = (voidpf)0;
compress_stream_.next_in = 0;
compress_stream_.avail_in = 0;
compress_stream_.next_out = 0;
compress_stream_.avail_out = 0;
memset(compressed_buf, 0, DEFLATE_BUFFER_SIZE);
if (deflateInit2(&compress_stream_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31,
8, Z_DEFAULT_STRATEGY) != Z_OK) {
// log_err("gzip deflateInit2 failed");
return E_COMPRESS_ERR;
}
zstream_valid_ = true;
return E_OK;
}
int GzipCompressor::end_zstream() {
if (!zstream_valid_) {
return E_OK;
}
if (deflateEnd(&compress_stream_) != Z_OK) {
// log_err("deflateEnd failed");
return E_COMPRESS_ERR;
}
zstream_valid_ = false;
return E_OK;
}
int GzipCompressor::compress_into_bytestream(char *uncompressed_buf,
uint32_t uncompressed_buf_len,
ByteStream &out) {
int ret = Z_OK;
compress_stream_.next_in = (Bytef *)uncompressed_buf;
compress_stream_.avail_in = uncompressed_buf_len;
compress_stream_.next_out = (Bytef *)compressed_buf;
compress_stream_.avail_out = DEFLATE_BUFFER_SIZE;
if (uncompressed_buf == nullptr || uncompressed_buf_len == 0) { // no more
if (compress_stream_.next_out) {
while (ret != Z_STREAM_END) {
ret = deflate(&compress_stream_, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END) {
// log_err("deflate failed");
return E_COMPRESS_ERR;
}
out.write_buf(compressed_buf,
DEFLATE_BUFFER_SIZE - compress_stream_.avail_out);
compress_stream_.next_out = (Bytef *)compressed_buf;
compress_stream_.avail_out = DEFLATE_BUFFER_SIZE;
}
}
return E_OK;
}
for (;;) {
ret = deflate(&compress_stream_, Z_NO_FLUSH);
if (ret != Z_OK) {
// log_err("deflate failed");
return E_COMPRESS_ERR;
}
if (compress_stream_.avail_in == 0) { // current input data are all
out.write_buf(compressed_buf,
DEFLATE_BUFFER_SIZE - compress_stream_.avail_out);
compress_stream_.next_out = (Bytef *)compressed_buf;
compress_stream_.avail_out = DEFLATE_BUFFER_SIZE;
break;
} else if (compress_stream_.avail_out ==
0) { // no more space for output
out.write_buf(compressed_buf, DEFLATE_BUFFER_SIZE);
compress_stream_.next_out = (Bytef *)compressed_buf;
compress_stream_.avail_out = DEFLATE_BUFFER_SIZE;
}
}
return E_OK;
}
int GzipCompressor::compress(char *uncompressed_buf,
uint32_t uncompressed_buf_len,
char *&compressed_buf,
uint32_t &compressed_buf_len) {
int ret = E_OK;
ByteStream out(DEFLATE_BUFFER_SIZE, MOD_COMPRESSOR_OBJ);
if (RET_FAIL(compress_into_bytestream(uncompressed_buf,
uncompressed_buf_len, out))) {
return ret;
}
if (RET_FAIL(compress_into_bytestream(nullptr, 0, out))) {
return ret;
}
compressed_buf = get_bytes_from_bytestream(out);
// Assume the length is legal.
compressed_buf_len = static_cast<uint32_t>(out.total_size());
out.destroy();
return ret;
}
GzipDeCompressor::GzipDeCompressor() : decompressed_buf() {
zstream_valid_ = false;
}
GzipDeCompressor::~GzipDeCompressor() { end_zstream(); }
int GzipDeCompressor::init_zstream() {
if (zstream_valid_) {
return E_OK;
}
decompress_stream_.zalloc = (alloc_func)0; // Z_NULL
decompress_stream_.zfree = (free_func)0;
decompress_stream_.opaque = (voidpf)0;
decompress_stream_.next_in = 0;
decompress_stream_.avail_in = 0;
decompress_stream_.next_out = 0;
decompress_stream_.avail_out = 0;
memset(decompressed_buf, 0, INFLATE_BUFFER_SIZE);
if (inflateInit2(&decompress_stream_, 31) != Z_OK) {
// log_err("inflateInit2 failed");
return E_COMPRESS_ERR;
}
zstream_valid_ = true;
return E_OK;
}
int GzipDeCompressor::end_zstream() {
if (!zstream_valid_) {
return E_OK;
}
if (inflateEnd(&decompress_stream_) != Z_OK) {
// log_err("inflateEnd failed");
return E_COMPRESS_ERR;
}
zstream_valid_ = false;
return E_OK;
}
int GzipDeCompressor::reset() {
int ret = E_OK;
if (RET_FAIL(end_zstream())) {
} else if (RET_FAIL(init_zstream())) {
}
return ret;
}
int GzipDeCompressor::decompress_into_bytestream(char *compressed_buf,
uint32_t compressed_buf_len,
ByteStream &out) {
int ret = Z_OK;
decompress_stream_.next_in = (Bytef *)compressed_buf;
decompress_stream_.avail_in = compressed_buf_len;
decompress_stream_.next_out = (Bytef *)decompressed_buf;
decompress_stream_.avail_out = INFLATE_BUFFER_SIZE;
if (compressed_buf == nullptr || compressed_buf_len == 0) {
if (decompress_stream_.next_out) {
while (ret != Z_STREAM_END) {
ret = inflate(&decompress_stream_, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END) {
// log_err("inflate failed");
return E_COMPRESS_ERR;
}
out.write_buf(
decompressed_buf,
INFLATE_BUFFER_SIZE - decompress_stream_.avail_out);
decompress_stream_.next_out = (Bytef *)decompressed_buf;
decompress_stream_.avail_out = INFLATE_BUFFER_SIZE;
}
}
return E_OK;
}
for (;;) {
ret = inflate(&decompress_stream_, Z_NO_FLUSH);
if (ret == Z_STREAM_END) {
out.write_buf(decompressed_buf,
INFLATE_BUFFER_SIZE - decompress_stream_.avail_out);
break;
}
if (ret != Z_OK) {
// log_err("inflate failed");
return E_COMPRESS_ERR;
}
if (decompress_stream_.avail_in == 0) {
out.write_buf(decompressed_buf,
INFLATE_BUFFER_SIZE - decompress_stream_.avail_out);
decompress_stream_.next_out = (Bytef *)decompressed_buf;
decompress_stream_.avail_out = INFLATE_BUFFER_SIZE;
break;
} else if (decompress_stream_.avail_out == 0) {
out.write_buf(decompressed_buf, INFLATE_BUFFER_SIZE);
decompress_stream_.next_out = (Bytef *)decompressed_buf;
decompress_stream_.avail_out = INFLATE_BUFFER_SIZE;
}
}
return E_OK;
}
int GzipDeCompressor::uncompress(char *compressed_buf,
uint32_t compressed_buf_len,
char *&uncompressed_buf,
uint32_t &uncompressed_buf_len) {
int ret = E_OK;
ByteStream out(INFLATE_BUFFER_SIZE, MOD_COMPRESSOR_OBJ);
if (RET_FAIL(decompress_into_bytestream(compressed_buf, compressed_buf_len,
out))) {
return ret;
}
if (RET_FAIL(decompress_into_bytestream(nullptr, 0, out))) {
return ret;
}
uncompressed_buf = get_bytes_from_bytestream(out);
uncompressed_buf_len = static_cast<uint32_t>(out.total_size());
// uncompressed_buf[uncompressed_buf_len] = '\0';
out.destroy();
return ret;
}
} // end namespace storage