size_t zstd_decompression_reader::read_some()

in src/native/io/compressed/zstd_decompression_reader.cpp [11:66]


size_t zstd_decompression_reader::read_some(std::span<char> buffer)
{
	ZSTD_outBuffer output_buffer{buffer.data(), buffer.size(), 0};

	size_t last_ret{};
	bool retry{false};

	size_t total_read = 0;

	do
	{
		size_t ret = ZSTD_decompressStream(m_zstd_dstream.get(), &output_buffer, &m_in_zstd_buffer);

		if (ZSTD_isError(ret))
		{
			auto error_name = ZSTD_getErrorName(ret);
			std::string msg = "ZSTD_decompressStream() failed. ret: " + std::to_string(ret)
			                + std::string(" error_name: ") + error_name;
			throw errors::user_exception(errors::error_code::io_zstd_decompress_stream_failed, msg);
		}

		total_read = output_buffer.pos;

		if ((total_read + m_read_offset) == m_uncompressed_result_size)
		{
			break;
		}

		// There wasn't enough data already present, so read some more
		if ((output_buffer.size != output_buffer.pos) && (m_in_zstd_buffer.size == m_in_zstd_buffer.pos))
		{
			auto to_read     = std::min(ret, m_in_vector.capacity());
			auto actual_read = m_reader->read_some(std::span<char>{m_in_vector.data(), to_read});

			m_in_zstd_buffer.src  = m_in_vector.data();
			m_in_zstd_buffer.size = actual_read;
			m_in_zstd_buffer.pos  = 0;

			bool maybe_incomplete = (actual_read == 0) && (last_ret == ret);

			if (maybe_incomplete && retry)
			{
				throw errors::user_exception(errors::error_code::io_zstd_decompress_cannot_finish);
			}

			retry = maybe_incomplete;
		}

		last_ret = ret;
	}
	while (output_buffer.size != output_buffer.pos);

	m_read_offset += total_read;

	return total_read;
}