Skip to content

Commit eb8f049

Browse files
committed
feat(xz): Make xz multi call decompression APIs public
1 parent 86cd905 commit eb8f049

File tree

5 files changed

+98
-6
lines changed

5 files changed

+98
-6
lines changed

components/utilities/xz/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# ChangeLog
22

3+
## v1.1.0 - 2025-3-25
4+
5+
### Features:
6+
7+
- Make the xz_embedded library's multi-call APIs public
8+
39
## v1.0.1 - 2025-2-20
410

511
### bugfix:
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
set(incs "include")
1+
set(incs "include"
2+
"xz-embedded/linux/include/linux")
23

34
set(priv_incs "port/include"
4-
"xz-embedded/linux/include/linux"
55
"xz-embedded/linux/lib/xz")
66

77
set(srcs "src/xz_decompress.c"
@@ -11,4 +11,4 @@ set(srcs "src/xz_decompress.c"
1111

1212
idf_component_register(SRCS ${srcs}
1313
INCLUDE_DIRS ${incs}
14-
PRIV_INCLUDE_DIRS ${priv_incs})
14+
PRIV_INCLUDE_DIRS ${priv_incs})

components/utilities/xz/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "1.0.1"
1+
version: "1.1.0"
22
description: xz decompression utility
33
url: https://github.com/espressif/esp-iot-solution/tree/master/components/utilities/xz
44
dependencies:
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
dependencies:
22
xz:
3-
version: "~1.0.0"
3+
version: "~1.1.0"
44
# Please comment the following line, if this example is installed by idf.py create-project-from-example.
55
override_path: "../../../../components/utilities/xz"

examples/utilities/xz_decompress_file/main/xz_decompress_file_example_main.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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
*/
@@ -10,6 +10,7 @@
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+
103185
void 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

Comments
 (0)