File compressor.hpp¶
File List > base > compressor.hpp
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed 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.
*
*/
/*
* compressor.hpp
*/
#ifndef _COMPRESSOR_HPP_
#define _COMPRESSOR_HPP_
#include "lz4.h"
#include "error_manager.h"
#include <memory>
#include <variant>
namespace cubcompress
{
struct LZ4 {};
/* add here */
/* options */
struct lz4_options
{
/* accel must be a value between 1 and LZ4_ACCELERATION_MAX (usually 65537). */
/* trade-off: accel ≈ 1 = best compression ratio. */
/* larger accel = higher throughput. */
int accel = 1;
};
/* add here */
using options = std::variant<lz4_options /*, add here */>;
/* ---------------------------------------------------------------------------- */
/* LZ4 */
/* ---------------------------------------------------------------------------- */
struct LZ4ContextDeleter
{
void operator () (LZ4_stream_t *ctx) const noexcept
{
if (ctx)
{
(void) LZ4_freeStream (ctx);
}
}
};
inline LZ4_stream_t *lz4_stream ()
{
thread_local std::unique_ptr<LZ4_stream_t, LZ4ContextDeleter> context { nullptr };
if (!context)
{
context.reset (LZ4_createStream ());
if (!context)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 1, "failed to create LZ4 stream context");
}
}
return context.get ();
}
inline int lz4_bound (int size)
{
return LZ4_compressBound (size);
}
inline int lz4_compress (const char *src, char *dst, int src_size, int dst_capacity, int accel)
{
LZ4_stream_t *ctx;
int compressed_size;
ctx = lz4_stream ();
if (!ctx)
{
/* failed to get lz4 stream (context) */
return 0;
}
LZ4_resetStream_fast (ctx);
compressed_size = LZ4_compress_fast_extState (ctx, src, dst, src_size, dst_capacity, accel);
if (compressed_size <= 0)
{
/* failed to compress */
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 1, "failed to compress with LZ4_compress_fast_extState");
}
return compressed_size;
}
inline int lz4_decompress (const char *src, char *dst, int compressed_size, int dst_capacity)
{
int decompressed_size;
decompressed_size = LZ4_decompress_safe (src, dst, compressed_size, dst_capacity);
if (decompressed_size < 0)
{
/* failed to decompress */
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 1, "failed to decompress with LZ4_decompress_safe");
}
return decompressed_size;
}
/* ---------------------------------------------------------------------------- */
/* interface */
/* ---------------------------------------------------------------------------- */
template <typename T>
inline int bound (int size)
{
static_assert (std::is_same_v<T, LZ4>, "T must be LZ4");
if constexpr (std::is_same<T, LZ4>::value)
{
return lz4_bound (size);
}
return -1;
}
template <typename T>
inline int compress (const void *src, int src_size, void *dst, int dst_capacity, const options &option)
{
static_assert (std::is_same_v<T, LZ4>, "T must be LZ4");
if constexpr (std::is_same<T, LZ4>::value)
{
if (auto *lz4_option = std::get_if<lz4_options> (&option))
{
return lz4_compress (static_cast<const char *> (src), static_cast<char *> (dst), src_size, dst_capacity,
lz4_option->accel);
}
}
return -1;
}
template <typename T>
inline int compress (const void *src, int src_size, void *dst, int dst_capacity)
{
static_assert (std::is_same_v<T, LZ4>, "T must be LZ4");
if constexpr (std::is_same<T, LZ4>::value)
{
lz4_options option;
return compress<T> (src, src_size, dst, dst_capacity, option);
}
return -1;
}
template <typename T>
inline int decompress (const void *src, int src_size, void *dst, int dst_capacity)
{
static_assert (std::is_same_v<T, LZ4>, "T must be LZ4");
if constexpr (std::is_same<T, LZ4>::value)
{
return lz4_decompress (static_cast<const char *> (src), static_cast<char *> (dst), src_size, dst_capacity);
}
return -1;
}
}
#endif