NVBIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lz4frame.c
Go to the documentation of this file.
1 /*
2 LZ4 auto-framing library
3 Copyright (C) 2011-2014, Yann Collet.
4 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
8 met:
9 
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following disclaimer
14 in the documentation and/or other materials provided with the
15 distribution.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 You can contact the author at :
30 - LZ4 source repository : http://code.google.com/p/lz4/
31 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
32 */
33 
34 /* LZ4F is a stand-alone API to create LZ4-compressed Frames
35 * fully conformant to specification v1.4.1.
36 * All related operations, including memory management, are handled by the library.
37 * */
38 
39 
40 /**************************************
41 Compiler Options
42 **************************************/
43 #ifdef _MSC_VER /* Visual Studio */
44 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
45 #endif
46 
47 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
48 #ifdef __GNUC__
49 # pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
50 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
51 #endif
52 
53 
54 /**************************************
55 Memory routines
56 **************************************/
57 #include <stdlib.h> /* malloc, calloc, free */
58 #define ALLOCATOR(s) calloc(1,s)
59 #define FREEMEM free
60 #include <string.h> /* memset, memcpy, memmove */
61 #define MEM_INIT memset
62 
63 
64 /**************************************
65 Includes
66 **************************************/
67 #include "lz4frame_static.h"
68 #include "lz4.h"
69 #include "lz4hc.h"
70 #include "xxhash.h"
71 
72 
73 /**************************************
74 Basic Types
75 **************************************/
76 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
77 # include <stdint.h>
78 typedef uint8_t BYTE;
79 typedef uint16_t U16;
80 typedef uint32_t U32;
81 typedef int32_t S32;
82 typedef uint64_t U64;
83 #else
84 typedef unsigned char BYTE;
85 typedef unsigned short U16;
86 typedef unsigned int U32;
87 typedef signed int S32;
88 typedef unsigned long long U64;
89 #endif
90 
91 
92 /**************************************
93 Constants
94 **************************************/
95 #define KB *(1<<10)
96 #define MB *(1<<20)
97 #define GB *(1<<30)
98 
99 #define _1BIT 0x01
100 #define _2BITS 0x03
101 #define _3BITS 0x07
102 #define _4BITS 0x0F
103 #define _8BITS 0xFF
104 
105 #define LZ4F_MAGICNUMBER 0x184D2204U
106 #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
107 #define LZ4F_MAXHEADERFRAME_SIZE 7
108 #define LZ4F_BLOCKSIZEID_DEFAULT max64KB
109 
110 static const U32 minHClevel = 3;
111 
112 /**************************************
113 Structures and local types
114 **************************************/
115 typedef struct
116 {
120  size_t maxBlockSize;
124  size_t tmpInSize;
126  void* lz4CtxPtr;
127  U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */
129 
130 typedef struct
131 {
133  unsigned version;
134  unsigned dStage;
135  size_t maxBlockSize;
137  const BYTE* srcExpect;
139  size_t tmpInSize;
140  size_t tmpInTarget;
143  size_t dictSize;
145  size_t tmpOutSize;
146  size_t tmpOutStart;
150 
151 
152 /**************************************
153 Macros
154 **************************************/
155 
156 
157 /**************************************
158 Error management
159 **************************************/
160 #define LZ4F_GENERATE_STRING(STRING) #STRING,
161 static const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) };
162 
163 
165 {
166  return (code > (LZ4F_errorCode_t)(-ERROR_maxCode));
167 }
168 
170 {
171  static const char* codeError = "Unspecified error code";
172  if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)];
173  return codeError;
174 }
175 
176 
177 /**************************************
178 Private functions
179 **************************************/
180 static size_t LZ4F_getBlockSize(unsigned blockSizeID)
181 {
182  static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB };
183 
184  if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
185  blockSizeID -= 4;
186  if (blockSizeID > 3) return (size_t)-ERROR_maxBlockSize_invalid;
187  return blockSizes[blockSizeID];
188 }
189 
190 
191 /* unoptimized version; solves endianess & alignment issues */
192 static void LZ4F_writeLE32 (BYTE* dstPtr, U32 value32)
193 {
194  dstPtr[0] = (BYTE)value32;
195  dstPtr[1] = (BYTE)(value32 >> 8);
196  dstPtr[2] = (BYTE)(value32 >> 16);
197  dstPtr[3] = (BYTE)(value32 >> 24);
198 }
199 
200 static U32 LZ4F_readLE32 (const BYTE* srcPtr)
201 {
202  U32 value32 = srcPtr[0];
203  value32 += (srcPtr[1]<<8);
204  value32 += (srcPtr[2]<<16);
205  value32 += (srcPtr[3]<<24);
206  return value32;
207 }
208 
209 
210 static BYTE LZ4F_headerChecksum (const BYTE* header, size_t length)
211 {
212  U32 xxh = XXH32(header, (U32)length, 0);
213  return (BYTE)(xxh >> 8);
214 }
215 
216 
217 /**************************************
218 Simple compression functions
219 **************************************/
220 size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
221 {
222  LZ4F_preferences_t prefs = { 0 };
223  size_t headerSize;
224  size_t streamSize;
225 
226  if (preferencesPtr!=NULL) prefs = *preferencesPtr;
227  {
228  blockSizeID_t proposedBSID = max64KB;
229  size_t maxBlockSize = 64 KB;
230  while (prefs.frameInfo.blockSizeID > proposedBSID)
231  {
232  if (srcSize <= maxBlockSize)
233  {
234  prefs.frameInfo.blockSizeID = proposedBSID;
235  break;
236  }
237  proposedBSID++;
238  maxBlockSize <<= 2;
239  }
240  }
241  prefs.autoFlush = 1;
242 
243  headerSize = 7; /* basic header size (no option) including magic number */
244  streamSize = LZ4F_compressBound(srcSize, &prefs);
245 
246  return headerSize + streamSize;
247 }
248 
249 
250 /* LZ4F_compressFrame()
251 * Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.4.1, in a single step.
252 * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
253 * You can get the minimum value of dstMaxSize by using LZ4F_compressFrameBound()
254 * If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode)
255 * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
256 * The result of the function is the number of bytes written into dstBuffer.
257 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
258 */
259 size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
260 {
261  LZ4F_cctx_internal_t cctxI = { 0 }; /* works because no allocation */
262  LZ4F_preferences_t prefs = { 0 };
263  LZ4F_compressOptions_t options = { 0 };
264  LZ4F_errorCode_t errorCode;
265  BYTE* const dstStart = (BYTE*) dstBuffer;
266  BYTE* dstPtr = dstStart;
267  BYTE* const dstEnd = dstStart + dstMaxSize;
268 
269 
270  cctxI.version = LZ4F_VERSION;
271  cctxI.maxBufferSize = 5 MB; /* mess with real buffer size to prevent allocation; works because autoflush==1 & stableSrc==1 */
272 
273  if (preferencesPtr!=NULL) prefs = *preferencesPtr;
274  {
275  blockSizeID_t proposedBSID = max64KB;
276  size_t maxBlockSize = 64 KB;
277  while (prefs.frameInfo.blockSizeID > proposedBSID)
278  {
279  if (srcSize <= maxBlockSize)
280  {
281  prefs.frameInfo.blockSizeID = proposedBSID;
282  break;
283  }
284  proposedBSID++;
285  maxBlockSize <<= 2;
286  }
287  }
288  prefs.autoFlush = 1;
289  if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID))
290  prefs.frameInfo.blockMode = blockIndependent; /* no need for linked blocks */
291 
292  options.stableSrc = 1;
293 
294  if (dstMaxSize < LZ4F_compressFrameBound(srcSize, &prefs))
295  return (size_t)-ERROR_dstMaxSize_tooSmall;
296 
297  errorCode = LZ4F_compressBegin(&cctxI, dstBuffer, dstMaxSize, &prefs); /* write header */
298  if (LZ4F_isError(errorCode)) return errorCode;
299  dstPtr += errorCode; /* header size */
300 
301  dstMaxSize -= errorCode;
302  errorCode = LZ4F_compressUpdate(&cctxI, dstPtr, dstMaxSize, srcBuffer, srcSize, &options);
303  if (LZ4F_isError(errorCode)) return errorCode;
304  dstPtr += errorCode;
305 
306  errorCode = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */
307  if (LZ4F_isError(errorCode)) return errorCode;
308  dstPtr += errorCode;
309 
310  FREEMEM(cctxI.lz4CtxPtr);
311 
312  return (dstPtr - dstStart);
313 }
314 
315 
316 /***********************************
317 * Advanced compression functions
318 * *********************************/
319 
320 /* LZ4F_createCompressionContext() :
321 * The first thing to do is to create a compressionContext object, which will be used in all compression operations.
322 * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
323 * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries.
324 * The function will provide a pointer to an allocated LZ4F_compressionContext_t object.
325 * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
326 * Object can release its memory using LZ4F_freeCompressionContext();
327 */
328 LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
329 {
330  LZ4F_cctx_internal_t* cctxPtr;
331 
333  if (cctxPtr==NULL) return (LZ4F_errorCode_t)(-ERROR_allocation_failed);
334 
335  cctxPtr->version = version;
336  cctxPtr->cStage = 0; /* Next stage : write header */
337 
338  *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr;
339 
340  return OK_NoError;
341 }
342 
343 
345 {
346  LZ4F_cctx_internal_t* cctxPtr = (LZ4F_cctx_internal_t*)LZ4F_compressionContext;
347 
348  FREEMEM(cctxPtr->lz4CtxPtr);
349  FREEMEM(cctxPtr->tmpBuff);
350  FREEMEM(LZ4F_compressionContext);
351 
352  return OK_NoError;
353 }
354 
355 
356 /* LZ4F_compressBegin() :
357 * will write the frame header into dstBuffer.
358 * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is LZ4F_MAXHEADERFRAME_SIZE bytes.
359 * The result of the function is the number of bytes written into dstBuffer for the header
360 * or an error code (can be tested using LZ4F_isError())
361 */
362 size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr)
363 {
364  LZ4F_preferences_t prefNull = { 0 };
365  LZ4F_cctx_internal_t* cctxPtr = (LZ4F_cctx_internal_t*)compressionContext;
366  BYTE* const dstStart = (BYTE*)dstBuffer;
367  BYTE* dstPtr = dstStart;
368  BYTE* headerStart;
369  size_t requiredBuffSize;
370 
371  if (dstMaxSize < LZ4F_MAXHEADERFRAME_SIZE) return (size_t)-ERROR_dstMaxSize_tooSmall;
372  if (cctxPtr->cStage != 0) return (size_t)-ERROR_GENERIC;
373  if (preferencesPtr == NULL) preferencesPtr = &prefNull;
374  cctxPtr->prefs = *preferencesPtr;
375 
376  /* ctx Management */
377  {
378  U32 targetCtxLevel = cctxPtr->prefs.compressionLevel<minHClevel ? 1 : 2;
379  if (cctxPtr->lz4CtxLevel < targetCtxLevel)
380  {
381  FREEMEM(cctxPtr->lz4CtxPtr);
382  if (cctxPtr->prefs.compressionLevel<minHClevel)
383  cctxPtr->lz4CtxPtr = (void*)LZ4_createStream();
384  else
385  cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC();
386  cctxPtr->lz4CtxLevel = targetCtxLevel;
387  }
388  }
389 
390  /* Buffer Management */
392  cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);
393 
394  requiredBuffSize = cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == blockLinked) * 128 KB);
395  if (preferencesPtr->autoFlush)
396  requiredBuffSize = (cctxPtr->prefs.frameInfo.blockMode == blockLinked) * 64 KB; /* just needs dict */
397 
398  if (cctxPtr->maxBufferSize < requiredBuffSize)
399  {
400  cctxPtr->maxBufferSize = requiredBuffSize;
401  FREEMEM(cctxPtr->tmpBuff);
402  cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(requiredBuffSize);
403  if (cctxPtr->tmpBuff == NULL) return (size_t)-ERROR_allocation_failed;
404  }
405  cctxPtr->tmpIn = cctxPtr->tmpBuff;
406  cctxPtr->tmpInSize = 0;
407  XXH32_reset(&(cctxPtr->xxh), 0);
408  if (cctxPtr->prefs.compressionLevel<minHClevel)
409  LZ4_resetStream((LZ4_stream_t*)(cctxPtr->lz4CtxPtr));
410  else
412 
413  /* Magic Number */
414  LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER);
415  dstPtr += 4;
416  headerStart = dstPtr;
417 
418  /* FLG Byte */
419  *dstPtr++ = ((1 & _2BITS) << 6) /* Version('01') */
420  + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5) /* Block mode */
421  + (char)((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2); /* Stream checksum */
422  /* BD Byte */
423  *dstPtr++ = (char)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
424  /* CRC Byte */
425  *dstPtr++ = LZ4F_headerChecksum(headerStart, 2);
426 
427  cctxPtr->cStage = 1; /* header written, wait for data block */
428 
429  return (dstPtr - dstStart);
430 }
431 
432 
433 /* LZ4F_compressBound() : gives the size of Dst buffer given a srcSize to handle worst case situations.
434 * The LZ4F_frameInfo_t structure is optional :
435 * you can provide NULL as argument, all preferences will then be set to default.
436 * */
437 size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
438 {
439  const LZ4F_preferences_t prefsNull = { 0 };
440  const LZ4F_preferences_t* prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
441  blockSizeID_t bid = prefsPtr->frameInfo.blockSizeID;
442  size_t blockSize = LZ4F_getBlockSize(bid);
443  unsigned nbBlocks = (unsigned)(srcSize / blockSize) + 1;
444  size_t lastBlockSize = prefsPtr->autoFlush ? srcSize % blockSize : blockSize;
445  size_t blockInfo = 4; /* default, without block CRC option */
446  size_t frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);
447  size_t result = (blockInfo * nbBlocks) + (blockSize * (nbBlocks-1)) + lastBlockSize + frameEnd;
448 
449  return result;
450 }
451 
452 
453 typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level);
454 
455 static size_t LZ4F_compressBlock(void* dst, const void* src, size_t srcSize, compressFunc_t compress, void* lz4ctx, int level)
456 {
457  /* compress one block */
458  BYTE* cSizePtr = (BYTE*)dst;
459  U32 cSize;
460  cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1), level);
461  LZ4F_writeLE32(cSizePtr, cSize);
462  if (cSize == 0) /* compression failed */
463  {
464  cSize = (U32)srcSize;
465  LZ4F_writeLE32(cSizePtr, cSize + LZ4F_BLOCKUNCOMPRESSED_FLAG);
466  memcpy(cSizePtr+4, src, srcSize);
467  }
468  return cSize + 4;
469 }
470 
471 
472 static int LZ4F_localLZ4_compress_limitedOutput_withState(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)
473 {
474  (void) level;
475  return LZ4_compress_limitedOutput_withState(ctx, src, dst, srcSize, dstSize);
476 }
477 
478 static int LZ4F_localLZ4_compress_limitedOutput_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)
479 {
480  (void) level;
481  return LZ4_compress_limitedOutput_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstSize);
482 }
483 
484 static int LZ4F_localLZ4_compressHC_limitedOutput_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)
485 {
486  (void) level;
487  return LZ4_compressHC_limitedOutput_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstSize);
488 }
489 
490 static compressFunc_t LZ4F_selectCompression(blockMode_t blockMode, U32 level)
491 {
492  if (level < minHClevel)
493  {
494  if (blockMode == blockIndependent) return LZ4F_localLZ4_compress_limitedOutput_withState;
495  return LZ4F_localLZ4_compress_limitedOutput_continue;
496  }
498  return LZ4F_localLZ4_compressHC_limitedOutput_continue;
499 }
500 
501 static int LZ4F_localSaveDict(LZ4F_cctx_internal_t* cctxPtr)
502 {
503  if (cctxPtr->prefs.compressionLevel < minHClevel)
504  return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
505  return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
506 }
507 
509 
510 /* LZ4F_compressUpdate()
511 * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
512 * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
513 * If this condition is not respected, LZ4F_compress() will fail (result is an errorCode)
514 * You can get the minimum value of dstMaxSize by using LZ4F_compressBound()
515 * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
516 * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.
517 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
518 */
519 size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr)
520 {
521  LZ4F_compressOptions_t cOptionsNull = { 0 };
522  LZ4F_cctx_internal_t* cctxPtr = (LZ4F_cctx_internal_t*)compressionContext;
523  size_t blockSize = cctxPtr->maxBlockSize;
524  const BYTE* srcPtr = (const BYTE*)srcBuffer;
525  const BYTE* const srcEnd = srcPtr + srcSize;
526  BYTE* const dstStart = (BYTE*)dstBuffer;
527  BYTE* dstPtr = dstStart;
528  LZ4F_lastBlockStatus lastBlockCompressed = notDone;
530 
531 
532  if (cctxPtr->cStage != 1) return (size_t)-ERROR_GENERIC;
533  if (dstMaxSize < LZ4F_compressBound(srcSize, &(cctxPtr->prefs))) return (size_t)-ERROR_dstMaxSize_tooSmall;
534  if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
535 
536  /* select compression function */
537  compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
538 
539  /* complete tmp buffer */
540  if (cctxPtr->tmpInSize > 0) /* some data already within tmp buffer */
541  {
542  size_t sizeToCopy = blockSize - cctxPtr->tmpInSize;
543  if (sizeToCopy > srcSize)
544  {
545  /* add src to tmpIn buffer */
546  memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
547  srcPtr = srcEnd;
548  cctxPtr->tmpInSize += srcSize;
549  /* still needs some CRC */
550  }
551  else
552  {
553  /* complete tmpIn block and then compress it */
554  lastBlockCompressed = fromTmpBuffer;
555  memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
556  srcPtr += sizeToCopy;
557 
558  dstPtr += LZ4F_compressBlock(dstPtr, cctxPtr->tmpIn, blockSize, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
559 
560  if (cctxPtr->prefs.frameInfo.blockMode==blockLinked) cctxPtr->tmpIn += blockSize;
561  cctxPtr->tmpInSize = 0;
562  }
563  }
564 
565  while ((size_t)(srcEnd - srcPtr) >= blockSize)
566  {
567  /* compress full block */
568  lastBlockCompressed = fromSrcBuffer;
569  dstPtr += LZ4F_compressBlock(dstPtr, srcPtr, blockSize, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
570  srcPtr += blockSize;
571  }
572 
573  if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd))
574  {
575  /* compress remaining input < blockSize */
576  lastBlockCompressed = fromSrcBuffer;
577  dstPtr += LZ4F_compressBlock(dstPtr, srcPtr, srcEnd - srcPtr, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
578  srcPtr = srcEnd;
579  }
580 
581  /* preserve dictionary if necessary */
582  if ((cctxPtr->prefs.frameInfo.blockMode==blockLinked) && (lastBlockCompressed==fromSrcBuffer))
583  {
584  if (compressOptionsPtr->stableSrc)
585  {
586  cctxPtr->tmpIn = cctxPtr->tmpBuff;
587  }
588  else
589  {
590  int realDictSize = LZ4F_localSaveDict(cctxPtr);
591  if (realDictSize==0) return (size_t)-ERROR_GENERIC;
592  cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
593  }
594  }
595 
596  /* keep tmpIn within limits */
597  if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily blockLinked && lastBlockCompressed==fromTmpBuffer */
598  && !(cctxPtr->prefs.autoFlush))
599  {
600  LZ4F_localSaveDict(cctxPtr);
601  cctxPtr->tmpIn = cctxPtr->tmpBuff + 64 KB;
602  }
603 
604  /* some input data left, necessarily < blockSize */
605  if (srcPtr < srcEnd)
606  {
607  /* fill tmp buffer */
608  size_t sizeToCopy = srcEnd - srcPtr;
609  memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
610  cctxPtr->tmpInSize = sizeToCopy;
611  }
612 
614  XXH32_update(&(cctxPtr->xxh), srcBuffer, (unsigned)srcSize);
615 
616  return dstPtr - dstStart;
617 }
618 
619 
620 /* LZ4F_flush()
621 * Should you need to create compressed data immediately, without waiting for a block to be filled,
622 * you can call LZ4_flush(), which will immediately compress any remaining data stored within compressionContext.
623 * The result of the function is the number of bytes written into dstBuffer
624 * (it can be zero, this means there was no data left within compressionContext)
625 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
626 * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
627 */
628 size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
629 {
630  LZ4F_compressOptions_t cOptionsNull = { 0 };
631  LZ4F_cctx_internal_t* cctxPtr = (LZ4F_cctx_internal_t*)compressionContext;
632  BYTE* const dstStart = (BYTE*)dstBuffer;
633  BYTE* dstPtr = dstStart;
635 
636 
637  if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
638  if (cctxPtr->cStage != 1) return (size_t)-ERROR_GENERIC;
639  if (dstMaxSize < (cctxPtr->tmpInSize + 16)) return (size_t)-ERROR_dstMaxSize_tooSmall;
640  if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
641  (void)compressOptionsPtr; /* not yet useful */
642 
643  /* select compression function */
644  compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
645 
646  /* compress tmp buffer */
647  dstPtr += LZ4F_compressBlock(dstPtr, cctxPtr->tmpIn, cctxPtr->tmpInSize, compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
648  if (cctxPtr->prefs.frameInfo.blockMode==blockLinked) cctxPtr->tmpIn += cctxPtr->tmpInSize;
649  cctxPtr->tmpInSize = 0;
650 
651  /* keep tmpIn within limits */
652  if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) /* necessarily blockLinked */
653  {
654  LZ4F_localSaveDict(cctxPtr);
655  cctxPtr->tmpIn = cctxPtr->tmpBuff + 64 KB;
656  }
657 
658  return dstPtr - dstStart;
659 }
660 
661 
662 /* LZ4F_compressEnd()
663 * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
664 * It will flush whatever data remained within compressionContext (like LZ4_flush())
665 * but also properly finalize the frame, with an endMark and a checksum.
666 * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
667 * The function outputs an error code if it fails (can be tested using LZ4F_isError())
668 * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
669 * compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.
670 */
671 size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr)
672 {
673  LZ4F_cctx_internal_t* cctxPtr = (LZ4F_cctx_internal_t*)compressionContext;
674  BYTE* const dstStart = (BYTE*)dstBuffer;
675  BYTE* dstPtr = dstStart;
676  size_t errorCode;
677 
678  errorCode = LZ4F_flush(compressionContext, dstBuffer, dstMaxSize, compressOptionsPtr);
679  if (LZ4F_isError(errorCode)) return errorCode;
680  dstPtr += errorCode;
681 
682  LZ4F_writeLE32(dstPtr, 0);
683  dstPtr+=4; /* endMark */
684 
686  {
687  U32 xxh = XXH32_digest(&(cctxPtr->xxh));
688  LZ4F_writeLE32(dstPtr, xxh);
689  dstPtr+=4; /* content Checksum */
690  }
691 
692  cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
693 
694  return dstPtr - dstStart;
695 }
696 
697 
698 /***********************************
699 * Decompression functions
700 * *********************************/
701 
702 /* Resource management */
703 
704 /* LZ4F_createDecompressionContext() :
705 * The first thing to do is to create a decompressionContext object, which will be used in all decompression operations.
706 * This is achieved using LZ4F_createDecompressionContext().
707 * The function will provide a pointer to a fully allocated and initialized LZ4F_decompressionContext object.
708 * If the result LZ4F_errorCode_t is not zero, there was an error during context creation.
709 * Object can release its memory using LZ4F_freeDecompressionContext();
710 */
711 LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_compressionContext_t* LZ4F_decompressionContextPtr, unsigned versionNumber)
712 {
713  LZ4F_dctx_internal_t* dctxPtr;
714 
715  dctxPtr = ALLOCATOR(sizeof(LZ4F_dctx_internal_t));
716  if (dctxPtr==NULL) return (LZ4F_errorCode_t)-ERROR_GENERIC;
717 
718  dctxPtr->version = versionNumber;
719  *LZ4F_decompressionContextPtr = (LZ4F_compressionContext_t)dctxPtr;
720  return OK_NoError;
721 }
722 
724 {
725  LZ4F_dctx_internal_t* dctxPtr = (LZ4F_dctx_internal_t*)LZ4F_decompressionContext;
726  FREEMEM(dctxPtr->tmpIn);
727  FREEMEM(dctxPtr->tmpOutBuffer);
728  FREEMEM(dctxPtr);
729  return OK_NoError;
730 }
731 
732 
733 /* Decompression */
734 
735 static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const BYTE* srcPtr, size_t srcSize)
736 {
737  BYTE FLG, BD, HC;
738  unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictFlag, blockSizeID;
739  size_t bufferNeeded;
740 
741  /* need to decode header to get frameInfo */
742  if (srcSize < 7) return (size_t)-ERROR_GENERIC; /* minimal header size */
743 
744  /* control magic number */
745  if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) return (size_t)-ERROR_GENERIC;
746  srcPtr += 4;
747 
748  /* Flags */
749  FLG = srcPtr[0];
750  version = (FLG>>6)&_2BITS;
751  blockMode = (FLG>>5) & _1BIT;
752  blockChecksumFlag = (FLG>>4) & _1BIT;
753  contentSizeFlag = (FLG>>3) & _1BIT;
754  contentChecksumFlag = (FLG>>2) & _1BIT;
755  dictFlag = (FLG>>0) & _1BIT;
756  BD = srcPtr[1];
757  blockSizeID = (BD>>4) & _3BITS;
758 
759  /* check */
760  HC = LZ4F_headerChecksum(srcPtr, 2);
761  if (HC != srcPtr[2]) return (size_t)-ERROR_GENERIC; /* Bad header checksum error */
762 
763  /* validate */
764  if (version != 1) return (size_t)-ERROR_GENERIC; /* Version Number, only supported value */
765  if (blockChecksumFlag != 0) return (size_t)-ERROR_GENERIC; /* Only supported value for the time being */
766  if (contentSizeFlag != 0) return (size_t)-ERROR_GENERIC; /* Only supported value for the time being */
767  if (((FLG>>1)&_1BIT) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bit */
768  if (dictFlag != 0) return (size_t)-ERROR_GENERIC; /* Only supported value for the time being */
769  if (((BD>>7)&_1BIT) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bit */
770  if (blockSizeID < 4) return (size_t)-ERROR_GENERIC; /* Only supported values for the time being */
771  if (((BD>>0)&_4BITS) != 0) return (size_t)-ERROR_GENERIC; /* Reserved bits */
772 
773  /* save */
774  dctxPtr->frameInfo.blockMode = blockMode;
775  dctxPtr->frameInfo.contentChecksumFlag = contentChecksumFlag;
776  dctxPtr->frameInfo.blockSizeID = blockSizeID;
777  dctxPtr->maxBlockSize = LZ4F_getBlockSize(blockSizeID);
778 
779  /* init */
780  if (contentChecksumFlag) XXH32_reset(&(dctxPtr->xxh), 0);
781 
782  /* alloc */
783  bufferNeeded = dctxPtr->maxBlockSize + ((dctxPtr->frameInfo.blockMode==blockLinked) * 128 KB);
784  if (bufferNeeded > dctxPtr->maxBufferSize) /* tmp buffers too small */
785  {
786  FREEMEM(dctxPtr->tmpIn);
787  FREEMEM(dctxPtr->tmpOutBuffer);
788  dctxPtr->maxBufferSize = bufferNeeded;
789  dctxPtr->tmpIn = ALLOCATOR(dctxPtr->maxBlockSize);
790  if (dctxPtr->tmpIn == NULL) return (size_t)-ERROR_GENERIC;
791  dctxPtr->tmpOutBuffer= ALLOCATOR(dctxPtr->maxBufferSize);
792  if (dctxPtr->tmpOutBuffer== NULL) return (size_t)-ERROR_GENERIC;
793  }
794  dctxPtr->tmpInSize = 0;
795  dctxPtr->tmpInTarget = 0;
796  dctxPtr->dict = dctxPtr->tmpOutBuffer;
797  dctxPtr->dictSize = 0;
798  dctxPtr->tmpOut = dctxPtr->tmpOutBuffer;
799  dctxPtr->tmpOutStart = 0;
800  dctxPtr->tmpOutSize = 0;
801 
802  return 7;
803 }
804 
805 
812 } dStage_t;
813 
814 
815 /* LZ4F_getFrameInfo()
816 * This function decodes frame header information, such as blockSize.
817 * It is optional : you could start by calling directly LZ4F_decompress() instead.
818 * The objective is to extract header information without starting decompression, typically for allocation purposes.
819 * LZ4F_getFrameInfo() can also be used *after* starting decompression, on a valid LZ4F_decompressionContext_t.
820 * The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
821 * You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)
822 * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress,
823 * or an error code which can be tested using LZ4F_isError().
824 */
825 LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t decompressionContext, LZ4F_frameInfo_t* frameInfoPtr, const void* srcBuffer, size_t* srcSizePtr)
826 {
827  LZ4F_dctx_internal_t* dctxPtr = (LZ4F_dctx_internal_t*)decompressionContext;
828 
829  if (dctxPtr->dStage == dstage_getHeader)
830  {
831  LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, srcBuffer, *srcSizePtr);
832  if (LZ4F_isError(errorCode)) return errorCode;
833  *srcSizePtr = errorCode;
834  *frameInfoPtr = dctxPtr->frameInfo;
835  dctxPtr->srcExpect = NULL;
836  dctxPtr->dStage = dstage_getCBlockSize;
837  return 4;
838  }
839 
840  /* frameInfo already decoded */
841  *srcSizePtr = 0;
842  *frameInfoPtr = dctxPtr->frameInfo;
843  return 0;
844 }
845 
846 
847 static int LZ4F_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize)
848 {
849  (void)dictStart;
850  (void)dictSize;
851  return LZ4_decompress_safe (source, dest, compressedSize, maxDecompressedSize);
852 }
853 
854 
855 
856 static void LZ4F_updateDict(LZ4F_dctx_internal_t* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)
857 {
858  if (dctxPtr->dictSize==0)
859  dctxPtr->dict = (BYTE*)dstPtr; /* priority to dictionary continuity */
860 
861  if (dctxPtr->dict + dctxPtr->dictSize == dstPtr) /* dictionary continuity */
862  {
863  dctxPtr->dictSize += dstSize;
864  return;
865  }
866 
867  if (dstPtr - dstPtr0 + dstSize >= 64 KB) /* dstBuffer large enough to become dictionary */
868  {
869  dctxPtr->dict = (BYTE*)dstPtr0;
870  dctxPtr->dictSize = dstPtr - dstPtr0 + dstSize;
871  return;
872  }
873 
874  if ((withinTmp) && (dctxPtr->dict == dctxPtr->tmpOutBuffer))
875  {
876  /* assumption : dctxPtr->dict + dctxPtr->dictSize == dctxPtr->tmpOut + dctxPtr->tmpOutStart */
877  dctxPtr->dictSize += dstSize;
878  return;
879  }
880 
881  if (withinTmp) /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */
882  {
883 #if 0
884  size_t savedDictSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;
885  memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart- savedDictSize, savedDictSize);
886  dctxPtr->dict = dctxPtr->tmpOutBuffer;
887  dctxPtr->dictSize = savedDictSize + dctxPtr->tmpOutStart + dstSize;
888  return;
889 
890 #else
891 
892  size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;
893  size_t copySize = 64 KB - dctxPtr->tmpOutSize;
894  BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;
895  if (dctxPtr->tmpOutSize > 64 KB) copySize = 0;
896  if (copySize > preserveSize) copySize = preserveSize;
897 
898  memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
899 
900  dctxPtr->dict = dctxPtr->tmpOutBuffer;
901  dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart + dstSize;
902  return;
903 #endif
904  }
905 
906  if (dctxPtr->dict == dctxPtr->tmpOutBuffer) /* copy dst into tmp to complete dict */
907  {
908  if (dctxPtr->dictSize + dstSize > dctxPtr->maxBufferSize) /* tmp buffer not large enough */
909  {
910  size_t preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
911  memcpy(dctxPtr->dict, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);
912  dctxPtr->dictSize = preserveSize;
913  }
914  memcpy(dctxPtr->dict + dctxPtr->dictSize, dstPtr, dstSize);
915  dctxPtr->dictSize += dstSize;
916  return;
917  }
918 
919  /* join dict & dest into tmp */
920  {
921  size_t preserveSize = 64 KB - dstSize; /* note : dstSize < 64 KB */
922  if (preserveSize > dctxPtr->dictSize) preserveSize = dctxPtr->dictSize;
923  memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);
924  memcpy(dctxPtr->tmpOutBuffer + preserveSize, dstPtr, dstSize);
925  dctxPtr->dict = dctxPtr->tmpOutBuffer;
926  dctxPtr->dictSize = preserveSize + dstSize;
927  }
928 }
929 
930 
931 
932 /* LZ4F_decompress()
933 * Call this function repetitively to regenerate data compressed within srcBuffer.
934 * The function will attempt to decode *srcSizePtr from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
935 *
936 * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
937 *
938 * The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
939 * If the number of bytes read is < number of bytes provided, then the decompression operation is not complete.
940 * You will have to call it again, continuing from where it stopped.
941 *
942 * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
943 * Basically, it's the size of the current (or remaining) compressed block + header of next block.
944 * Respecting the hint provides some boost to performance, since it allows less buffer shuffling.
945 * Note that this is just a hint, you can always provide any srcSize you want.
946 * When a frame is fully decoded, the function result will be 0.
947 * If decompression failed, function result is an error code which can be tested using LZ4F_isError().
948 */
949 size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
950  void* dstBuffer, size_t* dstSizePtr,
951  const void* srcBuffer, size_t* srcSizePtr,
952  const LZ4F_decompressOptions_t* decompressOptionsPtr)
953 {
954  LZ4F_dctx_internal_t* dctxPtr = (LZ4F_dctx_internal_t*)decompressionContext;
955  static const LZ4F_decompressOptions_t optionsNull = { 0 };
956  const BYTE* const srcStart = (const BYTE*)srcBuffer;
957  const BYTE* const srcEnd = srcStart + *srcSizePtr;
958  const BYTE* srcPtr = srcStart;
959  BYTE* const dstStart = (BYTE*)dstBuffer;
960  BYTE* const dstEnd = dstStart + *dstSizePtr;
961  BYTE* dstPtr = dstStart;
962  const BYTE* selectedIn=NULL;
963  unsigned doAnotherStage = 1;
964  size_t nextSrcSizeHint = 1;
965 
966 
967  if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
968  *srcSizePtr = 0;
969  *dstSizePtr = 0;
970 
971  /* expect to continue decoding src buffer where it left previously */
972  if (dctxPtr->srcExpect != NULL)
973  {
974  if (srcStart != dctxPtr->srcExpect) return (size_t)-ERROR_GENERIC;
975  }
976 
977  /* programmed as a state machine */
978 
979  while (doAnotherStage)
980  {
981 
982  switch(dctxPtr->dStage)
983  {
984 
985  case dstage_getHeader:
986  {
987  if (srcEnd-srcPtr >= 7)
988  {
989  selectedIn = srcPtr;
990  srcPtr += 7;
991  dctxPtr->dStage = dstage_decodeHeader;
992  break;
993  }
994  dctxPtr->tmpInSize = 0;
995  dctxPtr->dStage = dstage_storeHeader;
996  break;
997  }
998 
999  case dstage_storeHeader:
1000  {
1001  size_t sizeToCopy = 7 - dctxPtr->tmpInSize;
1002  if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1003  memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1004  dctxPtr->tmpInSize += sizeToCopy;
1005  srcPtr += sizeToCopy;
1006  if (dctxPtr->tmpInSize < 7)
1007  {
1008  nextSrcSizeHint = (7 - dctxPtr->tmpInSize) + 4;
1009  doAnotherStage = 0; /* no enough src, wait to get some more */
1010  break;
1011  }
1012  selectedIn = dctxPtr->header;
1013  dctxPtr->dStage = dstage_decodeHeader;
1014  break;
1015  }
1016 
1017  case dstage_decodeHeader:
1018  {
1019  LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, selectedIn, 7);
1020  if (LZ4F_isError(errorCode)) return errorCode;
1021  dctxPtr->dStage = dstage_getCBlockSize;
1022  break;
1023  }
1024 
1025  case dstage_getCBlockSize:
1026  {
1027  if ((srcEnd - srcPtr) >= 4)
1028  {
1029  selectedIn = srcPtr;
1030  srcPtr += 4;
1031  dctxPtr->dStage = dstage_decodeCBlockSize;
1032  break;
1033  }
1034  /* not enough input to read cBlockSize field */
1035  dctxPtr->tmpInSize = 0;
1036  dctxPtr->dStage = dstage_storeCBlockSize;
1037  break;
1038  }
1039 
1041  {
1042  size_t sizeToCopy = 4 - dctxPtr->tmpInSize;
1043  if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1044  memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1045  srcPtr += sizeToCopy;
1046  dctxPtr->tmpInSize += sizeToCopy;
1047  if (dctxPtr->tmpInSize < 4) /* not enough input to get full cBlockSize; wait for more */
1048  {
1049  nextSrcSizeHint = 4 - dctxPtr->tmpInSize;
1050  doAnotherStage=0;
1051  break;
1052  }
1053  selectedIn = dctxPtr->tmpIn;
1054  dctxPtr->dStage = dstage_decodeCBlockSize;
1055  break;
1056  }
1057 
1059  {
1060  size_t nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
1061  if (nextCBlockSize==0) /* frameEnd signal, no more CBlock */
1062  {
1063  dctxPtr->dStage = dstage_getSuffix;
1064  break;
1065  }
1066  if (nextCBlockSize > dctxPtr->maxBlockSize) return (size_t)-ERROR_GENERIC; /* invalid cBlockSize */
1067  dctxPtr->tmpInTarget = nextCBlockSize;
1068  if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG)
1069  {
1070  dctxPtr->dStage = dstage_copyDirect;
1071  break;
1072  }
1073  dctxPtr->dStage = dstage_getCBlock;
1074  if (dstPtr==dstEnd)
1075  {
1076  nextSrcSizeHint = nextCBlockSize + 4;
1077  doAnotherStage = 0;
1078  }
1079  break;
1080  }
1081 
1082  case dstage_copyDirect: /* uncompressed block */
1083  {
1084  size_t sizeToCopy = dctxPtr->tmpInTarget;
1085  if ((size_t)(srcEnd-srcPtr) < sizeToCopy) sizeToCopy = srcEnd - srcPtr; /* not enough input to read full block */
1086  if ((size_t)(dstEnd-dstPtr) < sizeToCopy) sizeToCopy = dstEnd - dstPtr;
1087  memcpy(dstPtr, srcPtr, sizeToCopy);
1088  if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), srcPtr, (U32)sizeToCopy);
1089 
1090  /* dictionary management */
1091  if (dctxPtr->frameInfo.blockMode==blockLinked)
1092  LZ4F_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 0);
1093 
1094  srcPtr += sizeToCopy;
1095  dstPtr += sizeToCopy;
1096  if (sizeToCopy == dctxPtr->tmpInTarget) /* all copied */
1097  {
1098  dctxPtr->dStage = dstage_getCBlockSize;
1099  break;
1100  }
1101  dctxPtr->tmpInTarget -= sizeToCopy; /* still need to copy more */
1102  nextSrcSizeHint = dctxPtr->tmpInTarget + 4;
1103  doAnotherStage = 0;
1104  break;
1105  }
1106 
1107  case dstage_getCBlock: /* entry from dstage_decodeCBlockSize */
1108  {
1109  if ((size_t)(srcEnd-srcPtr) < dctxPtr->tmpInTarget)
1110  {
1111  dctxPtr->tmpInSize = 0;
1112  dctxPtr->dStage = dstage_storeCBlock;
1113  break;
1114  }
1115  selectedIn = srcPtr;
1116  srcPtr += dctxPtr->tmpInTarget;
1117  dctxPtr->dStage = dstage_decodeCBlock;
1118  break;
1119  }
1120 
1121  case dstage_storeCBlock:
1122  {
1123  size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;
1124  if (sizeToCopy > (size_t)(srcEnd-srcPtr)) sizeToCopy = srcEnd-srcPtr;
1125  memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1126  dctxPtr->tmpInSize += sizeToCopy;
1127  srcPtr += sizeToCopy;
1128  if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) /* need more input */
1129  {
1130  nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + 4;
1131  doAnotherStage=0;
1132  break;
1133  }
1134  selectedIn = dctxPtr->tmpIn;
1135  dctxPtr->dStage = dstage_decodeCBlock;
1136  break;
1137  }
1138 
1139  case dstage_decodeCBlock:
1140  {
1141  if ((size_t)(dstEnd-dstPtr) < dctxPtr->maxBlockSize) /* not enough place into dst : decode into tmpOut */
1143  else
1145  break;
1146  }
1147 
1149  {
1150  int (*decoder)(const char*, char*, int, int, const char*, int);
1151  int decodedSize;
1152 
1153  if (dctxPtr->frameInfo.blockMode == blockLinked)
1155  else
1156  decoder = LZ4F_decompress_safe;
1157 
1158  decodedSize = decoder((const char*)selectedIn, (char*)dstPtr, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
1159  if (decodedSize < 0) return (size_t)-ERROR_GENERIC; /* decompression failed */
1160  if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dstPtr, decodedSize);
1161 
1162  /* dictionary management */
1163  if (dctxPtr->frameInfo.blockMode==blockLinked)
1164  LZ4F_updateDict(dctxPtr, dstPtr, decodedSize, dstStart, 0);
1165 
1166  dstPtr += decodedSize;
1167  dctxPtr->dStage = dstage_getCBlockSize;
1168  break;
1169  }
1170 
1172  {
1173  /* not enough place into dst : decode into tmpOut */
1174  int (*decoder)(const char*, char*, int, int, const char*, int);
1175  int decodedSize;
1176 
1177  if (dctxPtr->frameInfo.blockMode == blockLinked)
1179  else
1180  decoder = LZ4F_decompress_safe;
1181 
1182  /* ensure enough place for tmpOut */
1183  if (dctxPtr->frameInfo.blockMode == blockLinked)
1184  {
1185  if (dctxPtr->dict == dctxPtr->tmpOutBuffer)
1186  {
1187  if (dctxPtr->dictSize > 128 KB)
1188  {
1189  memcpy(dctxPtr->dict, dctxPtr->dict + dctxPtr->dictSize - 64 KB, 64 KB);
1190  dctxPtr->dictSize = 64 KB;
1191  }
1192  dctxPtr->tmpOut = dctxPtr->dict + dctxPtr->dictSize;
1193  }
1194  else /* dict not within tmp */
1195  {
1196  size_t reservedDictSpace = dctxPtr->dictSize;
1197  if (reservedDictSpace > 64 KB) reservedDictSpace = 64 KB;
1198  dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + reservedDictSpace;
1199  }
1200  }
1201 
1202  /* Decode */
1203  decodedSize = decoder((const char*)selectedIn, (char*)dctxPtr->tmpOut, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
1204  if (decodedSize < 0) return (size_t)-ERROR_decompressionFailed; /* decompression failed */
1205  if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dctxPtr->tmpOut, decodedSize);
1206  dctxPtr->tmpOutSize = decodedSize;
1207  dctxPtr->tmpOutStart = 0;
1208  dctxPtr->dStage = dstage_flushOut;
1209  break;
1210  }
1211 
1212  case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
1213  {
1214  size_t sizeToCopy = dctxPtr->tmpOutSize - dctxPtr->tmpOutStart;
1215  if (sizeToCopy > (size_t)(dstEnd-dstPtr)) sizeToCopy = dstEnd-dstPtr;
1216  memcpy(dstPtr, dctxPtr->tmpOut + dctxPtr->tmpOutStart, sizeToCopy);
1217 
1218  /* dictionary management */
1219  if (dctxPtr->frameInfo.blockMode==blockLinked)
1220  LZ4F_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 1);
1221 
1222  dctxPtr->tmpOutStart += sizeToCopy;
1223  dstPtr += sizeToCopy;
1224 
1225  /* end of flush ? */
1226  if (dctxPtr->tmpOutStart == dctxPtr->tmpOutSize)
1227  {
1228  dctxPtr->dStage = dstage_getCBlockSize;
1229  break;
1230  }
1231  nextSrcSizeHint = 4;
1232  doAnotherStage = 0; /* still some data to flush */
1233  break;
1234  }
1235 
1236  case dstage_getSuffix:
1237  {
1238  size_t suffixSize = dctxPtr->frameInfo.contentChecksumFlag * 4;
1239  if (suffixSize == 0) /* frame completed */
1240  {
1241  nextSrcSizeHint = 0;
1242  dctxPtr->dStage = dstage_getHeader;
1243  doAnotherStage = 0;
1244  break;
1245  }
1246  if ((srcEnd - srcPtr) >= 4) /* CRC present */
1247  {
1248  selectedIn = srcPtr;
1249  srcPtr += 4;
1250  dctxPtr->dStage = dstage_checkSuffix;
1251  break;
1252  }
1253  dctxPtr->tmpInSize = 0;
1254  dctxPtr->dStage = dstage_storeSuffix;
1255  break;
1256  }
1257 
1258  case dstage_storeSuffix:
1259  {
1260  size_t sizeToCopy = 4 - dctxPtr->tmpInSize;
1261  if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1262  memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
1263  srcPtr += sizeToCopy;
1264  dctxPtr->tmpInSize += sizeToCopy;
1265  if (dctxPtr->tmpInSize < 4) /* not enough input to read complete suffix */
1266  {
1267  nextSrcSizeHint = 4 - dctxPtr->tmpInSize;
1268  doAnotherStage=0;
1269  break;
1270  }
1271  selectedIn = dctxPtr->tmpIn;
1272  dctxPtr->dStage = dstage_checkSuffix;
1273  break;
1274  }
1275 
1276  case dstage_checkSuffix:
1277  {
1278  U32 readCRC = LZ4F_readLE32(selectedIn);
1279  U32 resultCRC = XXH32_digest(&(dctxPtr->xxh));
1280  if (readCRC != resultCRC) return (size_t)-ERROR_checksum_invalid;
1281  nextSrcSizeHint = 0;
1282  dctxPtr->dStage = dstage_getHeader;
1283  doAnotherStage = 0;
1284  break;
1285  }
1286  }
1287  }
1288 
1289  /* preserve dictionary within tmp if necessary */
1290  if ( (dctxPtr->frameInfo.blockMode==blockLinked)
1291  &&(dctxPtr->dict != dctxPtr->tmpOutBuffer)
1292  &&(!decompressOptionsPtr->stableDst)
1293  &&((unsigned)(dctxPtr->dStage-1) < (unsigned)(dstage_getSuffix-1))
1294  )
1295  {
1296  if (dctxPtr->dStage == dstage_flushOut)
1297  {
1298  size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;
1299  size_t copySize = 64 KB - dctxPtr->tmpOutSize;
1300  BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;
1301  if (dctxPtr->tmpOutSize > 64 KB) copySize = 0;
1302  if (copySize > preserveSize) copySize = preserveSize;
1303 
1304  memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1305 
1306  dctxPtr->dict = dctxPtr->tmpOutBuffer;
1307  dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart;
1308  }
1309  else
1310  {
1311  size_t newDictSize = dctxPtr->dictSize;
1312  BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize;
1313  if ((newDictSize) > 64 KB) newDictSize = 64 KB;
1314 
1315  memcpy(dctxPtr->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1316 
1317  dctxPtr->dict = dctxPtr->tmpOutBuffer;
1318  dctxPtr->dictSize = newDictSize;
1319  dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + newDictSize;
1320  }
1321  }
1322 
1323  if (srcPtr<srcEnd) /* function must be called again with following source data */
1324  dctxPtr->srcExpect = srcPtr;
1325  else
1326  dctxPtr->srcExpect = NULL;
1327  *srcSizePtr = (srcPtr - srcStart);
1328  *dstSizePtr = (dstPtr - dstStart);
1329  return nextSrcSizeHint;
1330 }