in src/native/io/compressed/zlib_compression_reader.cpp [77:144]
size_t zlib_compression_reader::read_some(std::span<char> buffer)
{
auto to_read = static_cast<uInt>(buffer.size());
m_zstr.next_out = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(buffer.data()));
m_zstr.avail_out = to_read;
uint64_t actual_read = 0;
while (true)
{
bool last_chunk = m_processed_bytes == m_uncompressed_input_size;
auto flush_param = last_chunk ? Z_FINISH : Z_NO_FLUSH;
auto ret = ::deflate(&m_zstr, flush_param);
// if the state of compression is invalid, then error out
if (ret == Z_STREAM_ERROR)
{
auto msg = "deflate() failed. ret: " + std::to_string(ret);
throw errors::user_exception(errors::error_code::io_zlib_reader_deflate_failed, msg);
}
// If there's an issue with the buffers and we don't have any input for the deflate available,
// then read some data and make it available. We'll call deflate again.
if ((ret == Z_BUF_ERROR) && (m_zstr.avail_in == 0))
{
auto input_to_read = m_input_data.capacity();
auto from_reader = m_reader->read_some(std::span<char>{m_input_data.data(), input_to_read});
m_zstr.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(m_input_data.data()));
m_zstr.avail_in = static_cast<uInt>(from_reader);
m_processed_bytes += from_reader;
continue;
}
actual_read = m_zstr.total_out - m_read_offset;
if (ret == Z_STREAM_END)
{
break;
}
// If there was no error and we've read everything
if (ret == Z_OK && (m_processed_bytes == m_uncompressed_input_size))
{
break;
}
// If we've read as much as we expected and have no error or need more buffers then return
if (((ret == Z_OK) || ret == (Z_BUF_ERROR)) && (actual_read == to_read))
{
break;
}
// Otherwise, if we are in some error state, throw an exception
if (ret != Z_OK)
{
auto msg = "deflate() failed. ret: " + std::to_string(ret);
throw errors::user_exception(errors::error_code::io_zlib_reader_deflate_failed, msg);
}
}
m_read_offset = m_zstr.total_out;
return actual_read;
}