forked from alterware/iw6-mod
		
	Added helper util functions for (de)compression.
This commit is contained in:
		@@ -109,6 +109,86 @@ namespace utils::compression
 | 
			
		||||
			result.resize(length);
 | 
			
		||||
			return result;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::vector<std::uint8_t> decompress(std::span<const std::uint8_t> input, std::size_t exp_output_size, double growth_rate)
 | 
			
		||||
		{
 | 
			
		||||
			auto decompress_internal = [](std::uint8_t* output, uLong* output_size, const std::uint8_t* input, uLong* input_size)
 | 
			
		||||
			{
 | 
			
		||||
				return uncompress2(
 | 
			
		||||
					reinterpret_cast<Bytef*>(output), output_size,
 | 
			
		||||
					reinterpret_cast<const Bytef*>(input), input_size
 | 
			
		||||
				);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			auto output_size = static_cast<uLong>(std::max(exp_output_size, std::size_t(256)));
 | 
			
		||||
			std::vector<std::uint8_t> output(output_size);
 | 
			
		||||
 | 
			
		||||
			auto input_size = static_cast<uLong>(input.size());
 | 
			
		||||
			auto status = decompress_internal(output.data(), &output_size, input.data(), &input_size);
 | 
			
		||||
 | 
			
		||||
			if (status == Z_BUF_ERROR)
 | 
			
		||||
			{
 | 
			
		||||
				const auto decompression_ratio = (input_size / static_cast<double>(output.size())) - 0.04;
 | 
			
		||||
				output_size = static_cast<uLong>(std::max(input.size() / decompression_ratio, static_cast<double>(output_size)));
 | 
			
		||||
				output.resize(output_size);
 | 
			
		||||
 | 
			
		||||
				input_size = static_cast<uLong>(input.size());
 | 
			
		||||
				status = decompress_internal(output.data(), &output_size, input.data(), &input_size);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (growth_rate = std::max(growth_rate, 1.0); status == Z_BUF_ERROR;)
 | 
			
		||||
			{
 | 
			
		||||
				output_size = 4 + static_cast<uLong>(growth_rate * output.size());
 | 
			
		||||
				output.resize(output_size);
 | 
			
		||||
 | 
			
		||||
				input_size = static_cast<uLong>(input.size());
 | 
			
		||||
				status = decompress_internal(output.data(), &output_size, input.data(), &input_size);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (status != Z_OK)
 | 
			
		||||
			{
 | 
			
		||||
				output.clear();
 | 
			
		||||
				return output;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			output.resize(output_size);
 | 
			
		||||
			return output;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::vector<std::uint8_t> compress(std::span<const std::uint8_t> input, std::size_t exp_output_size, double growth_rate)
 | 
			
		||||
		{
 | 
			
		||||
			auto compress_internal = [](std::uint8_t* output, uLong* output_size, const std::uint8_t* input, uLong input_size)
 | 
			
		||||
			{
 | 
			
		||||
				return compress2(
 | 
			
		||||
					reinterpret_cast<Bytef*>(output), output_size,
 | 
			
		||||
					reinterpret_cast<const Bytef*>(input), input_size,
 | 
			
		||||
					Z_BEST_COMPRESSION
 | 
			
		||||
				);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			auto output_size = static_cast<uLong>(std::max(exp_output_size, std::size_t(256)));
 | 
			
		||||
			std::vector<std::uint8_t> output(output_size);
 | 
			
		||||
 | 
			
		||||
			const auto input_size = static_cast<uLong>(input.size());
 | 
			
		||||
			auto status = compress_internal(output.data(), &output_size, input.data(), input_size);
 | 
			
		||||
 | 
			
		||||
			for (growth_rate = std::max(growth_rate, 1.0); status == Z_BUF_ERROR;)
 | 
			
		||||
			{
 | 
			
		||||
				output_size = 4 + static_cast<uLong>(growth_rate * output.size());
 | 
			
		||||
				output.resize(output_size);
 | 
			
		||||
 | 
			
		||||
				status = compress_internal(output.data(), &output_size, input.data(), input_size);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (status != Z_OK)
 | 
			
		||||
			{
 | 
			
		||||
				output.clear();
 | 
			
		||||
				return output;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			output.resize(output_size);
 | 
			
		||||
			return output;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	namespace zip
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,9 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <span>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#define CHUNK 16384u
 | 
			
		||||
 | 
			
		||||
@@ -11,6 +13,9 @@ namespace utils::compression
 | 
			
		||||
	{
 | 
			
		||||
		std::string compress(const std::string& data);
 | 
			
		||||
		std::string decompress(const std::string& data);
 | 
			
		||||
 | 
			
		||||
		std::vector<std::uint8_t> compress(std::span<const std::uint8_t> input, std::size_t exp_output_size, double growth_rate = 2.0);
 | 
			
		||||
		std::vector<std::uint8_t> decompress(std::span<const std::uint8_t> input, std::size_t exp_output_size, double growth_rate = 2.0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	namespace zip
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user