diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/blockcodecs/codecs | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/blockcodecs/codecs')
18 files changed, 741 insertions, 0 deletions
diff --git a/library/cpp/blockcodecs/codecs/brotli/brotli.cpp b/library/cpp/blockcodecs/codecs/brotli/brotli.cpp new file mode 100644 index 0000000000..6e3cd971bd --- /dev/null +++ b/library/cpp/blockcodecs/codecs/brotli/brotli.cpp @@ -0,0 +1,67 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/brotli/include/brotli/encode.h> +#include <contrib/libs/brotli/include/brotli/decode.h> + +using namespace NBlockCodecs; + +namespace { + struct TBrotliCodec : public TAddLengthCodec<TBrotliCodec> { + static constexpr int BEST_QUALITY = 11; + + inline TBrotliCodec(ui32 level) + : Quality(level) + , MyName(TStringBuf("brotli_") + ToString(level)) + { + } + + static inline size_t DoMaxCompressedLength(size_t l) noexcept { + return BrotliEncoderMaxCompressedSize(l); + } + + inline size_t DoCompress(const TData& in, void* out) const { + size_t resultSize = MaxCompressedLength(in); + auto result = BrotliEncoderCompress( + /*quality*/ Quality, + /*window*/ BROTLI_DEFAULT_WINDOW, + /*mode*/ BrotliEncoderMode::BROTLI_MODE_GENERIC, + /*input_size*/ in.size(), + /*input_buffer*/ (const unsigned char*)(in.data()), + /*encoded_size*/ &resultSize, + /*encoded_buffer*/ static_cast<unsigned char*>(out)); + if (result != BROTLI_TRUE) { + ythrow yexception() << "internal brotli error during compression"; + } + + return resultSize; + } + + inline void DoDecompress(const TData& in, void* out, size_t dsize) const { + size_t decoded = dsize; + auto result = BrotliDecoderDecompress(in.size(), (const unsigned char*)in.data(), &decoded, static_cast<unsigned char*>(out)); + if (result != BROTLI_DECODER_RESULT_SUCCESS) { + ythrow yexception() << "internal brotli error during decompression"; + } else if (decoded != dsize) { + ythrow TDecompressError(dsize, decoded); + } + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + const int Quality = BEST_QUALITY; + const TString MyName; + }; + + struct TBrotliRegistrar { + TBrotliRegistrar() { + for (int i = 1; i <= TBrotliCodec::BEST_QUALITY; ++i) { + RegisterCodec(MakeHolder<TBrotliCodec>(i)); + } + } + }; + const TBrotliRegistrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/brotli/ya.make b/library/cpp/blockcodecs/codecs/brotli/ya.make new file mode 100644 index 0000000000..17aff0bb72 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/brotli/ya.make @@ -0,0 +1,15 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/brotli/enc + contrib/libs/brotli/dec + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL brotli.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/bzip/bzip.cpp b/library/cpp/blockcodecs/codecs/bzip/bzip.cpp new file mode 100644 index 0000000000..3a5cfdd0e9 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/bzip/bzip.cpp @@ -0,0 +1,62 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/libbz2/bzlib.h> + +using namespace NBlockCodecs; + +namespace { + struct TBZipCodec: public TAddLengthCodec<TBZipCodec> { + inline TBZipCodec(int level) + : Level(level) + , MyName("bzip2-" + ToString(Level)) + { + } + + static inline size_t DoMaxCompressedLength(size_t in) noexcept { + // very strange + return in * 2 + 128; + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + inline size_t DoCompress(const TData& in, void* buf) const { + unsigned int ret = DoMaxCompressedLength(in.size()); + const int res = BZ2_bzBuffToBuffCompress((char*)buf, &ret, (char*)in.data(), in.size(), Level, 0, 0); + if (res != BZ_OK) { + ythrow TCompressError(res); + } + + return ret; + } + + inline void DoDecompress(const TData& in, void* out, size_t len) const { + unsigned int tmp = SafeIntegerCast<unsigned int>(len); + const int res = BZ2_bzBuffToBuffDecompress((char*)out, &tmp, (char*)in.data(), in.size(), 0, 0); + + if (res != BZ_OK) { + ythrow TDecompressError(res); + } + + if (len != tmp) { + ythrow TDecompressError(len, tmp); + } + } + + const int Level; + const TString MyName; + }; + + struct TBZipRegistrar { + TBZipRegistrar() { + for (int i = 1; i < 10; ++i) { + RegisterCodec(MakeHolder<TBZipCodec>(i)); + } + RegisterAlias("bzip2", "bzip2-6"); + } + }; + const TBZipRegistrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/bzip/ya.make b/library/cpp/blockcodecs/codecs/bzip/ya.make new file mode 100644 index 0000000000..f0a8aefd62 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/bzip/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/libbz2 + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL bzip.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/fastlz/fastlz.cpp b/library/cpp/blockcodecs/codecs/fastlz/fastlz.cpp new file mode 100644 index 0000000000..da2831fbd2 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/fastlz/fastlz.cpp @@ -0,0 +1,54 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/fastlz/fastlz.h> + +using namespace NBlockCodecs; + +namespace { + struct TFastLZCodec: public TAddLengthCodec<TFastLZCodec> { + inline TFastLZCodec(int level) + : MyName("fastlz-" + ToString(level)) + , Level(level) + { + } + + static inline size_t DoMaxCompressedLength(size_t in) noexcept { + return Max<size_t>(in + in / 20, 128); + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + inline size_t DoCompress(const TData& in, void* buf) const { + if (Level) { + return fastlz_compress_level(Level, in.data(), in.size(), buf); + } + + return fastlz_compress(in.data(), in.size(), buf); + } + + inline void DoDecompress(const TData& in, void* out, size_t len) const { + const int ret = fastlz_decompress(in.data(), in.size(), out, len); + + if (ret < 0 || (size_t)ret != len) { + ythrow TDataError() << TStringBuf("can not decompress"); + } + } + + const TString MyName; + const int Level; + }; + + struct TFastLZRegistrar { + TFastLZRegistrar() { + for (int i = 0; i < 3; ++i) { + RegisterCodec(MakeHolder<TFastLZCodec>(i)); + } + RegisterAlias("fastlz", "fastlz-0"); + } + }; + const TFastLZRegistrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/fastlz/ya.make b/library/cpp/blockcodecs/codecs/fastlz/ya.make new file mode 100644 index 0000000000..59c09b329b --- /dev/null +++ b/library/cpp/blockcodecs/codecs/fastlz/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/fastlz + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL fastlz.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/legacy_zstd06/legacy_zstd06.cpp b/library/cpp/blockcodecs/codecs/legacy_zstd06/legacy_zstd06.cpp new file mode 100644 index 0000000000..042f031679 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/legacy_zstd06/legacy_zstd06.cpp @@ -0,0 +1,58 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/zstd06/common/zstd.h> +#include <contrib/libs/zstd06/common/zstd_static.h> + +using namespace NBlockCodecs; + +namespace { + struct TZStd06Codec: public TAddLengthCodec<TZStd06Codec> { + inline TZStd06Codec(unsigned level) + : Level(level) + , MyName(TStringBuf("zstd06_") + ToString(Level)) + { + } + + static inline size_t CheckError(size_t ret, const char* what) { + if (ZSTD_isError(ret)) { + ythrow yexception() << what << TStringBuf(" zstd error: ") << ZSTD_getErrorName(ret); + } + + return ret; + } + + static inline size_t DoMaxCompressedLength(size_t l) noexcept { + return ZSTD_compressBound(l); + } + + inline size_t DoCompress(const TData& in, void* out) const { + return CheckError(ZSTD_compress(out, DoMaxCompressedLength(in.size()), in.data(), in.size(), Level), "compress"); + } + + inline void DoDecompress(const TData& in, void* out, size_t dsize) const { + const size_t res = CheckError(ZSTD_decompress(out, dsize, in.data(), in.size()), "decompress"); + + if (res != dsize) { + ythrow TDecompressError(dsize, res); + } + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + const unsigned Level; + const TString MyName; + }; + + struct TZStd06Registrar { + TZStd06Registrar() { + for (unsigned i = 1; i <= ZSTD_maxCLevel(); ++i) { + RegisterCodec(MakeHolder<TZStd06Codec>(i)); + } + } + }; + const TZStd06Registrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/legacy_zstd06/ya.make b/library/cpp/blockcodecs/codecs/legacy_zstd06/ya.make new file mode 100644 index 0000000000..067f731233 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/legacy_zstd06/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/zstd06 + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL legacy_zstd06.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/lz4/lz4.cpp b/library/cpp/blockcodecs/codecs/lz4/lz4.cpp new file mode 100644 index 0000000000..fbf0fe110f --- /dev/null +++ b/library/cpp/blockcodecs/codecs/lz4/lz4.cpp @@ -0,0 +1,123 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/lz4/lz4.h> +#include <contrib/libs/lz4/lz4hc.h> +#include <contrib/libs/lz4/generated/iface.h> + +using namespace NBlockCodecs; + +namespace { + struct TLz4Base { + static inline size_t DoMaxCompressedLength(size_t in) { + return LZ4_compressBound(SafeIntegerCast<int>(in)); + } + }; + + struct TLz4FastCompress { + inline TLz4FastCompress(int memory) + : Memory(memory) + , Methods(LZ4Methods(Memory)) + { + } + + inline size_t DoCompress(const TData& in, void* buf) const { + return Methods->LZ4CompressLimited(in.data(), (char*)buf, in.size(), LZ4_compressBound(in.size())); + } + + inline TString CPrefix() { + return "fast" + ToString(Memory); + } + + const int Memory; + const TLZ4Methods* Methods; + }; + + struct TLz4BestCompress { + inline size_t DoCompress(const TData& in, void* buf) const { + return LZ4_compress_HC(in.data(), (char*)buf, in.size(), LZ4_compressBound(in.size()), 0); + } + + static inline TString CPrefix() { + return "hc"; + } + }; + + struct TLz4FastDecompress { + inline void DoDecompress(const TData& in, void* out, size_t len) const { + ssize_t res = LZ4_decompress_fast(in.data(), (char*)out, len); + if (res < 0) { + ythrow TDecompressError(res); + } + } + + static inline TStringBuf DPrefix() { + return TStringBuf("fast"); + } + }; + + struct TLz4SafeDecompress { + inline void DoDecompress(const TData& in, void* out, size_t len) const { + ssize_t res = LZ4_decompress_safe(in.data(), (char*)out, in.size(), len); + if (res < 0) { + ythrow TDecompressError(res); + } + } + + static inline TStringBuf DPrefix() { + return TStringBuf("safe"); + } + }; + + template <class TC, class TD> + struct TLz4Codec: public TAddLengthCodec<TLz4Codec<TC, TD>>, public TLz4Base, public TC, public TD { + inline TLz4Codec() + : MyName("lz4-" + TC::CPrefix() + "-" + TD::DPrefix()) + { + } + + template <class T> + inline TLz4Codec(const T& t) + : TC(t) + , MyName("lz4-" + TC::CPrefix() + "-" + TD::DPrefix()) + { + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + const TString MyName; + }; + + struct TLz4Registrar { + TLz4Registrar() { + for (int i = 0; i < 30; ++i) { + typedef TLz4Codec<TLz4FastCompress, TLz4FastDecompress> T1; + typedef TLz4Codec<TLz4FastCompress, TLz4SafeDecompress> T2; + + THolder<T1> t1(new T1(i)); + THolder<T2> t2(new T2(i)); + + if (t1->Methods) { + RegisterCodec(std::move(t1)); + } + + if (t2->Methods) { + RegisterCodec(std::move(t2)); + } + } + + RegisterCodec(MakeHolder<TLz4Codec<TLz4BestCompress, TLz4FastDecompress>>()); + RegisterCodec(MakeHolder<TLz4Codec<TLz4BestCompress, TLz4SafeDecompress>>()); + + RegisterAlias("lz4-fast-safe", "lz4-fast14-safe"); + RegisterAlias("lz4-fast-fast", "lz4-fast14-fast"); + RegisterAlias("lz4", "lz4-fast-safe"); + RegisterAlias("lz4fast", "lz4-fast-fast"); + RegisterAlias("lz4hc", "lz4-hc-safe"); + } + }; + const TLz4Registrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/lz4/ya.make b/library/cpp/blockcodecs/codecs/lz4/ya.make new file mode 100644 index 0000000000..f2471d7d96 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/lz4/ya.make @@ -0,0 +1,15 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/lz4 + contrib/libs/lz4/generated + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL lz4.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/lzma/lzma.cpp b/library/cpp/blockcodecs/codecs/lzma/lzma.cpp new file mode 100644 index 0000000000..6c8d5fded4 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/lzma/lzma.cpp @@ -0,0 +1,74 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/lzmasdk/LzmaLib.h> + +using namespace NBlockCodecs; + +namespace { + struct TLzmaCodec: public TAddLengthCodec<TLzmaCodec> { + inline TLzmaCodec(int level) + : Level(level) + , MyName("lzma-" + ToString(Level)) + { + } + + static inline size_t DoMaxCompressedLength(size_t in) noexcept { + return Max<size_t>(in + in / 20, 128) + LZMA_PROPS_SIZE; + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + inline size_t DoCompress(const TData& in, void* buf) const { + unsigned char* props = (unsigned char*)buf; + unsigned char* data = props + LZMA_PROPS_SIZE; + size_t destLen = Max<size_t>(); + size_t outPropsSize = LZMA_PROPS_SIZE; + + const int ret = LzmaCompress(data, &destLen, (const unsigned char*)in.data(), in.size(), props, &outPropsSize, Level, 0, -1, -1, -1, -1, -1); + + if (ret != SZ_OK) { + ythrow TCompressError(ret); + } + + return destLen + LZMA_PROPS_SIZE; + } + + inline void DoDecompress(const TData& in, void* out, size_t len) const { + if (in.size() <= LZMA_PROPS_SIZE) { + ythrow TDataError() << TStringBuf("broken lzma stream"); + } + + const unsigned char* props = (const unsigned char*)in.data(); + const unsigned char* data = props + LZMA_PROPS_SIZE; + size_t destLen = len; + SizeT srcLen = in.size() - LZMA_PROPS_SIZE; + + const int res = LzmaUncompress((unsigned char*)out, &destLen, data, &srcLen, props, LZMA_PROPS_SIZE); + + if (res != SZ_OK) { + ythrow TDecompressError(res); + } + + if (destLen != len) { + ythrow TDecompressError(len, destLen); + } + } + + const int Level; + const TString MyName; + }; + + struct TLzmaRegistrar { + TLzmaRegistrar() { + for (int i = 0; i < 10; ++i) { + RegisterCodec(MakeHolder<TLzmaCodec>(i)); + } + RegisterAlias("lzma", "lzma-5"); + } + }; + const TLzmaRegistrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/lzma/ya.make b/library/cpp/blockcodecs/codecs/lzma/ya.make new file mode 100644 index 0000000000..e145834da6 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/lzma/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/lzmasdk + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL lzma.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/snappy/snappy.cpp b/library/cpp/blockcodecs/codecs/snappy/snappy.cpp new file mode 100644 index 0000000000..f6be05a05f --- /dev/null +++ b/library/cpp/blockcodecs/codecs/snappy/snappy.cpp @@ -0,0 +1,52 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/snappy/snappy.h> + +using namespace NBlockCodecs; + +namespace { + struct TSnappyCodec: public ICodec { + size_t DecompressedLength(const TData& in) const override { + size_t ret; + + if (snappy::GetUncompressedLength(in.data(), in.size(), &ret)) { + return ret; + } + + ythrow TDecompressError(0); + } + + size_t MaxCompressedLength(const TData& in) const override { + return snappy::MaxCompressedLength(in.size()); + } + + size_t Compress(const TData& in, void* out) const override { + size_t ret; + + snappy::RawCompress(in.data(), in.size(), (char*)out, &ret); + + return ret; + } + + size_t Decompress(const TData& in, void* out) const override { + if (snappy::RawUncompress(in.data(), in.size(), (char*)out)) { + return DecompressedLength(in); + } + + ythrow TDecompressError(0); + } + + TStringBuf Name() const noexcept override { + return "snappy"; + } + }; + + struct TSnappyRegistrar { + TSnappyRegistrar() { + RegisterCodec(MakeHolder<TSnappyCodec>()); + } + }; + const TSnappyRegistrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/snappy/ya.make b/library/cpp/blockcodecs/codecs/snappy/ya.make new file mode 100644 index 0000000000..0cf2be2f94 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/snappy/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/snappy + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL snappy.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/zlib/ya.make b/library/cpp/blockcodecs/codecs/zlib/ya.make new file mode 100644 index 0000000000..9f04995f66 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/zlib/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/zlib + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL zlib.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/zlib/zlib.cpp b/library/cpp/blockcodecs/codecs/zlib/zlib.cpp new file mode 100644 index 0000000000..cdb556c36d --- /dev/null +++ b/library/cpp/blockcodecs/codecs/zlib/zlib.cpp @@ -0,0 +1,64 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#include <contrib/libs/zlib/zlib.h> + +using namespace NBlockCodecs; + +namespace { + struct TZLibCodec: public TAddLengthCodec<TZLibCodec> { + inline TZLibCodec(int level) + : MyName("zlib-" + ToString(level)) + , Level(level) + { + } + + static inline size_t DoMaxCompressedLength(size_t in) noexcept { + return compressBound(in); + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + inline size_t DoCompress(const TData& in, void* buf) const { + //TRASH detected + uLong ret = Max<unsigned int>(); + + int cres = compress2((Bytef*)buf, &ret, (const Bytef*)in.data(), in.size(), Level); + + if (cres != Z_OK) { + ythrow TCompressError(cres); + } + + return ret; + } + + inline void DoDecompress(const TData& in, void* out, size_t len) const { + uLong ret = len; + + int uncres = uncompress((Bytef*)out, &ret, (const Bytef*)in.data(), in.size()); + if (uncres != Z_OK) { + ythrow TDecompressError(uncres); + } + + if (ret != len) { + ythrow TDecompressError(len, ret); + } + } + + const TString MyName; + const int Level; + }; + + struct TZLibRegistrar { + TZLibRegistrar() { + for (int i = 0; i < 10; ++i) { + RegisterCodec(MakeHolder<TZLibCodec>(i)); + } + RegisterAlias("zlib", "zlib-6"); + } + }; + const TZLibRegistrar Registrar{}; +} diff --git a/library/cpp/blockcodecs/codecs/zstd/ya.make b/library/cpp/blockcodecs/codecs/zstd/ya.make new file mode 100644 index 0000000000..c077dd47b7 --- /dev/null +++ b/library/cpp/blockcodecs/codecs/zstd/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER(pg) + +PEERDIR( + contrib/libs/zstd + library/cpp/blockcodecs/core +) + +SRCS( + GLOBAL zstd.cpp +) + +END() diff --git a/library/cpp/blockcodecs/codecs/zstd/zstd.cpp b/library/cpp/blockcodecs/codecs/zstd/zstd.cpp new file mode 100644 index 0000000000..95299b3f6d --- /dev/null +++ b/library/cpp/blockcodecs/codecs/zstd/zstd.cpp @@ -0,0 +1,59 @@ +#include <library/cpp/blockcodecs/core/codecs.h> +#include <library/cpp/blockcodecs/core/common.h> +#include <library/cpp/blockcodecs/core/register.h> + +#define ZSTD_STATIC_LINKING_ONLY +#include <contrib/libs/zstd/include/zstd.h> + +using namespace NBlockCodecs; + +namespace { + struct TZStd08Codec: public TAddLengthCodec<TZStd08Codec> { + inline TZStd08Codec(unsigned level) + : Level(level) + , MyName(TStringBuf("zstd08_") + ToString(Level)) + { + } + + static inline size_t CheckError(size_t ret, const char* what) { + if (ZSTD_isError(ret)) { + ythrow yexception() << what << TStringBuf(" zstd error: ") << ZSTD_getErrorName(ret); + } + + return ret; + } + + static inline size_t DoMaxCompressedLength(size_t l) noexcept { + return ZSTD_compressBound(l); + } + + inline size_t DoCompress(const TData& in, void* out) const { + return CheckError(ZSTD_compress(out, DoMaxCompressedLength(in.size()), in.data(), in.size(), Level), "compress"); + } + + inline void DoDecompress(const TData& in, void* out, size_t dsize) const { + const size_t res = CheckError(ZSTD_decompress(out, dsize, in.data(), in.size()), "decompress"); + + if (res != dsize) { + ythrow TDecompressError(dsize, res); + } + } + + TStringBuf Name() const noexcept override { + return MyName; + } + + const unsigned Level; + const TString MyName; + }; + + struct TZStd08Registrar { + TZStd08Registrar() { + for (int i = 1; i <= ZSTD_maxCLevel(); ++i) { + RegisterCodec(MakeHolder<TZStd08Codec>(i)); + RegisterAlias("zstd_" + ToString(i), "zstd08_" + ToString(i)); + } + } + }; + const TZStd08Registrar Registrar{}; +} |