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
);