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