blob: 89195cc1094d06e99b1c1bce30d3d8a9df127733 [file]
/*
* 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 "zstd_compressor.h"
#include <limits>
#include "common/allocator/alloc_base.h"
using namespace common;
namespace storage {
int ZstdCompressor::reset(bool /* for_compress */) { return E_OK; }
void ZstdCompressor::destroy() {
if (compressed_buf_ != nullptr) {
mem_free(compressed_buf_);
compressed_buf_ = nullptr;
}
if (uncompressed_buf_ != nullptr) {
mem_free(uncompressed_buf_);
uncompressed_buf_ = nullptr;
}
}
int ZstdCompressor::compress(char* uncompressed_buf,
uint32_t uncompressed_buf_len,
char*& compressed_buf,
uint32_t& compressed_buf_len) {
const size_t max_dst_size = ZSTD_compressBound(uncompressed_buf_len);
if (max_dst_size > std::numeric_limits<uint32_t>::max()) {
return E_COMPRESS_ERR;
}
compressed_buf_ =
static_cast<char*>(mem_alloc(max_dst_size, MOD_COMPRESSOR_OBJ));
if (compressed_buf_ == nullptr) {
return E_OOM;
}
const size_t compressed_data_size =
ZSTD_compress(compressed_buf_, max_dst_size, uncompressed_buf,
uncompressed_buf_len, ZSTD_CLEVEL_DEFAULT);
if (ZSTD_isError(compressed_data_size)) {
mem_free(compressed_buf_);
compressed_buf_ = nullptr;
return E_COMPRESS_ERR;
}
char* compressed_data =
static_cast<char*>(mem_realloc(compressed_buf_, compressed_data_size));
if (compressed_data == nullptr) {
mem_free(compressed_buf_);
compressed_buf_ = nullptr;
return E_OOM;
}
compressed_buf_ = compressed_data;
compressed_buf = compressed_data;
compressed_buf_len = static_cast<uint32_t>(compressed_data_size);
return E_OK;
}
void ZstdCompressor::after_compress(char* compressed_buf) {
if (compressed_buf != nullptr) {
mem_free(compressed_buf);
if (compressed_buf_ == compressed_buf) {
compressed_buf_ = nullptr;
}
}
}
int ZstdCompressor::uncompress(char* compressed_buf,
uint32_t compressed_buf_len,
char*& uncompressed_buf,
uint32_t& uncompressed_buf_len) {
const unsigned long long content_size =
ZSTD_getFrameContentSize(compressed_buf, compressed_buf_len);
if (content_size == ZSTD_CONTENTSIZE_ERROR ||
content_size == ZSTD_CONTENTSIZE_UNKNOWN ||
content_size > std::numeric_limits<uint32_t>::max()) {
return E_COMPRESS_ERR;
}
const size_t alloc_size =
content_size == 0 ? 1 : static_cast<size_t>(content_size);
uncompressed_buf_ =
static_cast<char*>(mem_alloc(alloc_size, MOD_COMPRESSOR_OBJ));
if (uncompressed_buf_ == nullptr) {
return E_OOM;
}
const size_t decompressed_size =
ZSTD_decompress(uncompressed_buf_, static_cast<size_t>(content_size),
compressed_buf, compressed_buf_len);
if (ZSTD_isError(decompressed_size) || decompressed_size != content_size) {
mem_free(uncompressed_buf_);
uncompressed_buf_ = nullptr;
return E_COMPRESS_ERR;
}
uncompressed_buf = uncompressed_buf_;
uncompressed_buf_len = static_cast<uint32_t>(decompressed_size);
return E_OK;
}
void ZstdCompressor::after_uncompress(char* uncompressed_buf) {
if (uncompressed_buf != nullptr) {
mem_free(uncompressed_buf);
if (uncompressed_buf_ == uncompressed_buf) {
uncompressed_buf_ = nullptr;
}
}
}
} // namespace storage