From 52571bc9602e3dd41626876ffc6c2e65b0e098bc Mon Sep 17 00:00:00 2001 From: TapTap Date: Thu, 16 Jul 2026 12:29:31 +0200 Subject: [PATCH] streaming zstd: switch to ZSTD_compressStream2 / ZSTD_decompressStream Replaced one-shot ZSTD_compress / ZSTD_decompress with streaming API (ZSTD_compressStream2 + ZSTD_decompressStream) in both data_compress and data_decompress. Interface unchanged. Prepares for true streaming transfer where compression can be interleaved with transmission. --- src/shared/compression.c | 68 +++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/src/shared/compression.c b/src/shared/compression.c index 627659c..cc605e8 100644 --- a/src/shared/compression.c +++ b/src/shared/compression.c @@ -6,18 +6,31 @@ Data *data_compress(Data *data_to_compress, int compression_level) { log_message(LOG_LEVEL_DEBUG, "Starting to compress data"); - Data *compressed_data = - data_create_empty(ZSTD_compressBound(data_to_compress->size)); + size_t dst_size = ZSTD_compressBound(data_to_compress->size); + Data *compressed_data = data_create_empty(dst_size); - compressed_data->size = ZSTD_compress( - compressed_data->data, compressed_data->size, data_to_compress->data, - data_to_compress->size, compression_level); - if (ZSTD_isError(compressed_data->size)) { - log_message(LOG_LEVEL_ERROR, "Compression failed: %s", - ZSTD_getErrorName(compressed_data->size)); + ZSTD_CCtx *cctx = ZSTD_createCCtx(); + if (!cctx) { + log_message(LOG_LEVEL_ERROR, "Failed to create ZSTD compression context"); exit(EXIT_FAILURE); } + ZSTD_inBuffer input = {data_to_compress->data, data_to_compress->size, 0}; + ZSTD_outBuffer output = {compressed_data->data, dst_size, 0}; + + size_t ret; + do { + ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end); + if (ZSTD_isError(ret)) { + log_message(LOG_LEVEL_ERROR, "Compression failed: %s", + ZSTD_getErrorName(ret)); + exit(EXIT_FAILURE); + } + } while (ret > 0); + + compressed_data->size = output.pos; + ZSTD_freeCCtx(cctx); + log_message(LOG_LEVEL_DEBUG, "Data succesfully compressed from %zu to %zu", data_to_compress->size, compressed_data->size); return compressed_data; @@ -25,22 +38,39 @@ Data *data_compress(Data *data_to_compress, int compression_level) { Data *data_decompress(Data *compressed_data) { log_message(LOG_LEVEL_DEBUG, "Start to decompress data"); - Data *uncompressed_data = data_create_empty( - ZSTD_getFrameContentSize(compressed_data->data, compressed_data->size)); - if (ZSTD_isError(uncompressed_data->size)) { - log_message(LOG_LEVEL_ERROR, "Decompression failed: %s", - ZSTD_getErrorName(uncompressed_data->size)); + unsigned long long dst_size = ZSTD_getFrameContentSize( + compressed_data->data, compressed_data->size); + if (ZSTD_isError(dst_size)) { + log_message(LOG_LEVEL_ERROR, "Failed to get decompressed size: %s", + ZSTD_getErrorName(dst_size)); exit(EXIT_FAILURE); } - uncompressed_data->size = - ZSTD_decompress(uncompressed_data->data, uncompressed_data->size, - compressed_data->data, compressed_data->size); - if (ZSTD_isError(uncompressed_data->size)) { - log_message(LOG_LEVEL_ERROR, "Decompression failed: %s", - ZSTD_getErrorName(uncompressed_data->size)); + Data *uncompressed_data = data_create_empty((size_t)dst_size); + + ZSTD_DCtx *dctx = ZSTD_createDCtx(); + if (!dctx) { + log_message(LOG_LEVEL_ERROR, + "Failed to create ZSTD decompression context"); exit(EXIT_FAILURE); } + + ZSTD_inBuffer input = {compressed_data->data, compressed_data->size, 0}; + ZSTD_outBuffer output = {uncompressed_data->data, (size_t)dst_size, 0}; + + size_t ret; + do { + ret = ZSTD_decompressStream(dctx, &output, &input); + if (ZSTD_isError(ret)) { + log_message(LOG_LEVEL_ERROR, "Decompression failed: %s", + ZSTD_getErrorName(ret)); + exit(EXIT_FAILURE); + } + } while (ret > 0); + + uncompressed_data->size = output.pos; + ZSTD_freeDCtx(dctx); + log_message(LOG_LEVEL_DEBUG, "Decompressed data successfully"); return uncompressed_data; }