Home | History | Annotate | Download | only in lib
      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 {
    117     LZ4F_preferences_t prefs;
    118     U32 version;
    119     U32 cStage;
    120     size_t maxBlockSize;
    121     size_t maxBufferSize;
    122     BYTE*  tmpBuff;
    123     BYTE*  tmpIn;
    124     size_t tmpInSize;
    125     XXH32_state_t xxh;
    126     void* lz4CtxPtr;
    127     U32 lz4CtxLevel;     /* 0: unallocated;  1: LZ4_stream_t;  3: LZ4_streamHC_t */
    128 } LZ4F_cctx_internal_t;
    129 
    130 typedef struct
    131 {
    132     LZ4F_frameInfo_t frameInfo;
    133     unsigned version;
    134     unsigned dStage;
    135     size_t maxBlockSize;
    136     size_t maxBufferSize;
    137     const BYTE* srcExpect;
    138     BYTE*  tmpIn;
    139     size_t tmpInSize;
    140     size_t tmpInTarget;
    141     BYTE*  tmpOutBuffer;
    142     BYTE*  dict;
    143     size_t dictSize;
    144     BYTE*  tmpOut;
    145     size_t tmpOutSize;
    146     size_t tmpOutStart;
    147     XXH32_state_t xxh;
    148     BYTE   header[8];
    149 } LZ4F_dctx_internal_t;
    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 
    164 U32 LZ4F_isError(LZ4F_errorCode_t code)
    165 {
    166     return (code > (LZ4F_errorCode_t)(-ERROR_maxCode));
    167 }
    168 
    169 const char* LZ4F_getErrorName(LZ4F_errorCode_t code)
    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 
    332     cctxPtr = (LZ4F_cctx_internal_t*)ALLOCATOR(sizeof(LZ4F_cctx_internal_t));
    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 
    344 LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
    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 */
    391     if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
    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
    411         LZ4_resetStreamHC((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), cctxPtr->prefs.compressionLevel);
    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     }
    497     if (blockMode == blockIndependent) return LZ4_compressHC2_limitedOutput_withStateHC;
    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 
    508 typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
    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;
    529     compressFunc_t compress;
    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 
    613     if (cctxPtr->prefs.frameInfo.contentChecksumFlag == contentChecksumEnabled)
    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;
    634     compressFunc_t compress;
    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 
    685     if (cctxPtr->prefs.frameInfo.contentChecksumFlag == contentChecksumEnabled)
    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 
    723 LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_compressionContext_t LZ4F_decompressionContext)
    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 
    806 typedef enum { dstage_getHeader=0, dstage_storeHeader, dstage_decodeHeader,
    807     dstage_getCBlockSize, dstage_storeCBlockSize, dstage_decodeCBlockSize,
    808     dstage_copyDirect,
    809     dstage_getCBlock, dstage_storeCBlock, dstage_decodeCBlock,
    810     dstage_decodeCBlock_intoDst, dstage_decodeCBlock_intoTmp, dstage_flushOut,
    811     dstage_getSuffix, dstage_storeSuffix, dstage_checkSuffix
    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 
   1040         case dstage_storeCBlockSize:
   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 
   1058         case dstage_decodeCBlockSize:
   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 */
   1142                     dctxPtr->dStage = dstage_decodeCBlock_intoTmp;
   1143                 else
   1144                     dctxPtr->dStage = dstage_decodeCBlock_intoDst;
   1145                 break;
   1146             }
   1147 
   1148         case dstage_decodeCBlock_intoDst:
   1149             {
   1150                 int (*decoder)(const char*, char*, int, int, const char*, int);
   1151                 int decodedSize;
   1152 
   1153                 if (dctxPtr->frameInfo.blockMode == blockLinked)
   1154                     decoder = LZ4_decompress_safe_usingDict;
   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 
   1171         case dstage_decodeCBlock_intoTmp:
   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)
   1178                     decoder = LZ4_decompress_safe_usingDict;
   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 }
   1331