mb/google/nissa/var/telith: Configure Acoustic noise mitigation
[coreboot2.git] / util / cbfstool / lz4 / lib / lz4frame.c
blobaef508d8dfc9f726688c4dba92a24c0de811f7a9
1 /*
2 LZ4 auto-framing library
3 Copyright (C) 2011-2015, Yann Collet.
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
9 met:
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
16 distribution.
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 source repository : https://github.com/Cyan4973/lz4
32 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
35 /* LZ4F is a stand-alone API to create LZ4-compressed Frames
36 * in full conformance with specification v1.5.0
37 * All related operations, including memory management, are handled by the library.
38 * */
41 /**************************************
42 * Compiler Options
43 **************************************/
44 #ifdef _MSC_VER /* Visual Studio */
45 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
46 #endif
49 /**************************************
50 * Memory routines
51 **************************************/
52 #include <stdlib.h> /* malloc, calloc, free */
53 #define ALLOCATOR(s) calloc(1,s)
54 #define FREEMEM free
55 #include <string.h> /* memset, memcpy, memmove */
56 #define MEM_INIT memset
59 /**************************************
60 * Includes
61 **************************************/
62 #include "lz4frame_static.h"
63 #include "lz4.h"
64 #include "lz4hc.h"
65 #include "xxhash.h"
68 /**************************************
69 * Basic Types
70 **************************************/
71 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
72 # include <stdint.h>
73 typedef uint8_t BYTE;
74 typedef uint16_t U16;
75 typedef uint32_t U32;
76 typedef int32_t S32;
77 typedef uint64_t U64;
78 #else
79 typedef unsigned char BYTE;
80 typedef unsigned short U16;
81 typedef unsigned int U32;
82 typedef signed int S32;
83 typedef unsigned long long U64;
84 #endif
87 /**************************************
88 * Constants
89 **************************************/
90 #define KB *(1<<10)
91 #define MB *(1<<20)
92 #define GB *(1<<30)
94 #define _1BIT 0x01
95 #define _2BITS 0x03
96 #define _3BITS 0x07
97 #define _4BITS 0x0F
98 #define _8BITS 0xFF
100 #define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
101 #define LZ4F_MAGICNUMBER 0x184D2204U
102 #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
103 #define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB
105 static const size_t minFHSize = 7;
106 static const size_t maxFHSize = 15;
107 static const size_t BHSize = 4;
108 static const int minHClevel = 3;
111 /**************************************
112 * Structures and local types
113 **************************************/
114 typedef struct LZ4F_cctx_s
116 LZ4F_preferences_t prefs;
117 U32 version;
118 U32 cStage;
119 size_t maxBlockSize;
120 size_t maxBufferSize;
121 BYTE* tmpBuff;
122 BYTE* tmpIn;
123 size_t tmpInSize;
124 U64 totalInSize;
125 XXH32_state_t xxh;
126 void* lz4CtxPtr;
127 U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
128 } LZ4F_cctx_t;
130 typedef struct LZ4F_dctx_s
132 LZ4F_frameInfo_t frameInfo;
133 U32 version;
134 U32 dStage;
135 U64 frameRemainingSize;
136 size_t maxBlockSize;
137 size_t maxBufferSize;
138 const BYTE* srcExpect;
139 BYTE* tmpIn;
140 size_t tmpInSize;
141 size_t tmpInTarget;
142 BYTE* tmpOutBuffer;
143 const BYTE* dict;
144 size_t dictSize;
145 BYTE* tmpOut;
146 size_t tmpOutSize;
147 size_t tmpOutStart;
148 XXH32_state_t xxh;
149 BYTE header[16];
150 } LZ4F_dctx_t;
153 /**************************************
154 * Error management
155 **************************************/
156 #define LZ4F_GENERATE_STRING(STRING) #STRING,
157 static const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) };
160 unsigned LZ4F_isError(LZ4F_errorCode_t code)
162 return (code > (LZ4F_errorCode_t)(-LZ4F_ERROR_maxCode));
165 const char* LZ4F_getErrorName(LZ4F_errorCode_t code)
167 static const char* codeError = "Unspecified error code";
168 if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)];
169 return codeError;
173 /**************************************
174 * Private functions
175 **************************************/
176 static size_t LZ4F_getBlockSize(unsigned blockSizeID)
178 static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB };
180 if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
181 blockSizeID -= 4;
182 if (blockSizeID > 3) return (size_t)-LZ4F_ERROR_maxBlockSize_invalid;
183 return blockSizes[blockSizeID];
187 /* unoptimized version; solves endianness & alignment issues */
188 static U32 LZ4F_readLE32 (const BYTE* srcPtr)
190 U32 value32 = srcPtr[0];
191 value32 += (srcPtr[1]<<8);
192 value32 += (srcPtr[2]<<16);
193 value32 += ((U32)srcPtr[3])<<24;
194 return value32;
197 static void LZ4F_writeLE32 (BYTE* dstPtr, U32 value32)
199 dstPtr[0] = (BYTE)value32;
200 dstPtr[1] = (BYTE)(value32 >> 8);
201 dstPtr[2] = (BYTE)(value32 >> 16);
202 dstPtr[3] = (BYTE)(value32 >> 24);
205 static U64 LZ4F_readLE64 (const BYTE* srcPtr)
207 U64 value64 = srcPtr[0];
208 value64 += ((U64)srcPtr[1]<<8);
209 value64 += ((U64)srcPtr[2]<<16);
210 value64 += ((U64)srcPtr[3]<<24);
211 value64 += ((U64)srcPtr[4]<<32);
212 value64 += ((U64)srcPtr[5]<<40);
213 value64 += ((U64)srcPtr[6]<<48);
214 value64 += ((U64)srcPtr[7]<<56);
215 return value64;
218 static void LZ4F_writeLE64 (BYTE* dstPtr, U64 value64)
220 dstPtr[0] = (BYTE)value64;
221 dstPtr[1] = (BYTE)(value64 >> 8);
222 dstPtr[2] = (BYTE)(value64 >> 16);
223 dstPtr[3] = (BYTE)(value64 >> 24);
224 dstPtr[4] = (BYTE)(value64 >> 32);
225 dstPtr[5] = (BYTE)(value64 >> 40);
226 dstPtr[6] = (BYTE)(value64 >> 48);
227 dstPtr[7] = (BYTE)(value64 >> 56);
231 static BYTE LZ4F_headerChecksum (const void* header, size_t length)
233 U32 xxh = XXH32(header, length, 0);
234 return (BYTE)(xxh >> 8);
238 /**************************************
239 * Simple compression functions
240 **************************************/
241 static LZ4F_blockSizeID_t LZ4F_optimalBSID(const LZ4F_blockSizeID_t requestedBSID, const size_t srcSize)
243 LZ4F_blockSizeID_t proposedBSID = LZ4F_max64KB;
244 size_t maxBlockSize = 64 KB;
245 while (requestedBSID > proposedBSID)
247 if (srcSize <= maxBlockSize)
248 return proposedBSID;
249 proposedBSID = (LZ4F_blockSizeID_t)((int)proposedBSID + 1);
250 maxBlockSize <<= 2;
252 return requestedBSID;
256 size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
258 LZ4F_preferences_t prefs;
259 size_t headerSize;
260 size_t streamSize;
262 if (preferencesPtr!=NULL) prefs = *preferencesPtr;
263 else memset(&prefs, 0, sizeof(prefs));
265 prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);
266 prefs.autoFlush = 1;
268 headerSize = maxFHSize; /* header size, including magic number and frame content size*/
269 streamSize = LZ4F_compressBound(srcSize, &prefs);
271 return headerSize + streamSize;
275 /* LZ4F_compressFrame()
276 * Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.5.0, in a single step.
277 * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
278 * You can get the minimum value of dstMaxSize by using LZ4F_compressFrameBound()
279 * If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode)
280 * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will then be set to default.
281 * The result of the function is the number of bytes written into dstBuffer.
282 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
284 size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
286 LZ4F_cctx_t cctxI;
287 LZ4_stream_t lz4ctx;
288 LZ4F_preferences_t prefs;
289 LZ4F_compressOptions_t options;
290 LZ4F_errorCode_t errorCode;
291 BYTE* const dstStart = (BYTE*) dstBuffer;
292 BYTE* dstPtr = dstStart;
293 BYTE* const dstEnd = dstStart + dstMaxSize;
295 memset(&cctxI, 0, sizeof(cctxI)); /* works because no allocation */
296 memset(&options, 0, sizeof(options));
298 cctxI.version = LZ4F_VERSION;
299 cctxI.maxBufferSize = 5 MB; /* mess with real buffer size to prevent allocation; works because autoflush==1 & stableSrc==1 */
301 if (preferencesPtr!=NULL)
302 prefs = *preferencesPtr;
303 else
304 memset(&prefs, 0, sizeof(prefs));
305 if (prefs.frameInfo.contentSize != 0)
306 prefs.frameInfo.contentSize = (U64)srcSize; /* auto-correct content size if selected (!=0) */
308 if (prefs.compressionLevel < (int)minHClevel)
310 cctxI.lz4CtxPtr = &lz4ctx;
311 cctxI.lz4CtxLevel = 1;
314 prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);
315 prefs.autoFlush = 1;
316 if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID))
317 prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* no need for linked blocks */
319 options.stableSrc = 1;
321 if (dstMaxSize < LZ4F_compressFrameBound(srcSize, &prefs))
322 return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
324 errorCode = LZ4F_compressBegin(&cctxI, dstBuffer, dstMaxSize, &prefs); /* write header */
325 if (LZ4F_isError(errorCode)) return errorCode;
326 dstPtr += errorCode; /* header size */
328 errorCode = LZ4F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);
329 if (LZ4F_isError(errorCode)) return errorCode;
330 dstPtr += errorCode;
332 errorCode = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */
333 if (LZ4F_isError(errorCode)) return errorCode;
334 dstPtr += errorCode;
336 if (prefs.compressionLevel >= (int)minHClevel) /* no allocation necessary with lz4 fast */
337 FREEMEM(cctxI.lz4CtxPtr);
339 return (dstPtr - dstStart);
343 /***********************************
344 * Advanced compression functions
345 ***********************************/
347 /* LZ4F_createCompressionContext() :
348 * The first thing to do is to create a compressionContext object, which will be used in all compression operations.
349 * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
350 * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries.
351 * The function will provide a pointer to an allocated LZ4F_compressionContext_t object.
352 * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
353 * Object can release its memory using LZ4F_freeCompressionContext();
355 LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
357 LZ4F_cctx_t* cctxPtr;
359 cctxPtr = (LZ4F_cctx_t*)ALLOCATOR(sizeof(LZ4F_cctx_t));
360 if (cctxPtr==NULL) return (LZ4F_errorCode_t)(-LZ4F_ERROR_allocation_failed);
362 cctxPtr->version = version;
363 cctxPtr->cStage = 0; /* Next stage : write header */
365 *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr;
367 return LZ4F_OK_NoError;
371 LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
373 LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
375 if (cctxPtr != NULL) /* null pointers can be safely provided to this function, like free() */
377 FREEMEM(cctxPtr->lz4CtxPtr);
378 FREEMEM(cctxPtr->tmpBuff);
379 FREEMEM(LZ4F_compressionContext);
382 return LZ4F_OK_NoError;
386 /* LZ4F_compressBegin() :
387 * will write the frame header into dstBuffer.
388 * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is LZ4F_MAXHEADERFRAME_SIZE bytes.
389 * The result of the function is the number of bytes written into dstBuffer for the header
390 * or an error code (can be tested using LZ4F_isError())
392 size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr)
394 LZ4F_preferences_t prefNull;
395 LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
396 BYTE* const dstStart = (BYTE*)dstBuffer;
397 BYTE* dstPtr = dstStart;
398 BYTE* headerStart;
399 size_t requiredBuffSize;
401 if (dstMaxSize < maxFHSize) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
402 if (cctxPtr->cStage != 0) return (size_t)-LZ4F_ERROR_GENERIC;
403 memset(&prefNull, 0, sizeof(prefNull));
404 if (preferencesPtr == NULL) preferencesPtr = &prefNull;
405 cctxPtr->prefs = *preferencesPtr;
407 /* ctx Management */
409 U32 tableID = (cctxPtr->prefs.compressionLevel < minHClevel) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */
410 if (cctxPtr->lz4CtxLevel < tableID)
412 FREEMEM(cctxPtr->lz4CtxPtr);
413 if (cctxPtr->prefs.compressionLevel < minHClevel)
414 cctxPtr->lz4CtxPtr = (void*)LZ4_createStream();
415 else
416 cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC();
417 cctxPtr->lz4CtxLevel = tableID;
421 /* Buffer Management */
422 if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
423 cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);
425 requiredBuffSize = cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) * 128 KB);
426 if (preferencesPtr->autoFlush)
427 requiredBuffSize = (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) * 64 KB; /* just needs dict */
429 if (cctxPtr->maxBufferSize < requiredBuffSize)
431 cctxPtr->maxBufferSize = requiredBuffSize;
432 FREEMEM(cctxPtr->tmpBuff);
433 cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(requiredBuffSize);
434 if (cctxPtr->tmpBuff == NULL) return (size_t)-LZ4F_ERROR_allocation_failed;
436 cctxPtr->tmpIn = cctxPtr->tmpBuff;
437 cctxPtr->tmpInSize = 0;
438 XXH32_reset(&(cctxPtr->xxh), 0);
439 if (cctxPtr->prefs.compressionLevel < minHClevel)
440 LZ4_resetStream((LZ4_stream_t*)(cctxPtr->lz4CtxPtr));
441 else
442 LZ4_resetStreamHC((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), cctxPtr->prefs.compressionLevel);
444 /* Magic Number */
445 LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER);
446 dstPtr += 4;
447 headerStart = dstPtr;
449 /* FLG Byte */
450 *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */
451 + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5) /* Block mode */
452 + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2) /* Frame checksum */
453 + ((cctxPtr->prefs.frameInfo.contentSize > 0) << 3)); /* Frame content size */
454 /* BD Byte */
455 *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
456 /* Optional Frame content size field */
457 if (cctxPtr->prefs.frameInfo.contentSize)
459 LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize);
460 dstPtr += 8;
461 cctxPtr->totalInSize = 0;
463 /* CRC Byte */
464 *dstPtr = LZ4F_headerChecksum(headerStart, dstPtr - headerStart);
465 dstPtr++;
467 cctxPtr->cStage = 1; /* header written, now request input data block */
469 return (dstPtr - dstStart);
473 /* LZ4F_compressBound() : gives the size of Dst buffer given a srcSize to handle worst case situations.
474 * The LZ4F_frameInfo_t structure is optional :
475 * you can provide NULL as argument, preferences will then be set to cover worst case situations.
476 * */
477 size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
479 LZ4F_preferences_t prefsNull;
480 memset(&prefsNull, 0, sizeof(prefsNull));
481 prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; /* worst case */
483 const LZ4F_preferences_t* prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
484 LZ4F_blockSizeID_t bid = prefsPtr->frameInfo.blockSizeID;
485 size_t blockSize = LZ4F_getBlockSize(bid);
486 unsigned nbBlocks = (unsigned)(srcSize / blockSize) + 1;
487 size_t lastBlockSize = prefsPtr->autoFlush ? srcSize % blockSize : blockSize;
488 size_t blockInfo = 4; /* default, without block CRC option */
489 size_t frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);
491 return (blockInfo * nbBlocks) + (blockSize * (nbBlocks-1)) + lastBlockSize + frameEnd;;
496 typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level);
498 static size_t LZ4F_compressBlock(void* dst, const void* src, size_t srcSize, compressFunc_t compress, void* lz4ctx, int level)
500 /* compress one block */
501 BYTE* cSizePtr = (BYTE*)dst;
502 U32 cSize;
503 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1), level);
504 LZ4F_writeLE32(cSizePtr, cSize);
505 if (cSize == 0) /* compression failed */
507 cSize = (U32)srcSize;
508 LZ4F_writeLE32(cSizePtr, cSize + LZ4F_BLOCKUNCOMPRESSED_FLAG);
509 memcpy(cSizePtr+4, src, srcSize);
511 return cSize + 4;
515 static int LZ4F_localLZ4_compress_limitedOutput_withState(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)
517 (void) level;
518 return LZ4_compress_limitedOutput_withState(ctx, src, dst, srcSize, dstSize);
521 static int LZ4F_localLZ4_compress_limitedOutput_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)
523 (void) level;
524 return LZ4_compress_limitedOutput_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstSize);
527 static int LZ4F_localLZ4_compressHC_limitedOutput_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)
529 (void) level;
530 return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstSize);
533 static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level)
535 if (level < minHClevel)
537 if (blockMode == LZ4F_blockIndependent) return LZ4F_localLZ4_compress_limitedOutput_withState;
538 return LZ4F_localLZ4_compress_limitedOutput_continue;
540 if (blockMode == LZ4F_blockIndependent) return LZ4_compress_HC_extStateHC;
541 return LZ4F_localLZ4_compressHC_limitedOutput_continue;
544 static int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr)
546 if (cctxPtr->prefs.compressionLevel < minHClevel)
547 return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
548 return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
551 typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
553 /* LZ4F_compressUpdate()
554 * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
555 * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
556 * If this condition is not respected, LZ4F_compress() will fail (result is an errorCode)
557 * You can get the minimum value of dstMaxSize by using LZ4F_compressBound()
558 * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
559 * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.
560 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
562 size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr)
564 LZ4F_compressOptions_t cOptionsNull;
565 LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
566 size_t blockSize = cctxPtr->maxBlockSize;
567 const BYTE* srcPtr = (const BYTE*)srcBuffer;
568 const BYTE* const srcEnd = srcPtr + srcSize;
569 BYTE* const dstStart = (BYTE*)dstBuffer;
570 BYTE* dstPtr = dstStart;
571 LZ4F_lastBlockStatus lastBlockCompressed = notDone;
572 compressFunc_t compress;
575 if (cctxPtr->cStage != 1) return (size_t)-LZ4F_ERROR_GENERIC;
576 if (dstMaxSize < LZ4F_compressBound(srcSize, &(cctxPtr->prefs))) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
577 memset(&cOptionsNull, 0, sizeof(cOptionsNull));
578 if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
580 /* select compression function */
581 compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
583 /* complete tmp buffer */
584 if (cctxPtr->tmpInSize > 0) /* some data already within tmp buffer */
586 size_t sizeToCopy = blockSize - cctxPtr->tmpInSize;
587 if (sizeToCopy > srcSize)
589 /* add src to tmpIn buffer */
590 memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
591 srcPtr = srcEnd;
592 cctxPtr->tmpInSize += srcSize;
593 /* still needs some CRC */
595 else
597 /* complete tmpIn block and then compress it */
598 lastBlockCompressed = fromTmpBuffer;
599 memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
600 srcPtr += sizeToCopy;
602 dstPtr += LZ4F_compressBlock(dstPtr, cctxPtr->tmpIn, blockSize, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
604 if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
605 cctxPtr->tmpInSize = 0;
609 while ((size_t)(srcEnd - srcPtr) >= blockSize)
611 /* compress full block */
612 lastBlockCompressed = fromSrcBuffer;
613 dstPtr += LZ4F_compressBlock(dstPtr, srcPtr, blockSize, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
614 srcPtr += blockSize;
617 if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd))
619 /* compress remaining input < blockSize */
620 lastBlockCompressed = fromSrcBuffer;
621 dstPtr += LZ4F_compressBlock(dstPtr, srcPtr, srcEnd - srcPtr, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
622 srcPtr = srcEnd;
625 /* preserve dictionary if necessary */
626 if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer))
628 if (compressOptionsPtr->stableSrc)
630 cctxPtr->tmpIn = cctxPtr->tmpBuff;
632 else
634 int realDictSize = LZ4F_localSaveDict(cctxPtr);
635 if (realDictSize==0) return (size_t)-LZ4F_ERROR_GENERIC;
636 cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
640 /* keep tmpIn within limits */
641 if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily LZ4F_blockLinked && lastBlockCompressed==fromTmpBuffer */
642 && !(cctxPtr->prefs.autoFlush))
644 int realDictSize = LZ4F_localSaveDict(cctxPtr);
645 cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
648 /* some input data left, necessarily < blockSize */
649 if (srcPtr < srcEnd)
651 /* fill tmp buffer */
652 size_t sizeToCopy = srcEnd - srcPtr;
653 memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
654 cctxPtr->tmpInSize = sizeToCopy;
657 if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
658 XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
660 cctxPtr->totalInSize += srcSize;
661 return dstPtr - dstStart;
665 /* LZ4F_flush()
666 * Should you need to create compressed data immediately, without waiting for a block to be filled,
667 * you can call LZ4_flush(), which will immediately compress any remaining data stored within compressionContext.
668 * The result of the function is the number of bytes written into dstBuffer
669 * (it can be zero, this means there was no data left within compressionContext)
670 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
671 * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
673 size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
675 LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
676 BYTE* const dstStart = (BYTE*)dstBuffer;
677 BYTE* dstPtr = dstStart;
678 compressFunc_t compress;
681 if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
682 if (cctxPtr->cStage != 1) return (size_t)-LZ4F_ERROR_GENERIC;
683 if (dstMaxSize < (cctxPtr->tmpInSize + 8)) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall; /* +8 : block header(4) + block checksum(4) */
684 (void)compressOptionsPtr; /* not yet useful */
686 /* select compression function */
687 compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
689 /* compress tmp buffer */
690 dstPtr += LZ4F_compressBlock(dstPtr, cctxPtr->tmpIn, cctxPtr->tmpInSize, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
691 if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += cctxPtr->tmpInSize;
692 cctxPtr->tmpInSize = 0;
694 /* keep tmpIn within limits */
695 if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) /* necessarily LZ4F_blockLinked */
697 int realDictSize = LZ4F_localSaveDict(cctxPtr);
698 cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
701 return dstPtr - dstStart;
705 /* LZ4F_compressEnd()
706 * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
707 * It will flush whatever data remained within compressionContext (like LZ4_flush())
708 * but also properly finalize the frame, with an endMark and a checksum.
709 * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
710 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
711 * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
712 * compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.
714 size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
716 LZ4F_cctx_t* cctxPtr = (LZ4F_cctx_t*)compressionContext;
717 BYTE* const dstStart = (BYTE*)dstBuffer;
718 BYTE* dstPtr = dstStart;
719 size_t errorCode;
721 errorCode = LZ4F_flush(compressionContext, dstBuffer, dstMaxSize, compressOptionsPtr);
722 if (LZ4F_isError(errorCode)) return errorCode;
723 dstPtr += errorCode;
725 LZ4F_writeLE32(dstPtr, 0);
726 dstPtr+=4; /* endMark */
728 if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
730 U32 xxh = XXH32_digest(&(cctxPtr->xxh));
731 LZ4F_writeLE32(dstPtr, xxh);
732 dstPtr+=4; /* content Checksum */
735 cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
737 if (cctxPtr->prefs.frameInfo.contentSize)
739 if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)
740 return (size_t)-LZ4F_ERROR_frameSize_wrong;
743 return dstPtr - dstStart;
747 /**********************************
748 * Decompression functions
749 **********************************/
751 /* Resource management */
753 /* LZ4F_createDecompressionContext() :
754 * The first thing to do is to create a decompressionContext object, which will be used in all decompression operations.
755 * This is achieved using LZ4F_createDecompressionContext().
756 * The function will provide a pointer to a fully allocated and initialized LZ4F_decompressionContext object.
757 * If the result LZ4F_errorCode_t is not zero, there was an error during context creation.
758 * Object can release its memory using LZ4F_freeDecompressionContext();
760 LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_decompressionContext_t* LZ4F_decompressionContextPtr, unsigned versionNumber)
762 LZ4F_dctx_t* dctxPtr;
764 dctxPtr = (LZ4F_dctx_t*)ALLOCATOR(sizeof(LZ4F_dctx_t));
765 if (dctxPtr==NULL) return (LZ4F_errorCode_t)-LZ4F_ERROR_GENERIC;
767 dctxPtr->version = versionNumber;
768 *LZ4F_decompressionContextPtr = (LZ4F_decompressionContext_t)dctxPtr;
769 return LZ4F_OK_NoError;
772 LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t LZ4F_decompressionContext)
774 LZ4F_errorCode_t result = LZ4F_OK_NoError;
775 LZ4F_dctx_t* dctxPtr = (LZ4F_dctx_t*)LZ4F_decompressionContext;
776 if (dctxPtr != NULL) /* can accept NULL input, like free() */
778 result = (LZ4F_errorCode_t)dctxPtr->dStage;
779 FREEMEM(dctxPtr->tmpIn);
780 FREEMEM(dctxPtr->tmpOutBuffer);
781 FREEMEM(dctxPtr);
783 return result;
787 /* ******************************************************************** */
788 /* ********************* Decompression ******************************** */
789 /* ******************************************************************** */
791 typedef enum { dstage_getHeader=0, dstage_storeHeader,
792 dstage_getCBlockSize, dstage_storeCBlockSize,
793 dstage_copyDirect,
794 dstage_getCBlock, dstage_storeCBlock,
795 dstage_decodeCBlock, dstage_decodeCBlock_intoDst,
796 dstage_decodeCBlock_intoTmp, dstage_flushOut,
797 dstage_getSuffix, dstage_storeSuffix,
798 dstage_getSFrameSize, dstage_storeSFrameSize,
799 dstage_skipSkippable
800 } dStage_t;
803 /* LZ4F_decodeHeader
804 return : nb Bytes read from srcVoidPtr (necessarily <= srcSize)
805 or an error code (testable with LZ4F_isError())
806 output : set internal values of dctx, such as
807 dctxPtr->frameInfo and dctxPtr->dStage.
808 input : srcVoidPtr points at the **beginning of the frame**
810 static size_t LZ4F_decodeHeader(LZ4F_dctx_t* dctxPtr, const void* srcVoidPtr, size_t srcSize)
812 BYTE FLG, BD, HC;
813 unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, blockSizeID;
814 size_t bufferNeeded;
815 size_t frameHeaderSize;
816 const BYTE* srcPtr = (const BYTE*)srcVoidPtr;
818 /* need to decode header to get frameInfo */
819 if (srcSize < minFHSize) return (size_t)-LZ4F_ERROR_frameHeader_incomplete; /* minimal frame header size */
820 memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));
822 /* special case : skippable frames */
823 if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
825 dctxPtr->frameInfo.frameType = LZ4F_skippableFrame;
826 if (srcVoidPtr == (void*)(dctxPtr->header))
828 dctxPtr->tmpInSize = srcSize;
829 dctxPtr->tmpInTarget = 8;
830 dctxPtr->dStage = dstage_storeSFrameSize;
831 return srcSize;
833 else
835 dctxPtr->dStage = dstage_getSFrameSize;
836 return 4;
840 /* control magic number */
841 if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) return (size_t)-LZ4F_ERROR_frameType_unknown;
842 dctxPtr->frameInfo.frameType = LZ4F_frame;
844 /* Flags */
845 FLG = srcPtr[4];
846 version = (FLG>>6) & _2BITS;
847 blockMode = (FLG>>5) & _1BIT;
848 blockChecksumFlag = (FLG>>4) & _1BIT;
849 contentSizeFlag = (FLG>>3) & _1BIT;
850 contentChecksumFlag = (FLG>>2) & _1BIT;
852 /* Frame Header Size */
853 frameHeaderSize = contentSizeFlag ? maxFHSize : minFHSize;
855 if (srcSize < frameHeaderSize)
857 /* not enough input to fully decode frame header */
858 if (srcPtr != dctxPtr->header)
859 memcpy(dctxPtr->header, srcPtr, srcSize);
860 dctxPtr->tmpInSize = srcSize;
861 dctxPtr->tmpInTarget = frameHeaderSize;
862 dctxPtr->dStage = dstage_storeHeader;
863 return srcSize;
866 BD = srcPtr[5];
867 blockSizeID = (BD>>4) & _3BITS;
869 /* validate */
870 if (version != 1) return (size_t)-LZ4F_ERROR_headerVersion_wrong; /* Version Number, only supported value */
871 if (blockChecksumFlag != 0) return (size_t)-LZ4F_ERROR_blockChecksum_unsupported; /* Not supported for the time being */
872 if (((FLG>>0)&_2BITS) != 0) return (size_t)-LZ4F_ERROR_reservedFlag_set; /* Reserved bits */
873 if (((BD>>7)&_1BIT) != 0) return (size_t)-LZ4F_ERROR_reservedFlag_set; /* Reserved bit */
874 if (blockSizeID < 4) return (size_t)-LZ4F_ERROR_maxBlockSize_invalid; /* 4-7 only supported values for the time being */
875 if (((BD>>0)&_4BITS) != 0) return (size_t)-LZ4F_ERROR_reservedFlag_set; /* Reserved bits */
877 /* check */
878 HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
879 if (HC != srcPtr[frameHeaderSize-1]) return (size_t)-LZ4F_ERROR_headerChecksum_invalid; /* Bad header checksum error */
881 /* save */
882 dctxPtr->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode;
883 dctxPtr->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag;
884 dctxPtr->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID;
885 dctxPtr->maxBlockSize = LZ4F_getBlockSize(blockSizeID);
886 if (contentSizeFlag)
887 dctxPtr->frameRemainingSize = dctxPtr->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6);
889 /* init */
890 if (contentChecksumFlag) XXH32_reset(&(dctxPtr->xxh), 0);
892 /* alloc */
893 bufferNeeded = dctxPtr->maxBlockSize + ((dctxPtr->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB);
894 if (bufferNeeded > dctxPtr->maxBufferSize) /* tmp buffers too small */
896 FREEMEM(dctxPtr->tmpIn);
897 FREEMEM(dctxPtr->tmpOutBuffer);
898 dctxPtr->maxBufferSize = bufferNeeded;
899 dctxPtr->tmpIn = (BYTE*)ALLOCATOR(dctxPtr->maxBlockSize);
900 if (dctxPtr->tmpIn == NULL) return (size_t)-LZ4F_ERROR_GENERIC;
901 dctxPtr->tmpOutBuffer= (BYTE*)ALLOCATOR(dctxPtr->maxBufferSize);
902 if (dctxPtr->tmpOutBuffer== NULL) return (size_t)-LZ4F_ERROR_GENERIC;
904 dctxPtr->tmpInSize = 0;
905 dctxPtr->tmpInTarget = 0;
906 dctxPtr->dict = dctxPtr->tmpOutBuffer;
907 dctxPtr->dictSize = 0;
908 dctxPtr->tmpOut = dctxPtr->tmpOutBuffer;
909 dctxPtr->tmpOutStart = 0;
910 dctxPtr->tmpOutSize = 0;
912 dctxPtr->dStage = dstage_getCBlockSize;
914 return frameHeaderSize;
918 /* LZ4F_getFrameInfo()
919 * This function decodes frame header information, such as blockSize.
920 * It is optional : you could start by calling directly LZ4F_decompress() instead.
921 * The objective is to extract header information without starting decompression, typically for allocation purposes.
922 * LZ4F_getFrameInfo() can also be used *after* starting decompression, on a valid LZ4F_decompressionContext_t.
923 * The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
924 * You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)
925 * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress,
926 * or an error code which can be tested using LZ4F_isError().
928 LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t dCtx, LZ4F_frameInfo_t* frameInfoPtr,
929 const void* srcBuffer, size_t* srcSizePtr)
931 LZ4F_dctx_t* dctxPtr = (LZ4F_dctx_t*)dCtx;
933 if (dctxPtr->dStage > dstage_storeHeader) /* note : requires dstage_* header related to be at beginning of enum */
935 size_t o=0, i=0;
936 /* frameInfo already decoded */
937 *srcSizePtr = 0;
938 *frameInfoPtr = dctxPtr->frameInfo;
939 return LZ4F_decompress(dCtx, NULL, &o, NULL, &i, NULL);
941 else
943 size_t o=0;
944 size_t nextSrcSize = LZ4F_decompress(dCtx, NULL, &o, srcBuffer, srcSizePtr, NULL);
945 if (dctxPtr->dStage <= dstage_storeHeader) /* note : requires dstage_* header related to be at beginning of enum */
946 return (size_t)-LZ4F_ERROR_frameHeader_incomplete;
947 *frameInfoPtr = dctxPtr->frameInfo;
948 return nextSrcSize;
953 /* trivial redirector, for common prototype */
954 static int LZ4F_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize)
956 (void)dictStart; (void)dictSize;
957 return LZ4_decompress_safe (source, dest, compressedSize, maxDecompressedSize);
961 static void LZ4F_updateDict(LZ4F_dctx_t* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
963 if (dctxPtr->dictSize==0)
964 dctxPtr->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
966 if (dctxPtr->dict + dctxPtr->dictSize == dstPtr) /* dictionary continuity */
968 dctxPtr->dictSize += dstSize;
969 return;
972 if (dstPtr - dstPtr0 + dstSize >= 64 KB) /* dstBuffer large enough to become dictionary */
974 dctxPtr->dict = (const BYTE*)dstPtr0;
975 dctxPtr->dictSize = dstPtr - dstPtr0 + dstSize;
976 return;
979 if ((withinTmp) && (dctxPtr->dict == dctxPtr->tmpOutBuffer))
981 /* assumption : dctxPtr->dict + dctxPtr->dictSize == dctxPtr->tmpOut + dctxPtr->tmpOutStart */
982 dctxPtr->dictSize += dstSize;
983 return;
986 if (withinTmp) /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */
988 size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;
989 size_t copySize = 64 KB - dctxPtr->tmpOutSize;
990 const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;
991 if (dctxPtr->tmpOutSize > 64 KB) copySize = 0;
992 if (copySize > preserveSize) copySize = preserveSize;
994 memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
996 dctxPtr->dict = dctxPtr->tmpOutBuffer;
997 dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart + dstSize;
998 return;
1001 if (dctxPtr->dict == dctxPtr->tmpOutBuffer) /* copy dst into tmp to complete dict */
1003 if (dctxPtr->dictSize + dstSize > dctxPtr->maxBufferSize) /* tmp buffer not large enough */
1005 size_t preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
1006 memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);
1007 dctxPtr->dictSize = preserveSize;
1009 memcpy(dctxPtr->tmpOutBuffer + dctxPtr->dictSize, dstPtr, dstSize);
1010 dctxPtr->dictSize += dstSize;
1011 return;
1014 /* join dict & dest into tmp */
1016 size_t preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
1017 if (preserveSize > dctxPtr->dictSize) preserveSize = dctxPtr->dictSize;
1018 memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);
1019 memcpy(dctxPtr->tmpOutBuffer + preserveSize, dstPtr, dstSize);
1020 dctxPtr->dict = dctxPtr->tmpOutBuffer;
1021 dctxPtr->dictSize = preserveSize + dstSize;
1027 /* LZ4F_decompress()
1028 * Call this function repetitively to regenerate data compressed within srcBuffer.
1029 * The function will attempt to decode *srcSizePtr from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
1031 * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
1033 * The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
1034 * If the number of bytes read is < number of bytes provided, then the decompression operation is not complete.
1035 * You will have to call it again, continuing from where it stopped.
1037 * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
1038 * Basically, it's the size of the current (or remaining) compressed block + header of next block.
1039 * Respecting the hint provides some boost to performance, since it allows less buffer shuffling.
1040 * Note that this is just a hint, you can always provide any srcSize you want.
1041 * When a frame is fully decoded, the function result will be 0.
1042 * If decompression failed, function result is an error code which can be tested using LZ4F_isError().
1044 size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
1045 void* dstBuffer, size_t* dstSizePtr,
1046 const void* srcBuffer, size_t* srcSizePtr,
1047 const LZ4F_decompressOptions_t* decompressOptionsPtr)
1049 LZ4F_dctx_t* dctxPtr = (LZ4F_dctx_t*)decompressionContext;
1050 LZ4F_decompressOptions_t optionsNull;
1051 const BYTE* const srcStart = (const BYTE*)srcBuffer;
1052 const BYTE* const srcEnd = srcStart + *srcSizePtr;
1053 const BYTE* srcPtr = srcStart;
1054 BYTE* const dstStart = (BYTE*)dstBuffer;
1055 BYTE* const dstEnd = dstStart + *dstSizePtr;
1056 BYTE* dstPtr = dstStart;
1057 const BYTE* selectedIn = NULL;
1058 unsigned doAnotherStage = 1;
1059 size_t nextSrcSizeHint = 1;
1062 memset(&optionsNull, 0, sizeof(optionsNull));
1063 if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
1064 *srcSizePtr = 0;
1065 *dstSizePtr = 0;
1067 /* expect to continue decoding src buffer where it left previously */
1068 if (dctxPtr->srcExpect != NULL)
1070 if (srcStart != dctxPtr->srcExpect) return (size_t)-LZ4F_ERROR_srcPtr_wrong;
1073 /* programmed as a state machine */
1075 while (doAnotherStage)
1078 switch(dctxPtr->dStage)
1081 case dstage_getHeader:
1083 if ((size_t)(srcEnd-srcPtr) >= maxFHSize) /* enough to decode - shortcut */
1085 LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, srcPtr, srcEnd-srcPtr);
1086 if (LZ4F_isError(errorCode)) return errorCode;
1087 srcPtr += errorCode;
1088 break;
1090 dctxPtr->tmpInSize = 0;
1091 dctxPtr->tmpInTarget = minFHSize; /* minimum to attempt decode */
1092 dctxPtr->dStage = dstage_storeHeader;
1094 /* Falls through. */
1095 case dstage_storeHeader:
1097 size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
1098 if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1099 memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1100 dctxPtr->tmpInSize += sizeToCopy;
1101 srcPtr += sizeToCopy;
1102 if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget)
1104 nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
1105 doAnotherStage = 0; /* not enough src data, ask for some more */
1106 break;
1109 LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, dctxPtr->header, dctxPtr->tmpInTarget);
1110 if (LZ4F_isError(errorCode)) return errorCode;
1112 break;
1115 case dstage_getCBlockSize:
1117 if ((size_t)(srcEnd - srcPtr) >= BHSize)
1119 selectedIn = srcPtr;
1120 srcPtr += BHSize;
1122 else
1124 /* not enough input to read cBlockSize field */
1125 dctxPtr->tmpInSize = 0;
1126 dctxPtr->dStage = dstage_storeCBlockSize;
1130 if (dctxPtr->dStage == dstage_storeCBlockSize)
1131 case dstage_storeCBlockSize:
1133 size_t sizeToCopy = BHSize - dctxPtr->tmpInSize;
1134 if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1135 memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1136 srcPtr += sizeToCopy;
1137 dctxPtr->tmpInSize += sizeToCopy;
1138 if (dctxPtr->tmpInSize < BHSize) /* not enough input to get full cBlockSize; wait for more */
1140 nextSrcSizeHint = BHSize - dctxPtr->tmpInSize;
1141 doAnotherStage = 0;
1142 break;
1144 selectedIn = dctxPtr->tmpIn;
1147 /* case dstage_decodeCBlockSize: */ /* no more direct access, to prevent scan-build warning */
1149 size_t nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
1150 if (nextCBlockSize==0) /* frameEnd signal, no more CBlock */
1152 dctxPtr->dStage = dstage_getSuffix;
1153 break;
1155 if (nextCBlockSize > dctxPtr->maxBlockSize) return (size_t)-LZ4F_ERROR_GENERIC; /* invalid cBlockSize */
1156 dctxPtr->tmpInTarget = nextCBlockSize;
1157 if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG)
1159 dctxPtr->dStage = dstage_copyDirect;
1160 break;
1162 dctxPtr->dStage = dstage_getCBlock;
1163 if (dstPtr==dstEnd)
1165 nextSrcSizeHint = nextCBlockSize + BHSize;
1166 doAnotherStage = 0;
1168 break;
1171 case dstage_copyDirect: /* uncompressed block */
1173 size_t sizeToCopy = dctxPtr->tmpInTarget;
1174 if ((size_t)(srcEnd-srcPtr) < sizeToCopy) sizeToCopy = srcEnd - srcPtr; /* not enough input to read full block */
1175 if ((size_t)(dstEnd-dstPtr) < sizeToCopy) sizeToCopy = dstEnd - dstPtr;
1176 memcpy(dstPtr, srcPtr, sizeToCopy);
1177 if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), srcPtr, sizeToCopy);
1178 if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= sizeToCopy;
1180 /* dictionary management */
1181 if (dctxPtr->frameInfo.blockMode==LZ4F_blockLinked)
1182 LZ4F_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 0);
1184 srcPtr += sizeToCopy;
1185 dstPtr += sizeToCopy;
1186 if (sizeToCopy == dctxPtr->tmpInTarget) /* all copied */
1188 dctxPtr->dStage = dstage_getCBlockSize;
1189 break;
1191 dctxPtr->tmpInTarget -= sizeToCopy; /* still need to copy more */
1192 nextSrcSizeHint = dctxPtr->tmpInTarget + BHSize;
1193 doAnotherStage = 0;
1194 break;
1197 case dstage_getCBlock: /* entry from dstage_decodeCBlockSize */
1199 if ((size_t)(srcEnd-srcPtr) < dctxPtr->tmpInTarget)
1201 dctxPtr->tmpInSize = 0;
1202 dctxPtr->dStage = dstage_storeCBlock;
1203 break;
1205 selectedIn = srcPtr;
1206 srcPtr += dctxPtr->tmpInTarget;
1207 dctxPtr->dStage = dstage_decodeCBlock;
1208 break;
1211 case dstage_storeCBlock:
1213 size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
1214 if (sizeToCopy > (size_t)(srcEnd-srcPtr)) sizeToCopy = srcEnd-srcPtr;
1215 memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1216 dctxPtr->tmpInSize += sizeToCopy;
1217 srcPtr += sizeToCopy;
1218 if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) /* need more input */
1220 nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize;
1221 doAnotherStage=0;
1222 break;
1224 selectedIn = dctxPtr->tmpIn;
1225 dctxPtr->dStage = dstage_decodeCBlock;
1226 break;
1229 case dstage_decodeCBlock:
1231 if ((size_t)(dstEnd-dstPtr) < dctxPtr->maxBlockSize) /* not enough place into dst : decode into tmpOut */
1232 dctxPtr->dStage = dstage_decodeCBlock_intoTmp;
1233 else
1234 dctxPtr->dStage = dstage_decodeCBlock_intoDst;
1235 break;
1238 case dstage_decodeCBlock_intoDst:
1240 int (*decoder)(const char*, char*, int, int, const char*, int);
1241 int decodedSize;
1243 if (dctxPtr->frameInfo.blockMode == LZ4F_blockLinked)
1244 decoder = LZ4_decompress_safe_usingDict;
1245 else
1246 decoder = LZ4F_decompress_safe;
1248 decodedSize = decoder((const char*)selectedIn, (char*)dstPtr, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
1249 if (decodedSize < 0) return (size_t)-LZ4F_ERROR_GENERIC; /* decompression failed */
1250 if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dstPtr, decodedSize);
1251 if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;
1253 /* dictionary management */
1254 if (dctxPtr->frameInfo.blockMode==LZ4F_blockLinked)
1255 LZ4F_updateDict(dctxPtr, dstPtr, decodedSize, dstStart, 0);
1257 dstPtr += decodedSize;
1258 dctxPtr->dStage = dstage_getCBlockSize;
1259 break;
1262 case dstage_decodeCBlock_intoTmp:
1264 /* not enough place into dst : decode into tmpOut */
1265 int (*decoder)(const char*, char*, int, int, const char*, int);
1266 int decodedSize;
1268 if (dctxPtr->frameInfo.blockMode == LZ4F_blockLinked)
1269 decoder = LZ4_decompress_safe_usingDict;
1270 else
1271 decoder = LZ4F_decompress_safe;
1273 /* ensure enough place for tmpOut */
1274 if (dctxPtr->frameInfo.blockMode == LZ4F_blockLinked)
1276 if (dctxPtr->dict == dctxPtr->tmpOutBuffer)
1278 if (dctxPtr->dictSize > 128 KB)
1280 memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - 64 KB, 64 KB);
1281 dctxPtr->dictSize = 64 KB;
1283 dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + dctxPtr->dictSize;
1285 else /* dict not within tmp */
1287 size_t reservedDictSpace = dctxPtr->dictSize;
1288 if (reservedDictSpace > 64 KB) reservedDictSpace = 64 KB;
1289 dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + reservedDictSpace;
1293 /* Decode */
1294 decodedSize = decoder((const char*)selectedIn, (char*)dctxPtr->tmpOut, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
1295 if (decodedSize < 0) return (size_t)-LZ4F_ERROR_decompressionFailed; /* decompression failed */
1296 if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dctxPtr->tmpOut, decodedSize);
1297 if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;
1298 dctxPtr->tmpOutSize = decodedSize;
1299 dctxPtr->tmpOutStart = 0;
1300 dctxPtr->dStage = dstage_flushOut;
1301 break;
1304 case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
1306 size_t sizeToCopy = dctxPtr->tmpOutSize - dctxPtr->tmpOutStart;
1307 if (sizeToCopy > (size_t)(dstEnd-dstPtr)) sizeToCopy = dstEnd-dstPtr;
1308 memcpy(dstPtr, dctxPtr->tmpOut + dctxPtr->tmpOutStart, sizeToCopy);
1310 /* dictionary management */
1311 if (dctxPtr->frameInfo.blockMode==LZ4F_blockLinked)
1312 LZ4F_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 1);
1314 dctxPtr->tmpOutStart += sizeToCopy;
1315 dstPtr += sizeToCopy;
1317 /* end of flush ? */
1318 if (dctxPtr->tmpOutStart == dctxPtr->tmpOutSize)
1320 dctxPtr->dStage = dstage_getCBlockSize;
1321 break;
1323 nextSrcSizeHint = BHSize;
1324 doAnotherStage = 0; /* still some data to flush */
1325 break;
1328 case dstage_getSuffix:
1330 size_t suffixSize = dctxPtr->frameInfo.contentChecksumFlag * 4;
1331 if (dctxPtr->frameRemainingSize) return (size_t)-LZ4F_ERROR_frameSize_wrong; /* incorrect frame size decoded */
1332 if (suffixSize == 0) /* frame completed */
1334 nextSrcSizeHint = 0;
1335 dctxPtr->dStage = dstage_getHeader;
1336 doAnotherStage = 0;
1337 break;
1339 if ((srcEnd - srcPtr) < 4) /* not enough size for entire CRC */
1341 dctxPtr->tmpInSize = 0;
1342 dctxPtr->dStage = dstage_storeSuffix;
1344 else
1346 selectedIn = srcPtr;
1347 srcPtr += 4;
1351 if (dctxPtr->dStage == dstage_storeSuffix)
1352 case dstage_storeSuffix:
1354 size_t sizeToCopy = 4 - dctxPtr->tmpInSize;
1355 if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1356 memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1357 srcPtr += sizeToCopy;
1358 dctxPtr->tmpInSize += sizeToCopy;
1359 if (dctxPtr->tmpInSize < 4) /* not enough input to read complete suffix */
1361 nextSrcSizeHint = 4 - dctxPtr->tmpInSize;
1362 doAnotherStage=0;
1363 break;
1365 selectedIn = dctxPtr->tmpIn;
1368 /* case dstage_checkSuffix: */ /* no direct call, to avoid scan-build warning */
1370 U32 readCRC = LZ4F_readLE32(selectedIn);
1371 U32 resultCRC = XXH32_digest(&(dctxPtr->xxh));
1372 if (readCRC != resultCRC) return (size_t)-LZ4F_ERROR_contentChecksum_invalid;
1373 nextSrcSizeHint = 0;
1374 dctxPtr->dStage = dstage_getHeader;
1375 doAnotherStage = 0;
1376 break;
1379 case dstage_getSFrameSize:
1381 if ((srcEnd - srcPtr) >= 4)
1383 selectedIn = srcPtr;
1384 srcPtr += 4;
1386 else
1388 /* not enough input to read cBlockSize field */
1389 dctxPtr->tmpInSize = 4;
1390 dctxPtr->tmpInTarget = 8;
1391 dctxPtr->dStage = dstage_storeSFrameSize;
1395 if (dctxPtr->dStage == dstage_storeSFrameSize)
1396 case dstage_storeSFrameSize:
1398 size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
1399 if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1400 memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1401 srcPtr += sizeToCopy;
1402 dctxPtr->tmpInSize += sizeToCopy;
1403 if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) /* not enough input to get full sBlockSize; wait for more */
1405 nextSrcSizeHint = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
1406 doAnotherStage = 0;
1407 break;
1409 selectedIn = dctxPtr->header + 4;
1412 /* case dstage_decodeSFrameSize: */ /* no direct access */
1414 size_t SFrameSize = LZ4F_readLE32(selectedIn);
1415 dctxPtr->frameInfo.contentSize = SFrameSize;
1416 dctxPtr->tmpInTarget = SFrameSize;
1417 dctxPtr->dStage = dstage_skipSkippable;
1418 break;
1421 case dstage_skipSkippable:
1423 size_t skipSize = dctxPtr->tmpInTarget;
1424 if (skipSize > (size_t)(srcEnd-srcPtr)) skipSize = srcEnd-srcPtr;
1425 srcPtr += skipSize;
1426 dctxPtr->tmpInTarget -= skipSize;
1427 doAnotherStage = 0;
1428 nextSrcSizeHint = dctxPtr->tmpInTarget;
1429 if (nextSrcSizeHint) break;
1430 dctxPtr->dStage = dstage_getHeader;
1431 break;
1436 /* preserve dictionary within tmp if necessary */
1437 if ( (dctxPtr->frameInfo.blockMode==LZ4F_blockLinked)
1438 &&(dctxPtr->dict != dctxPtr->tmpOutBuffer)
1439 &&(!decompressOptionsPtr->stableDst)
1440 &&((unsigned)(dctxPtr->dStage-1) < (unsigned)(dstage_getSuffix-1))
1443 if (dctxPtr->dStage == dstage_flushOut)
1445 size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;
1446 size_t copySize = 64 KB - dctxPtr->tmpOutSize;
1447 const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;
1448 if (dctxPtr->tmpOutSize > 64 KB) copySize = 0;
1449 if (copySize > preserveSize) copySize = preserveSize;
1451 memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1453 dctxPtr->dict = dctxPtr->tmpOutBuffer;
1454 dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart;
1456 else
1458 size_t newDictSize = dctxPtr->dictSize;
1459 const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize;
1460 if ((newDictSize) > 64 KB) newDictSize = 64 KB;
1462 memcpy(dctxPtr->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1464 dctxPtr->dict = dctxPtr->tmpOutBuffer;
1465 dctxPtr->dictSize = newDictSize;
1466 dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + newDictSize;
1470 /* require function to be called again from position where it stopped */
1471 if (srcPtr<srcEnd)
1472 dctxPtr->srcExpect = srcPtr;
1473 else
1474 dctxPtr->srcExpect = NULL;
1476 *srcSizePtr = (srcPtr - srcStart);
1477 *dstSizePtr = (dstPtr - dstStart);
1478 return nextSrcSizeHint;