aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/blockcodecs/codecs/lz4/lz4.cpp
blob: fbf0fe110f1141eaefd0d308d3ed9c5009b56a7c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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{};
}