-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCompressionUtils.hpp
More file actions
189 lines (156 loc) · 5.29 KB
/
Copy pathCompressionUtils.hpp
File metadata and controls
189 lines (156 loc) · 5.29 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#pragma once
#ifndef LOGIT_CPP_HEADER_LOGIT_CPP_LOGIT_DETAIL_COMPRESSIONUTILS_HPP_INCLUDED
#define LOGIT_CPP_HEADER_LOGIT_CPP_LOGIT_DETAIL_COMPRESSIONUTILS_HPP_INCLUDED
/// \file CompressionUtils.hpp
/// \brief Shared gzip/zstd compression helpers used by OTLP and MDBX backends.
#include <cstddef>
#include <string>
#if defined(LOGIT_HAS_ZLIB)
# include <zlib.h>
#endif
#if defined(LOGIT_HAS_ZSTD)
# include <zstd.h>
#endif
namespace logit {
namespace detail {
/// \brief Compress a string with gzip.
/// \param input Uncompressed data.
/// \param[out] output Compressed result (valid only on success).
/// \param level Compression level 1-9.
/// \return true on success, false if zlib is unavailable or compression fails.
/// \note Callers must check the return value and handle fallback explicitly.
inline bool compress_string_gzip(const std::string& input, std::string& output, int level) {
#if defined(LOGIT_HAS_ZLIB)
z_stream zs;
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(input.data()));
zs.avail_in = static_cast<uInt>(input.size());
zs.next_out = Z_NULL;
zs.avail_out = 0;
if (level < 1) level = 1;
if (level > 9) level = 9;
int window_bits = 15 + 16;
if (deflateInit2(&zs, level, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
return false;
}
output.clear();
int ret = Z_OK;
std::size_t offset = 0;
const std::size_t buf_size = 32768;
do {
output.resize(offset + buf_size);
zs.next_out = reinterpret_cast<Bytef*>(&output[offset]);
zs.avail_out = static_cast<uInt>(buf_size);
ret = deflate(&zs, Z_FINISH);
if (ret == Z_STREAM_ERROR) {
deflateEnd(&zs);
return false;
}
offset = zs.total_out;
} while (ret != Z_STREAM_END);
output.resize(zs.total_out);
deflateEnd(&zs);
return true;
#else
(void)input; (void)output; (void)level;
return false;
#endif
}
/// \brief Decompress gzip-compressed bytes.
/// \param input Compressed data.
/// \param[out] output Decompressed result (valid only on success).
/// \return true on success, false if zlib is unavailable or decompression fails.
inline bool decompress_string_gzip(const std::string& input, std::string& output) {
#if defined(LOGIT_HAS_ZLIB)
z_stream zs;
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(input.data()));
zs.avail_in = static_cast<uInt>(input.size());
zs.next_out = Z_NULL;
zs.avail_out = 0;
int window_bits = 15 + 32; // automatic header detection (gzip/zlib)
if (inflateInit2(&zs, window_bits) != Z_OK) {
return false;
}
output.clear();
int ret = Z_OK;
std::size_t offset = 0;
const std::size_t buf_size = 32768;
do {
output.resize(offset + buf_size);
zs.next_out = reinterpret_cast<Bytef*>(&output[offset]);
zs.avail_out = static_cast<uInt>(buf_size);
ret = inflate(&zs, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
inflateEnd(&zs);
return false;
}
offset = zs.total_out;
} while (ret != Z_STREAM_END);
output.resize(zs.total_out);
inflateEnd(&zs);
return true;
#else
(void)input; (void)output;
return false;
#endif
}
/// \brief Compress a string with zstd.
/// \param input Uncompressed data.
/// \param[out] output Compressed result (valid only on success).
/// \param level Compression level 1-19.
/// \return true on success, false if zstd is unavailable or compression fails.
/// \note Callers must check the return value and handle fallback explicitly.
inline bool compress_string_zstd(const std::string& input, std::string& output, int level) {
#if defined(LOGIT_HAS_ZSTD)
if (level < 1) level = 1;
if (level > 19) level = 19;
std::size_t bound = ZSTD_compressBound(input.size());
output.resize(bound);
std::size_t result = ZSTD_compress(
&output[0], output.size(),
input.data(), input.size(),
level);
if (ZSTD_isError(result)) {
output.clear();
return false;
}
output.resize(result);
return true;
#else
(void)input; (void)output; (void)level;
return false;
#endif
}
/// \brief Decompress zstd-compressed bytes.
/// \param input Compressed data.
/// \param[out] output Decompressed result (valid only on success).
/// \return true on success, false if zstd is unavailable or decompression fails.
inline bool decompress_string_zstd(const std::string& input, std::string& output) {
#if defined(LOGIT_HAS_ZSTD)
std::size_t const d_size = ZSTD_getFrameContentSize(input.data(), input.size());
if (d_size == ZSTD_CONTENTSIZE_ERROR || d_size == ZSTD_CONTENTSIZE_UNKNOWN) {
return false;
}
output.resize(d_size);
std::size_t const result = ZSTD_decompress(
&output[0], output.size(),
input.data(), input.size());
if (ZSTD_isError(result)) {
output.clear();
return false;
}
output.resize(result);
return true;
#else
(void)input; (void)output;
return false;
#endif
}
} // namespace detail
} // namespace logit
#endif // LOGIT_CPP_HEADER_LOGIT_CPP_LOGIT_DETAIL_COMPRESSIONUTILS_HPP_INCLUDED