11/*
2- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
2+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33 *
44 * SPDX-License-Identifier: CC0-1.0
55 */
1010#include "esp_log.h"
1111
1212#include "xz_decompress.h"
13+ #include "xz.h"
1314
1415#define IO_BUFFER_LEN (2048)
1516
@@ -100,6 +101,87 @@ static void test_cb_to_buf(void)
100101 free (in_buf );
101102}
102103
104+ #define CHUNK_SIZE 4096
105+ static void test_chunked_api (void )
106+ {
107+ ESP_LOGI (TAG , "Using chunked decompression API" );
108+
109+ // Initialize the decoder with prealloc mode to control memory usage
110+ // Using a smaller dictionary size reduces memory requirements
111+ struct xz_dec * decoder = xz_dec_init (XZ_PREALLOC , 1 << 16 ); // 64KB dictionary
112+ if (!decoder ) {
113+ ESP_LOGE (TAG , "Failed to initialize XZ decoder" );
114+ return ;
115+ }
116+
117+ uint8_t * in_buffer = malloc (CHUNK_SIZE );
118+ uint8_t * out_buffer = malloc (CHUNK_SIZE );
119+
120+ if (!in_buffer || !out_buffer ) {
121+ ESP_LOGE (TAG , "Failed to allocate buffers" );
122+ free (in_buffer );
123+ free (out_buffer );
124+ xz_dec_end (decoder );
125+ return ;
126+ }
127+
128+ struct xz_buf buffer = {
129+ .in = in_buffer ,
130+ .in_pos = 0 ,
131+ .in_size = 0 ,
132+ .out = out_buffer ,
133+ .out_pos = 0 ,
134+ .out_size = CHUNK_SIZE
135+ };
136+
137+ // Track total bytes processed
138+ size_t total_in = 0 ;
139+ size_t total_out = 0 ;
140+ size_t remaining = compressed_file_length ;
141+
142+ // Process the compressed data in chunks
143+ enum xz_ret ret = XZ_OK ;
144+ while (ret != XZ_STREAM_END ) {
145+ if (buffer .in_pos == buffer .in_size && remaining > 0 ) {
146+ size_t read_size = remaining > CHUNK_SIZE ? CHUNK_SIZE : remaining ;
147+
148+ memcpy (in_buffer , xz_compressed_file_start + total_in , read_size );
149+
150+ buffer .in_pos = 0 ;
151+ buffer .in_size = read_size ;
152+
153+ total_in += read_size ;
154+ remaining -= read_size ;
155+ }
156+
157+ ret = xz_dec_run (decoder , & buffer );
158+
159+ if (buffer .out_pos > 0 ) {
160+ // Only for this example, as we would be printing the entire decompressed data
161+ out_buffer [buffer .out_pos ] = '\0' ;
162+ ESP_LOGI (TAG , "Decompressed chunk (%u bytes)" , buffer .out_pos );
163+
164+ total_out += buffer .out_pos ;
165+ buffer .out_pos = 0 ;
166+ }
167+
168+ if (ret != XZ_OK && ret != XZ_STREAM_END ) {
169+ ESP_LOGE (TAG , "Decompression error: %d" , ret );
170+ break ;
171+ }
172+ }
173+
174+ ESP_LOGI (TAG , "Chunked decompression stats:" );
175+ ESP_LOGI (TAG , "Input bytes processed: %u" , total_in );
176+ ESP_LOGI (TAG , "Output bytes produced: %u" , total_out );
177+ ESP_LOGI (TAG , "Decompressed data:\n%s" , out_buffer );
178+
179+ // Clean up
180+ free (in_buffer );
181+ free (out_buffer );
182+ xz_dec_end (decoder );
183+ }
184+
103185void app_main (void )
104186{
105187 size_t origin_file_length = origin_file_end - origin_file_start ;
@@ -126,6 +208,10 @@ void app_main(void)
126208 test_buf_to_cb ();
127209 ESP_LOGI (TAG , "*****************test buf to callback end*************\n" );
128210
211+ ESP_LOGI (TAG , "*****************test chunked API begin***************\n" );
212+ test_chunked_api ();
213+ ESP_LOGI (TAG , "*****************test chunked API end*****************\n" );
214+
129215 // All done
130216 ESP_LOGI (TAG , "TASK FINISH" );
131217}
0 commit comments