1
0
Fork 0
Univerxel/src/core/utils/zctx.hpp

98 lines
2.9 KiB
C++

#pragma once
#include <zstd.h>
#include "../data/mem.hpp"
#include "logger.hpp"
namespace zstd {
/// Decompressor with ref to dictionnary
class read_ctx {
public:
read_ctx(ZSTD_DDict *dict): ctx(ZSTD_createDCtx()), dict(dict) { }
~read_ctx() {
ZSTD_freeDCtx(ctx);
}
/// Extract in to out (error message on failure)
template<typename I, typename O>
std::optional<const char*> decompress(const I& in, O& out) const {
const auto maxSize = ZSTD_getFrameContentSize(in.data(), in.size());
out.resize(maxSize);
const auto actualSize = ZSTD_decompress_usingDDict(ctx, out.data(), out.size(), in.data(), in.size(), dict);
if(ZSTD_isError(actualSize)) {
return ZSTD_getErrorName(actualSize);
}
out.resize(actualSize);
return std::nullopt;
}
protected:
ZSTD_DCtx *ctx;
ZSTD_DDict *dict;
};
/// Decompressor with builtin dictionnary
class read_dict_ctx: public read_ctx {
public:
read_dict_ctx(const void* data, size_t size): read_ctx(ZSTD_createDDict(data, size)) {
assert(dict != NULL);
}
~read_dict_ctx() {
ZSTD_freeDDict(dict);
}
};
/// Compressor with ref to dictionnary
class write_ctx {
public:
write_ctx(ZSTD_CDict *dict): ctx(ZSTD_createCCtx()), dict(dict) { }
~write_ctx() {
ZSTD_freeCCtx(ctx);
}
/// Compress in to out (error message on failure)
template<typename I, typename O>
std::optional<const char*> compress(const I& in, O& out) const {
const auto maxSize = ZSTD_compressBound(in.size());
out.resize(maxSize);
const auto actualSize = ZSTD_compress_usingCDict(ctx, out.data(), out.size(), in.data(), in.size(), dict);
if(ZSTD_isError(actualSize)) {
return ZSTD_getErrorName(actualSize);
}
out.resize(actualSize);
return std::nullopt;
}
protected:
ZSTD_CCtx *ctx;
ZSTD_CDict *dict;
};
class dict_set {
public:
dict_set(const std::vector<char>& data) { load(data.data(), data.size()); }
dict_set(const data::out_view& data) { load(data.data(), data.size()); }
~dict_set() {
ZSTD_freeCDict(c);
ZSTD_freeDDict(d);
}
read_ctx make_reader() const {
return read_ctx(d);
}
write_ctx make_writer() const {
return write_ctx(c);
}
private:
void load(const void* data, size_t size) {
c = ZSTD_createCDict(data, size, ZSTD_CLEVEL_DEFAULT);
assert(c != NULL);
d = ZSTD_createDDict(data, size);
assert(d != NULL);
}
ZSTD_CDict *c;
ZSTD_DDict *d;
};
}