3
* Copyright (C) 2022, Xiaomi Inc.
5
* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* - Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* - Redistributions in binary form must reproduce the above
14
* copyright notice, this list of conditions and the following disclaimer
15
* in the documentation and/or other materials provided with the
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
* You can contact the author at :
31
* - LZ4 homepage : http://www.lz4.org
32
* - LZ4 source repository : https://github.com/lz4/lz4
39
struct LZ4_readFile_s {
48
struct LZ4_writeFile_s {
54
LZ4F_errorCode_t errCode;
57
LZ4F_errorCode_t LZ4F_readOpen(LZ4_readFile_t** lz4fRead, FILE* fp)
59
char buf[LZ4F_HEADER_SIZE_MAX];
62
LZ4F_frameInfo_t info;
64
if (fp == NULL || lz4fRead == NULL) {
65
return -LZ4F_ERROR_GENERIC;
68
*lz4fRead = (LZ4_readFile_t*)calloc(1, sizeof(LZ4_readFile_t));
69
if (*lz4fRead == NULL) {
70
return -LZ4F_ERROR_allocation_failed;
73
ret = LZ4F_createDecompressionContext(&(*lz4fRead)->dctxPtr, LZ4F_getVersion());
74
if (LZ4F_isError(ret)) {
80
consumedSize = fread(buf, 1, sizeof(buf), (*lz4fRead)->fp);
81
if (consumedSize != sizeof(buf)) {
83
return -LZ4F_ERROR_GENERIC;
86
ret = LZ4F_getFrameInfo((*lz4fRead)->dctxPtr, &info, buf, &consumedSize);
87
if (LZ4F_isError(ret)) {
88
LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
93
switch (info.blockSizeID) {
96
(*lz4fRead)->srcBufMaxSize = 64 * 1024;
99
(*lz4fRead)->srcBufMaxSize = 256 * 1024;
102
(*lz4fRead)->srcBufMaxSize = 1 * 1024 * 1024;
105
(*lz4fRead)->srcBufMaxSize = 4 * 1024 * 1024;
108
LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
110
return -LZ4F_ERROR_maxBlockSize_invalid;
113
(*lz4fRead)->srcBuf = (LZ4_byte*)malloc((*lz4fRead)->srcBufMaxSize);
114
if ((*lz4fRead)->srcBuf == NULL) {
115
LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
117
return -LZ4F_ERROR_allocation_failed;
120
(*lz4fRead)->srcBufSize = sizeof(buf) - consumedSize;
121
memcpy((*lz4fRead)->srcBuf, buf + consumedSize, (*lz4fRead)->srcBufSize);
126
size_t LZ4F_read(LZ4_readFile_t* lz4fRead, void* buf, size_t size)
128
LZ4_byte* p = (LZ4_byte*)buf;
131
if (lz4fRead == NULL || buf == NULL)
132
return -LZ4F_ERROR_GENERIC;
134
while (next < size) {
135
size_t srcsize = lz4fRead->srcBufSize - lz4fRead->srcBufNext;
136
size_t dstsize = size - next;
140
ret = fread(lz4fRead->srcBuf, 1, lz4fRead->srcBufMaxSize, lz4fRead->fp);
142
lz4fRead->srcBufSize = ret;
143
srcsize = lz4fRead->srcBufSize;
144
lz4fRead->srcBufNext = 0;
150
return -LZ4F_ERROR_GENERIC;
154
ret = LZ4F_decompress(lz4fRead->dctxPtr,
156
lz4fRead->srcBuf + lz4fRead->srcBufNext,
159
if (LZ4F_isError(ret)) {
163
lz4fRead->srcBufNext += srcsize;
171
LZ4F_errorCode_t LZ4F_readClose(LZ4_readFile_t* lz4fRead)
173
if (lz4fRead == NULL)
174
return -LZ4F_ERROR_GENERIC;
175
LZ4F_freeDecompressionContext(lz4fRead->dctxPtr);
176
free(lz4fRead->srcBuf);
178
return LZ4F_OK_NoError;
181
LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4F_preferences_t* prefsPtr)
183
LZ4_byte buf[LZ4F_HEADER_SIZE_MAX];
186
if (fp == NULL || lz4fWrite == NULL)
187
return -LZ4F_ERROR_GENERIC;
189
*lz4fWrite = (LZ4_writeFile_t*)malloc(sizeof(LZ4_writeFile_t));
190
if (*lz4fWrite == NULL) {
191
return -LZ4F_ERROR_allocation_failed;
193
if (prefsPtr != NULL) {
194
switch (prefsPtr->frameInfo.blockSizeID) {
197
(*lz4fWrite)->maxWriteSize = 64 * 1024;
200
(*lz4fWrite)->maxWriteSize = 256 * 1024;
203
(*lz4fWrite)->maxWriteSize = 1 * 1024 * 1024;
206
(*lz4fWrite)->maxWriteSize = 4 * 1024 * 1024;
210
return -LZ4F_ERROR_maxBlockSize_invalid;
213
(*lz4fWrite)->maxWriteSize = 64 * 1024;
216
(*lz4fWrite)->dstBufMaxSize = LZ4F_compressBound((*lz4fWrite)->maxWriteSize, prefsPtr);
217
(*lz4fWrite)->dstBuf = (LZ4_byte*)malloc((*lz4fWrite)->dstBufMaxSize);
218
if ((*lz4fWrite)->dstBuf == NULL) {
220
return -LZ4F_ERROR_allocation_failed;
223
ret = LZ4F_createCompressionContext(&(*lz4fWrite)->cctxPtr, LZ4F_getVersion());
224
if (LZ4F_isError(ret)) {
225
free((*lz4fWrite)->dstBuf);
230
ret = LZ4F_compressBegin((*lz4fWrite)->cctxPtr, buf, LZ4F_HEADER_SIZE_MAX, prefsPtr);
231
if (LZ4F_isError(ret)) {
232
LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr);
233
free((*lz4fWrite)->dstBuf);
238
if (ret != fwrite(buf, 1, ret, fp)) {
239
LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr);
240
free((*lz4fWrite)->dstBuf);
242
return -LZ4F_ERROR_GENERIC;
245
(*lz4fWrite)->fp = fp;
246
(*lz4fWrite)->errCode = LZ4F_OK_NoError;
247
return LZ4F_OK_NoError;
250
size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, void* buf, size_t size)
252
LZ4_byte* p = (LZ4_byte*)buf;
253
size_t remain = size;
257
if (lz4fWrite == NULL || buf == NULL)
258
return -LZ4F_ERROR_GENERIC;
260
if (remain > lz4fWrite->maxWriteSize)
261
chunk = lz4fWrite->maxWriteSize;
265
ret = LZ4F_compressUpdate(lz4fWrite->cctxPtr,
266
lz4fWrite->dstBuf, lz4fWrite->dstBufMaxSize,
269
if (LZ4F_isError(ret)) {
270
lz4fWrite->errCode = ret;
274
if(ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) {
275
lz4fWrite->errCode = -LZ4F_ERROR_GENERIC;
276
return -LZ4F_ERROR_GENERIC;
286
LZ4F_errorCode_t LZ4F_writeClose(LZ4_writeFile_t* lz4fWrite)
288
LZ4F_errorCode_t ret = LZ4F_OK_NoError;
290
if (lz4fWrite == NULL)
291
return -LZ4F_ERROR_GENERIC;
293
if (lz4fWrite->errCode == LZ4F_OK_NoError) {
294
ret = LZ4F_compressEnd(lz4fWrite->cctxPtr,
295
lz4fWrite->dstBuf, lz4fWrite->dstBufMaxSize,
297
if (LZ4F_isError(ret)) {
301
if (ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) {
302
ret = -LZ4F_ERROR_GENERIC;
307
LZ4F_freeCompressionContext(lz4fWrite->cctxPtr);
308
free(lz4fWrite->dstBuf);