1f24c1d75SAlexey Budankov // SPDX-License-Identifier: GPL-2.0
2f24c1d75SAlexey Budankov
3f24c1d75SAlexey Budankov #include <string.h>
4f24c1d75SAlexey Budankov
5f24c1d75SAlexey Budankov #include "util/compress.h"
6f24c1d75SAlexey Budankov #include "util/debug.h"
7f24c1d75SAlexey Budankov
zstd_init(struct zstd_data * data,int level)8f24c1d75SAlexey Budankov int zstd_init(struct zstd_data *data, int level)
9f24c1d75SAlexey Budankov {
10f24c1d75SAlexey Budankov size_t ret;
11f24c1d75SAlexey Budankov
12cb62c6f1SAlexey Budankov data->dstream = ZSTD_createDStream();
13cb62c6f1SAlexey Budankov if (data->dstream == NULL) {
14cb62c6f1SAlexey Budankov pr_err("Couldn't create decompression stream.\n");
15cb62c6f1SAlexey Budankov return -1;
16cb62c6f1SAlexey Budankov }
17cb62c6f1SAlexey Budankov
18cb62c6f1SAlexey Budankov ret = ZSTD_initDStream(data->dstream);
19cb62c6f1SAlexey Budankov if (ZSTD_isError(ret)) {
20cb62c6f1SAlexey Budankov pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret));
21cb62c6f1SAlexey Budankov return -1;
22cb62c6f1SAlexey Budankov }
23cb62c6f1SAlexey Budankov
24cb62c6f1SAlexey Budankov if (!level)
25cb62c6f1SAlexey Budankov return 0;
26cb62c6f1SAlexey Budankov
27f24c1d75SAlexey Budankov data->cstream = ZSTD_createCStream();
28f24c1d75SAlexey Budankov if (data->cstream == NULL) {
29f24c1d75SAlexey Budankov pr_err("Couldn't create compression stream.\n");
30f24c1d75SAlexey Budankov return -1;
31f24c1d75SAlexey Budankov }
32f24c1d75SAlexey Budankov
33f24c1d75SAlexey Budankov ret = ZSTD_initCStream(data->cstream, level);
34f24c1d75SAlexey Budankov if (ZSTD_isError(ret)) {
35f24c1d75SAlexey Budankov pr_err("Failed to initialize compression stream: %s\n", ZSTD_getErrorName(ret));
36f24c1d75SAlexey Budankov return -1;
37f24c1d75SAlexey Budankov }
38f24c1d75SAlexey Budankov
39f24c1d75SAlexey Budankov return 0;
40f24c1d75SAlexey Budankov }
41f24c1d75SAlexey Budankov
zstd_fini(struct zstd_data * data)42f24c1d75SAlexey Budankov int zstd_fini(struct zstd_data *data)
43f24c1d75SAlexey Budankov {
44cb62c6f1SAlexey Budankov if (data->dstream) {
45cb62c6f1SAlexey Budankov ZSTD_freeDStream(data->dstream);
46cb62c6f1SAlexey Budankov data->dstream = NULL;
47cb62c6f1SAlexey Budankov }
48cb62c6f1SAlexey Budankov
49f24c1d75SAlexey Budankov if (data->cstream) {
50f24c1d75SAlexey Budankov ZSTD_freeCStream(data->cstream);
51f24c1d75SAlexey Budankov data->cstream = NULL;
52f24c1d75SAlexey Budankov }
53f24c1d75SAlexey Budankov
54f24c1d75SAlexey Budankov return 0;
55f24c1d75SAlexey Budankov }
56f24c1d75SAlexey Budankov
zstd_compress_stream_to_records(struct zstd_data * data,void * dst,size_t dst_size,void * src,size_t src_size,size_t max_record_size,size_t process_header (void * record,size_t increment))57f24c1d75SAlexey Budankov size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size,
58f24c1d75SAlexey Budankov void *src, size_t src_size, size_t max_record_size,
59f24c1d75SAlexey Budankov size_t process_header(void *record, size_t increment))
60f24c1d75SAlexey Budankov {
61f24c1d75SAlexey Budankov size_t ret, size, compressed = 0;
62f24c1d75SAlexey Budankov ZSTD_inBuffer input = { src, src_size, 0 };
63f24c1d75SAlexey Budankov ZSTD_outBuffer output;
64f24c1d75SAlexey Budankov void *record;
65f24c1d75SAlexey Budankov
66f24c1d75SAlexey Budankov while (input.pos < input.size) {
67f24c1d75SAlexey Budankov record = dst;
68f24c1d75SAlexey Budankov size = process_header(record, 0);
69f24c1d75SAlexey Budankov compressed += size;
70f24c1d75SAlexey Budankov dst += size;
71f24c1d75SAlexey Budankov dst_size -= size;
72f24c1d75SAlexey Budankov output = (ZSTD_outBuffer){ dst, (dst_size > max_record_size) ?
73f24c1d75SAlexey Budankov max_record_size : dst_size, 0 };
74f24c1d75SAlexey Budankov ret = ZSTD_compressStream(data->cstream, &output, &input);
75f24c1d75SAlexey Budankov ZSTD_flushStream(data->cstream, &output);
76f24c1d75SAlexey Budankov if (ZSTD_isError(ret)) {
77f24c1d75SAlexey Budankov pr_err("failed to compress %ld bytes: %s\n",
78f24c1d75SAlexey Budankov (long)src_size, ZSTD_getErrorName(ret));
79f24c1d75SAlexey Budankov memcpy(dst, src, src_size);
80f24c1d75SAlexey Budankov return src_size;
81f24c1d75SAlexey Budankov }
82f24c1d75SAlexey Budankov size = output.pos;
83f24c1d75SAlexey Budankov size = process_header(record, size);
84f24c1d75SAlexey Budankov compressed += size;
85f24c1d75SAlexey Budankov dst += size;
86f24c1d75SAlexey Budankov dst_size -= size;
87f24c1d75SAlexey Budankov }
88f24c1d75SAlexey Budankov
89f24c1d75SAlexey Budankov return compressed;
90f24c1d75SAlexey Budankov }
91cb62c6f1SAlexey Budankov
zstd_decompress_stream(struct zstd_data * data,void * src,size_t src_size,void * dst,size_t dst_size)92cb62c6f1SAlexey Budankov size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size,
93cb62c6f1SAlexey Budankov void *dst, size_t dst_size)
94cb62c6f1SAlexey Budankov {
95cb62c6f1SAlexey Budankov size_t ret;
96cb62c6f1SAlexey Budankov ZSTD_inBuffer input = { src, src_size, 0 };
97cb62c6f1SAlexey Budankov ZSTD_outBuffer output = { dst, dst_size, 0 };
98cb62c6f1SAlexey Budankov
99cb62c6f1SAlexey Budankov while (input.pos < input.size) {
100cb62c6f1SAlexey Budankov ret = ZSTD_decompressStream(data->dstream, &output, &input);
101cb62c6f1SAlexey Budankov if (ZSTD_isError(ret)) {
102*20befbb1SChris Wilson pr_err("failed to decompress (B): %zd -> %zd, dst_size %zd : %s\n",
103872c8ee8SAlexey Budankov src_size, output.size, dst_size, ZSTD_getErrorName(ret));
104cb62c6f1SAlexey Budankov break;
105cb62c6f1SAlexey Budankov }
106cb62c6f1SAlexey Budankov output.dst = dst + output.pos;
107cb62c6f1SAlexey Budankov output.size = dst_size - output.pos;
108cb62c6f1SAlexey Budankov }
109cb62c6f1SAlexey Budankov
110cb62c6f1SAlexey Budankov return output.pos;
111cb62c6f1SAlexey Budankov }
112