38 bool isValidStrategy(
int strategy) {
39 std::array<int, 5> strategies{{
46 return std::any_of(strategies.begin(), strategies.end(), [&](
int i) {
51 int getWindowBits(Options::Format
format,
int windowSize) {
53 case Options::Format::ZLIB:
55 case Options::Format::GZIP:
56 return windowSize + 16;
57 case Options::Format::RAW:
59 case Options::Format::AUTO:
60 return windowSize + 32;
67 if (options.windowSize == 15 && options.format == Options::Format::ZLIB) {
70 options.windowSize == 15 && options.format == Options::Format::GZIP) {
77 class ZlibStreamCodec final :
public StreamCodec {
79 static std::unique_ptr<Codec> createCodec(Options options,
int level);
80 static std::unique_ptr<StreamCodec> createStream(Options options,
int level);
82 explicit ZlibStreamCodec(Options options,
int level);
83 ~ZlibStreamCodec()
override;
85 std::vector<std::string> validPrefixes()
const override;
86 bool canUncompress(
const IOBuf*
data, Optional<uint64_t> uncompressedLength)
92 void doResetStream()
override;
93 bool doCompressStream(
97 bool doUncompressStream(
102 void resetDeflateStream();
103 void resetInflateStream();
107 Optional<z_stream> deflateStream_{};
108 Optional<z_stream> inflateStream_{};
110 bool needReset_{
true};
112 static constexpr
uint16_t kGZIPMagicLE = 0x8B1F;
114 std::vector<std::string> ZlibStreamCodec::validPrefixes()
const {
132 std::vector<std::string> result;
139 for (
uint32_t second = 0x00; second <= 0xE0; second += 0x20) {
142 prefix += 31 - (prefix % 31);
145 if ((prefix & 0x1F) == 31) {
160 bool ZlibStreamCodec::canUncompress(
const IOBuf*
data, Optional<uint64_t>)
165 if (!cursor.tryReadBE(value)) {
169 return (value & 0x0F00) == 0x0800 && value % 31 == 0;
177 uint64_t ZlibStreamCodec::doMaxCompressedLength(
178 uint64_t uncompressedLength)
const {
181 return deflateBound(
nullptr, uncompressedLength) +
182 (options_.format == Options::Format::GZIP ? 12 : 0);
185 std::unique_ptr<Codec> ZlibStreamCodec::createCodec(
188 return std::make_unique<ZlibStreamCodec>(options, level);
191 std::unique_ptr<StreamCodec> ZlibStreamCodec::createStream(
194 return std::make_unique<ZlibStreamCodec>(options, level);
197 static bool inBounds(
int value,
int low,
int high) {
198 return (value >= low) && (value <= high);
201 static int zlibConvertLevel(
int level) {
210 if (!inBounds(level, 0, 9)) {
211 throw std::invalid_argument(
212 to<std::string>(
"ZlibStreamCodec: invalid level: ", level));
217 ZlibStreamCodec::ZlibStreamCodec(Options options,
int level)
219 getCodecType(options),
220 zlibConvertLevel(level),
222 level_(zlibConvertLevel(level)) {
230 if (!inBounds(options_.windowSize, 9, 15)) {
231 throw std::invalid_argument(to<std::string>(
232 "ZlibStreamCodec: invalid windowSize option: ", options.windowSize));
234 if (!inBounds(options_.memLevel, 1, 9)) {
235 throw std::invalid_argument(to<std::string>(
236 "ZlibStreamCodec: invalid memLevel option: ", options.memLevel));
238 if (!isValidStrategy(options_.strategy)) {
239 throw std::invalid_argument(to<std::string>(
240 "ZlibStreamCodec: invalid strategy: ", options.strategy));
244 ZlibStreamCodec::~ZlibStreamCodec() {
245 if (deflateStream_) {
246 deflateEnd(deflateStream_.get_pointer());
247 deflateStream_.clear();
249 if (inflateStream_) {
250 inflateEnd(inflateStream_.get_pointer());
251 inflateStream_.clear();
255 void ZlibStreamCodec::doResetStream() {
259 void ZlibStreamCodec::resetDeflateStream() {
260 if (deflateStream_) {
261 int const rc = deflateReset(deflateStream_.get_pointer());
263 deflateStream_.clear();
264 throw std::runtime_error(
265 to<std::string>(
"ZlibStreamCodec: deflateReset error: ", rc));
269 deflateStream_ = z_stream{};
273 int const windowBits = getWindowBits(
274 options_.format == Options::Format::AUTO ? Options::Format::ZLIB
276 options_.windowSize);
278 int const rc = deflateInit2(
279 deflateStream_.get_pointer(),
286 deflateStream_.clear();
287 throw std::runtime_error(
288 to<std::string>(
"ZlibStreamCodec: deflateInit error: ", rc));
292 void ZlibStreamCodec::resetInflateStream() {
293 if (inflateStream_) {
294 int const rc = inflateReset(inflateStream_.get_pointer());
296 inflateStream_.clear();
297 throw std::runtime_error(
298 to<std::string>(
"ZlibStreamCodec: inflateReset error: ", rc));
302 inflateStream_ = z_stream{};
303 int const rc = inflateInit2(
304 inflateStream_.get_pointer(),
305 getWindowBits(options_.format, options_.windowSize));
307 inflateStream_.clear();
308 throw std::runtime_error(
309 to<std::string>(
"ZlibStreamCodec: inflateInit error: ", rc));
313 static int zlibTranslateFlush(StreamCodec::FlushOp flush) {
315 case StreamCodec::FlushOp::NONE:
317 case StreamCodec::FlushOp::FLUSH:
319 case StreamCodec::FlushOp::END:
322 throw std::invalid_argument(
"ZlibStreamCodec: Invalid flush");
326 static int zlibThrowOnError(
int rc) {
333 throw std::runtime_error(to<std::string>(
"ZlibStreamCodec: error: ", rc));
337 bool ZlibStreamCodec::doCompressStream(
340 StreamCodec::FlushOp flush) {
342 resetDeflateStream();
345 DCHECK(deflateStream_.hasValue());
347 if (output.data() ==
nullptr) {
350 deflateStream_->next_in =
const_cast<uint8_t*
>(input.data());
351 deflateStream_->avail_in = input.size();
352 deflateStream_->next_out = output.data();
353 deflateStream_->avail_out = output.size();
355 input.uncheckedAdvance(input.size() - deflateStream_->avail_in);
356 output.uncheckedAdvance(output.size() - deflateStream_->avail_out);
358 int const rc = zlibThrowOnError(
359 deflate(deflateStream_.get_pointer(), zlibTranslateFlush(flush)));
361 case StreamCodec::FlushOp::NONE:
363 case StreamCodec::FlushOp::FLUSH:
364 return deflateStream_->avail_in == 0 && deflateStream_->avail_out != 0;
365 case StreamCodec::FlushOp::END:
366 return rc == Z_STREAM_END;
368 throw std::invalid_argument(
"ZlibStreamCodec: Invalid flush");
372 bool ZlibStreamCodec::doUncompressStream(
375 StreamCodec::FlushOp flush) {
377 resetInflateStream();
380 DCHECK(inflateStream_.hasValue());
382 if (output.data() ==
nullptr) {
385 inflateStream_->next_in =
const_cast<uint8_t*
>(input.data());
386 inflateStream_->avail_in = input.size();
387 inflateStream_->next_out = output.data();
388 inflateStream_->avail_out = output.size();
390 input.advance(input.size() - inflateStream_->avail_in);
391 output.advance(output.size() - inflateStream_->avail_out);
393 int const rc = zlibThrowOnError(
394 inflate(inflateStream_.get_pointer(), zlibTranslateFlush(flush)));
395 return rc == Z_STREAM_END;
400 Options defaultGzipOptions() {
401 return Options(Options::Format::GZIP);
404 Options defaultZlibOptions() {
405 return Options(Options::Format::ZLIB);
408 std::unique_ptr<Codec>
getCodec(Options options,
int level) {
409 return ZlibStreamCodec::createCodec(options, level);
412 std::unique_ptr<StreamCodec>
getStreamCodec(Options options,
int level) {
413 return ZlibStreamCodec::createStream(options, level);
420 #endif // FOLLY_HAVE_LIBZ constexpr int COMPRESSION_LEVEL_DEFAULT
—— Concurrent Priority Queue Implementation ——
bool prefix(Cursor &c, uint32_t expected)
Range< unsigned char * > MutableByteRange
std::enable_if< std::is_arithmetic< T >::value, std::string >::type prefixToStringLE(T prefix, uint64_t n=sizeof(T))
std::unique_ptr< StreamCodec > getStreamCodec(CodecType type, int level)
constexpr auto data(C &c) -> decltype(c.data())
constexpr int COMPRESSION_LEVEL_BEST
Range< const unsigned char * > ByteRange
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
Formatter< false, Args... > format(StringPiece fmt, Args &&...args)
std::enable_if< std::is_unsigned< T >::value, bool >::type dataStartsWithLE(const IOBuf *data, T prefix, uint64_t n=sizeof(T))
constexpr int COMPRESSION_LEVEL_FASTEST
std::unique_ptr< Codec > getCodec(CodecType type, int level)
constexpr detail::First first