MCPcopy Create free account
hub / github.com/apache/arrow / Decompress

Method Decompress

cpp/src/arrow/util/compression_zlib.cc:392–448  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

390 }
391
392 Result<int64_t> Decompress(int64_t input_length, const uint8_t* input,
393 int64_t output_buffer_length, uint8_t* output) override {
394 int64_t read_input_bytes = 0;
395 int64_t decompressed_bytes = 0;
396
397 if (!decompressor_initialized_) {
398 RETURN_NOT_OK(InitDecompressor());
399 }
400 if (output_buffer_length == 0) {
401 // The zlib library does not allow *output to be NULL, even when
402 // output_buffer_length is 0 (inflate() will return Z_STREAM_ERROR). We don't
403 // consider this an error, so bail early if no output is expected. Note that we
404 // don't signal an error if the input actually contains compressed data.
405 return 0;
406 }
407
408 // inflate() will not automatically decode concatenated gzip members, keep calling
409 // inflate until reading all input data (GH-38271).
410 while (read_input_bytes < input_length) {
411 // Reset the stream for this block
412 if (inflateReset(&stream_) != Z_OK) {
413 return ZlibErrorPrefix("zlib inflateReset failed: ", stream_.msg);
414 }
415
416 int ret = 0;
417 // gzip can run in streaming mode or non-streaming mode. We only
418 // support the non-streaming use case where we present it the entire
419 // compressed input and a buffer big enough to contain the entire
420 // compressed output. In the case where we don't know the output,
421 // we just make a bigger buffer and try the non-streaming mode
422 // from the beginning again.
423 stream_.next_in =
424 const_cast<Bytef*>(reinterpret_cast<const Bytef*>(input + read_input_bytes));
425 stream_.avail_in = static_cast<uInt>(input_length - read_input_bytes);
426 stream_.next_out = reinterpret_cast<Bytef*>(output + decompressed_bytes);
427 stream_.avail_out = static_cast<uInt>(output_buffer_length - decompressed_bytes);
428
429 // We know the output size. In this case, we can use Z_FINISH
430 // which is more efficient.
431 ret = inflate(&stream_, Z_FINISH);
432 if (ret == Z_OK) {
433 // Failure, buffer was too small
434 return Status::IOError("Too small a buffer passed to GZipCodec. InputLength=",
435 input_length, " OutputLength=", output_buffer_length);
436 }
437
438 // Failure for some other reason
439 if (ret != Z_STREAM_END) {
440 return ZlibErrorPrefix("GZipCodec failed: ", stream_.msg);
441 }
442
443 read_input_bytes += stream_.total_in;
444 decompressed_bytes += stream_.total_out;
445 }
446
447 return decompressed_bytes;
448 }
449

Callers

nothing calls this directly

Calls 2

ZlibErrorPrefixFunction · 0.85
IOErrorFunction · 0.85

Tested by

no test coverage detected