Added helper util functions for zlib (de)compression. #8
| @@ -109,6 +109,86 @@ namespace utils::compression | |||||||
| 			result.resize(length); | 			result.resize(length); | ||||||
| 			return result; | 			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 | 	namespace zip | ||||||
|   | |||||||
| @@ -1,7 +1,9 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <span> | ||||||
| #include <string> | #include <string> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
| #define CHUNK 16384u | #define CHUNK 16384u | ||||||
|  |  | ||||||
| @@ -11,6 +13,9 @@ namespace utils::compression | |||||||
| 	{ | 	{ | ||||||
| 		std::string compress(const std::string& data); | 		std::string compress(const std::string& data); | ||||||
| 		std::string decompress(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 | 	namespace zip | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user