File Coverage

lz4frame.c
Criterion Covered Total %
statement 430 786 54.7
branch 134 370 36.2
condition n/a
subroutine n/a
pod n/a
total 564 1156 48.7


line stmt bran cond sub pod time code
1             /*
2             LZ4 auto-framing library
3             Copyright (C) 2011-2016, Yann Collet.
4              
5             BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6              
7             Redistribution and use in source and binary forms, with or without
8             modification, are permitted provided that the following conditions are
9             met:
10              
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.
17              
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.
29              
30             You can contact the author at :
31             - LZ4 homepage : http://www.lz4.org
32             - LZ4 source repository : https://github.com/lz4/lz4
33             */
34              
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             * */
39              
40              
41             /*-************************************
42             * Compiler Options
43             **************************************/
44             #ifdef _MSC_VER /* Visual Studio */
45             # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
46             #endif
47              
48              
49             /*-************************************
50             * Memory routines
51             **************************************/
52             #include /* malloc, calloc, free */
53             #define ALLOCATOR(s) calloc(1,s)
54             #define FREEMEM free
55             #include /* memset, memcpy, memmove */
56             #define MEM_INIT memset
57              
58              
59             /*-************************************
60             * Includes
61             **************************************/
62             #include "lz4frame_static.h"
63             #include "lz4.h"
64             #define LZ4_HC_STATIC_LINKING_ONLY
65             #include "lz4hc.h"
66             #define XXH_STATIC_LINKING_ONLY
67             #include "xxhash.h"
68              
69              
70             /*-************************************
71             * Debug
72             **************************************/
73             #define LZ4F_STATIC_ASSERT(c) { enum { LZ4F_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
74              
75              
76             /*-************************************
77             * Basic Types
78             **************************************/
79             #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
80             # include
81             typedef uint8_t BYTE;
82             typedef uint16_t U16;
83             typedef uint32_t U32;
84             typedef int32_t S32;
85             typedef uint64_t U64;
86             #else
87             typedef unsigned char BYTE;
88             typedef unsigned short U16;
89             typedef unsigned int U32;
90             typedef signed int S32;
91             typedef unsigned long long U64;
92             #endif
93              
94              
95             /* unoptimized version; solves endianess & alignment issues */
96 122           static U32 LZ4F_readLE32 (const void* src)
97             {
98 122           const BYTE* const srcPtr = (const BYTE*)src;
99 122           U32 value32 = srcPtr[0];
100 122           value32 += (srcPtr[1]<<8);
101 122           value32 += (srcPtr[2]<<16);
102 122           value32 += ((U32)srcPtr[3])<<24;
103 122           return value32;
104             }
105              
106 15           static void LZ4F_writeLE32 (void* dst, U32 value32)
107             {
108 15           BYTE* const dstPtr = (BYTE*)dst;
109 15           dstPtr[0] = (BYTE)value32;
110 15           dstPtr[1] = (BYTE)(value32 >> 8);
111 15           dstPtr[2] = (BYTE)(value32 >> 16);
112 15           dstPtr[3] = (BYTE)(value32 >> 24);
113 15           }
114              
115 4           static U64 LZ4F_readLE64 (const void* src)
116             {
117 4           const BYTE* const srcPtr = (const BYTE*)src;
118 4           U64 value64 = srcPtr[0];
119 4           value64 += ((U64)srcPtr[1]<<8);
120 4           value64 += ((U64)srcPtr[2]<<16);
121 4           value64 += ((U64)srcPtr[3]<<24);
122 4           value64 += ((U64)srcPtr[4]<<32);
123 4           value64 += ((U64)srcPtr[5]<<40);
124 4           value64 += ((U64)srcPtr[6]<<48);
125 4           value64 += ((U64)srcPtr[7]<<56);
126 4           return value64;
127             }
128              
129 1           static void LZ4F_writeLE64 (void* dst, U64 value64)
130             {
131 1           BYTE* const dstPtr = (BYTE*)dst;
132 1           dstPtr[0] = (BYTE)value64;
133 1           dstPtr[1] = (BYTE)(value64 >> 8);
134 1           dstPtr[2] = (BYTE)(value64 >> 16);
135 1           dstPtr[3] = (BYTE)(value64 >> 24);
136 1           dstPtr[4] = (BYTE)(value64 >> 32);
137 1           dstPtr[5] = (BYTE)(value64 >> 40);
138 1           dstPtr[6] = (BYTE)(value64 >> 48);
139 1           dstPtr[7] = (BYTE)(value64 >> 56);
140 1           }
141              
142              
143             /*-************************************
144             * Constants
145             **************************************/
146             #define KB *(1<<10)
147             #define MB *(1<<20)
148             #define GB *(1<<30)
149              
150             #define _1BIT 0x01
151             #define _2BITS 0x03
152             #define _3BITS 0x07
153             #define _4BITS 0x0F
154             #define _8BITS 0xFF
155              
156             #define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
157             #define LZ4F_MAGICNUMBER 0x184D2204U
158             #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
159             #define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB
160              
161             static const size_t minFHSize = 7;
162             static const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX; /* 19 */
163             static const size_t BHSize = 4;
164              
165              
166             /*-************************************
167             * Structures and local types
168             **************************************/
169             typedef struct LZ4F_cctx_s
170             {
171             LZ4F_preferences_t prefs;
172             U32 version;
173             U32 cStage;
174             const LZ4F_CDict* cdict;
175             size_t maxBlockSize;
176             size_t maxBufferSize;
177             BYTE* tmpBuff;
178             BYTE* tmpIn;
179             size_t tmpInSize;
180             U64 totalInSize;
181             XXH32_state_t xxh;
182             void* lz4CtxPtr;
183             U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
184             } LZ4F_cctx_t;
185              
186              
187             /*-************************************
188             * Error management
189             **************************************/
190             #define LZ4F_GENERATE_STRING(STRING) #STRING,
191             static const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) };
192              
193              
194 557           unsigned LZ4F_isError(LZ4F_errorCode_t code)
195             {
196 557           return (code > (LZ4F_errorCode_t)(-LZ4F_ERROR_maxCode));
197             }
198              
199 0           const char* LZ4F_getErrorName(LZ4F_errorCode_t code)
200             {
201             static const char* codeError = "Unspecified error code";
202 0 0         if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)];
203 0           return codeError;
204             }
205              
206 0           LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult)
207             {
208 0 0         if (!LZ4F_isError(functionResult)) return LZ4F_OK_NoError;
209 0           return (LZ4F_errorCodes)(-(ptrdiff_t)functionResult);
210             }
211              
212 1           static LZ4F_errorCode_t err0r(LZ4F_errorCodes code)
213             {
214             /* A compilation error here means sizeof(ptrdiff_t) is not large enough */
215             LZ4F_STATIC_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t));
216 1           return (LZ4F_errorCode_t)-(ptrdiff_t)code;
217             }
218              
219 0           unsigned LZ4F_getVersion(void) { return LZ4F_VERSION; }
220              
221 0           int LZ4F_compressionLevel_max(void) { return LZ4HC_CLEVEL_MAX; }
222              
223              
224             /*-************************************
225             * Private functions
226             **************************************/
227             #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
228              
229 12           static size_t LZ4F_getBlockSize(unsigned blockSizeID)
230             {
231             static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB };
232              
233 12 100         if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
234 12           blockSizeID -= 4;
235 12 50         if (blockSizeID > 3) return err0r(LZ4F_ERROR_maxBlockSize_invalid);
236 12           return blockSizes[blockSizeID];
237             }
238              
239 8           static BYTE LZ4F_headerChecksum (const void* header, size_t length)
240             {
241 8           U32 const xxh = XXH32(header, length, 0);
242 8           return (BYTE)(xxh >> 8);
243             }
244              
245              
246             /*-************************************
247             * Simple-pass compression functions
248             **************************************/
249 1           static LZ4F_blockSizeID_t LZ4F_optimalBSID(const LZ4F_blockSizeID_t requestedBSID,
250             const size_t srcSize)
251             {
252 1           LZ4F_blockSizeID_t proposedBSID = LZ4F_max64KB;
253 1           size_t maxBlockSize = 64 KB;
254 1 50         while (requestedBSID > proposedBSID) {
255 0 0         if (srcSize <= maxBlockSize)
256 0           return proposedBSID;
257 0           proposedBSID = (LZ4F_blockSizeID_t)((int)proposedBSID + 1);
258 0           maxBlockSize <<= 2;
259             }
260 1           return requestedBSID;
261             }
262              
263             /*! LZ4F_compressBound_internal() :
264             * Provides dstCapacity given a srcSize to guarantee operation success in worst case situations.
265             * prefsPtr is optional : if NULL is provided, preferences will be set to cover worst case scenario.
266             * @return is always the same for a srcSize and prefsPtr, so it can be relied upon to size reusable buffers.
267             * When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations.
268             */
269 3           static size_t LZ4F_compressBound_internal(size_t srcSize,
270             const LZ4F_preferences_t* preferencesPtr,
271             size_t alreadyBuffered)
272             {
273             LZ4F_preferences_t prefsNull;
274 3           memset(&prefsNull, 0, sizeof(prefsNull));
275 3           prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; /* worst case */
276 3 50         { const LZ4F_preferences_t* const prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
277 3           U32 const flush = prefsPtr->autoFlush | (srcSize==0);
278 3           LZ4F_blockSizeID_t const blockID = prefsPtr->frameInfo.blockSizeID;
279 3           size_t const blockSize = LZ4F_getBlockSize(blockID);
280 3           size_t const maxBuffered = blockSize - 1;
281 3           size_t const bufferedSize = MIN(alreadyBuffered, maxBuffered);
282 3           size_t const maxSrcSize = srcSize + bufferedSize;
283 3           unsigned const nbFullBlocks = (unsigned)(maxSrcSize / blockSize);
284 3           size_t const partialBlockSize = (srcSize - (srcSize==0)) & (blockSize-1); /* 0 => -1 == MAX => blockSize-1 */
285 3 50         size_t const lastBlockSize = flush ? partialBlockSize : 0;
286 3           unsigned const nbBlocks = nbFullBlocks + (lastBlockSize>0);
287              
288 3           size_t const blockHeaderSize = 4;
289 3           size_t const blockCRCSize = 4 * prefsPtr->frameInfo.blockChecksumFlag;
290 3           size_t const frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);
291              
292 3           return ((blockHeaderSize + blockCRCSize) * nbBlocks) +
293 6           (blockSize * nbFullBlocks) + lastBlockSize + frameEnd;
294             }
295             }
296              
297 2           size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
298             {
299             LZ4F_preferences_t prefs;
300 2           size_t const headerSize = maxFHSize; /* max header size, including optional fields */
301              
302 2 50         if (preferencesPtr!=NULL) prefs = *preferencesPtr;
303 0           else memset(&prefs, 0, sizeof(prefs));
304 2           prefs.autoFlush = 1;
305              
306 2           return headerSize + LZ4F_compressBound_internal(srcSize, &prefs, 0);;
307             }
308              
309              
310             /*! LZ4F_compressFrame_usingCDict() :
311             * Compress srcBuffer using a dictionary, in a single step.
312             * cdict can be NULL, in which case, no dictionary is used.
313             * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).
314             * The LZ4F_preferences_t structure is optional : you may provide NULL as argument,
315             * however, it's the only way to provide a dictID, so it's not recommended.
316             * @return : number of bytes written into dstBuffer,
317             * or an error code if it fails (can be tested using LZ4F_isError())
318             */
319 1           size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity,
320             const void* srcBuffer, size_t srcSize,
321             const LZ4F_CDict* cdict,
322             const LZ4F_preferences_t* preferencesPtr)
323             {
324             LZ4F_cctx_t cctxI;
325             LZ4_stream_t lz4ctx;
326             LZ4F_preferences_t prefs;
327             LZ4F_compressOptions_t options;
328 1           BYTE* const dstStart = (BYTE*) dstBuffer;
329 1           BYTE* dstPtr = dstStart;
330 1           BYTE* const dstEnd = dstStart + dstCapacity;
331              
332 1           memset(&cctxI, 0, sizeof(cctxI));
333 1           cctxI.version = LZ4F_VERSION;
334 1           cctxI.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */
335              
336 1 50         if (preferencesPtr!=NULL)
337 1           prefs = *preferencesPtr;
338             else
339 0           memset(&prefs, 0, sizeof(prefs));
340 1 50         if (prefs.frameInfo.contentSize != 0)
341 1           prefs.frameInfo.contentSize = (U64)srcSize; /* auto-correct content size if selected (!=0) */
342              
343 1           prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);
344 1           prefs.autoFlush = 1;
345 1 50         if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID))
346 0           prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* only one block => no need for inter-block link */
347              
348 1 50         if (prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
349 1           cctxI.lz4CtxPtr = &lz4ctx;
350 1           cctxI.lz4CtxLevel = 1;
351             } /* fast compression context pre-created on stack */
352              
353 1           memset(&options, 0, sizeof(options));
354 1           options.stableSrc = 1;
355              
356 1 50         if (dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs)) /* condition to guarantee success */
357 0           return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
358              
359 1           { size_t const headerSize = LZ4F_compressBegin_usingCDict(&cctxI, dstBuffer, dstCapacity, cdict, &prefs); /* write header */
360 1 50         if (LZ4F_isError(headerSize)) return headerSize;
361 1           dstPtr += headerSize; /* header size */ }
362              
363 1           { size_t const cSize = LZ4F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);
364 1 50         if (LZ4F_isError(cSize)) return cSize;
365 1           dstPtr += cSize; }
366              
367 1           { size_t const tailSize = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */
368 1 50         if (LZ4F_isError(tailSize)) return tailSize;
369 1           dstPtr += tailSize; }
370              
371 1 50         if (prefs.compressionLevel >= LZ4HC_CLEVEL_MIN) /* Ctx allocation only for lz4hc */
372 0           FREEMEM(cctxI.lz4CtxPtr);
373              
374 1           return (dstPtr - dstStart);
375             }
376              
377              
378             /*! LZ4F_compressFrame() :
379             * Compress an entire srcBuffer into a valid LZ4 frame, in a single step.
380             * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).
381             * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
382             * @return : number of bytes written into dstBuffer.
383             * or an error code if it fails (can be tested using LZ4F_isError())
384             */
385 1           size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,
386             const void* srcBuffer, size_t srcSize,
387             const LZ4F_preferences_t* preferencesPtr)
388             {
389 1           return LZ4F_compressFrame_usingCDict(dstBuffer, dstCapacity,
390             srcBuffer, srcSize,
391             NULL, preferencesPtr);
392             }
393              
394              
395             /*-***************************************************
396             * Dictionary compression
397             *****************************************************/
398              
399             struct LZ4F_CDict_s {
400             void* dictContent;
401             LZ4_stream_t* fastCtx;
402             LZ4_streamHC_t* HCCtx;
403             }; /* typedef'd to LZ4F_CDict within lz4frame_static.h */
404              
405             /*! LZ4F_createCDict() :
406             * When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
407             * LZ4F_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
408             * LZ4F_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
409             * `dictBuffer` can be released after LZ4F_CDict creation, since its content is copied within CDict
410             * @return : digested dictionary for compression, or NULL if failed */
411 0           LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize)
412             {
413 0           const char* dictStart = (const char*)dictBuffer;
414 0           LZ4F_CDict* cdict = (LZ4F_CDict*) malloc(sizeof(*cdict));
415 0 0         if (!cdict) return NULL;
416 0 0         if (dictSize > 64 KB) {
417 0           dictStart += dictSize - 64 KB;
418 0           dictSize = 64 KB;
419             }
420 0           cdict->dictContent = ALLOCATOR(dictSize);
421 0           cdict->fastCtx = LZ4_createStream();
422 0           cdict->HCCtx = LZ4_createStreamHC();
423 0 0         if (!cdict->dictContent || !cdict->fastCtx || !cdict->HCCtx) {
    0          
    0          
424 0           LZ4F_freeCDict(cdict);
425 0           return NULL;
426             }
427 0           memcpy(cdict->dictContent, dictStart, dictSize);
428 0           LZ4_resetStream(cdict->fastCtx);
429 0           LZ4_loadDict (cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize);
430 0           LZ4_resetStreamHC(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT);
431 0           LZ4_loadDictHC(cdict->HCCtx, (const char*)cdict->dictContent, (int)dictSize);
432 0           return cdict;
433             }
434              
435 0           void LZ4F_freeCDict(LZ4F_CDict* cdict)
436             {
437 0 0         if (cdict==NULL) return; /* support free on NULL */
438 0           FREEMEM(cdict->dictContent);
439 0           LZ4_freeStream(cdict->fastCtx);
440 0           LZ4_freeStreamHC(cdict->HCCtx);
441 0           FREEMEM(cdict);
442             }
443              
444              
445             /*-*********************************
446             * Advanced compression functions
447             ***********************************/
448              
449             /*! LZ4F_createCompressionContext() :
450             * The first thing to do is to create a compressionContext object, which will be used in all compression operations.
451             * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
452             * The version provided MUST be LZ4F_VERSION. It is intended to track potential incompatible differences between different binaries.
453             * The function will provide a pointer to an allocated LZ4F_compressionContext_t object.
454             * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
455             * Object can release its memory using LZ4F_freeCompressionContext();
456             */
457 0           LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
458             {
459 0           LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOCATOR(sizeof(LZ4F_cctx_t));
460 0 0         if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
461              
462 0           cctxPtr->version = version;
463 0           cctxPtr->cStage = 0; /* Next stage : init stream */
464              
465 0           *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr;
466              
467 0           return LZ4F_OK_NoError;
468             }
469              
470              
471 0           LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
472             {
473 0           LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
474              
475 0 0         if (cctxPtr != NULL) { /* support free on NULL */
476 0           FREEMEM(cctxPtr->lz4CtxPtr); /* works because LZ4_streamHC_t and LZ4_stream_t are simple POD types */
477 0           FREEMEM(cctxPtr->tmpBuff);
478 0           FREEMEM(LZ4F_compressionContext);
479             }
480              
481 0           return LZ4F_OK_NoError;
482             }
483              
484              
485             /*! LZ4F_compressBegin_usingCDict() :
486             * init streaming compression and writes frame header into dstBuffer.
487             * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
488             * @return : number of bytes written into dstBuffer for the header
489             * or an error code (can be tested using LZ4F_isError())
490             */
491 1           size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
492             void* dstBuffer, size_t dstCapacity,
493             const LZ4F_CDict* cdict,
494             const LZ4F_preferences_t* preferencesPtr)
495             {
496             LZ4F_preferences_t prefNull;
497 1           BYTE* const dstStart = (BYTE*)dstBuffer;
498 1           BYTE* dstPtr = dstStart;
499             BYTE* headerStart;
500              
501 1 50         if (dstCapacity < maxFHSize) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
502 1           memset(&prefNull, 0, sizeof(prefNull));
503 1 50         if (preferencesPtr == NULL) preferencesPtr = &prefNull;
504 1           cctxPtr->prefs = *preferencesPtr;
505              
506             /* Ctx Management */
507 1 50         { U32 const tableID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */
508 1 50         if (cctxPtr->lz4CtxLevel < tableID) {
509 0           FREEMEM(cctxPtr->lz4CtxPtr);
510 0 0         if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
511 0           cctxPtr->lz4CtxPtr = (void*)LZ4_createStream();
512             else
513 0           cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC();
514 0 0         if (cctxPtr->lz4CtxPtr == NULL) return err0r(LZ4F_ERROR_allocation_failed);
515 0           cctxPtr->lz4CtxLevel = tableID;
516             } }
517              
518             /* Buffer Management */
519 1 50         if (cctxPtr->prefs.frameInfo.blockSizeID == 0)
520 1           cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
521 1           cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);
522              
523 2           { size_t const requiredBuffSize = preferencesPtr->autoFlush ?
524 1 50         (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) * 64 KB : /* only needs windows size */
    50          
525 0 0         cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) * 128 KB);
526              
527 1 50         if (cctxPtr->maxBufferSize < requiredBuffSize) {
528 0           cctxPtr->maxBufferSize = 0;
529 0           FREEMEM(cctxPtr->tmpBuff);
530 0           cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(requiredBuffSize);
531 0 0         if (cctxPtr->tmpBuff == NULL) return err0r(LZ4F_ERROR_allocation_failed);
532 0           cctxPtr->maxBufferSize = requiredBuffSize;
533             } }
534 1           cctxPtr->tmpIn = cctxPtr->tmpBuff;
535 1           cctxPtr->tmpInSize = 0;
536 1           XXH32_reset(&(cctxPtr->xxh), 0);
537              
538             /* context init */
539 1           cctxPtr->cdict = cdict;
540 1 50         if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) {
541             /* frame init only for blockLinked : blockIndependent will be init at each block */
542 1 50         if (cdict) {
543 0 0         if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
544 0           memcpy(cctxPtr->lz4CtxPtr, cdict->fastCtx, sizeof(*cdict->fastCtx));
545             } else {
546 0           memcpy(cctxPtr->lz4CtxPtr, cdict->HCCtx, sizeof(*cdict->HCCtx));
547 0           LZ4_setCompressionLevel((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
548             }
549             } else {
550 1 50         if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
551 1           LZ4_resetStream((LZ4_stream_t*)(cctxPtr->lz4CtxPtr));
552             else
553 0           LZ4_resetStreamHC((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), cctxPtr->prefs.compressionLevel);
554             }
555             }
556              
557             /* Magic Number */
558 1           LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER);
559 1           dstPtr += 4;
560 1           headerStart = dstPtr;
561              
562             /* FLG Byte */
563 1 50         *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */
564 1           + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5)
565 1           + ((cctxPtr->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4)
566 1           + ((cctxPtr->prefs.frameInfo.contentSize > 0) << 3)
567 1           + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)
568 1           + (cctxPtr->prefs.frameInfo.dictID > 0) );
569             /* BD Byte */
570 1           *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
571             /* Optional Frame content size field */
572 1 50         if (cctxPtr->prefs.frameInfo.contentSize) {
573 1           LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize);
574 1           dstPtr += 8;
575 1           cctxPtr->totalInSize = 0;
576             }
577             /* Optional dictionary ID field */
578 1 50         if (cctxPtr->prefs.frameInfo.dictID) {
579 0           LZ4F_writeLE32(dstPtr, cctxPtr->prefs.frameInfo.dictID);
580 0           dstPtr += 4;
581             }
582             /* Header CRC Byte */
583 1           *dstPtr = LZ4F_headerChecksum(headerStart, dstPtr - headerStart);
584 1           dstPtr++;
585              
586 1           cctxPtr->cStage = 1; /* header written, now request input data block */
587 1           return (dstPtr - dstStart);
588             }
589              
590              
591             /*! LZ4F_compressBegin() :
592             * init streaming compression and writes frame header into dstBuffer.
593             * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
594             * preferencesPtr can be NULL, in which case default parameters are selected.
595             * @return : number of bytes written into dstBuffer for the header
596             * or an error code (can be tested using LZ4F_isError())
597             */
598 0           size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr,
599             void* dstBuffer, size_t dstCapacity,
600             const LZ4F_preferences_t* preferencesPtr)
601             {
602 0           return LZ4F_compressBegin_usingCDict(cctxPtr, dstBuffer, dstCapacity,
603             NULL, preferencesPtr);
604             }
605              
606              
607             /* LZ4F_compressBound() :
608             * @ return size of Dst buffer given a srcSize to handle worst case situations.
609             * The LZ4F_frameInfo_t structure is optional : if NULL, preferences will be set to cover worst case situations.
610             * This function cannot fail.
611             */
612 0           size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
613             {
614 0           return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1);
615             }
616              
617              
618             typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level, const LZ4F_CDict* cdict);
619              
620              
621             /*! LZ4F_makeBlock():
622             * compress a single block, add header and checksum
623             * assumption : dst buffer capacity is >= srcSize */
624 13           static size_t LZ4F_makeBlock(void* dst, const void* src, size_t srcSize,
625             compressFunc_t compress, void* lz4ctx, int level,
626             const LZ4F_CDict* cdict, LZ4F_blockChecksum_t crcFlag)
627             {
628 13           BYTE* const cSizePtr = (BYTE*)dst;
629 13           U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+4),
630             (int)(srcSize), (int)(srcSize-1),
631             level, cdict);
632 13           LZ4F_writeLE32(cSizePtr, cSize);
633 13 50         if (cSize == 0) { /* compression failed */
634 0           cSize = (U32)srcSize;
635 0           LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG);
636 0           memcpy(cSizePtr+4, src, srcSize);
637             }
638 13 50         if (crcFlag) {
639 0           U32 const crc32 = XXH32(cSizePtr+4, cSize, 0); /* checksum of compressed data */
640 0           LZ4F_writeLE32(cSizePtr+4+cSize, crc32);
641             }
642 13           return 4 + cSize + ((U32)crcFlag)*4;
643             }
644              
645              
646 0           static int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
647             {
648 0 0         int const acceleration = (level < -1) ? -level : 1;
649 0 0         if (cdict) {
650 0           memcpy(ctx, cdict->fastCtx, sizeof(*cdict->fastCtx));
651 0           return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
652             }
653 0           return LZ4_compress_fast_extState(ctx, src, dst, srcSize, dstCapacity, acceleration);
654             }
655              
656 13           static int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
657             {
658 13 50         int const acceleration = (level < -1) ? -level : 1;
659             (void)cdict; /* init once at beginning of frame */
660 13           return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
661             }
662              
663 0           static int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
664             {
665 0 0         if (cdict) {
666 0           memcpy(ctx, cdict->HCCtx, sizeof(*cdict->HCCtx));
667 0           LZ4_setCompressionLevel((LZ4_streamHC_t*)ctx, level);
668 0           return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
669             }
670 0           return LZ4_compress_HC_extStateHC(ctx, src, dst, srcSize, dstCapacity, level);
671             }
672              
673 0           static int LZ4F_compressBlockHC_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
674             {
675             (void)level; (void)cdict; /* init once at beginning of frame */
676 0           return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
677             }
678              
679 1           static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level)
680             {
681 1 50         if (level < LZ4HC_CLEVEL_MIN) {
682 1 50         if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlock;
683 1           return LZ4F_compressBlock_continue;
684             }
685 0 0         if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlockHC;
686 0           return LZ4F_compressBlockHC_continue;
687             }
688              
689 0           static int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr)
690             {
691 0 0         if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
692 0           return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
693 0           return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
694             }
695              
696             typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
697              
698             /*! LZ4F_compressUpdate() :
699             * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
700             * dstBuffer MUST be >= LZ4F_compressBound(srcSize, preferencesPtr).
701             * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
702             * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.
703             * or an error code if it fails (which can be tested using LZ4F_isError())
704             */
705 1           size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
706             void* dstBuffer, size_t dstCapacity,
707             const void* srcBuffer, size_t srcSize,
708             const LZ4F_compressOptions_t* compressOptionsPtr)
709             {
710             LZ4F_compressOptions_t cOptionsNull;
711 1           size_t const blockSize = cctxPtr->maxBlockSize;
712 1           const BYTE* srcPtr = (const BYTE*)srcBuffer;
713 1           const BYTE* const srcEnd = srcPtr + srcSize;
714 1           BYTE* const dstStart = (BYTE*)dstBuffer;
715 1           BYTE* dstPtr = dstStart;
716 1           LZ4F_lastBlockStatus lastBlockCompressed = notDone;
717 1           compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
718              
719              
720 1 50         if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
721 1 50         if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize)) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
722 1           memset(&cOptionsNull, 0, sizeof(cOptionsNull));
723 1 50         if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
724              
725             /* complete tmp buffer */
726 1 50         if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */
727 0           size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
728 0 0         if (sizeToCopy > srcSize) {
729             /* add src to tmpIn buffer */
730 0           memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
731 0           srcPtr = srcEnd;
732 0           cctxPtr->tmpInSize += srcSize;
733             /* still needs some CRC */
734             } else {
735             /* complete tmpIn block and then compress it */
736 0           lastBlockCompressed = fromTmpBuffer;
737 0           memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
738 0           srcPtr += sizeToCopy;
739              
740 0           dstPtr += LZ4F_makeBlock(dstPtr, cctxPtr->tmpIn, blockSize,
741             compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
742             cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
743              
744 0 0         if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
745 0           cctxPtr->tmpInSize = 0;
746             }
747             }
748              
749 13 100         while ((size_t)(srcEnd - srcPtr) >= blockSize) {
750             /* compress full blocks */
751 12           lastBlockCompressed = fromSrcBuffer;
752 12           dstPtr += LZ4F_makeBlock(dstPtr, srcPtr, blockSize,
753             compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
754             cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
755 12           srcPtr += blockSize;
756             }
757              
758 1 50         if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {
    50          
759             /* compress remaining input < blockSize */
760 1           lastBlockCompressed = fromSrcBuffer;
761 1           dstPtr += LZ4F_makeBlock(dstPtr, srcPtr, srcEnd - srcPtr,
762             compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
763             cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
764 1           srcPtr = srcEnd;
765             }
766              
767             /* preserve dictionary if necessary */
768 1 50         if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {
    50          
769 1 50         if (compressOptionsPtr->stableSrc) {
770 1           cctxPtr->tmpIn = cctxPtr->tmpBuff;
771             } else {
772 0           int const realDictSize = LZ4F_localSaveDict(cctxPtr);
773 0 0         if (realDictSize==0) return err0r(LZ4F_ERROR_GENERIC);
774 0           cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
775             }
776             }
777              
778             /* keep tmpIn within limits */
779 1 50         if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily LZ4F_blockLinked && lastBlockCompressed==fromTmpBuffer */
780 0 0         && !(cctxPtr->prefs.autoFlush))
781             {
782 0           int const realDictSize = LZ4F_localSaveDict(cctxPtr);
783 0           cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
784             }
785              
786             /* some input data left, necessarily < blockSize */
787 1 50         if (srcPtr < srcEnd) {
788             /* fill tmp buffer */
789 0           size_t const sizeToCopy = srcEnd - srcPtr;
790 0           memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
791 0           cctxPtr->tmpInSize = sizeToCopy;
792             }
793              
794 1 50         if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
795 0           XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
796              
797 1           cctxPtr->totalInSize += srcSize;
798 1           return dstPtr - dstStart;
799             }
800              
801              
802             /*! LZ4F_flush() :
803             * Should you need to create compressed data immediately, without waiting for a block to be filled,
804             * you can call LZ4_flush(), which will immediately compress any remaining data stored within compressionContext.
805             * The result of the function is the number of bytes written into dstBuffer
806             * (it can be zero, this means there was no data left within compressionContext)
807             * The function outputs an error code if it fails (can be tested using LZ4F_isError())
808             * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
809             */
810 1           size_t LZ4F_flush(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t* compressOptionsPtr)
811             {
812 1           BYTE* const dstStart = (BYTE*)dstBuffer;
813 1           BYTE* dstPtr = dstStart;
814             compressFunc_t compress;
815              
816 1 50         if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
817 0 0         if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
818 0 0         if (dstCapacity < (cctxPtr->tmpInSize + 4)) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); /* +4 : block header(4) */
819             (void)compressOptionsPtr; /* not yet useful */
820              
821             /* select compression function */
822 0           compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
823              
824             /* compress tmp buffer */
825 0           dstPtr += LZ4F_makeBlock(dstPtr, cctxPtr->tmpIn, cctxPtr->tmpInSize,
826             compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
827             cctxPtr->cdict, cctxPtr->prefs.frameInfo.blockChecksumFlag);
828 0 0         if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += cctxPtr->tmpInSize;
829 0           cctxPtr->tmpInSize = 0;
830              
831             /* keep tmpIn within limits */
832 0 0         if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) { /* necessarily LZ4F_blockLinked */
833 0           int realDictSize = LZ4F_localSaveDict(cctxPtr);
834 0           cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
835             }
836              
837 0           return dstPtr - dstStart;
838             }
839              
840              
841             /*! LZ4F_compressEnd() :
842             * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
843             * It will flush whatever data remained within compressionContext (like LZ4_flush())
844             * but also properly finalize the frame, with an endMark and a checksum.
845             * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
846             * The function outputs an error code if it fails (can be tested using LZ4F_isError())
847             * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
848             * compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.
849             */
850 1           size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
851             {
852 1           BYTE* const dstStart = (BYTE*)dstBuffer;
853 1           BYTE* dstPtr = dstStart;
854              
855 1           size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstMaxSize, compressOptionsPtr);
856 1 50         if (LZ4F_isError(flushSize)) return flushSize;
857 1           dstPtr += flushSize;
858              
859 1           LZ4F_writeLE32(dstPtr, 0);
860 1           dstPtr+=4; /* endMark */
861              
862 1 50         if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {
863 0           U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
864 0           LZ4F_writeLE32(dstPtr, xxh);
865 0           dstPtr+=4; /* content Checksum */
866             }
867              
868 1           cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
869 1           cctxPtr->maxBufferSize = 0; /* reuse HC context */
870              
871 1 50         if (cctxPtr->prefs.frameInfo.contentSize) {
872 1 50         if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)
873 0           return err0r(LZ4F_ERROR_frameSize_wrong);
874             }
875              
876 1           return dstPtr - dstStart;
877             }
878              
879              
880             /*-***************************************************
881             * Frame Decompression
882             *****************************************************/
883              
884             typedef enum {
885             dstage_getFrameHeader=0, dstage_storeFrameHeader,
886             dstage_init,
887             dstage_getBlockHeader, dstage_storeBlockHeader,
888             dstage_copyDirect, dstage_getBlockChecksum,
889             dstage_getCBlock, dstage_storeCBlock,
890             dstage_decodeCBlock, dstage_decodeCBlock_intoDst,
891             dstage_decodeCBlock_intoTmp, dstage_flushOut,
892             dstage_getSuffix, dstage_storeSuffix,
893             dstage_getSFrameSize, dstage_storeSFrameSize,
894             dstage_skipSkippable
895             } dStage_t;
896              
897             struct LZ4F_dctx_s {
898             LZ4F_frameInfo_t frameInfo;
899             U32 version;
900             dStage_t dStage;
901             U64 frameRemainingSize;
902             size_t maxBlockSize;
903             size_t maxBufferSize;
904             BYTE* tmpIn;
905             size_t tmpInSize;
906             size_t tmpInTarget;
907             BYTE* tmpOutBuffer;
908             const BYTE* dict;
909             size_t dictSize;
910             BYTE* tmpOut;
911             size_t tmpOutSize;
912             size_t tmpOutStart;
913             XXH32_state_t xxh;
914             XXH32_state_t blockChecksum;
915             BYTE header[LZ4F_HEADER_SIZE_MAX];
916             }; /* typedef'd to LZ4F_dctx in lz4frame.h */
917              
918              
919             /*! LZ4F_createDecompressionContext() :
920             * Create a decompressionContext object, which will track all decompression operations.
921             * Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object.
922             * Object can later be released using LZ4F_freeDecompressionContext().
923             * @return : if != 0, there was an error during context creation.
924             */
925 8           LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber)
926             {
927 8           LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOCATOR(sizeof(LZ4F_dctx));
928 8 50         if (dctx==NULL) return err0r(LZ4F_ERROR_GENERIC);
929              
930 8           dctx->version = versionNumber;
931 8           *LZ4F_decompressionContextPtr = dctx;
932 8           return LZ4F_OK_NoError;
933             }
934              
935 6           LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx)
936             {
937 6           LZ4F_errorCode_t result = LZ4F_OK_NoError;
938 6 50         if (dctx != NULL) { /* can accept NULL input, like free() */
939 6           result = (LZ4F_errorCode_t)dctx->dStage;
940 6           FREEMEM(dctx->tmpIn);
941 6           FREEMEM(dctx->tmpOutBuffer);
942 6           FREEMEM(dctx);
943             }
944 6           return result;
945             }
946              
947              
948             /*==--- Streaming Decompression operations ---==*/
949              
950 5           void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx)
951             {
952 5           dctx->dStage = dstage_getFrameHeader;
953 5           dctx->dict = NULL;
954 5           dctx->dictSize = 0;
955 5           }
956              
957              
958             /*! LZ4F_headerSize() :
959             * @return : size of frame header
960             * or an error code, which can be tested using LZ4F_isError()
961             */
962 8           static size_t LZ4F_headerSize(const void* src, size_t srcSize)
963             {
964             /* minimal srcSize to determine header size */
965 8 50         if (srcSize < 5) return err0r(LZ4F_ERROR_frameHeader_incomplete);
966              
967             /* special case : skippable frames */
968 8 50         if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) return 8;
969              
970             /* control magic number */
971 8 100         if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER)
972 1           return err0r(LZ4F_ERROR_frameType_unknown);
973              
974             /* Frame Header Size */
975 7           { BYTE const FLG = ((const BYTE*)src)[4];
976 7           U32 const contentSizeFlag = (FLG>>3) & _1BIT;
977 7           U32 const dictIDFlag = FLG & _1BIT;
978 7           return minFHSize + (contentSizeFlag*8) + (dictIDFlag*4);
979             }
980             }
981              
982              
983             /*! LZ4F_decodeHeader() :
984             * input : `src` points at the **beginning of the frame**
985             * output : set internal values of dctx, such as
986             * dctx->frameInfo and dctx->dStage.
987             * Also allocates internal buffers.
988             * @return : nb Bytes read from src (necessarily <= srcSize)
989             * or an error code (testable with LZ4F_isError())
990             */
991 7           static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize)
992             {
993             unsigned blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictIDFlag, blockSizeID;
994             size_t frameHeaderSize;
995 7           const BYTE* srcPtr = (const BYTE*)src;
996              
997             /* need to decode header to get frameInfo */
998 7 50         if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */
999 7           memset(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));
1000              
1001             /* special case : skippable frames */
1002 7 50         if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) {
1003 0           dctx->frameInfo.frameType = LZ4F_skippableFrame;
1004 0 0         if (src == (void*)(dctx->header)) {
1005 0           dctx->tmpInSize = srcSize;
1006 0           dctx->tmpInTarget = 8;
1007 0           dctx->dStage = dstage_storeSFrameSize;
1008 0           return srcSize;
1009             } else {
1010 0           dctx->dStage = dstage_getSFrameSize;
1011 0           return 4;
1012             }
1013             }
1014              
1015             /* control magic number */
1016 7 50         if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER)
1017 0           return err0r(LZ4F_ERROR_frameType_unknown);
1018 7           dctx->frameInfo.frameType = LZ4F_frame;
1019              
1020             /* Flags */
1021 7           { U32 const FLG = srcPtr[4];
1022 7           U32 const version = (FLG>>6) & _2BITS;
1023 7           blockChecksumFlag = (FLG>>4) & _1BIT;
1024 7           blockMode = (FLG>>5) & _1BIT;
1025 7           contentSizeFlag = (FLG>>3) & _1BIT;
1026 7           contentChecksumFlag = (FLG>>2) & _1BIT;
1027 7           dictIDFlag = FLG & _1BIT;
1028             /* validate */
1029 7 50         if (((FLG>>1)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
1030 7 50         if (version != 1) return err0r(LZ4F_ERROR_headerVersion_wrong); /* Version Number, only supported value */
1031             }
1032              
1033             /* Frame Header Size */
1034 7           frameHeaderSize = minFHSize + (contentSizeFlag*8) + (dictIDFlag*4);
1035              
1036 7 50         if (srcSize < frameHeaderSize) {
1037             /* not enough input to fully decode frame header */
1038 0 0         if (srcPtr != dctx->header)
1039 0           memcpy(dctx->header, srcPtr, srcSize);
1040 0           dctx->tmpInSize = srcSize;
1041 0           dctx->tmpInTarget = frameHeaderSize;
1042 0           dctx->dStage = dstage_storeFrameHeader;
1043 0           return srcSize;
1044             }
1045              
1046 7           { U32 const BD = srcPtr[5];
1047 7           blockSizeID = (BD>>4) & _3BITS;
1048             /* validate */
1049 7 50         if (((BD>>7)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
1050 7 50         if (blockSizeID < 4) return err0r(LZ4F_ERROR_maxBlockSize_invalid); /* 4-7 only supported values for the time being */
1051 7 50         if (((BD>>0)&_4BITS) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bits */
1052             }
1053              
1054             /* check header */
1055 7           { BYTE const HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
1056 7 50         if (HC != srcPtr[frameHeaderSize-1])
1057 0           return err0r(LZ4F_ERROR_headerChecksum_invalid);
1058             }
1059              
1060             /* save */
1061 7           dctx->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode;
1062 7           dctx->frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)blockChecksumFlag;
1063 7           dctx->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag;
1064 7           dctx->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID;
1065 7           dctx->maxBlockSize = LZ4F_getBlockSize(blockSizeID);
1066 7 100         if (contentSizeFlag)
1067 4           dctx->frameRemainingSize =
1068 4           dctx->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6);
1069 7 50         if (dictIDFlag)
1070 0           dctx->frameInfo.dictID = LZ4F_readLE32(srcPtr + frameHeaderSize - 5);
1071              
1072 7           dctx->dStage = dstage_init;
1073              
1074 7           return frameHeaderSize;
1075             }
1076              
1077              
1078             /*! LZ4F_getFrameInfo() :
1079             * This function extracts frame parameters (max blockSize, frame checksum, etc.).
1080             * Usage is optional. Objective is to provide relevant information for allocation purposes.
1081             * This function works in 2 situations :
1082             * - At the beginning of a new frame, in which case it will decode this information from `srcBuffer`, and start the decoding process.
1083             * Amount of input data provided must be large enough to successfully decode the frame header.
1084             * A header size is variable, but is guaranteed to be <= LZ4F_HEADER_SIZE_MAX bytes. It's possible to provide more input data than this minimum.
1085             * - After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx.
1086             * The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
1087             * Decompression must resume from (srcBuffer + *srcSizePtr).
1088             * @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call,
1089             * or an error code which can be tested using LZ4F_isError()
1090             * note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped.
1091             * note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.
1092             */
1093 8           LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx, LZ4F_frameInfo_t* frameInfoPtr,
1094             const void* srcBuffer, size_t* srcSizePtr)
1095             {
1096 8 50         if (dctx->dStage > dstage_storeFrameHeader) { /* assumption : dstage_* header enum at beginning of range */
1097             /* frameInfo already decoded */
1098 0           size_t o=0, i=0;
1099 0           *srcSizePtr = 0;
1100 0           *frameInfoPtr = dctx->frameInfo;
1101             /* returns : recommended nb of bytes for LZ4F_decompress() */
1102 0           return LZ4F_decompress(dctx, NULL, &o, NULL, &i, NULL);
1103             } else {
1104 8 50         if (dctx->dStage == dstage_storeFrameHeader) {
1105             /* frame decoding already started, in the middle of header => automatic fail */
1106 0           *srcSizePtr = 0;
1107 0           return err0r(LZ4F_ERROR_frameDecoding_alreadyStarted);
1108             } else {
1109             size_t decodeResult;
1110 8           size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);
1111 8 100         if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }
1112 7 50         if (*srcSizePtr < hSize) {
1113 0           *srcSizePtr=0;
1114 0           return err0r(LZ4F_ERROR_frameHeader_incomplete);
1115             }
1116              
1117 7           decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);
1118 7 50         if (LZ4F_isError(decodeResult)) {
1119 0           *srcSizePtr = 0;
1120             } else {
1121 7           *srcSizePtr = decodeResult;
1122 7           decodeResult = BHSize; /* block header size */
1123             }
1124 7           *frameInfoPtr = dctx->frameInfo;
1125 7           return decodeResult;
1126             } }
1127             }
1128              
1129              
1130             /* LZ4F_updateDict() :
1131             * only used for LZ4F_blockLinked mode */
1132 39           static void LZ4F_updateDict(LZ4F_dctx* dctx, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
1133             {
1134 39 100         if (dctx->dictSize==0)
1135 3           dctx->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
1136              
1137 39 50         if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity */
1138 39           dctx->dictSize += dstSize;
1139 39           return;
1140             }
1141              
1142 0 0         if (dstPtr - dstPtr0 + dstSize >= 64 KB) { /* dstBuffer large enough to become dictionary */
1143 0           dctx->dict = (const BYTE*)dstPtr0;
1144 0           dctx->dictSize = dstPtr - dstPtr0 + dstSize;
1145 0           return;
1146             }
1147              
1148 0 0         if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) {
    0          
1149             /* assumption : dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart */
1150 0           dctx->dictSize += dstSize;
1151 0           return;
1152             }
1153              
1154 0 0         if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */
1155 0           size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer;
1156 0           size_t copySize = 64 KB - dctx->tmpOutSize;
1157 0           const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1158 0 0         if (dctx->tmpOutSize > 64 KB) copySize = 0;
1159 0 0         if (copySize > preserveSize) copySize = preserveSize;
1160              
1161 0           memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1162              
1163 0           dctx->dict = dctx->tmpOutBuffer;
1164 0           dctx->dictSize = preserveSize + dctx->tmpOutStart + dstSize;
1165 0           return;
1166             }
1167              
1168 0 0         if (dctx->dict == dctx->tmpOutBuffer) { /* copy dst into tmp to complete dict */
1169 0 0         if (dctx->dictSize + dstSize > dctx->maxBufferSize) { /* tmp buffer not large enough */
1170 0           size_t const preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
1171 0           memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
1172 0           dctx->dictSize = preserveSize;
1173             }
1174 0           memcpy(dctx->tmpOutBuffer + dctx->dictSize, dstPtr, dstSize);
1175 0           dctx->dictSize += dstSize;
1176 0           return;
1177             }
1178              
1179             /* join dict & dest into tmp */
1180 0           { size_t preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
1181 0 0         if (preserveSize > dctx->dictSize) preserveSize = dctx->dictSize;
1182 0           memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
1183 0           memcpy(dctx->tmpOutBuffer + preserveSize, dstPtr, dstSize);
1184 0           dctx->dict = dctx->tmpOutBuffer;
1185 0           dctx->dictSize = preserveSize + dstSize;
1186             }
1187             }
1188              
1189              
1190              
1191             /*! LZ4F_decompress() :
1192             * Call this function repetitively to regenerate compressed data in srcBuffer.
1193             * The function will attempt to decode up to *srcSizePtr bytes from srcBuffer
1194             * into dstBuffer of capacity *dstSizePtr.
1195             *
1196             * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
1197             *
1198             * The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
1199             * If number of bytes read is < number of bytes provided, then decompression operation is not complete.
1200             * Remaining data will have to be presented again in a subsequent invocation.
1201             *
1202             * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
1203             * Schematically, it's the size of the current (or remaining) compressed block + header of next block.
1204             * Respecting the hint provides a small boost to performance, since it allows less buffer shuffling.
1205             * Note that this is just a hint, and it's always possible to any srcSize value.
1206             * When a frame is fully decoded, @return will be 0.
1207             * If decompression failed, @return is an error code which can be tested using LZ4F_isError().
1208             */
1209 520           size_t LZ4F_decompress(LZ4F_dctx* dctx,
1210             void* dstBuffer, size_t* dstSizePtr,
1211             const void* srcBuffer, size_t* srcSizePtr,
1212             const LZ4F_decompressOptions_t* decompressOptionsPtr)
1213             {
1214             LZ4F_decompressOptions_t optionsNull;
1215 520           const BYTE* const srcStart = (const BYTE*)srcBuffer;
1216 520           const BYTE* const srcEnd = srcStart + *srcSizePtr;
1217 520           const BYTE* srcPtr = srcStart;
1218 520           BYTE* const dstStart = (BYTE*)dstBuffer;
1219 520           BYTE* const dstEnd = dstStart + *dstSizePtr;
1220 520           BYTE* dstPtr = dstStart;
1221 520           const BYTE* selectedIn = NULL;
1222 520           unsigned doAnotherStage = 1;
1223 520           size_t nextSrcSizeHint = 1;
1224              
1225              
1226 520           memset(&optionsNull, 0, sizeof(optionsNull));
1227 520 50         if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
1228 520           *srcSizePtr = 0;
1229 520           *dstSizePtr = 0;
1230              
1231             /* behaves as a state machine */
1232              
1233 1214 100         while (doAnotherStage) {
1234              
1235 694           switch(dctx->dStage)
1236             {
1237              
1238             case dstage_getFrameHeader:
1239 0 0         if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */
1240 0           size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, srcEnd-srcPtr); /* will update dStage appropriately */
1241 0 0         if (LZ4F_isError(hSize)) return hSize;
1242 0           srcPtr += hSize;
1243 0           break;
1244             }
1245 0           dctx->tmpInSize = 0;
1246 0 0         if (srcEnd-srcPtr == 0) return minFHSize; /* 0-size input */
1247 0           dctx->tmpInTarget = minFHSize; /* minimum to attempt decode */
1248 0           dctx->dStage = dstage_storeFrameHeader;
1249             /* fall-through */
1250              
1251             case dstage_storeFrameHeader:
1252 0           { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr));
1253 0           memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1254 0           dctx->tmpInSize += sizeToCopy;
1255 0           srcPtr += sizeToCopy;
1256 0 0         if (dctx->tmpInSize < dctx->tmpInTarget) {
1257 0           nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
1258 0           doAnotherStage = 0; /* not enough src data, ask for some more */
1259 0           break;
1260             }
1261 0           { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */
1262 0 0         if (LZ4F_isError(hSize)) return hSize;
1263             }
1264 0           break;
1265             }
1266              
1267             case dstage_init:
1268 6 100         if (dctx->frameInfo.contentChecksumFlag) XXH32_reset(&(dctx->xxh), 0);
1269             /* internal buffers allocation */
1270 6 100         { size_t const bufferNeeded = dctx->maxBlockSize + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB) + 4 /* block checksum */;
1271 6 50         if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */
1272 6           dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/
1273 6           FREEMEM(dctx->tmpIn);
1274 6           dctx->tmpIn = (BYTE*)ALLOCATOR(dctx->maxBlockSize);
1275 6 50         if (dctx->tmpIn == NULL) return err0r(LZ4F_ERROR_allocation_failed);
1276 6           FREEMEM(dctx->tmpOutBuffer);
1277 6           dctx->tmpOutBuffer= (BYTE*)ALLOCATOR(bufferNeeded);
1278 6 50         if (dctx->tmpOutBuffer== NULL) return err0r(LZ4F_ERROR_allocation_failed);
1279 6           dctx->maxBufferSize = bufferNeeded;
1280             } }
1281 6           dctx->tmpInSize = 0;
1282 6           dctx->tmpInTarget = 0;
1283 6           dctx->tmpOut = dctx->tmpOutBuffer;
1284 6           dctx->tmpOutStart = 0;
1285 6           dctx->tmpOutSize = 0;
1286              
1287 6           dctx->dStage = dstage_getBlockHeader;
1288             /* fall-through */
1289              
1290             case dstage_getBlockHeader:
1291 48 50         if ((size_t)(srcEnd - srcPtr) >= BHSize) {
1292 48           selectedIn = srcPtr;
1293 48           srcPtr += BHSize;
1294             } else {
1295             /* not enough input to read cBlockSize field */
1296 0           dctx->tmpInSize = 0;
1297 0           dctx->dStage = dstage_storeBlockHeader;
1298             }
1299              
1300 48 50         if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */
1301             case dstage_storeBlockHeader:
1302 0           { size_t sizeToCopy = BHSize - dctx->tmpInSize;
1303 0 0         if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1304 0           memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1305 0           srcPtr += sizeToCopy;
1306 0           dctx->tmpInSize += sizeToCopy;
1307 0 0         if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */
1308 0           nextSrcSizeHint = BHSize - dctx->tmpInSize;
1309 0           doAnotherStage = 0;
1310 0           break;
1311             }
1312 0           selectedIn = dctx->tmpIn;
1313             }
1314              
1315             /* decode block header */
1316 48           { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
1317 48           size_t const crcSize = dctx->frameInfo.blockChecksumFlag * 4;
1318 48 100         if (nextCBlockSize==0) { /* frameEnd signal, no more block */
1319 5           dctx->dStage = dstage_getSuffix;
1320 5           break;
1321             }
1322 43 50         if (nextCBlockSize > dctx->maxBlockSize)
1323 0           return err0r(LZ4F_ERROR_maxBlockSize_invalid);
1324 43 50         if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
1325             /* next block is uncompressed */
1326 0           dctx->tmpInTarget = nextCBlockSize;
1327 0 0         if (dctx->frameInfo.blockChecksumFlag) {
1328 0           XXH32_reset(&dctx->blockChecksum, 0);
1329             }
1330 0           dctx->dStage = dstage_copyDirect;
1331 0           break;
1332             }
1333             /* next block is a compressed block */
1334 43           dctx->tmpInTarget = nextCBlockSize + crcSize;
1335 43           dctx->dStage = dstage_getCBlock;
1336 43 100         if (dstPtr==dstEnd) {
1337 1           nextSrcSizeHint = nextCBlockSize + crcSize + BHSize;
1338 1           doAnotherStage = 0;
1339             }
1340 43           break;
1341             }
1342              
1343             case dstage_copyDirect: /* uncompressed block */
1344 0           { size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
1345 0           size_t const sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
1346 0           memcpy(dstPtr, srcPtr, sizeToCopy);
1347 0 0         if (dctx->frameInfo.blockChecksumFlag) {
1348 0           XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
1349             }
1350 0 0         if (dctx->frameInfo.contentChecksumFlag)
1351 0           XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
1352 0 0         if (dctx->frameInfo.contentSize)
1353 0           dctx->frameRemainingSize -= sizeToCopy;
1354              
1355             /* history management (linked blocks only)*/
1356 0 0         if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
1357 0           LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
1358              
1359 0           srcPtr += sizeToCopy;
1360 0           dstPtr += sizeToCopy;
1361 0 0         if (sizeToCopy == dctx->tmpInTarget) { /* all done */
1362 0 0         if (dctx->frameInfo.blockChecksumFlag) {
1363 0           dctx->tmpInSize = 0;
1364 0           dctx->dStage = dstage_getBlockChecksum;
1365             } else
1366 0           dctx->dStage = dstage_getBlockHeader; /* new block */
1367 0           break;
1368             }
1369 0           dctx->tmpInTarget -= sizeToCopy; /* need to copy more */
1370 0           nextSrcSizeHint = dctx->tmpInTarget +
1371 0           + dctx->frameInfo.contentChecksumFlag * 4 /* block checksum */
1372 0           + BHSize /* next header size */;
1373 0           doAnotherStage = 0;
1374 0           break;
1375             }
1376              
1377             /* check block checksum for recently transferred uncompressed block */
1378             case dstage_getBlockChecksum:
1379             { const void* crcSrc;
1380 0 0         if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) {
    0          
1381 0           crcSrc = srcPtr;
1382 0           srcPtr += 4;
1383             } else {
1384 0           size_t const stillToCopy = 4 - dctx->tmpInSize;
1385 0           size_t const sizeToCopy = MIN(stillToCopy, (size_t)(srcEnd-srcPtr));
1386 0           memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1387 0           dctx->tmpInSize += sizeToCopy;
1388 0           srcPtr += sizeToCopy;
1389 0 0         if (dctx->tmpInSize < 4) { /* all input consumed */
1390 0           doAnotherStage = 0;
1391 0           break;
1392             }
1393 0           crcSrc = dctx->header;
1394             }
1395 0           { U32 const readCRC = LZ4F_readLE32(crcSrc);
1396 0           U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);
1397 0 0         if (readCRC != calcCRC)
1398 0           return err0r(LZ4F_ERROR_blockChecksum_invalid);
1399             }
1400             }
1401 0           dctx->dStage = dstage_getBlockHeader; /* new block */
1402 0           break;
1403              
1404             case dstage_getCBlock: /* entry from dstage_decodeCBlockSize */
1405 43 100         if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {
1406 1           dctx->tmpInSize = 0;
1407 1           dctx->dStage = dstage_storeCBlock;
1408 1           break;
1409             }
1410             /* input large enough to read full block directly */
1411 42           selectedIn = srcPtr;
1412 42           srcPtr += dctx->tmpInTarget;
1413 42           dctx->dStage = dstage_decodeCBlock;
1414 42           break;
1415              
1416             case dstage_storeCBlock:
1417 1           { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd-srcPtr));
1418 1           memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1419 1           dctx->tmpInSize += sizeToCopy;
1420 1           srcPtr += sizeToCopy;
1421 1 50         if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */
1422 1           nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize;
1423 1           doAnotherStage=0;
1424 1           break;
1425             }
1426 0           selectedIn = dctx->tmpIn;
1427 0           dctx->dStage = dstage_decodeCBlock;
1428             }
1429             /* fall-through */
1430              
1431             /* At this stage, input is large enough to decode a block */
1432             case dstage_decodeCBlock:
1433 42 50         if (dctx->frameInfo.blockChecksumFlag) {
1434 0           dctx->tmpInTarget -= 4;
1435 0           { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget);
1436 0           U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0);
1437 0 0         if (readBlockCrc != calcBlockCrc)
1438 0           return err0r(LZ4F_ERROR_blockChecksum_invalid);
1439             } }
1440 42 100         if ((size_t)(dstEnd-dstPtr) < dctx->maxBlockSize) /* not enough place into dst : decode into tmpOut */
1441 5           dctx->dStage = dstage_decodeCBlock_intoTmp;
1442             else
1443 37           dctx->dStage = dstage_decodeCBlock_intoDst;
1444 42           break;
1445              
1446             case dstage_decodeCBlock_intoDst:
1447 37           { int const decodedSize = LZ4_decompress_safe_usingDict(
1448             (const char*)selectedIn, (char*)dstPtr,
1449 74           (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
1450 74           (const char*)dctx->dict, (int)dctx->dictSize);
1451 37 50         if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */
1452 37 50         if (dctx->frameInfo.contentChecksumFlag)
1453 0           XXH32_update(&(dctx->xxh), dstPtr, decodedSize);
1454 37 100         if (dctx->frameInfo.contentSize)
1455 36           dctx->frameRemainingSize -= decodedSize;
1456              
1457             /* dictionary management */
1458 37 100         if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1459 36           LZ4F_updateDict(dctx, dstPtr, decodedSize, dstStart, 0);
1460              
1461 37           dstPtr += decodedSize;
1462 37           dctx->dStage = dstage_getBlockHeader;
1463 37           break;
1464             }
1465              
1466             case dstage_decodeCBlock_intoTmp:
1467             /* not enough place into dst : decode into tmpOut */
1468              
1469             /* ensure enough place for tmpOut */
1470 5 100         if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
1471 3 50         if (dctx->dict == dctx->tmpOutBuffer) {
1472 0 0         if (dctx->dictSize > 128 KB) {
1473 0           memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB);
1474 0           dctx->dictSize = 64 KB;
1475             }
1476 0           dctx->tmpOut = dctx->tmpOutBuffer + dctx->dictSize;
1477             } else { /* dict not within tmp */
1478 3           size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB);
1479 3           dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace;
1480             }
1481             }
1482              
1483             /* Decode block */
1484 5           { int const decodedSize = LZ4_decompress_safe_usingDict(
1485 5           (const char*)selectedIn, (char*)dctx->tmpOut,
1486 10           (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
1487 10           (const char*)dctx->dict, (int)dctx->dictSize);
1488 5 50         if (decodedSize < 0) /* decompression failed */
1489 0           return err0r(LZ4F_ERROR_decompressionFailed);
1490 5 100         if (dctx->frameInfo.contentChecksumFlag)
1491 1           XXH32_update(&(dctx->xxh), dctx->tmpOut, decodedSize);
1492 5 100         if (dctx->frameInfo.contentSize)
1493 3           dctx->frameRemainingSize -= decodedSize;
1494 5           dctx->tmpOutSize = decodedSize;
1495 5           dctx->tmpOutStart = 0;
1496 5           dctx->dStage = dstage_flushOut;
1497             }
1498             /* fall-through */
1499              
1500             case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
1501 518           { size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
1502 518           memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
1503              
1504             /* dictionary management */
1505 518 100         if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1506 3           LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1);
1507              
1508 518           dctx->tmpOutStart += sizeToCopy;
1509 518           dstPtr += sizeToCopy;
1510              
1511 518 100         if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */
1512 5           dctx->dStage = dstage_getBlockHeader; /* get next block */
1513 5           break;
1514             }
1515 513           nextSrcSizeHint = BHSize;
1516 513           doAnotherStage = 0; /* still some data to flush */
1517 513           break;
1518             }
1519              
1520             case dstage_getSuffix:
1521 5           { size_t const suffixSize = dctx->frameInfo.contentChecksumFlag * 4;
1522 5 50         if (dctx->frameRemainingSize)
1523 0           return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
1524 5 100         if (suffixSize == 0) { /* frame completed */
1525 4           nextSrcSizeHint = 0;
1526 4           LZ4F_resetDecompressionContext(dctx);
1527 4           doAnotherStage = 0;
1528 4           break;
1529             }
1530 1 50         if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */
1531 0           dctx->tmpInSize = 0;
1532 0           dctx->dStage = dstage_storeSuffix;
1533             } else {
1534 1           selectedIn = srcPtr;
1535 1           srcPtr += 4;
1536             }
1537             }
1538              
1539 1 50         if (dctx->dStage == dstage_storeSuffix) /* can be skipped */
1540             case dstage_storeSuffix:
1541             {
1542 0           size_t sizeToCopy = 4 - dctx->tmpInSize;
1543 0 0         if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1544 0           memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1545 0           srcPtr += sizeToCopy;
1546 0           dctx->tmpInSize += sizeToCopy;
1547 0 0         if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */
1548 0           nextSrcSizeHint = 4 - dctx->tmpInSize;
1549 0           doAnotherStage=0;
1550 0           break;
1551             }
1552 0           selectedIn = dctx->tmpIn;
1553             }
1554              
1555             /* case dstage_checkSuffix: */ /* no direct call, avoid scan-build warning */
1556 1           { U32 const readCRC = LZ4F_readLE32(selectedIn);
1557 1           U32 const resultCRC = XXH32_digest(&(dctx->xxh));
1558 1 50         if (readCRC != resultCRC)
1559 0           return err0r(LZ4F_ERROR_contentChecksum_invalid);
1560 1           nextSrcSizeHint = 0;
1561 1           LZ4F_resetDecompressionContext(dctx);
1562 1           doAnotherStage = 0;
1563 1           break;
1564             }
1565              
1566             case dstage_getSFrameSize:
1567 0 0         if ((srcEnd - srcPtr) >= 4) {
1568 0           selectedIn = srcPtr;
1569 0           srcPtr += 4;
1570             } else {
1571             /* not enough input to read cBlockSize field */
1572 0           dctx->tmpInSize = 4;
1573 0           dctx->tmpInTarget = 8;
1574 0           dctx->dStage = dstage_storeSFrameSize;
1575             }
1576              
1577 0 0         if (dctx->dStage == dstage_storeSFrameSize)
1578             case dstage_storeSFrameSize:
1579             {
1580 0           size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,
1581             (size_t)(srcEnd - srcPtr) );
1582 0           memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1583 0           srcPtr += sizeToCopy;
1584 0           dctx->tmpInSize += sizeToCopy;
1585 0 0         if (dctx->tmpInSize < dctx->tmpInTarget) {
1586             /* not enough input to get full sBlockSize; wait for more */
1587 0           nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize;
1588 0           doAnotherStage = 0;
1589 0           break;
1590             }
1591 0           selectedIn = dctx->header + 4;
1592             }
1593              
1594             /* case dstage_decodeSFrameSize: */ /* no direct access */
1595 0           { size_t const SFrameSize = LZ4F_readLE32(selectedIn);
1596 0           dctx->frameInfo.contentSize = SFrameSize;
1597 0           dctx->tmpInTarget = SFrameSize;
1598 0           dctx->dStage = dstage_skipSkippable;
1599 0           break;
1600             }
1601              
1602             case dstage_skipSkippable:
1603 0           { size_t const skipSize = MIN(dctx->tmpInTarget, (size_t)(srcEnd-srcPtr));
1604 0           srcPtr += skipSize;
1605 0           dctx->tmpInTarget -= skipSize;
1606 0           doAnotherStage = 0;
1607 0           nextSrcSizeHint = dctx->tmpInTarget;
1608 0 0         if (nextSrcSizeHint) break; /* still more to skip */
1609 0           LZ4F_resetDecompressionContext(dctx);
1610 0           break;
1611             }
1612             }
1613             }
1614              
1615             /* preserve history within tmp if necessary */
1616 520 100         if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1617 3 50         && (dctx->dict != dctx->tmpOutBuffer)
1618 3 50         && (dctx->dStage != dstage_getFrameHeader)
1619 0 0         && (!decompressOptionsPtr->stableDst)
1620 0 0         && ((unsigned)(dctx->dStage-1) < (unsigned)(dstage_getSuffix-1)) )
1621             {
1622 0 0         if (dctx->dStage == dstage_flushOut) {
1623 0           size_t preserveSize = dctx->tmpOut - dctx->tmpOutBuffer;
1624 0           size_t copySize = 64 KB - dctx->tmpOutSize;
1625 0           const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1626 0 0         if (dctx->tmpOutSize > 64 KB) copySize = 0;
1627 0 0         if (copySize > preserveSize) copySize = preserveSize;
1628              
1629 0           memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1630              
1631 0           dctx->dict = dctx->tmpOutBuffer;
1632 0           dctx->dictSize = preserveSize + dctx->tmpOutStart;
1633             } else {
1634 0           size_t newDictSize = dctx->dictSize;
1635 0           const BYTE* oldDictEnd = dctx->dict + dctx->dictSize;
1636 0 0         if ((newDictSize) > 64 KB) newDictSize = 64 KB;
1637              
1638 0           memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1639              
1640 0           dctx->dict = dctx->tmpOutBuffer;
1641 0           dctx->dictSize = newDictSize;
1642 0           dctx->tmpOut = dctx->tmpOutBuffer + newDictSize;
1643             }
1644             }
1645              
1646 520           *srcSizePtr = (srcPtr - srcStart);
1647 520           *dstSizePtr = (dstPtr - dstStart);
1648 520           return nextSrcSizeHint;
1649             }
1650              
1651             /*! LZ4F_decompress_usingDict() :
1652             * Same as LZ4F_decompress(), using a predefined dictionary.
1653             * Dictionary is used "in place", without any preprocessing.
1654             * It must remain accessible throughout the entire frame decoding.
1655             */
1656 0           size_t LZ4F_decompress_usingDict(LZ4F_dctx* dctx,
1657             void* dstBuffer, size_t* dstSizePtr,
1658             const void* srcBuffer, size_t* srcSizePtr,
1659             const void* dict, size_t dictSize,
1660             const LZ4F_decompressOptions_t* decompressOptionsPtr)
1661             {
1662 0 0         if (dctx->dStage <= dstage_init) {
1663 0           dctx->dict = (const BYTE*)dict;
1664 0           dctx->dictSize = dictSize;
1665             }
1666 0           return LZ4F_decompress(dctx, dstBuffer, dstSizePtr,
1667             srcBuffer, srcSizePtr,
1668             decompressOptionsPtr);
1669             }