From 559693c75bcc0f0d411eaf8c3faa7e40f3f07562 Mon Sep 17 00:00:00 2001 From: Tino Reichardt Date: Tue, 9 Aug 2016 09:44:05 +0200 Subject: [PATCH] zstd release 0.8.0 - made an extra zstd.mak file - removed Format7zZStd - SFXSetup also has zstd now - the big 7z.dll is backward compatible to: 0.5 .. 0.7 - the small 7za.dll has only support for zstd 0.8 --- C/zstd/entropy_common.c | 65 +- C/zstd/fse_compress.c | 2 +- C/zstd/huf.h | 2 +- C/zstd/huf_compress.c | 77 +- C/zstd/mem.h | 26 +- C/zstd/zbuff.h | 17 +- C/zstd/zbuff_compress.c | 53 +- C/zstd/zbuff_decompress.c | 49 +- C/zstd/zstd.h | 185 +- C/zstd/zstd_compress.c | 797 ++-- C/zstd/zstd_decompress.c | 554 ++- C/zstd/zstd_internal.h | 70 +- C/zstd/zstd_legacy.h | 53 +- C/zstd/zstd_opt.h | 96 +- C/zstd/zstd_v05.c | 433 +- C/zstd/zstd_v05.h | 37 +- C/zstd/zstd_v06.c | 4 +- C/zstd/zstd_v06.h | 2 +- C/zstd/zstd_v07.c | 4936 +++++++++++++++++++++ C/zstd/zstd_v07.h | 196 + CPP/7zip/7zip.mak | 4 +- CPP/7zip/Bundles/Format7z/makefile | 32 +- CPP/7zip/Bundles/Format7zF/makefile | 19 +- CPP/7zip/Bundles/Format7zZStd/StdAfx.cpp | 3 - CPP/7zip/Bundles/Format7zZStd/StdAfx.h | 8 - CPP/7zip/Bundles/Format7zZStd/makefile | 158 - CPP/7zip/Bundles/Format7zZStd/resource.rc | 5 - CPP/7zip/Bundles/SFXCon/makefile | 13 +- CPP/7zip/Bundles/SFXSetup/makefile | 1 + CPP/7zip/Bundles/SFXWin/makefile | 13 +- CPP/7zip/Compress/ZstdDecoder.cpp | 824 ++-- CPP/7zip/Compress/ZstdDecoder.h | 220 +- CPP/7zip/Compress/ZstdEncoder.cpp | 382 +- CPP/7zip/Compress/ZstdEncoder.h | 152 +- CPP/7zip/Compress/ZstdRegister.cpp | 36 +- CPP/7zip/zstd.mak | 14 + CPP/build-x32.cmd | 35 +- CPP/build-x64.cmd | 38 +- 38 files changed, 7010 insertions(+), 2601 deletions(-) create mode 100644 C/zstd/zstd_v07.c create mode 100644 C/zstd/zstd_v07.h delete mode 100644 CPP/7zip/Bundles/Format7zZStd/StdAfx.cpp delete mode 100644 CPP/7zip/Bundles/Format7zZStd/StdAfx.h delete mode 100644 CPP/7zip/Bundles/Format7zZStd/makefile delete mode 100644 CPP/7zip/Bundles/Format7zZStd/resource.rc create mode 100644 CPP/7zip/zstd.mak diff --git a/C/zstd/entropy_common.c b/C/zstd/entropy_common.c index b42acb4a..acd96699 100644 --- a/C/zstd/entropy_common.c +++ b/C/zstd/entropy_common.c @@ -38,10 +38,9 @@ #include "mem.h" #include "error_private.h" /* ERR_*, ERROR */ #define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ -#include "fse.h" /* FSE_isError, FSE_getErrorName */ +#include "fse.h" #define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */ -#include "huf.h" /* HUF_isError, HUF_getErrorName */ - +#include "huf.h" /*-**************************************** @@ -63,7 +62,7 @@ const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } /*-************************************************************** * FSE NCount encoding-decoding ****************************************************************/ -static short FSE_abs(short a) { return a<0 ? -a : a; } +static short FSE_abs(short a) { return (short)(a<0 ? -a : a); } size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, const void* headerBuffer, size_t hbSize) @@ -90,22 +89,22 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t threshold = 1<1) && (charnum<=*maxSVPtr)) { + while ((remaining>1) & (charnum<=*maxSVPtr)) { if (previous0) { unsigned n0 = charnum; while ((bitStream & 0xFFFF) == 0xFFFF) { - n0+=24; + n0 += 24; if (ip < iend-5) { - ip+=2; + ip += 2; bitStream = MEM_readLE32(ip) >> bitCount; } else { bitStream >>= 16; - bitCount+=16; + bitCount += 16; } } while ((bitStream & 3) == 3) { - n0+=3; - bitStream>>=2; - bitCount+=2; + n0 += 3; + bitStream >>= 2; + bitCount += 2; } n0 += bitStream & 3; bitCount += 2; @@ -115,10 +114,9 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t ip += bitCount>>3; bitCount &= 7; bitStream = MEM_readLE32(ip) >> bitCount; - } - else + } else { bitStream >>= 2; - } + } } { short const max = (short)((2*threshold-1)-remaining); short count; @@ -148,12 +146,12 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t ip = iend - 4; } bitStream = MEM_readLE32(ip) >> (bitCount & 31); - } } /* while ((remaining>1) && (charnum<=*maxSVPtr)) */ - if (remaining != 1) return ERROR(GENERIC); + } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ + if (remaining != 1) return ERROR(corruption_detected); + if (bitCount > 32) return ERROR(corruption_detected); *maxSVPtr = charnum-1; ip += (bitCount+7)>>3; - if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong); return ip-istart; } @@ -162,7 +160,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t Read compact Huffman tree, saved by HUF_writeCTable(). `huffWeight` is destination buffer. @return : size read from `src` , or an error Code . - Note : Needed by HUF_readCTable() and HUF_readDTableXn() . + Note : Needed by HUF_readCTable() and HUF_readDTableX?() . */ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, @@ -173,26 +171,19 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, size_t iSize = ip[0]; size_t oSize; - //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ - if (iSize >= 128) { /* special header */ - if (iSize >= (242)) { /* RLE */ - static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 }; - oSize = l[iSize-242]; - memset(huffWeight, 1, hwSize); - iSize = 0; - } - else { /* Incompressible */ - oSize = iSize - 127; - iSize = ((oSize+1)/2); - if (iSize+1 > srcSize) return ERROR(srcSize_wrong); - if (oSize >= hwSize) return ERROR(corruption_detected); - ip += 1; - { U32 n; - for (n=0; n> 4; - huffWeight[n+1] = ip[n/2] & 15; - } } } } + if (iSize >= 128) { /* special header */ + oSize = iSize - 127; + iSize = ((oSize+1)/2); + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + if (oSize >= hwSize) return ERROR(corruption_detected); + ip += 1; + { U32 n; + for (n=0; n> 4; + huffWeight[n+1] = ip[n/2] & 15; + } } } else { /* header compressed with FSE (normal case) */ if (iSize+1 > srcSize) return ERROR(srcSize_wrong); oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */ diff --git a/C/zstd/fse_compress.c b/C/zstd/fse_compress.c index 192d5502..386b2c01 100644 --- a/C/zstd/fse_compress.c +++ b/C/zstd/fse_compress.c @@ -190,7 +190,7 @@ size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog) return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ } -static short FSE_abs(short a) { return a<0 ? -a : a; } +static short FSE_abs(short a) { return (short)(a<0 ? -a : a); } static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, diff --git a/C/zstd/huf.h b/C/zstd/huf.h index 3b837f10..29bab4b7 100644 --- a/C/zstd/huf.h +++ b/C/zstd/huf.h @@ -100,7 +100,7 @@ size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize /* *** Constants *** */ #define HUF_TABLELOG_ABSOLUTEMAX 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ #define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ -#define HUF_TABLELOG_DEFAULT HUF_TABLELOG_MAX /* tableLog by default, when not specified */ +#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */ #define HUF_SYMBOLVALUE_MAX 255 #if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX) # error "HUF_TABLELOG_MAX is too large !" diff --git a/C/zstd/huf_compress.c b/C/zstd/huf_compress.c index 301b5f91..86a53c2e 100644 --- a/C/zstd/huf_compress.c +++ b/C/zstd/huf_compress.c @@ -105,68 +105,39 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog) { BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; - BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; - U32 n; + BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; BYTE* op = (BYTE*)dst; - size_t size; + U32 n; /* check conditions */ - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX + 1) - return ERROR(GENERIC); + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC); /* convert to weight */ bitsToWeight[0] = 0; - for (n=1; n<=huffLog; n++) + for (n=1; n= 128) return ERROR(GENERIC); /* should never happen, since maxSymbolValue <= 255 */ - if ((size <= 1) || (size >= maxSymbolValue/2)) { - if (size==1) { /* RLE */ - /* only possible case : series of 1 (because there are at least 2) */ - /* can only be 2^n or (2^n-1), otherwise not an huffman tree */ - BYTE code; - switch(maxSymbolValue) - { - case 1: code = 0; break; - case 2: code = 1; break; - case 3: code = 2; break; - case 4: code = 3; break; - case 7: code = 4; break; - case 8: code = 5; break; - case 15: code = 6; break; - case 16: code = 7; break; - case 31: code = 8; break; - case 32: code = 9; break; - case 63: code = 10; break; - case 64: code = 11; break; - case 127: code = 12; break; - case 128: code = 13; break; - default : return ERROR(corruption_detected); - } - op[0] = (BYTE)(255-13 + code); - return 1; - } - /* Not compressible */ - if (maxSymbolValue > (241-128)) return ERROR(GENERIC); /* not implemented (not possible with current format) */ - if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ - op[0] = (BYTE)(128 /*special case*/ + 0 /* Not Compressible */ + (maxSymbolValue-1)); - huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause issue in final combination */ - for (n=0; n1) & (size < maxSymbolValue/2)) { /* FSE compressed */ + op[0] = (BYTE)size; + return size+1; + } } + + /* raw values */ + if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen */ + if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ + op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1)); + huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause issue in final combination */ + for (n=0; n /* size_t, ptrdiff_t */ #include /* memcpy */ -#if defined(_MSC_VER) /* Visual Studio */ -# include /* _byteswap_ulong */ -#endif /*-**************************************** * Compiler specifics ******************************************/ -#if defined(_MSC_VER) -# include /* _byteswap_ */ +#if defined(_MSC_VER) /* Visual Studio */ +# include /* _byteswap_ulong */ +# include /* _byteswap_* */ #endif #if defined(__GNUC__) -# define MEM_STATIC static __attribute__((unused)) +# define MEM_STATIC static __inline __attribute__((unused)) #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define MEM_STATIC static inline #elif defined(_MSC_VER) @@ -65,6 +63,10 @@ extern "C" { # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ #endif +/* code only tested on 32 and 64 bits systems */ +#define MEM_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } +MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } + /*-************************************************************** * Basic Types @@ -256,6 +258,17 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) } } +MEM_STATIC U32 MEM_readLE24(const void* memPtr) +{ + return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); +} + +MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val) +{ + MEM_writeLE16(memPtr, (U16)val); + ((BYTE*)memPtr)[2] = (BYTE)(val>>16); +} + MEM_STATIC U32 MEM_readLE32(const void* memPtr) { if (MEM_isLittleEndian()) @@ -374,4 +387,3 @@ MEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length) #endif #endif /* MEM_H_MODULE */ - diff --git a/C/zstd/zbuff.h b/C/zstd/zbuff.h index 7820db26..269dc227 100644 --- a/C/zstd/zbuff.h +++ b/C/zstd/zbuff.h @@ -56,6 +56,12 @@ extern "C" { /* ************************************* * Streaming functions ***************************************/ +/* This is the easier "buffered" streaming API, +* using an internal buffer to lift all restrictions on user-provided buffers +* which can be any size, any place, for both input and output. +* ZBUFF and ZSTD are 100% interoperable, +* frames created by one can be decoded by the other one */ + typedef struct ZBUFF_CCtx_s ZBUFF_CCtx; ZSTDLIB_API ZBUFF_CCtx* ZBUFF_createCCtx(void); ZSTDLIB_API size_t ZBUFF_freeCCtx(ZBUFF_CCtx* cctx); @@ -133,8 +139,9 @@ ZSTDLIB_API size_t ZBUFF_decompressContinue(ZBUFF_DCtx* dctx, * The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. * Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. * The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`. -* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency), -* or 0 when a frame is completely decoded, +* @return : 0 when a frame is completely decoded and fully flushed, +* 1 when there is still some data left within internal buffer to flush, +* >1 when more data is expected, with value being a suggested next input size (it's just a hint, which helps latency), * or an error code, which can be tested using ZBUFF_isError(). * * Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize() and ZBUFF_recommendedDOutSize() @@ -168,11 +175,11 @@ ZSTDLIB_API size_t ZBUFF_recommendedDOutSize(void); * ==================================================================================== */ /*--- Dependency ---*/ -#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */ +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_customMem */ #include "zstd.h" -/*--- External memory ---*/ +/*--- Custom memory allocator ---*/ /*! ZBUFF_createCCtx_advanced() : * Create a ZBUFF compression context using external alloc and free functions */ ZSTDLIB_API ZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem); @@ -182,7 +189,7 @@ ZSTDLIB_API ZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem); ZSTDLIB_API ZBUFF_DCtx* ZBUFF_createDCtx_advanced(ZSTD_customMem customMem); -/*--- Advanced Streaming function ---*/ +/*--- Advanced Streaming Initialization ---*/ ZSTDLIB_API size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); diff --git a/C/zstd/zbuff_compress.c b/C/zstd/zbuff_compress.c index 837d22cf..5d929185 100644 --- a/C/zstd/zbuff_compress.c +++ b/C/zstd/zbuff_compress.c @@ -46,7 +46,7 @@ static size_t const ZBUFF_endFrameSize = ZSTD_BLOCKHEADERSIZE; -/*_************************************************** +/*-*********************************************************** * Streaming compression * * A ZBUFF_CCtx object is required to track streaming operation. @@ -77,7 +77,7 @@ static size_t const ZBUFF_endFrameSize = ZSTD_BLOCKHEADERSIZE; * Hint : recommended buffer sizes (not compulsory) * input : ZSTD_BLOCKSIZE_MAX (128 KB), internal unit size, it improves latency to use this value. * output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed. -* **************************************************/ +* ***********************************************************/ typedef enum { ZBUFFcs_init, ZBUFFcs_load, ZBUFFcs_flush, ZBUFFcs_final } ZBUFF_cStage; @@ -95,6 +95,8 @@ struct ZBUFF_CCtx_s { size_t outBuffContentSize; size_t outBuffFlushedSize; ZBUFF_cStage stage; + U32 checksum; + U32 frameEnded; ZSTD_customMem customMem; }; /* typedef'd tp ZBUFF_CCtx within "zstd_buffered.h" */ @@ -133,7 +135,7 @@ size_t ZBUFF_freeCCtx(ZBUFF_CCtx* zbc) } -/* *** Initialization *** */ +/* ====== Initialization ====== */ size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, @@ -147,7 +149,7 @@ size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, zbc->inBuff = (char*)zbc->customMem.customAlloc(zbc->customMem.opaque, neededInBuffSize); if (zbc->inBuff == NULL) return ERROR(memory_allocation); } - zbc->blockSize = MIN(ZSTD_BLOCKSIZE_MAX, neededInBuffSize); + zbc->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize); } if (zbc->outBuffSize < ZSTD_compressBound(zbc->blockSize)+1) { zbc->outBuffSize = ZSTD_compressBound(zbc->blockSize)+1; @@ -164,6 +166,8 @@ size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, zbc->inBuffTarget = zbc->blockSize; zbc->outBuffContentSize = zbc->outBuffFlushedSize = 0; zbc->stage = ZBUFFcs_load; + zbc->checksum = params.fParams.checksumFlag > 0; + zbc->frameEnded = 0; return 0; /* ready to go */ } @@ -189,14 +193,16 @@ MEM_STATIC size_t ZBUFF_limitCopy(void* dst, size_t dstCapacity, const void* src } -/* *** Compression *** */ +/* ====== Compression ====== */ + +typedef enum { zbf_gather, zbf_flush, zbf_end } ZBUFF_flush_e; static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr, const void* src, size_t* srcSizePtr, - int flush) + ZBUFF_flush_e const flush) { - U32 notDone = 1; + U32 someMoreWork = 1; const char* const istart = (const char*)src; const char* const iend = istart + *srcSizePtr; const char* ip = istart; @@ -204,7 +210,7 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc, char* const oend = ostart + *dstCapacityPtr; char* op = ostart; - while (notDone) { + while (someMoreWork) { switch(zbc->stage) { case ZBUFFcs_init: return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */ @@ -216,7 +222,7 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc, zbc->inBuffPos += loaded; ip += loaded; if ( (zbc->inBuffPos==zbc->inToCompress) || (!flush && (toLoad != loaded)) ) { - notDone = 0; break; /* not enough input to get a full block : stop there, wait for more */ + someMoreWork = 0; break; /* not enough input to get a full block : stop there, wait for more */ } } /* compress current block (note : this stage cannot be stopped in the middle) */ { void* cDst; @@ -227,8 +233,11 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc, cDst = op; /* compress directly into output buffer (avoid flush stage) */ else cDst = zbc->outBuff, oSize = zbc->outBuffSize; - cSize = ZSTD_compressContinue(zbc->zc, cDst, oSize, zbc->inBuff + zbc->inToCompress, iSize); + cSize = (flush == zbf_end) ? + ZSTD_compressEnd(zbc->zc, cDst, oSize, zbc->inBuff + zbc->inToCompress, iSize) : + ZSTD_compressContinue(zbc->zc, cDst, oSize, zbc->inBuff + zbc->inToCompress, iSize); if (ZSTD_isError(cSize)) return cSize; + if (flush == zbf_end) zbc->frameEnded = 1; /* prepare next block */ zbc->inBuffTarget = zbc->inBuffPos + zbc->blockSize; if (zbc->inBuffTarget > zbc->inBuffSize) @@ -245,14 +254,14 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc, size_t const flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush); op += flushed; zbc->outBuffFlushedSize += flushed; - if (toFlush!=flushed) { notDone = 0; break; } /* dst too small to store flushed data : stop there */ + if (toFlush!=flushed) { someMoreWork = 0; break; } /* dst too small to store flushed data : stop there */ zbc->outBuffContentSize = zbc->outBuffFlushedSize = 0; zbc->stage = ZBUFFcs_load; break; } case ZBUFFcs_final: - notDone = 0; /* do nothing */ + someMoreWork = 0; /* do nothing */ break; default: @@ -262,6 +271,7 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc, *srcSizePtr = ip - istart; *dstCapacityPtr = op - ostart; + if (zbc->frameEnded) return 0; { size_t hintInSize = zbc->inBuffTarget - zbc->inBuffPos; if (hintInSize==0) hintInSize = zbc->blockSize; return hintInSize; @@ -272,17 +282,17 @@ size_t ZBUFF_compressContinue(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr, const void* src, size_t* srcSizePtr) { - return ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, src, srcSizePtr, 0); + return ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, src, srcSizePtr, zbf_gather); } -/* *** Finalize *** */ +/* ====== Finalize ====== */ size_t ZBUFF_compressFlush(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr) { size_t srcSize = 0; - ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, &srcSize, &srcSize, 1); /* use a valid src address instead of NULL */ + ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, &srcSize, &srcSize, zbf_flush); /* use a valid src address instead of NULL */ return zbc->outBuffContentSize - zbc->outBuffFlushedSize; } @@ -296,15 +306,18 @@ size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr) if (zbc->stage != ZBUFFcs_final) { /* flush whatever remains */ size_t outSize = *dstCapacityPtr; - size_t const remainingToFlush = ZBUFF_compressFlush(zbc, dst, &outSize); + size_t srcSize = 0; + size_t const notEnded = ZBUFF_compressContinue_generic(zbc, dst, &outSize, &srcSize, &srcSize, zbf_end); /* use a valid address instead of NULL */ + size_t const remainingToFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize; op += outSize; if (remainingToFlush) { *dstCapacityPtr = op-ostart; - return remainingToFlush + ZBUFF_endFrameSize; + return remainingToFlush + ZBUFF_endFrameSize + (zbc->checksum * 4); } /* create epilogue */ zbc->stage = ZBUFFcs_final; - zbc->outBuffContentSize = ZSTD_compressEnd(zbc->zc, zbc->outBuff, zbc->outBuffSize); /* epilogue into outBuff */ + zbc->outBuffContentSize = !notEnded ? 0 : + ZSTD_compressEnd(zbc->zc, zbc->outBuff, zbc->outBuffSize, NULL, 0); /* write epilogue into outBuff */ } /* flush epilogue */ @@ -323,5 +336,5 @@ size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr) /* ************************************* * Tool functions ***************************************/ -size_t ZBUFF_recommendedCInSize(void) { return ZSTD_BLOCKSIZE_MAX; } -size_t ZBUFF_recommendedCOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize; } +size_t ZBUFF_recommendedCInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; } +size_t ZBUFF_recommendedCOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize; } diff --git a/C/zstd/zbuff_decompress.c b/C/zstd/zbuff_decompress.c index e74fb5d1..908120fc 100644 --- a/C/zstd/zbuff_decompress.c +++ b/C/zstd/zbuff_decompress.c @@ -158,9 +158,9 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, char* const ostart = (char*)dst; char* const oend = ostart + *dstCapacityPtr; char* op = ostart; - U32 notDone = 1; + U32 someMoreWork = 1; - while (notDone) { + while (someMoreWork) { switch(zbd->stage) { case ZBUFFds_init : @@ -168,9 +168,9 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, case ZBUFFds_loadHeader : { size_t const hSize = ZSTD_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize); - if (hSize != 0) { + if (ZSTD_isError(hSize)) return hSize; + if (hSize != 0) { /* need more input */ size_t const toLoad = hSize - zbd->lhSize; /* if hSize!=0, hSize > zbd->lhSize */ - if (ZSTD_isError(hSize)) return hSize; if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */ memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip); zbd->lhSize += iend-ip; @@ -184,7 +184,7 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, /* Consume header */ { size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zbd->zd); /* == ZSTD_frameHeaderSize_min */ size_t const h1Result = ZSTD_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size); - if (ZSTD_isError(h1Result)) return h1Result; + if (ZSTD_isError(h1Result)) return h1Result; /* should not happen : already checked */ if (h1Size < zbd->lhSize) { /* long header */ size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zbd->zd); size_t const h2Result = ZSTD_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size); @@ -194,7 +194,8 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); /* Frame header instruct buffer sizes */ - { size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTD_BLOCKSIZE_MAX); + { size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); + size_t const neededOutSize = zbd->fParams.windowSize + blockSize; zbd->blockSize = blockSize; if (zbd->inBuffSize < blockSize) { zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff); @@ -202,20 +203,20 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize); if (zbd->inBuff == NULL) return ERROR(memory_allocation); } - { size_t const neededOutSize = zbd->fParams.windowSize + blockSize; - if (zbd->outBuffSize < neededOutSize) { - zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff); - zbd->outBuffSize = neededOutSize; - zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize); - if (zbd->outBuff == NULL) return ERROR(memory_allocation); - } } } + if (zbd->outBuffSize < neededOutSize) { + zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff); + zbd->outBuffSize = neededOutSize; + zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize); + if (zbd->outBuff == NULL) return ERROR(memory_allocation); + } } zbd->stage = ZBUFFds_read; + /* pass-through */ case ZBUFFds_read: { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbd->zd); if (neededInSize==0) { /* end of frame */ zbd->stage = ZBUFFds_init; - notDone = 0; + someMoreWork = 0; break; } if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */ @@ -230,8 +231,9 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, zbd->stage = ZBUFFds_flush; break; } - if (ip==iend) { notDone = 0; break; } /* no more input */ + if (ip==iend) { someMoreWork = 0; break; } /* no more input */ zbd->stage = ZBUFFds_load; + /* pass-through */ } case ZBUFFds_load: @@ -242,7 +244,7 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, loadedSize = ZBUFF_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip); ip += loadedSize; zbd->inPos += loadedSize; - if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */ + if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */ /* decode loaded input */ { const int isSkipFrame = ZSTD_isSkipFrame(zbd->zd); @@ -254,7 +256,7 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; } /* this was just a header */ zbd->outEnd = zbd->outStart + decodedSize; zbd->stage = ZBUFFds_flush; - // break; /* ZBUFFds_flush follows */ + /* pass-through */ } } case ZBUFFds_flush: @@ -262,14 +264,14 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, size_t const flushedSize = ZBUFF_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize); op += flushedSize; zbd->outStart += flushedSize; - if (flushedSize == toFlushSize) { + if (flushedSize == toFlushSize) { /* flush completed */ zbd->stage = ZBUFFds_read; if (zbd->outStart + zbd->blockSize > zbd->outBuffSize) zbd->outStart = zbd->outEnd = 0; break; } /* cannot flush everything */ - notDone = 0; + someMoreWork = 0; break; } default: return ERROR(GENERIC); /* impossible */ @@ -279,16 +281,17 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, *srcSizePtr = ip-istart; *dstCapacityPtr = op-ostart; { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbd->zd); -// if (nextSrcSizeHint > ZSTD_blockHeaderSize) nextSrcSizeHint+= ZSTD_blockHeaderSize; /* get following block header too */ + if (!nextSrcSizeHint) return (zbd->outEnd != zbd->outStart); /* return 0 only if fully flushed too */ + nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zbd->zd) == ZSTDnit_block); + if (zbd->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */ nextSrcSizeHint -= zbd->inPos; /* already loaded*/ return nextSrcSizeHint; } } - /* ************************************* * Tool functions ***************************************/ -size_t ZBUFF_recommendedDInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize /* block header size*/ ; } -size_t ZBUFF_recommendedDOutSize(void) { return ZSTD_BLOCKSIZE_MAX; } +size_t ZBUFF_recommendedDInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize /* block header size*/ ; } +size_t ZBUFF_recommendedDOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; } diff --git a/C/zstd/zstd.h b/C/zstd/zstd.h index f30e76cc..cb33b558 100644 --- a/C/zstd/zstd.h +++ b/C/zstd/zstd.h @@ -36,15 +36,11 @@ extern "C" { #endif -/*-************************************* -* Dependencies -***************************************/ +/*====== Dependency ======*/ #include /* size_t */ -/*-*************************************************************** -* Export parameters -*****************************************************************/ +/*====== Export for Windows ======*/ /*! * ZSTD_DLL_EXPORT : * Enable exporting of functions when building a Windows DLL @@ -56,12 +52,10 @@ extern "C" { #endif -/* ************************************* -* Version -***************************************/ +/*====== Version ======*/ #define ZSTD_VERSION_MAJOR 0 -#define ZSTD_VERSION_MINOR 7 -#define ZSTD_VERSION_RELEASE 4 +#define ZSTD_VERSION_MINOR 8 +#define ZSTD_VERSION_RELEASE 0 #define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE #define ZSTD_QUOTE(str) #str @@ -73,61 +67,72 @@ ZSTDLIB_API unsigned ZSTD_versionNumber (void); /* ************************************* -* Simple functions +* Simple API ***************************************/ /*! ZSTD_compress() : - Compresses `srcSize` bytes from buffer `src` into buffer `dst` of size `dstCapacity`. - Destination buffer must be already allocated. - Compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. - @return : the number of bytes written into `dst`, + Compresses `src` buffer into already allocated `dst`. + Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. + @return : the number of bytes written into `dst` (<= `dstCapacity), or an error code if it fails (which can be tested using ZSTD_isError()) */ -ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); +ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); -/** ZSTD_getDecompressedSize() : -* @return : decompressed size if known, 0 otherwise. - note : to know precise reason why result is `0`, follow up with ZSTD_getFrameParams() */ +/*! ZSTD_getDecompressedSize() : +* @return : decompressed size as a 64-bits value _if known_, 0 otherwise. +* note 1 : decompressed size can be very large (64-bits value), +* potentially larger than what local system can handle as a single memory segment. +* In which case, it's necessary to use streaming mode to decompress data. +* note 2 : decompressed size is an optional field, that may not be present. +* When `return==0`, consider data to decompress could have any size. +* In which case, it's necessary to use streaming mode to decompress data, +* or rely on application's implied limits. +* (For example, it may know that its own data is necessarily cut into blocks <= 16 KB). +* note 3 : decompressed size could be wrong or intentionally modified ! +* Always ensure result fits within application's authorized limits ! +* Each application can have its own set of conditions. +* If the intention is to decompress public data compressed by zstd command line utility, +* it is recommended to support at least 8 MB for extended compatibility. +* note 4 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameParams() to know more. */ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); /*! ZSTD_decompress() : - `compressedSize` : is the _exact_ size of compressed input, otherwise decompression will fail. - `dstCapacity` must be equal or larger than originalSize. + `compressedSize` : must be the _exact_ size of compressed input, otherwise decompression will fail. + `dstCapacity` must be equal or larger than originalSize (see ZSTD_getDecompressedSize() ). + If originalSize is unknown, and if there is no implied application-specific limitations, + it's necessary to use streaming mode to decompress data. @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), or an errorCode if it fails (which can be tested using ZSTD_isError()) */ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, const void* src, size_t compressedSize); -/* ************************************* -* Helper functions -***************************************/ -ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */ - -/* Error Management */ +/*====== Helper functions ======*/ +ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ +ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */ ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ -ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string for an error code */ +ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ -/* ************************************* +/*-************************************* * Explicit memory management ***************************************/ /** Compression context */ typedef struct ZSTD_CCtx_s ZSTD_CCtx; /*< incomplete type */ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); -ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /*!< @return : errorCode */ +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /** ZSTD_compressCCtx() : - Same as ZSTD_compress(), but requires an already allocated ZSTD_CCtx (see ZSTD_createCCtx()) */ + Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()) */ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel); /** Decompression context */ -typedef struct ZSTD_DCtx_s ZSTD_DCtx; +typedef struct ZSTD_DCtx_s ZSTD_DCtx; /*< incomplete type */ ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); -ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /*!< @return : errorCode */ +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /** ZSTD_decompressDCtx() : -* Same as ZSTD_decompress(), but requires an already allocated ZSTD_DCtx (see ZSTD_createDCtx()) */ +* Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()) */ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); @@ -135,10 +140,8 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t dstCapa * Simple dictionary API ***************************/ /*! ZSTD_compress_usingDict() : -* Compression using a pre-defined Dictionary content (see dictBuilder). -* Note 1 : This function load the dictionary, resulting in a significant startup time. -* Note 2 : `dict` must remain accessible and unmodified during compression operation. -* Note 3 : `dict` can be `NULL`, in which case, it's equivalent to ZSTD_compressCCtx() */ +* Compression using a predefined Dictionary (see dictBuilder/zdict.h). +* Note : This function load the dictionary, resulting in a significant startup time. */ ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -146,11 +149,9 @@ ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, int compressionLevel); /*! ZSTD_decompress_usingDict() : -* Decompression using a pre-defined Dictionary content (see dictBuilder). +* Decompression using a predefined Dictionary (see dictBuilder/zdict.h). * Dictionary must be identical to the one used during compression. -* Note 1 : This function load the dictionary, resulting in a significant startup time -* Note 2 : `dict` must remain accessible and unmodified during compression operation. -* Note 3 : `dict` can be `NULL`, in which case, it's equivalent to ZSTD_decompressDCtx() */ +* Note : This function load the dictionary, resulting in a significant startup time */ ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -158,7 +159,7 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, /*-************************** -* Advanced Dictionary API +* Fast Dictionary API ****************************/ /*! ZSTD_createCDict() : * Create a digested dictionary, ready to start compression operation without startup delay. @@ -168,8 +169,8 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); /*! ZSTD_compress_usingCDict() : -* Compression using a pre-digested Dictionary. -* Much faster than ZSTD_compress_usingDict() when same dictionary is used multiple times. +* Compression using a digested Dictionary. +* Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. * Note that compression level is decided during dictionary creation */ ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, @@ -184,15 +185,14 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize); ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); /*! ZSTD_decompress_usingDDict() : -* Decompression using a pre-digested Dictionary -* Much faster than ZSTD_decompress_usingDict() when same dictionary is used multiple times. */ +* Decompression using a digested Dictionary +* Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const ZSTD_DDict* ddict); - #ifdef ZSTD_STATIC_LINKING_ONLY /* ==================================================================================== @@ -203,7 +203,7 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, * ==================================================================================== */ /*--- Constants ---*/ -#define ZSTD_MAGICNUMBER 0xFD2FB527 /* v0.7 */ +#define ZSTD_MAGICNUMBER 0xFD2FB528 /* v0.8 */ #define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U #define ZSTD_WINDOWLOG_MAX_32 25 @@ -215,7 +215,6 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, #define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX #define ZSTD_HASHLOG_MIN 12 #define ZSTD_HASHLOG3_MAX 17 -#define ZSTD_HASHLOG3_MIN 15 #define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) #define ZSTD_SEARCHLOG_MIN 1 #define ZSTD_SEARCHLENGTH_MAX 7 @@ -265,7 +264,7 @@ typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; v /*! ZSTD_estimateCCtxSize() : * Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters. * `frameContentSize` is an optional parameter, provide `0` if unknown */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned long long frameContentSize); +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); /*! ZSTD_createCCtx_advanced() : * Create a ZSTD compression context using external alloc and free functions */ @@ -280,8 +279,6 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictS * Gives the amount of memory used by a given ZSTD_CCtx */ ZSTDLIB_API size_t ZSTD_sizeofCCtx(const ZSTD_CCtx* cctx); -ZSTDLIB_API unsigned ZSTD_maxCLevel (void); - /*! ZSTD_getParams() : * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of a `ZSTD_compressionParameters`. * All fields of `ZSTD_frameParameters` are set to default (0) */ @@ -326,15 +323,20 @@ ZSTDLIB_API size_t ZSTD_sizeofDCtx(const ZSTD_DCtx* dctx); /* ****************************************************************** -* Streaming functions (direct mode - synchronous and buffer-less) +* Buffer-less streaming functions (synchronous mode) ********************************************************************/ +/* This is an advanced API, giving full control over buffer management, for users which need direct control over memory. +* But it's also a complex one, with a lot of restrictions (documented below). +* For an easier streaming API, look into common/zbuff.h +* which removes all restrictions by allocating and managing its own internal buffer */ + ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx); ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity); +ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); /* A ZSTD_CCtx object is required to track streaming operations. @@ -349,7 +351,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci Then, consume your input using ZSTD_compressContinue(). There are some important considerations to keep in mind when using this advanced function : - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffer only. - - Interface is synchronous : input is consumed entirely and produce 1 (or more) compressed blocks. + - Interface is synchronous : input is consumed entirely and produce 1+ (or more) compressed blocks. - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. Worst case evaluation is provided by ZSTD_compressBound(). ZSTD_compressContinue() doesn't guarantee recover after a failed compression. @@ -358,9 +360,9 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. In which case, it will "discard" the relevant memory section from its history. - - Finish a frame with ZSTD_compressEnd(), which will write the epilogue. - Without epilogue, frames will be considered unfinished (broken) by decoders. + Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. + It's possible to use a NULL,0 src content, in which case, it will write a final empty block to end the frame, + Without last block mark, frames will be considered unfinished (broken) by decoders. You can then reuse `ZSTD_CCtx` (ZSTD_compressBegin()) to compress some new frame. */ @@ -372,7 +374,7 @@ typedef struct { unsigned checksumFlag; } ZSTD_frameParams; -ZSTDLIB_API size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +ZSTDLIB_API size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */ ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); @@ -381,49 +383,58 @@ ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx) ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); + /* - Streaming decompression, direct mode (bufferless) + Buffer-less streaming decompression (synchronous mode) A ZSTD_DCtx object is required to track streaming operations. Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. A ZSTD_DCtx object can be re-used multiple times. - First optional operation is to retrieve frame parameters, using ZSTD_getFrameParams(), which doesn't consume the input. - It can provide the minimum size of rolling buffer required to properly decompress data (`windowSize`), - and optionally the final size of uncompressed content. - (Note : content size is an optional info that may not be present. 0 means : content size unknown) - Frame parameters are extracted from the beginning of compressed frame. - The amount of data to read is variable, from ZSTD_frameHeaderSize_min to ZSTD_frameHeaderSize_max (so if `srcSize` >= ZSTD_frameHeaderSize_max, it will always work) - If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result. - Result : 0 when successful, it means the ZSTD_frameParams structure has been filled. - >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header. - errorCode, which can be tested using ZSTD_isError() + First typical operation is to retrieve frame parameters, using ZSTD_getFrameParams(). + It fills a ZSTD_frameParams structure which provide important information to correctly decode the frame, + such as the minimum rolling buffer size to allocate to decompress data (`windowSize`), + and the dictionary ID used. + (Note : content size is optional, it may not be present. 0 means : content size unknown). + Note that these values could be wrong, either because of data malformation, or because an attacker is spoofing deliberate false information. + As a consequence, check that values remain within valid application range, especially `windowSize`, before allocation. + Each application can set its own limit, depending on local restrictions. For extended interoperability, it is recommended to support at least 8 MB. + Frame parameters are extracted from the beginning of the compressed frame. + Data fragment must be large enough to ensure successful decoding, typically `ZSTD_frameHeaderSize_max` bytes. + @result : 0 : successful decoding, the `ZSTD_frameParams` structure is correctly filled. + >0 : `srcSize` is too small, please provide at least @result bytes on next attempt. + errorCode, which can be tested using ZSTD_isError(). Start decompression, with ZSTD_decompressBegin() or ZSTD_decompressBegin_usingDict(). Alternatively, you can copy a prepared context, using ZSTD_copyDCtx(). Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. - ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() requires this exact amount of bytes, or it will fail. + ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). - It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. + It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some metadata item. + It can also be an error code, which can be tested with ZSTD_isError(). ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize`. They should preferably be located contiguously, prior to current block. Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters. ZSTD_decompressContinue() is very sensitive to contiguity, if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, - or that previous contiguous segment is large enough to properly handle maximum back-reference. + or that previous contiguous segment is large enough to properly handle maximum back-reference. A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. Context can then be reset to start a new decompression. + Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). + This information is not required to properly decode a frame. == Special case : skippable frames == - Skippable frames allow the integration of user-defined data into a flow of concatenated frames. - Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frame is following: + Skippable frames allow integration of user-defined data into a flow of concatenated frames. + Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frames is as follows : a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits c) Frame Content - any content (User Data) of length equal to Frame Size @@ -437,13 +448,10 @@ ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t ds * Block functions ****************************************/ /*! Block functions produce and decode raw zstd blocks, without frame metadata. - Frame metadata cost is typically ~18 bytes, which is non-negligible on very small blocks. + Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes). User will have to take in charge required information to regenerate data, such as compressed and content sizes. A few rules to respect : - - Uncompressed block size must be <= ZSTD_BLOCKSIZE_MAX (128 KB) - + If you need to compress more, cut data into multiple blocks - + Consider using the regular ZSTD_compress() instead, as frame metadata costs become negligible when source size is large. - Compressing and decompressing require a context structure + Use ZSTD_createCCtx() and ZSTD_createDCtx() - It is necessary to init context before starting @@ -451,19 +459,22 @@ ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t ds + decompression : ZSTD_decompressBegin() + variants _usingDict() are also allowed + copyCCtx() and copyDCtx() work too + - Block size is limited, it must be <= ZSTD_getBlockSizeMax() + + If you need to compress more, cut data into multiple blocks + + Consider using the regular ZSTD_compress() instead, as frame metadata costs become negligible when source size is large. - When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero. In which case, nothing is produced into `dst`. + User must test for such outcome and deal directly with uncompressed data + ZSTD_decompressBlock() doesn't accept uncompressed data as input !!! + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history. Use ZSTD_insertBlock() in such a case. - Insert block once it's copied into its final position. */ -#define ZSTD_BLOCKSIZE_MAX (128 * 1024) /* define, for static allocation */ +#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */ +ZSTDLIB_API size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx); ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful to track uncompressed blocks */ +ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */ #endif /* ZSTD_STATIC_LINKING_ONLY */ diff --git a/C/zstd/zstd_compress.c b/C/zstd/zstd_compress.c index 15a79d70..56c63601 100644 --- a/C/zstd/zstd_compress.c +++ b/C/zstd/zstd_compress.c @@ -66,6 +66,8 @@ * Constants ***************************************/ static const U32 g_searchStrength = 8; /* control skip over incompressible data */ +#define HASH_READ_SIZE 8 +typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e; /*-************************************* @@ -73,37 +75,14 @@ static const U32 g_searchStrength = 8; /* control skip over incompressible dat ***************************************/ size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; } -static U32 ZSTD_highbit32(U32 val) -{ -# if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - _BitScanReverse(&r, val); - return (unsigned)r; -# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ - return 31 - __builtin_clz(val); -# else /* Software version */ - static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; - U32 v = val; - int r; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27]; - return r; -# endif -} /*-************************************* * Sequence storage ***************************************/ static void ZSTD_resetSeqStore(seqStore_t* ssPtr) { - ssPtr->offset = ssPtr->offsetStart; ssPtr->lit = ssPtr->litStart; - ssPtr->litLength = ssPtr->litLengthStart; - ssPtr->matchLength = ssPtr->matchLengthStart; + ssPtr->sequences = ssPtr->sequencesStart; ssPtr->longLengthID = 0; } @@ -122,7 +101,7 @@ struct ZSTD_CCtx_s U32 nextToUpdate3; /* index from which to continue dictionary update */ U32 hashLog3; /* dispatch table : larger == faster, more memory */ U32 loadedDictEnd; - U32 stage; /* 0: created; 1: init,dictLoad; 2:started */ + ZSTD_compressionStage_e stage; U32 rep[ZSTD_REP_NUM]; U32 savedRep[ZSTD_REP_NUM]; U32 dictID; @@ -140,9 +119,9 @@ struct ZSTD_CCtx_s U32* chainTable; HUF_CElt* hufTable; U32 flagStaticTables; - FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)]; - FSE_CTable matchlengthCTable [FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)]; - FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)]; + FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)]; + FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)]; + FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)]; }; ZSTD_CCtx* ZSTD_createCCtx(void) @@ -152,7 +131,7 @@ ZSTD_CCtx* ZSTD_createCCtx(void) ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) { - ZSTD_CCtx* ctx; + ZSTD_CCtx* cctx; if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem; @@ -160,11 +139,11 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) if (!customMem.customAlloc || !customMem.customFree) return NULL; - ctx = (ZSTD_CCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTD_CCtx)); - if (!ctx) return NULL; - memset(ctx, 0, sizeof(ZSTD_CCtx)); - memcpy(&ctx->customMem, &customMem, sizeof(ZSTD_customMem)); - return ctx; + cctx = (ZSTD_CCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTD_CCtx)); + if (!cctx) return NULL; + memset(cctx, 0, sizeof(ZSTD_CCtx)); + memcpy(&(cctx->customMem), &customMem, sizeof(ZSTD_customMem)); + return cctx; } size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) @@ -249,20 +228,18 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u } -size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams, unsigned long long frameContentSize) +size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams) { - const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - const U32 divider = (cParams.searchLength==3) ? 3 : 4; - const size_t maxNbSeq = blockSize / divider; - const size_t tokenSpace = blockSize + 11*maxNbSeq; + size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog); + U32 const divider = (cParams.searchLength==3) ? 3 : 4; + size_t const maxNbSeq = blockSize / divider; + size_t const tokenSpace = blockSize + 11*maxNbSeq; - const size_t chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog); - const size_t hSize = ((size_t)1) << cParams.hashLog; - const U32 hashLog3 = (cParams.searchLength>3) ? 0 : - ( (!frameContentSize || frameContentSize >= 8192) ? ZSTD_HASHLOG3_MAX : - ((frameContentSize >= 2048) ? ZSTD_HASHLOG3_MIN + 1 : ZSTD_HASHLOG3_MIN) ); - const size_t h3Size = ((size_t)1) << hashLog3; - const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); + size_t const chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog); + size_t const hSize = ((size_t)1) << cParams.hashLog; + U32 const hashLog3 = (cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog); + size_t const h3Size = ((size_t)1) << hashLog3; + size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<3) ? 0 : - ( (!frameContentSize || frameContentSize >= 8192) ? ZSTD_HASHLOG3_MAX : - ((frameContentSize >= 2048) ? ZSTD_HASHLOG3_MIN + 1 : ZSTD_HASHLOG3_MIN) ); - const size_t h3Size = ((size_t)1) << hashLog3; - const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); + size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog); + U32 const divider = (params.cParams.searchLength==3) ? 3 : 4; + size_t const maxNbSeq = blockSize / divider; + size_t const tokenSpace = blockSize + 11*maxNbSeq; + size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog); + size_t const hSize = ((size_t)1) << params.cParams.hashLog; + U32 const hashLog3 = (params.cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog); + size_t const h3Size = ((size_t)1) << hashLog3; + size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); + void* ptr; /* Check if workSpace is large enough, alloc a new one if needed */ { size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<hashTable = (U32*)(zc->workSpace); zc->chainTable = zc->hashTable + hSize; zc->hashTable3 = zc->chainTable + chainSize; - zc->seqStore.buffer = zc->hashTable3 + h3Size; - zc->hufTable = (HUF_CElt*)zc->seqStore.buffer; + ptr = zc->hashTable3 + h3Size; + zc->hufTable = (HUF_CElt*)ptr; zc->flagStaticTables = 0; - zc->seqStore.buffer = ((U32*)(zc->seqStore.buffer)) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */ + ptr = ((U32*)ptr) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */ zc->nextToUpdate = 1; zc->nextSrc = NULL; @@ -324,27 +301,25 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc, { int i; for (i=0; irep[i] = repStartValue[i]; } if (params.cParams.strategy == ZSTD_btopt) { - zc->seqStore.litFreq = (U32*)(zc->seqStore.buffer); + zc->seqStore.litFreq = (U32*)ptr; zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1); zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1); - zc->seqStore.buffer = zc->seqStore.offCodeFreq + (MaxOff+1); - zc->seqStore.matchTable = (ZSTD_match_t*)zc->seqStore.buffer; - zc->seqStore.buffer = zc->seqStore.matchTable + ZSTD_OPT_NUM+1; - zc->seqStore.priceTable = (ZSTD_optimal_t*)zc->seqStore.buffer; - zc->seqStore.buffer = zc->seqStore.priceTable + ZSTD_OPT_NUM+1; + ptr = zc->seqStore.offCodeFreq + (MaxOff+1); + zc->seqStore.matchTable = (ZSTD_match_t*)ptr; + ptr = zc->seqStore.matchTable + ZSTD_OPT_NUM+1; + zc->seqStore.priceTable = (ZSTD_optimal_t*)ptr; + ptr = zc->seqStore.priceTable + ZSTD_OPT_NUM+1; zc->seqStore.litLengthSum = 0; } - zc->seqStore.offsetStart = (U32*)(zc->seqStore.buffer); - zc->seqStore.buffer = zc->seqStore.offsetStart + maxNbSeq; - zc->seqStore.litLengthStart = (U16*)zc->seqStore.buffer; - zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + maxNbSeq; - zc->seqStore.llCodeStart = (BYTE*) (zc->seqStore.matchLengthStart + maxNbSeq); - zc->seqStore.mlCodeStart = zc->seqStore.llCodeStart + maxNbSeq; - zc->seqStore.offCodeStart = zc->seqStore.mlCodeStart + maxNbSeq; - zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq; + zc->seqStore.sequencesStart = (seqDef*)ptr; + ptr = zc->seqStore.sequencesStart + maxNbSeq; + zc->seqStore.llCode = (BYTE*) ptr; + zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq; + zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq; + zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq; - zc->stage = 1; + zc->stage = ZSTDcs_init; zc->dictID = 0; zc->loadedDictEnd = 0; @@ -354,21 +329,21 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc, /*! ZSTD_copyCCtx() : * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. -* Only works during stage 1 (i.e. after creation, but before first call to ZSTD_compressContinue()). +* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). * @return : 0, or an error code */ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx) { - if (srcCCtx->stage!=1) return ERROR(stage_wrong); + if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong); memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params, srcCCtx->frameContentSize, 0); dstCCtx->params.fParams.contentSizeFlag = 0; /* content size different from the one set during srcCCtx init */ /* copy tables */ - { const size_t chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog); - const size_t hSize = ((size_t)1) << srcCCtx->params.cParams.hashLog; - const size_t h3Size = (size_t)1 << srcCCtx->hashLog3; - const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); + { size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog); + size_t const hSize = ((size_t)1) << srcCCtx->params.cParams.hashLog; + size_t const h3Size = (size_t)1 << srcCCtx->hashLog3; + size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace); } @@ -411,13 +386,13 @@ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reduce * rescale all indexes to avoid future overflow (indexes are U32) */ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue) { - { const U32 hSize = 1 << zc->params.cParams.hashLog; + { U32 const hSize = 1 << zc->params.cParams.hashLog; ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); } - { const U32 chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog); + { U32 const chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog); ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); } - { const U32 h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0; + { U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0; ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); } } @@ -426,149 +401,13 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue) * Block entropic compression *********************************************************/ -/* Frame format description - Frame Header - [ Block Header - Block ] - Frame End - 1) Frame Header - - 4 bytes : Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h) - - 1 byte : Frame Header Descriptor - - 1-13 bytes : Optional fields - 2) Block Header - - 3 bytes, starting with a 2-bits descriptor - Uncompressed, Compressed, Frame End, unused - 3) Block - See Block Format Description - 4) Frame End - - 3 bytes, compatible with Block Header -*/ - - -/* Frame header : - - 1 byte - FrameHeaderDescription : - bit 0-1 : dictID (0, 1, 2 or 4 bytes) - bit 2-4 : reserved (must be zero) - bit 5 : SkippedWindowLog (if 1, WindowLog byte is not present) - bit 6-7 : FrameContentFieldsize (0, 2, 4, or 8) - if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1; - - Optional : WindowLog (0 or 1 byte) - bit 0-2 : octal Fractional (1/8th) - bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB) - - Optional : content size (0, 1, 2, 4 or 8 bytes) - 0 : unknown - 1 : 0-255 bytes - 2 : 256 - 65535+256 - 8 : up to 16 exa - - Optional : dictID (0, 1, 2 or 4 bytes) - Automatic adaptation - 0 : no dictID - 1 : 1 - 255 - 2 : 256 - 65535 - 4 : all other values -*/ - - -/* Block format description - - Block = Literals Section - Sequences Section - Prerequisite : size of (compressed) block, maximum size of regenerated data - - 1) Literal Section - - 1.1) Header : 1-5 bytes - flags: 2 bits - 00 compressed by Huff0 - 01 repeat - 10 is Raw (uncompressed) - 11 is Rle - Note : using 01 => Huff0 with precomputed table ? - Note : delta map ? => compressed ? - - 1.1.1) Huff0-compressed literal block : 3-5 bytes - srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream - srcSize < 1 KB => 3 bytes (2-2-10-10) - srcSize < 16KB => 4 bytes (2-2-14-14) - else => 5 bytes (2-2-18-18) - big endian convention - - 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes - size : 5 bits: (IS_RAW<<6) + (0<<4) + size - 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8) - size&255 - 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16) - size>>8&255 - size&255 - - 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes - size : 5 bits: (IS_RLE<<6) + (0<<4) + size - 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8) - size&255 - 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16) - size>>8&255 - size&255 - - 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes - srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream - srcSize < 1 KB => 3 bytes (2-2-10-10) - srcSize < 16KB => 4 bytes (2-2-14-14) - else => 5 bytes (2-2-18-18) - big endian convention - - 1- CTable available (stored into workspace) - 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?) - - - 1.2) Literal block content - - 1.2.1) Huff0 block, using sizes from header - See Huff0 format - - 1.2.2) Huff0 block, using prepared table - - 1.2.3) Raw content - - 1.2.4) single byte - - - 2) Sequences section - - - Nb Sequences : 2 bytes, little endian - - Control Token : 1 byte (see below) - - Dumps Length : 1 or 2 bytes (depending on control token) - - Dumps : as stated by dumps length - - Literal Lengths FSE table (as needed depending on encoding method) - - Offset Codes FSE table (as needed depending on encoding method) - - Match Lengths FSE table (as needed depending on encoding method) - - 2.1) Control Token - 8 bits, divided as : - 0-1 : dumpsLength - 2-3 : MatchLength, FSE encoding method - 4-5 : Offset Codes, FSE encoding method - 6-7 : Literal Lengths, FSE encoding method - - FSE encoding method : - FSE_ENCODING_RAW : uncompressed; no header - FSE_ENCODING_RLE : single repeated value; header 1 byte - FSE_ENCODING_STATIC : use prepared table; no header - FSE_ENCODING_DYNAMIC : read NCount -*/ +/* See zstd_compression_format.md for detailed format description */ size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize) { - BYTE* const ostart = (BYTE* const)dst; - if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall); - memcpy(ostart + ZSTD_blockHeaderSize, src, srcSize); - - /* Build header */ - ostart[0] = (BYTE)(srcSize>>16); - ostart[1] = (BYTE)(srcSize>>8); - ostart[2] = (BYTE) srcSize; - ostart[0] += (BYTE)(bt_raw<<6); /* is a raw (uncompressed) block */ - + memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); + MEM_writeLE24(dst, (U32)(srcSize << 2) + (U32)bt_raw); return ZSTD_blockHeaderSize+srcSize; } @@ -576,24 +415,21 @@ size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, siz static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize) { BYTE* const ostart = (BYTE* const)dst; - U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); + U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall); switch(flSize) { case 1: /* 2 - 1 - 5 */ - ostart[0] = (BYTE)((lbt_raw<<6) + (0<<5) + srcSize); + ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3)); break; case 2: /* 2 - 2 - 12 */ - ostart[0] = (BYTE)((lbt_raw<<6) + (2<<4) + (srcSize >> 8)); - ostart[1] = (BYTE)srcSize; + MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4))); break; default: /*note : should not be necessary : flSize is within {1,2,3} */ case 3: /* 2 - 2 - 20 */ - ostart[0] = (BYTE)((lbt_raw<<6) + (3<<4) + (srcSize >> 16)); - ostart[1] = (BYTE)(srcSize>>8); - ostart[2] = (BYTE)srcSize; + MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4))); break; } @@ -604,24 +440,21 @@ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize) { BYTE* const ostart = (BYTE* const)dst; - U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); + U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); - (void)dstCapacity; /* dstCapacity guaranteed to be >=4, hence large enough */ + (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */ switch(flSize) { case 1: /* 2 - 1 - 5 */ - ostart[0] = (BYTE)((lbt_rle<<6) + (0<<5) + srcSize); + ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3)); break; case 2: /* 2 - 2 - 12 */ - ostart[0] = (BYTE)((lbt_rle<<6) + (2<<4) + (srcSize >> 8)); - ostart[1] = (BYTE)srcSize; + MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4))); break; default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */ case 3: /* 2 - 2 - 20 */ - ostart[0] = (BYTE)((lbt_rle<<6) + (3<<4) + (srcSize >> 16)); - ostart[1] = (BYTE)(srcSize>>8); - ostart[2] = (BYTE)srcSize; + MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4))); break; } @@ -638,9 +471,9 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc, { size_t const minGain = ZSTD_minGain(srcSize); size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); - BYTE* const ostart = (BYTE*)dst; + BYTE* const ostart = (BYTE*)dst; U32 singleStream = srcSize < 256; - litBlockType_t hType = lbt_huffman; + symbolEncodingType_e hType = set_compressed; size_t cLitSize; @@ -652,15 +485,15 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc, if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */ if (zc->flagStaticTables && (lhSize==3)) { - hType = lbt_repeat; + hType = set_repeat; singleStream = 1; cLitSize = HUF_compress1X_usingCTable(ostart+lhSize, dstCapacity-lhSize, src, srcSize, zc->hufTable); } else { - cLitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12) - : HUF_compress2 (ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12); + cLitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11) + : HUF_compress2 (ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11); } - if ((cLitSize==0) || (cLitSize >= srcSize - minGain)) + if ((cLitSize==0) | (cLitSize >= srcSize - minGain)) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); if (cLitSize==1) return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); @@ -669,79 +502,66 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc, switch(lhSize) { case 3: /* 2 - 2 - 10 - 10 */ - ostart[0] = (BYTE)((srcSize>>6) + (singleStream << 4) + (hType<<6)); - ostart[1] = (BYTE)((srcSize<<2) + (cLitSize>>8)); - ostart[2] = (BYTE)(cLitSize); - break; + { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14); + MEM_writeLE24(ostart, lhc); + break; + } case 4: /* 2 - 2 - 14 - 14 */ - ostart[0] = (BYTE)((srcSize>>10) + (2<<4) + (hType<<6)); - ostart[1] = (BYTE)(srcSize>> 2); - ostart[2] = (BYTE)((srcSize<<6) + (cLitSize>>8)); - ostart[3] = (BYTE)(cLitSize); - break; + { U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18); + MEM_writeLE32(ostart, lhc); + break; + } default: /* should not be necessary, lhSize is only {3,4,5} */ case 5: /* 2 - 2 - 18 - 18 */ - ostart[0] = (BYTE)((srcSize>>14) + (3<<4) + (hType<<6)); - ostart[1] = (BYTE)(srcSize>>6); - ostart[2] = (BYTE)((srcSize<<2) + (cLitSize>>16)); - ostart[3] = (BYTE)(cLitSize>>8); - ostart[4] = (BYTE)(cLitSize); - break; + { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22); + MEM_writeLE32(ostart, lhc); + ostart[4] = (BYTE)(cLitSize >> 10); + break; + } } return lhSize+cLitSize; } +static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 20, 20, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24 }; -void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq) +static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, + 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 }; + + +void ZSTD_seqToCodes(const seqStore_t* seqStorePtr) { - /* LL codes */ - { static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 16, 17, 17, 18, 18, 19, 19, - 20, 20, 20, 20, 21, 21, 21, 21, - 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24 }; - const BYTE LL_deltaCode = 19; - const U16* const llTable = seqStorePtr->litLengthStart; - BYTE* const llCodeTable = seqStorePtr->llCodeStart; - size_t u; - for (u=0; u63) ? (BYTE)ZSTD_highbit32(ll) + LL_deltaCode : LL_Code[ll]; - } - if (seqStorePtr->longLengthID==1) - llCodeTable[seqStorePtr->longLengthPos] = MaxLL; - } - - /* Offset codes */ - { const U32* const offsetTable = seqStorePtr->offsetStart; - BYTE* const ofCodeTable = seqStorePtr->offCodeStart; - size_t u; - for (u=0; umatchLengthStart; - BYTE* const mlCodeTable = seqStorePtr->mlCodeStart; - size_t u; - for (u=0; u127) ? (BYTE)ZSTD_highbit32(ml) + ML_deltaCode : ML_Code[ml]; - } - if (seqStorePtr->longLengthID==2) - mlCodeTable[seqStorePtr->longLengthPos] = MaxML; + BYTE const LL_deltaCode = 19; + BYTE const ML_deltaCode = 36; + const seqDef* const sequences = seqStorePtr->sequencesStart; + BYTE* const llCodeTable = seqStorePtr->llCode; + BYTE* const ofCodeTable = seqStorePtr->ofCode; + BYTE* const mlCodeTable = seqStorePtr->mlCode; + U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + U32 u; + for (u=0; u 63) ? (BYTE)ZSTD_highbit32(llv) + LL_deltaCode : LL_Code[llv]; + ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset); + mlCodeTable[u] = (mlv>127) ? (BYTE)ZSTD_highbit32(mlv) + ML_deltaCode : ML_Code[mlv]; } + if (seqStorePtr->longLengthID==1) + llCodeTable[seqStorePtr->longLengthPos] = MaxLL; + if (seqStorePtr->longLengthID==2) + mlCodeTable[seqStorePtr->longLengthPos] = MaxML; } @@ -756,17 +576,14 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, FSE_CTable* CTable_OffsetBits = zc->offcodeCTable; FSE_CTable* CTable_MatchLength = zc->matchlengthCTable; U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ - U16* const llTable = seqStorePtr->litLengthStart; - U16* const mlTable = seqStorePtr->matchLengthStart; - const U32* const offsetTable = seqStorePtr->offsetStart; - const U32* const offsetTableEnd = seqStorePtr->offset; - BYTE* const ofCodeTable = seqStorePtr->offCodeStart; - BYTE* const llCodeTable = seqStorePtr->llCodeStart; - BYTE* const mlCodeTable = seqStorePtr->mlCodeStart; + const seqDef* const sequences = seqStorePtr->sequencesStart; + const BYTE* const ofCodeTable = seqStorePtr->ofCode; + const BYTE* const llCodeTable = seqStorePtr->llCode; + const BYTE* const mlCodeTable = seqStorePtr->mlCode; BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstCapacity; BYTE* op = ostart; - size_t const nbSeq = offsetTableEnd - offsetTable; + size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; BYTE* seqHead; /* Compress literals */ @@ -791,7 +608,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, #define MAX_SEQ_FOR_STATIC_FSE 1000 /* convert length/distances into codes */ - ZSTD_seqToCodes(seqStorePtr, nbSeq); + ZSTD_seqToCodes(seqStorePtr); /* CTable for Literal Lengths */ { U32 max = MaxLL; @@ -799,12 +616,12 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, if ((mostFrequent == nbSeq) && (nbSeq > 2)) { *op++ = llCodeTable[0]; FSE_buildCTable_rle(CTable_LitLength, (BYTE)max); - LLtype = FSE_ENCODING_RLE; + LLtype = set_rle; } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { - LLtype = FSE_ENCODING_STATIC; + LLtype = set_repeat; } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog-1)))) { FSE_buildCTable(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog); - LLtype = FSE_ENCODING_RAW; + LLtype = set_basic; } else { size_t nbSeq_1 = nbSeq; const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max); @@ -814,7 +631,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, if (FSE_isError(NCountSize)) return ERROR(GENERIC); op += NCountSize; } FSE_buildCTable(CTable_LitLength, norm, max, tableLog); - LLtype = FSE_ENCODING_DYNAMIC; + LLtype = set_compressed; } } /* CTable for Offsets */ @@ -823,12 +640,12 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, if ((mostFrequent == nbSeq) && (nbSeq > 2)) { *op++ = ofCodeTable[0]; FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max); - Offtype = FSE_ENCODING_RLE; + Offtype = set_rle; } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { - Offtype = FSE_ENCODING_STATIC; + Offtype = set_repeat; } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (OF_defaultNormLog-1)))) { FSE_buildCTable(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog); - Offtype = FSE_ENCODING_RAW; + Offtype = set_basic; } else { size_t nbSeq_1 = nbSeq; const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max); @@ -838,7 +655,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, if (FSE_isError(NCountSize)) return ERROR(GENERIC); op += NCountSize; } FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog); - Offtype = FSE_ENCODING_DYNAMIC; + Offtype = set_compressed; } } /* CTable for MatchLengths */ @@ -847,12 +664,12 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, if ((mostFrequent == nbSeq) && (nbSeq > 2)) { *op++ = *mlCodeTable; FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max); - MLtype = FSE_ENCODING_RLE; + MLtype = set_rle; } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) { - MLtype = FSE_ENCODING_STATIC; + MLtype = set_repeat; } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog-1)))) { FSE_buildCTable(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog); - MLtype = FSE_ENCODING_RAW; + MLtype = set_basic; } else { size_t nbSeq_1 = nbSeq; const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max); @@ -862,7 +679,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, if (FSE_isError(NCountSize)) return ERROR(GENERIC); op += NCountSize; } FSE_buildCTable(CTable_MatchLength, norm, max, tableLog); - MLtype = FSE_ENCODING_DYNAMIC; + MLtype = set_compressed; } } *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); @@ -881,21 +698,21 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc, FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]); FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]); FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]); - BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[llCodeTable[nbSeq-1]]); + BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]); if (MEM_32bits()) BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, mlTable[nbSeq-1], ML_bits[mlCodeTable[nbSeq-1]]); + BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]); if (MEM_32bits()) BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, offsetTable[nbSeq-1], ofCodeTable[nbSeq-1]); + BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]); BIT_flushBits(&blockStream); { size_t n; for (n=nbSeq-2 ; n= 64-7-(LLFSELog+MLFSELog+OffFSELog))) BIT_flushBits(&blockStream); /* (7)*/ - BIT_addBits(&blockStream, llTable[n], llBits); + BIT_addBits(&blockStream, sequences[n].litLength, llBits); if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, mlTable[n], mlBits); + BIT_addBits(&blockStream, sequences[n].matchLength, mlBits); if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/ - BIT_addBits(&blockStream, offsetTable[n], ofBits); /* 31 */ + BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */ BIT_flushBits(&blockStream); /* (7)*/ } } @@ -955,15 +772,17 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v seqStorePtr->lit += litLength; /* literal Length */ - if (litLength>0xFFFF) { seqStorePtr->longLengthID = 1; seqStorePtr->longLengthPos = (U32)(seqStorePtr->litLength - seqStorePtr->litLengthStart); } - *seqStorePtr->litLength++ = (U16)litLength; + if (litLength>0xFFFF) { seqStorePtr->longLengthID = 1; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); } + seqStorePtr->sequences[0].litLength = (U16)litLength; /* match offset */ - *(seqStorePtr->offset++) = offsetCode + 1; + seqStorePtr->sequences[0].offset = offsetCode + 1; /* match Length */ - if (matchCode>0xFFFF) { seqStorePtr->longLengthID = 2; seqStorePtr->longLengthPos = (U32)(seqStorePtr->matchLength - seqStorePtr->matchLengthStart); } - *seqStorePtr->matchLength++ = (U16)matchCode; + if (matchCode>0xFFFF) { seqStorePtr->longLengthID = 2; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); } + seqStorePtr->sequences[0].matchLength = (U16)matchCode; + + seqStorePtr->sequences++; } @@ -1053,10 +872,9 @@ static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart) { const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd); - size_t matchLength = ZSTD_count(ip, match, vEnd); - if (match + matchLength == mEnd) - matchLength += ZSTD_count(ip+matchLength, iStart, iEnd); - return matchLength; + size_t const matchLength = ZSTD_count(ip, match, vEnd); + if (match + matchLength != mEnd) return matchLength; + return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd); } @@ -1083,7 +901,6 @@ static const U64 prime7bytes = 58295818150454627ULL; static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; } static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); } -//static const U64 prime8bytes = 58295818150454627ULL; static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; } static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } @@ -1108,10 +925,10 @@ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls) { U32* const hashTable = zc->hashTable; - const U32 hBits = zc->params.cParams.hashLog; + U32 const hBits = zc->params.cParams.hashLog; const BYTE* const base = zc->base; const BYTE* ip = base + zc->nextToUpdate; - const BYTE* const iend = ((const BYTE*)end) - 8; + const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; const size_t fastHashFillStep = 3; while(ip <= iend) { @@ -1127,16 +944,16 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx, const U32 mls) { U32* const hashTable = cctx->hashTable; - const U32 hBits = cctx->params.cParams.hashLog; + U32 const hBits = cctx->params.cParams.hashLog; seqStore_t* seqStorePtr = &(cctx->seqStore); const BYTE* const base = cctx->base; const BYTE* const istart = (const BYTE*)src; const BYTE* ip = istart; const BYTE* anchor = istart; - const U32 lowestIndex = cctx->dictLimit; + const U32 lowestIndex = cctx->dictLimit; const BYTE* const lowest = base + lowestIndex; const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; + const BYTE* const ilimit = iend - HASH_READ_SIZE; U32 offset_1=cctx->rep[0], offset_2=cctx->rep[1]; U32 offsetSaved = 0; @@ -1326,7 +1143,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx, static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize) { - const U32 mls = ctx->params.cParams.searchLength; + U32 const mls = ctx->params.cParams.searchLength; switch(mls) { default: @@ -1348,12 +1165,12 @@ static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx, static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls) { U32* const hashLarge = cctx->hashTable; - const U32 hBitsL = cctx->params.cParams.hashLog; + U32 const hBitsL = cctx->params.cParams.hashLog; U32* const hashSmall = cctx->chainTable; - const U32 hBitsS = cctx->params.cParams.chainLog; + U32 const hBitsS = cctx->params.cParams.chainLog; const BYTE* const base = cctx->base; const BYTE* ip = base + cctx->nextToUpdate; - const BYTE* const iend = ((const BYTE*)end) - 8; + const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; const size_t fastHashFillStep = 3; while(ip <= iend) { @@ -1381,7 +1198,7 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx, const U32 lowestIndex = cctx->dictLimit; const BYTE* const lowest = base + lowestIndex; const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; + const BYTE* const ilimit = iend - HASH_READ_SIZE; U32 offset_1=cctx->rep[0], offset_2=cctx->rep[1]; U32 offsetSaved = 0; @@ -1490,9 +1307,9 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx, const U32 mls) { U32* const hashLong = ctx->hashTable; - const U32 hBitsL = ctx->params.cParams.hashLog; + U32 const hBitsL = ctx->params.cParams.hashLog; U32* const hashSmall = ctx->chainTable; - const U32 hBitsS = ctx->params.cParams.chainLog; + U32 const hBitsS = ctx->params.cParams.chainLog; seqStore_t* seqStorePtr = &(ctx->seqStore); const BYTE* const base = ctx->base; const BYTE* const dictBase = ctx->dictBase; @@ -1603,7 +1420,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx, static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize) { - const U32 mls = ctx->params.cParams.searchLength; + U32 const mls = ctx->params.cParams.searchLength; switch(mls) { default: @@ -1628,13 +1445,13 @@ static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx, static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares, U32 extDict) { - U32* const hashTable = zc->hashTable; - const U32 hashLog = zc->params.cParams.hashLog; - const size_t h = ZSTD_hashPtr(ip, hashLog, mls); - U32* const bt = zc->chainTable; - const U32 btLog = zc->params.cParams.chainLog - 1; - const U32 btMask= (1 << btLog) - 1; - U32 matchIndex = hashTable[h]; + U32* const hashTable = zc->hashTable; + U32 const hashLog = zc->params.cParams.hashLog; + size_t const h = ZSTD_hashPtr(ip, hashLog, mls); + U32* const bt = zc->chainTable; + U32 const btLog = zc->params.cParams.chainLog - 1; + U32 const btMask = (1 << btLog) - 1; + U32 matchIndex = hashTable[h]; size_t commonLengthSmaller=0, commonLengthLarger=0; const BYTE* const base = zc->base; const BYTE* const dictBase = zc->dictBase; @@ -1647,7 +1464,7 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = smallerPtr + 1; U32 dummy32; /* to be nullified at the end */ - const U32 windowLow = zc->lowLimit; + U32 const windowLow = zc->lowLimit; U32 matchEndIdx = current+8; size_t bestLength = 8; #ifdef ZSTD_C_PREDICT @@ -1732,12 +1549,12 @@ static size_t ZSTD_insertBtAndFindBestMatch ( U32 nbCompares, const U32 mls, U32 extDict) { - U32* const hashTable = zc->hashTable; - const U32 hashLog = zc->params.cParams.hashLog; - const size_t h = ZSTD_hashPtr(ip, hashLog, mls); - U32* const bt = zc->chainTable; - const U32 btLog = zc->params.cParams.chainLog - 1; - const U32 btMask= (1 << btLog) - 1; + U32* const hashTable = zc->hashTable; + U32 const hashLog = zc->params.cParams.hashLog; + size_t const h = ZSTD_hashPtr(ip, hashLog, mls); + U32* const bt = zc->chainTable; + U32 const btLog = zc->params.cParams.chainLog - 1; + U32 const btMask = (1 << btLog) - 1; U32 matchIndex = hashTable[h]; size_t commonLengthSmaller=0, commonLengthLarger=0; const BYTE* const base = zc->base; @@ -1883,13 +1700,11 @@ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict ( -/* *********************** +/* ********************************* * Hash Chain -*************************/ - +***********************************/ #define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask] - /* Update chains up to ip (excluded) Assumption : always within prefix (ie. not within extDict) */ FORCE_INLINE @@ -2397,18 +2212,24 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCa } - - +/*! ZSTD_compress_generic() : +* Compress a chunk of data into one or multiple blocks. +* All blocks will be terminated, all input will be consumed. +* Function will issue an error if there is not enough `dstCapacity` to hold the compressed content. +* Frame is supposed already started (header already produced) +* @return : compressed size, or an error code +*/ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, - const void* src, size_t srcSize) + const void* src, size_t srcSize, + U32 lastFrameChunk) { size_t blockSize = cctx->blockSize; size_t remaining = srcSize; const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; - const U32 maxDist = 1 << cctx->params.cParams.windowLog; + U32 const maxDist = 1 << cctx->params.cParams.windowLog; ZSTD_stats_t* stats = &cctx->seqStore.stats; ZSTD_statsInit(stats); /* debug only */ @@ -2416,6 +2237,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, XXH64_update(&cctx->xxhState, src, srcSize); while (remaining) { + U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); size_t cSize; ZSTD_statsResetFreqs(stats); /* debug only */ @@ -2433,14 +2255,15 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, if (ZSTD_isError(cSize)) return cSize; if (cSize == 0) { /* block is not compressible */ - cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize); - if (ZSTD_isError(cSize)) return cSize; + U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(blockSize << 3); + if (blockSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall); + MEM_writeLE32(op, cBlockHeader24); /* no pb, 4th byte will be overwritten */ + memcpy(op + ZSTD_blockHeaderSize, ip, blockSize); + cSize = ZSTD_blockHeaderSize+blockSize; } else { - op[0] = (BYTE)(cSize>>16); - op[1] = (BYTE)(cSize>>8); - op[2] = (BYTE)cSize; - op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */ - cSize += 3; + U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24(op, cBlockHeader24); + cSize += ZSTD_blockHeaderSize; } remaining -= blockSize; @@ -2449,7 +2272,8 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, op += cSize; } - ZSTD_statsPrint(stats, cctx->params.cParams.searchLength); + if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending; + ZSTD_statsPrint(stats, cctx->params.cParams.searchLength); /* debug only */ return op-ostart; } @@ -2457,34 +2281,34 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID) { BYTE* const op = (BYTE*)dst; - U32 const dictIDSizeCode = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ - U32 const checksumFlag = params.fParams.checksumFlag>0; - U32 const windowSize = 1U << params.cParams.windowLog; - U32 const directModeFlag = params.fParams.contentSizeFlag && (windowSize > (pledgedSrcSize-1)); - BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); - U32 const fcsCode = params.fParams.contentSizeFlag ? + U32 const dictIDSizeCode = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ + U32 const checksumFlag = params.fParams.checksumFlag>0; + U32 const windowSize = 1U << params.cParams.windowLog; + U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize > (pledgedSrcSize-1)); + BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); + U32 const fcsCode = params.fParams.contentSizeFlag ? (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : /* 0-3 */ 0; - BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (directModeFlag<<5) + (fcsCode<<6) ); + BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); size_t pos; if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall); MEM_writeLE32(dst, ZSTD_MAGICNUMBER); op[4] = frameHeaderDecriptionByte; pos=5; - if (!directModeFlag) op[pos++] = windowLogByte; + if (!singleSegment) op[pos++] = windowLogByte; switch(dictIDSizeCode) { default: /* impossible */ case 0 : break; case 1 : op[pos] = (BYTE)(dictID); pos++; break; - case 2 : MEM_writeLE16(op+pos, (U16)(dictID)); pos+=2; break; + case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break; case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break; } switch(fcsCode) { default: /* impossible */ - case 0 : if (directModeFlag) op[pos++] = (BYTE)(pledgedSrcSize); break; + case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break; case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break; case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break; case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break; @@ -2496,30 +2320,31 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize, - U32 frame) + U32 frame, U32 lastFrameChunk) { const BYTE* const ip = (const BYTE*) src; size_t fhSize = 0; - if (zc->stage==0) return ERROR(stage_wrong); - if (frame && (zc->stage==1)) { /* copy saved header */ + if (zc->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */ + + if (frame && (zc->stage==ZSTDcs_init)) { fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, zc->params, zc->frameContentSize, zc->dictID); if (ZSTD_isError(fhSize)) return fhSize; dstCapacity -= fhSize; dst = (char*)dst + fhSize; - zc->stage = 2; + zc->stage = ZSTDcs_ongoing; } /* Check if blocks follow each other */ if (src != zc->nextSrc) { /* not contiguous */ - size_t const delta = zc->nextSrc - ip; + ptrdiff_t const delta = zc->nextSrc - ip; zc->lowLimit = zc->dictLimit; zc->dictLimit = (U32)(zc->nextSrc - zc->base); zc->dictBase = zc->base; zc->base -= delta; zc->nextToUpdate = zc->dictLimit; - if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */ + if (zc->dictLimit - zc->lowLimit < HASH_READ_SIZE) zc->lowLimit = zc->dictLimit; /* too small extDict */ } /* preemptive overflow correction */ @@ -2545,7 +2370,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc, zc->nextSrc = ip + srcSize; { size_t const cSize = frame ? - ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) : + ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize, lastFrameChunk) : ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize); if (ZSTD_isError(cSize)) return cSize; return cSize + fhSize; @@ -2553,19 +2378,25 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc, } -size_t ZSTD_compressContinue (ZSTD_CCtx* zc, +size_t ZSTD_compressContinue (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) { - return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 1); + return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 0); } -size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize) +size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx) { - if (srcSize > ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); - ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", zc->base, zc->params.cParams.searchLength); - return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 0); + return MIN (ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << cctx->params.cParams.windowLog); +} + +size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + size_t const blockSizeMax = ZSTD_getBlockSizeMax(cctx); + if (srcSize > blockSizeMax) return ERROR(srcSize_wrong); + ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", cctx->base, cctx->params.cParams.searchLength); + return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0, 0); } @@ -2583,7 +2414,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t zc->loadedDictEnd = (U32)(iend - zc->base); zc->nextSrc = iend; - if (srcSize <= 8) return 0; + if (srcSize <= HASH_READ_SIZE) return 0; switch(zc->params.cParams.strategy) { @@ -2598,12 +2429,12 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t case ZSTD_greedy: case ZSTD_lazy: case ZSTD_lazy2: - ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.cParams.searchLength); + ZSTD_insertAndFindFirstIndex (zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength); break; case ZSTD_btlazy2: case ZSTD_btopt: - ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength); + ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength); break; default: @@ -2618,8 +2449,8 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t /* Dictionary format : Magic == ZSTD_DICT_MAGIC (4 bytes) HUF_writeCTable(256) - FSE_writeNCount(ml) FSE_writeNCount(off) + FSE_writeNCount(ml) FSE_writeNCount(ll) RepOffsets Dictionary content @@ -2734,38 +2565,57 @@ size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel) } -/*! ZSTD_compressEnd() : -* Write frame epilogue. +/*! ZSTD_writeEpilogue() : +* Ends a frame. * @return : nb of bytes written into dst (or an error code) */ -size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) +static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) { - BYTE* op = (BYTE*)dst; + BYTE* const ostart = (BYTE*)dst; + BYTE* op = ostart; size_t fhSize = 0; - /* not even init ! */ - if (cctx->stage==0) return ERROR(stage_wrong); + if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /*< not even init ! */ /* special case : empty frame */ - if (cctx->stage==1) { + if (cctx->stage == ZSTDcs_init) { fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, 0, 0); if (ZSTD_isError(fhSize)) return fhSize; dstCapacity -= fhSize; op += fhSize; - cctx->stage = 2; + cctx->stage = ZSTDcs_ongoing; } - /* frame epilogue */ - if (dstCapacity < 3) return ERROR(dstSize_tooSmall); - { U32 const checksum = cctx->params.fParams.checksumFlag ? - (U32)((XXH64_digest(&cctx->xxhState) >> 11) & ((1<<22)-1)) : - 0; - op[0] = (BYTE)((bt_end<<6) + (checksum>>16)); - op[1] = (BYTE)(checksum>>8); - op[2] = (BYTE)checksum; + if (cctx->stage != ZSTDcs_ending) { + /* write one last empty block, make it the "last" block */ + U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0; + if (dstCapacity<4) return ERROR(dstSize_tooSmall); + MEM_writeLE32(op, cBlockHeader24); + op += ZSTD_blockHeaderSize; + dstCapacity -= ZSTD_blockHeaderSize; } - cctx->stage = 0; /* return to "created but not init" status */ - return 3+fhSize; + if (cctx->params.fParams.checksumFlag) { + U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); + if (dstCapacity<4) return ERROR(dstSize_tooSmall); + MEM_writeLE32(op, checksum); + op += 4; + } + + cctx->stage = ZSTDcs_created; /* return to "created but no init" status */ + return op-ostart; +} + + +size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + size_t endResult; + size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 1); + if (ZSTD_isError(cSize)) return cSize; + endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); + if (ZSTD_isError(endResult)) return endResult; + return cSize + endResult; } @@ -2778,44 +2628,23 @@ static size_t ZSTD_compress_usingPreparedCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* void* dst, size_t dstCapacity, const void* src, size_t srcSize) { - { size_t const errorCode = ZSTD_copyCCtx(cctx, preparedCCtx); - if (ZSTD_isError(errorCode)) return errorCode; - } - { size_t const cSize = ZSTD_compressContinue(cctx, dst, dstCapacity, src, srcSize); - if (ZSTD_isError(cSize)) return cSize; + size_t const errorCode = ZSTD_copyCCtx(cctx, preparedCCtx); + if (ZSTD_isError(errorCode)) return errorCode; - { size_t const endSize = ZSTD_compressEnd(cctx, (char*)dst+cSize, dstCapacity-cSize); - if (ZSTD_isError(endSize)) return endSize; - return cSize + endSize; - } } + return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); } -static size_t ZSTD_compress_internal (ZSTD_CCtx* ctx, +static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict,size_t dictSize, ZSTD_parameters params) { - BYTE* const ostart = (BYTE*)dst; - BYTE* op = ostart; + size_t const errorCode = ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize); + if(ZSTD_isError(errorCode)) return errorCode; - /* Init */ - { size_t const errorCode = ZSTD_compressBegin_internal(ctx, dict, dictSize, params, srcSize); - if(ZSTD_isError(errorCode)) return errorCode; } - - /* body (compression) */ - { size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize); - if(ZSTD_isError(oSize)) return oSize; - op += oSize; - dstCapacity -= oSize; } - - /* Close frame */ - { size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity); - if(ZSTD_isError(oSize)) return oSize; - op += oSize; } - - return (op - ostart); + return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); } size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx, @@ -2934,7 +2763,7 @@ ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, #define ZSTD_DEFAULT_CLEVEL 1 #define ZSTD_MAX_CLEVEL 22 -unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } +int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { { /* "default" */ @@ -2991,20 +2820,20 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV }, { /* for srcSize <= 128 KB */ /* W, C, H, S, L, T, strat */ - { 17, 12, 12, 1, 7, 4, ZSTD_fast }, /* level 0 - not used */ - { 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */ - { 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */ - { 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */ - { 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */ - { 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */ - { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ - { 17, 15, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 7 */ - { 17, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */ - { 17, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */ - { 17, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */ - { 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */ - { 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */ - { 17, 18, 17, 6, 4, 4, ZSTD_btlazy2 }, /* level 13.*/ + { 17, 12, 12, 1, 7, 8, ZSTD_fast }, /* level 0 - not used */ + { 17, 12, 13, 1, 6, 8, ZSTD_fast }, /* level 1 */ + { 17, 13, 16, 1, 5, 8, ZSTD_fast }, /* level 2 */ + { 17, 16, 16, 2, 5, 8, ZSTD_dfast }, /* level 3 */ + { 17, 13, 15, 3, 4, 8, ZSTD_greedy }, /* level 4 */ + { 17, 15, 17, 4, 4, 8, ZSTD_greedy }, /* level 5 */ + { 17, 16, 17, 3, 4, 8, ZSTD_lazy }, /* level 6 */ + { 17, 15, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 17, 17, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 11 */ + { 17, 17, 17, 8, 4, 8, ZSTD_lazy2 }, /* level 12 */ + { 17, 18, 17, 6, 4, 8, ZSTD_btlazy2 }, /* level 13.*/ { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/ { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/ { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/ @@ -3013,12 +2842,12 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/ { 17, 18, 17, 9, 3,256, ZSTD_btopt }, /* level 20.*/ { 17, 18, 17, 10, 3,256, ZSTD_btopt }, /* level 21.*/ - { 17, 18, 17, 11, 3,256, ZSTD_btopt }, /* level 22.*/ + { 17, 18, 17, 11, 3,512, ZSTD_btopt }, /* level 22.*/ }, { /* for srcSize <= 16 KB */ /* W, C, H, S, L, T, strat */ { 14, 12, 12, 1, 7, 6, ZSTD_fast }, /* level 0 - not used */ - { 14, 14, 14, 1, 7, 6, ZSTD_fast }, /* level 1 */ + { 14, 14, 14, 1, 6, 6, ZSTD_fast }, /* level 1 */ { 14, 14, 14, 1, 4, 6, ZSTD_fast }, /* level 2 */ { 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/ { 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/ diff --git a/C/zstd/zstd_decompress.c b/C/zstd/zstd_decompress.c index a48c9abd..958d6369 100644 --- a/C/zstd/zstd_decompress.c +++ b/C/zstd/zstd_decompress.c @@ -105,6 +105,7 @@ static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } ***************************************************************/ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock, + ZSTDds_decompressLastBlock, ZSTDds_checkChecksum, ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage; struct ZSTD_DCtx_s @@ -118,9 +119,9 @@ struct ZSTD_DCtx_s const void* vBase; const void* dictEnd; size_t expected; - U32 rep[3]; + U32 rep[ZSTD_REP_NUM]; ZSTD_frameParams fParams; - blockType_t bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */ + blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */ ZSTD_dStage stage; U32 litEntropy; U32 fseEntropy; @@ -131,7 +132,8 @@ struct ZSTD_DCtx_s ZSTD_customMem customMem; size_t litBufSize; size_t litSize; - BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH]; + size_t rleSize; + BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH]; BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; }; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */ @@ -186,7 +188,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) { memcpy(dstDCtx, srcDCtx, - sizeof(ZSTD_DCtx) - (ZSTD_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH + ZSTD_frameHeaderSize_max)); /* no need to copy workspace */ + sizeof(ZSTD_DCtx) - (ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH + ZSTD_frameHeaderSize_max)); /* no need to copy workspace */ } @@ -194,117 +196,7 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) * Decompression section ***************************************************************/ -/* Frame format description - Frame Header - [ Block Header - Block ] - Frame End - 1) Frame Header - - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd.h) - - 1 byte - Frame Descriptor - 2) Block Header - - 3 bytes, starting with a 2-bits descriptor - Uncompressed, Compressed, Frame End, unused - 3) Block - See Block Format Description - 4) Frame End - - 3 bytes, compatible with Block Header -*/ - - -/* Frame Header : - - 1 byte - FrameHeaderDescription : - bit 0-1 : dictID (0, 1, 2 or 4 bytes) - bit 2 : checksumFlag - bit 3 : reserved (must be zero) - bit 4 : reserved (unused, can be any value) - bit 5 : Single Segment (if 1, WindowLog byte is not present) - bit 6-7 : FrameContentFieldSize (0, 2, 4, or 8) - if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1; - - Optional : WindowLog (0 or 1 byte) - bit 0-2 : octal Fractional (1/8th) - bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB) - - Optional : dictID (0, 1, 2 or 4 bytes) - Automatic adaptation - 0 : no dictID - 1 : 1 - 255 - 2 : 256 - 65535 - 4 : all other values - - Optional : content size (0, 1, 2, 4 or 8 bytes) - 0 : unknown (fcfs==0 and swl==0) - 1 : 0-255 bytes (fcfs==0 and swl==1) - 2 : 256 - 65535+256 (fcfs==1) - 4 : 0 - 4GB-1 (fcfs==2) - 8 : 0 - 16EB-1 (fcfs==3) -*/ - - -/* Compressed Block, format description - - Block = Literal Section - Sequences Section - Prerequisite : size of (compressed) block, maximum size of regenerated data - - 1) Literal Section - - 1.1) Header : 1-5 bytes - flags: 2 bits - 00 compressed by Huff0 - 01 unused - 10 is Raw (uncompressed) - 11 is Rle - Note : using 01 => Huff0 with precomputed table ? - Note : delta map ? => compressed ? - - 1.1.1) Huff0-compressed literal block : 3-5 bytes - srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream - srcSize < 1 KB => 3 bytes (2-2-10-10) - srcSize < 16KB => 4 bytes (2-2-14-14) - else => 5 bytes (2-2-18-18) - big endian convention - - 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes - size : 5 bits: (IS_RAW<<6) + (0<<4) + size - 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8) - size&255 - 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16) - size>>8&255 - size&255 - - 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes - size : 5 bits: (IS_RLE<<6) + (0<<4) + size - 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8) - size&255 - 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16) - size>>8&255 - size&255 - - 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes - srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream - srcSize < 1 KB => 3 bytes (2-2-10-10) - srcSize < 16KB => 4 bytes (2-2-14-14) - else => 5 bytes (2-2-18-18) - big endian convention - - 1- CTable available (stored into workspace ?) - 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?) - - - 1.2) Literal block content - - 1.2.1) Huff0 block, using sizes from header - See Huff0 format - - 1.2.2) Huff0 block, using prepared table - - 1.2.3) Raw content - - 1.2.4) single byte - - - 2) Sequences section - TO DO -*/ +/* See compression format details in : zstd_compression_format.md */ /** ZSTD_frameHeaderSize() : * srcSize must be >= ZSTD_frameHeaderSize_min. @@ -314,10 +206,10 @@ static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); { BYTE const fhd = ((const BYTE*)src)[4]; U32 const dictID= fhd & 3; - U32 const directMode = (fhd >> 5) & 1; + U32 const singleSegment = (fhd >> 5) & 1; U32 const fcsId = fhd >> 6; - return ZSTD_frameHeaderSize_min + !directMode + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] - + (directMode && !ZSTD_fcs_fieldSize[fcsId]); + return ZSTD_frameHeaderSize_min + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + + (singleSegment && !ZSTD_fcs_fieldSize[fcsId]); } } @@ -351,14 +243,14 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t size_t pos = 5; U32 const dictIDSizeCode = fhdByte&3; U32 const checksumFlag = (fhdByte>>2)&1; - U32 const directMode = (fhdByte>>5)&1; + U32 const singleSegment = (fhdByte>>5)&1; U32 const fcsID = fhdByte>>6; U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; U32 windowSize = 0; U32 dictID = 0; U64 frameContentSize = 0; if ((fhdByte & 0x08) != 0) return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */ - if (!directMode) { + if (!singleSegment) { BYTE const wlByte = ip[pos++]; U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN; if (windowLog > ZSTD_WINDOWLOG_MAX) return ERROR(frameParameter_unsupported); @@ -377,7 +269,7 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t switch(fcsID) { default: /* impossible */ - case 0 : if (directMode) frameContentSize = ip[pos]; break; + case 0 : if (singleSegment) frameContentSize = ip[pos]; break; case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break; case 2 : frameContentSize = MEM_readLE32(ip+pos); break; case 3 : frameContentSize = MEM_readLE64(ip+pos); break; @@ -397,9 +289,9 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t * compatible with legacy mode * @return : decompressed size if known, 0 otherwise note : 0 can mean any of the following : - - decompressed size is not provided within frame header + - decompressed size is not present within frame header - frame header unknown / not supported - - frame header not completely provided (`srcSize` too small) */ + - frame header not complete (`srcSize` too small) */ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize) { #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1) @@ -427,7 +319,8 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t sr typedef struct { - blockType_t blockType; + blockType_e blockType; + U32 lastBlock; U32 origSize; } blockProperties_t; @@ -435,18 +328,16 @@ typedef struct * Provides the size of compressed block from block header `src` */ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr) { - const BYTE* const in = (const BYTE* const)src; - U32 cSize; - if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); - - bpPtr->blockType = (blockType_t)((*in) >> 6); - cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16); - bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0; - - if (bpPtr->blockType == bt_end) return 0; - if (bpPtr->blockType == bt_rle) return 1; - return cSize; + { U32 const cBlockHeader = MEM_readLE24(src); + U32 const cSize = cBlockHeader >> 3; + bpPtr->lastBlock = cBlockHeader & 1; + bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); + bpPtr->origSize = cSize; /* only useful for RLE */ + if (bpPtr->blockType == bt_rle) return 1; + if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected); + return cSize; + } } @@ -458,136 +349,143 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, } +static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, size_t regenSize) +{ + if (srcSize != 1) return ERROR(srcSize_wrong); + if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall); + memset(dst, *(const BYTE*)src, regenSize); + return regenSize; +} + /*! ZSTD_decodeLiteralsBlock() : @return : nb of bytes read from src (< srcSize ) */ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ { - const BYTE* const istart = (const BYTE*) src; - if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected); - switch((litBlockType_t)(istart[0]>> 6)) - { - case lbt_huffman: - { size_t litSize, litCSize, singleStream=0; - U32 lhSize = (istart[0] >> 4) & 3; - if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */ - switch(lhSize) - { - case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */ - /* 2 - 2 - 10 - 10 */ - lhSize=3; - singleStream = istart[0] & 16; - litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2); - litCSize = ((istart[1] & 3) << 8) + istart[2]; - break; - case 2: - /* 2 - 2 - 14 - 14 */ - lhSize=4; - litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6); - litCSize = ((istart[2] & 63) << 8) + istart[3]; - break; - case 3: - /* 2 - 2 - 18 - 18 */ - lhSize=5; - litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2); - litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4]; - break; - } - if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected); - if (litCSize + lhSize > srcSize) return ERROR(corruption_detected); + { const BYTE* const istart = (const BYTE*) src; + symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); - if (HUF_isError(singleStream ? - HUF_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) : - HUF_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) )) - return ERROR(corruption_detected); + switch(litEncType) + { + case set_repeat: + if (dctx->litEntropy==0) return ERROR(dictionary_corrupted); + /* fall-through */ + case set_compressed: + if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ + { size_t lhSize, litSize, litCSize; + U32 singleStream=0; + U32 const lhlCode = (istart[0] >> 2) & 3; + U32 const lhc = MEM_readLE32(istart); + switch(lhlCode) + { + case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */ + /* 2 - 2 - 10 - 10 */ + { singleStream = !lhlCode; + lhSize = 3; + litSize = (lhc >> 4) & 0x3FF; + litCSize = (lhc >> 14) & 0x3FF; + break; + } + case 2: + /* 2 - 2 - 14 - 14 */ + { lhSize = 4; + litSize = (lhc >> 4) & 0x3FFF; + litCSize = lhc >> 18; + break; + } + case 3: + /* 2 - 2 - 18 - 18 */ + { lhSize = 5; + litSize = (lhc >> 4) & 0x3FFFF; + litCSize = (lhc >> 22) + (istart[4] << 10); + break; + } + } + if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected); + if (litCSize + lhSize > srcSize) return ERROR(corruption_detected); - dctx->litPtr = dctx->litBuffer; - dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+8; - dctx->litSize = litSize; - dctx->litEntropy = 1; - return litCSize + lhSize; - } - case lbt_repeat: - { size_t litSize, litCSize; - U32 lhSize = ((istart[0]) >> 4) & 3; - if (lhSize != 1) /* only case supported for now : small litSize, single stream */ - return ERROR(corruption_detected); - if (dctx->litEntropy==0) - return ERROR(dictionary_corrupted); + if (HUF_isError((litEncType==set_repeat) ? + ( singleStream ? + HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable) : + HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable) ) : + ( singleStream ? + HUF_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) : + HUF_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize)) )) + return ERROR(corruption_detected); - /* 2 - 2 - 10 - 10 */ - lhSize=3; - litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2); - litCSize = ((istart[1] & 3) << 8) + istart[2]; - if (litCSize + lhSize > srcSize) return ERROR(corruption_detected); - - { size_t const errorCode = HUF_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable); - if (HUF_isError(errorCode)) return ERROR(corruption_detected); - } - dctx->litPtr = dctx->litBuffer; - dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH; - dctx->litSize = litSize; - return litCSize + lhSize; - } - case lbt_raw: - { size_t litSize; - U32 lhSize = ((istart[0]) >> 4) & 3; - switch(lhSize) - { - case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */ - lhSize=1; - litSize = istart[0] & 31; - break; - case 2: - litSize = ((istart[0] & 15) << 8) + istart[1]; - break; - case 3: - litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2]; - break; - } - - if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ - if (litSize+lhSize > srcSize) return ERROR(corruption_detected); - memcpy(dctx->litBuffer, istart+lhSize, litSize); dctx->litPtr = dctx->litBuffer; - dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+8; + dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH; + dctx->litSize = litSize; + dctx->litEntropy = 1; + return litCSize + lhSize; + } + + case set_basic: + { size_t litSize, lhSize; + U32 const lhlCode = ((istart[0]) >> 2) & 3; + switch(lhlCode) + { + case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ + lhSize = 1; + litSize = istart[0] >> 3; + break; + case 1: + lhSize = 2; + litSize = MEM_readLE16(istart) >> 4; + break; + case 3: + lhSize = 3; + litSize = MEM_readLE24(istart) >> 4; + break; + } + + if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ + if (litSize+lhSize > srcSize) return ERROR(corruption_detected); + memcpy(dctx->litBuffer, istart+lhSize, litSize); + dctx->litPtr = dctx->litBuffer; + dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+8; + dctx->litSize = litSize; + return lhSize+litSize; + } + /* direct reference into compressed stream */ + dctx->litPtr = istart+lhSize; + dctx->litBufSize = srcSize-lhSize; dctx->litSize = litSize; return lhSize+litSize; } - /* direct reference into compressed stream */ - dctx->litPtr = istart+lhSize; - dctx->litBufSize = srcSize-lhSize; - dctx->litSize = litSize; - return lhSize+litSize; - } - case lbt_rle: - { size_t litSize; - U32 lhSize = ((istart[0]) >> 4) & 3; - switch(lhSize) - { - case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */ - lhSize = 1; - litSize = istart[0] & 31; - break; - case 2: - litSize = ((istart[0] & 15) << 8) + istart[1]; - break; - case 3: - litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2]; - if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */ - break; + + case set_rle: + { U32 const lhlCode = ((istart[0]) >> 2) & 3; + size_t litSize, lhSize; + switch(lhlCode) + { + case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ + lhSize = 1; + litSize = istart[0] >> 3; + break; + case 1: + lhSize = 2; + litSize = MEM_readLE16(istart) >> 4; + break; + case 3: + lhSize = 3; + litSize = MEM_readLE24(istart) >> 4; + if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */ + break; + } + if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected); + memset(dctx->litBuffer, istart[lhSize], litSize); + dctx->litPtr = dctx->litBuffer; + dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH; + dctx->litSize = litSize; + return lhSize+1; } - if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected); - memset(dctx->litBuffer, istart[lhSize], litSize); - dctx->litPtr = dctx->litBuffer; - dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH; - dctx->litSize = litSize; - return lhSize+1; + default: + return ERROR(corruption_detected); /* impossible */ } - default: - return ERROR(corruption_detected); /* impossible */ + } } @@ -596,25 +494,25 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, @return : nb bytes read from src, or an error code if it fails, testable with ZSTD_isError() */ -FORCE_INLINE size_t ZSTD_buildSeqTable(FSE_DTable* DTable, U32 type, U32 max, U32 maxLog, +FORCE_INLINE size_t ZSTD_buildSeqTable(FSE_DTable* DTable, symbolEncodingType_e type, U32 max, U32 maxLog, const void* src, size_t srcSize, const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable) { switch(type) { - case FSE_ENCODING_RLE : + case set_rle : if (!srcSize) return ERROR(srcSize_wrong); if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected); FSE_buildDTable_rle(DTable, *(const BYTE*)src); /* if *src > max, data is corrupted */ return 1; - case FSE_ENCODING_RAW : + case set_basic : FSE_buildDTable(DTable, defaultNorm, max, defaultLog); return 0; - case FSE_ENCODING_STATIC: + case set_repeat: if (!flagRepeatTable) return ERROR(corruption_detected); return 0; default : /* impossible */ - case FSE_ENCODING_DYNAMIC : + case set_compressed : { U32 tableLog; S16 norm[MaxSeq+1]; size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); @@ -650,14 +548,12 @@ size_t ZSTD_decodeSeqHeaders(int* nbSeqPtr, } /* FSE table descriptors */ - { U32 const LLtype = *ip >> 6; - U32 const OFtype = (*ip >> 4) & 3; - U32 const MLtype = (*ip >> 2) & 3; + if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */ + { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); + symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); + symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); ip++; - /* check */ - if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */ - /* Build DTables */ { size_t const llhSize = ZSTD_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable); if (ZSTD_isError(llhSize)) return ERROR(corruption_detected); @@ -687,7 +583,7 @@ typedef struct { FSE_DState_t stateLL; FSE_DState_t stateOffb; FSE_DState_t stateML; - size_t prevOffset[ZSTD_REP_INIT]; + size_t prevOffset[ZSTD_REP_NUM]; } seqState_t; @@ -731,9 +627,9 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState) } if (ofCode <= 1) { - if ((llCode == 0) & (offset <= 1)) offset = 1-offset; + offset += (llCode==0); if (offset) { - size_t const temp = seqState->prevOffset[offset]; + size_t const temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; seqState->prevOffset[1] = seqState->prevOffset[0]; seqState->prevOffset[0] = offset = temp; @@ -774,7 +670,7 @@ size_t ZSTD_execSequence(BYTE* op, BYTE* const oLitEnd = op + sequence.litLength; size_t const sequenceLength = sequence.litLength + sequence.matchLength; BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ - BYTE* const oend_w = oend-WILDCOPY_OVERLENGTH; + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; const BYTE* const iLitEnd = *litPtr + sequence.litLength; const BYTE* match = oLitEnd - sequence.offset; @@ -867,7 +763,7 @@ static size_t ZSTD_decompressSequences( if (nbSeq) { seqState_t seqState; dctx->fseEntropy = 1; - { U32 i; for (i=0; irep[i]; } + { U32 i; for (i=0; irep[i]; } { size_t const errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip); if (ERR_isError(errorCode)) return ERROR(corruption_detected); } FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL); @@ -885,12 +781,11 @@ static size_t ZSTD_decompressSequences( /* check if reached exact end */ if (nbSeq) return ERROR(corruption_detected); /* save reps for next block */ - { U32 i; for (i=0; irep[i] = (U32)(seqState.prevOffset[i]); } + { U32 i; for (i=0; irep[i] = (U32)(seqState.prevOffset[i]); } } /* last literal segment */ { size_t const lastLLSize = litEnd - litPtr; - //if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */ if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); memcpy(op, litPtr, lastLLSize); op += lastLLSize; @@ -917,7 +812,7 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, { /* blockType == blockCompressed */ const BYTE* ip = (const BYTE*)src; - if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); + if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong); /* Decode literals sub-block */ { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); @@ -966,7 +861,6 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, const void* src, size_t srcSize) { const BYTE* ip = (const BYTE*)src; - const BYTE* const iend = ip + srcSize; BYTE* const ostart = (BYTE* const)dst; BYTE* const oend = ostart + dstCapacity; BYTE* op = ostart; @@ -977,9 +871,11 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, /* Frame Header */ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min); + size_t result; if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); - if (ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected); + result = ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize); + if (ZSTD_isError(result)) return result; ip += frameHeaderSize; remainingSize -= frameHeaderSize; } @@ -987,7 +883,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, while (1) { size_t decodedSize; blockProperties_t blockProperties; - size_t const cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties); + size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); if (ZSTD_isError(cBlockSize)) return cBlockSize; ip += ZSTD_blockHeaderSize; @@ -1005,23 +901,29 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, case bt_rle : decodedSize = ZSTD_generateNxBytes(op, oend-op, *ip, blockProperties.origSize); break; - case bt_end : - /* end of frame */ - if (remainingSize) return ERROR(srcSize_wrong); - decodedSize = 0; - break; + case bt_reserved : default: - return ERROR(GENERIC); /* impossible */ + return ERROR(corruption_detected); } - if (cBlockSize == 0) break; /* bt_end */ if (ZSTD_isError(decodedSize)) return decodedSize; if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize); op += decodedSize; ip += cBlockSize; remainingSize -= cBlockSize; + if (blockProperties.lastBlock) break; } + if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ + U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); + U32 checkRead; + if (remainingSize<4) return ERROR(checksum_wrong); + checkRead = MEM_readLE32(ip); + if (checkRead != checkCalc) return ERROR(checksum_wrong); + remainingSize -= 4; + } + + if (remainingSize) return ERROR(srcSize_wrong); return op-ostart; } @@ -1077,18 +979,33 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr } -/*_****************************** -* Streaming Decompression API -********************************/ -size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) -{ - return dctx->expected; +/*-********************************** +* Streaming Decompression API +************************************/ +size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; } + +ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { + switch(dctx->stage) + { + default: /* should not happen */ + case ZSTDds_getFrameHeaderSize: + case ZSTDds_decodeFrameHeader: + return ZSTDnit_frameHeader; + case ZSTDds_decodeBlockHeader: + return ZSTDnit_blockHeader; + case ZSTDds_decompressBlock: + return ZSTDnit_block; + case ZSTDds_decompressLastBlock: + return ZSTDnit_lastBlock; + case ZSTDds_checkChecksum: + return ZSTDnit_checksum; + case ZSTDds_decodeSkippableHeader: + case ZSTDds_skipFrame: + return ZSTDnit_skippableFrame; + } } -int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) -{ - return dctx->stage == ZSTDds_skipFrame; -} +int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */ /** ZSTD_decompressContinue() : * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity) @@ -1132,23 +1049,29 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c { blockProperties_t bp; size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); if (ZSTD_isError(cBlockSize)) return cBlockSize; - if (bp.blockType == bt_end) { + dctx->expected = cBlockSize; + dctx->bType = bp.blockType; + dctx->rleSize = bp.origSize; + if (cBlockSize) { + dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock; + return 0; + } + /* empty block */ + if (bp.lastBlock) { if (dctx->fParams.checksumFlag) { - U64 const h64 = XXH64_digest(&dctx->xxhState); - U32 const h32 = (U32)(h64>>11) & ((1<<22)-1); - const BYTE* const ip = (const BYTE*)src; - U32 const check32 = ip[2] + (ip[1] << 8) + ((ip[0] & 0x3F) << 16); - if (check32 != h32) return ERROR(checksum_wrong); + dctx->expected = 4; + dctx->stage = ZSTDds_checkChecksum; + } else { + dctx->expected = 0; /* end of frame */ + dctx->stage = ZSTDds_getFrameHeaderSize; } - dctx->expected = 0; - dctx->stage = ZSTDds_getFrameHeaderSize; } else { - dctx->expected = cBlockSize; - dctx->bType = bp.blockType; - dctx->stage = ZSTDds_decompressBlock; + dctx->expected = 3; /* go directly to next header */ + dctx->stage = ZSTDds_decodeBlockHeader; } return 0; } + case ZSTDds_decompressLastBlock: case ZSTDds_decompressBlock: { size_t rSize; switch(dctx->bType) @@ -1160,21 +1083,38 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); break; case bt_rle : - return ERROR(GENERIC); /* not yet handled */ - break; - case bt_end : /* should never happen (filtered at phase 1) */ - rSize = 0; + rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); break; + case bt_reserved : /* should never happen */ default: - return ERROR(GENERIC); /* impossible */ + return ERROR(corruption_detected); } - dctx->stage = ZSTDds_decodeBlockHeader; - dctx->expected = ZSTD_blockHeaderSize; - dctx->previousDstEnd = (char*)dst + rSize; if (ZSTD_isError(rSize)) return rSize; if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + + if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */ + if (dctx->fParams.checksumFlag) { /* another round for frame checksum */ + dctx->expected = 4; + dctx->stage = ZSTDds_checkChecksum; + } else { + dctx->expected = 0; /* ends here */ + dctx->stage = ZSTDds_getFrameHeaderSize; + } + } else { + dctx->stage = ZSTDds_decodeBlockHeader; + dctx->expected = ZSTD_blockHeaderSize; + dctx->previousDstEnd = (char*)dst + rSize; + } return rSize; } + case ZSTDds_checkChecksum: + { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); + U32 const check32 = MEM_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */ + if (check32 != h32) return ERROR(checksum_wrong); + dctx->expected = 0; + dctx->stage = ZSTDds_getFrameHeaderSize; + return 0; + } case ZSTDds_decodeSkippableHeader: { memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected); dctx->expected = MEM_readLE32(dctx->headerBuffer + 4); diff --git a/C/zstd/zstd_internal.h b/C/zstd/zstd_internal.h index 43cbc9a3..0a1935a9 100644 --- a/C/zstd/zstd_internal.h +++ b/C/zstd/zstd_internal.h @@ -52,8 +52,9 @@ * Common constants ***************************************/ #define ZSTD_OPT_DEBUG 0 /* 3 = compression stats; 5 = check encoded sequences; 9 = full logs */ -#include #if defined(ZSTD_OPT_DEBUG) && ZSTD_OPT_DEBUG>=9 + #include + #include #define ZSTD_LOG_PARSER(...) printf(__VA_ARGS__) #define ZSTD_LOG_ENCODE(...) printf(__VA_ARGS__) #define ZSTD_LOG_BLOCK(...) printf(__VA_ARGS__) @@ -64,10 +65,10 @@ #endif #define ZSTD_OPT_NUM (1<<12) -#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7 */ +#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */ -#define ZSTD_REP_NUM 3 -#define ZSTD_REP_INIT ZSTD_REP_NUM +#define ZSTD_REP_NUM 3 /* number of repcodes */ +#define ZSTD_REP_CHECK (ZSTD_REP_NUM-0) /* number of repcodes to check by the optimal parser */ #define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; @@ -88,13 +89,13 @@ static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; -typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; +typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */ #define HufLog 12 -typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t; +typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e; #define LONGNBSEQ 0x7F00 @@ -111,11 +112,6 @@ typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t; #define LLFSELog 9 #define OffFSELog 8 -#define FSE_ENCODING_RAW 0 -#define FSE_ENCODING_RLE 1 -#define FSE_ENCODING_STATIC 2 -#define FSE_ENCODING_DYNAMIC 3 - static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12, 13,14,15,16 }; @@ -174,7 +170,7 @@ typedef struct { U32 off; U32 mlen; U32 litlen; - U32 rep[ZSTD_REP_INIT]; + U32 rep[ZSTD_REP_NUM]; } ZSTD_optimal_t; #if ZSTD_OPT_DEBUG == 3 @@ -187,19 +183,22 @@ typedef struct { MEM_STATIC void ZSTD_statsUpdatePrices(ZSTD_stats_t* stats, size_t litLength, const BYTE* literals, size_t offset, size_t matchLength) { (void)stats; (void)litLength; (void)literals; (void)offset; (void)matchLength; } #endif /* #if ZSTD_OPT_DEBUG == 3 */ + +typedef struct seqDef_s { + U32 offset; + U16 litLength; + U16 matchLength; +} seqDef; + + typedef struct { - void* buffer; - U32* offsetStart; - U32* offset; - BYTE* offCodeStart; + seqDef* sequencesStart; + seqDef* sequences; BYTE* litStart; BYTE* lit; - U16* litLengthStart; - U16* litLength; - BYTE* llCodeStart; - U16* matchLengthStart; - U16* matchLength; - BYTE* mlCodeStart; + BYTE* llCode; + BYTE* mlCode; + BYTE* ofCode; U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ U32 longLengthPos; /* opt */ @@ -227,7 +226,7 @@ typedef struct { } seqStore_t; const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); -void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq); +void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); int ZSTD_isSkipFrame(ZSTD_DCtx* dctx); /* custom memory allocation functions */ @@ -235,4 +234,29 @@ void* ZSTD_defaultAllocFunction(void* opaque, size_t size); void ZSTD_defaultFreeFunction(void* opaque, void* address); static const ZSTD_customMem defaultCustomMem = { ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL }; +/*====== common function ======*/ + +MEM_STATIC U32 ZSTD_highbit32(U32 val) +{ +# if defined(_MSC_VER) /* Visual */ + unsigned long r=0; + _BitScanReverse(&r, val); + return (unsigned)r; +# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ + return 31 - __builtin_clz(val); +# else /* Software version */ + static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; + U32 v = val; + int r; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27]; + return r; +# endif +} + + #endif /* ZSTD_CCOMMON_H_MODULE */ diff --git a/C/zstd/zstd_legacy.h b/C/zstd/zstd_legacy.h index ab07cbd6..9fb946c6 100644 --- a/C/zstd/zstd_legacy.h +++ b/C/zstd/zstd_legacy.h @@ -44,32 +44,65 @@ extern "C" { #include "error_private.h" /* ERROR */ #include "zstd_v05.h" #include "zstd_v06.h" +#include "zstd_v07.h" /** ZSTD_isLegacy() : @return : > 0 if supported by legacy decoder. 0 otherwise. return value is the version. */ -MEM_STATIC unsigned ZSTD_isLegacy (U32 magicNumberLE) +MEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize) { + U32 magicNumberLE; + if (srcSize<4) return 0; + magicNumberLE = MEM_readLE32(src); switch(magicNumberLE) { case ZSTDv05_MAGICNUMBER : return 5; case ZSTDv06_MAGICNUMBER : return 6; + case ZSTDv07_MAGICNUMBER : return 7; default : return 0; } } +MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize) +{ + if (srcSize < 4) return 0; + + { U32 const version = ZSTD_isLegacy(src, srcSize); + if (version < 5) return 0; /* no decompressed size in frame header, or not a legacy format */ + if (version==5) { + ZSTDv05_parameters fParams; + size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize); + if (frResult != 0) return 0; + return fParams.srcSize; + } + if (version==6) { + ZSTDv06_frameParams fParams; + size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize); + if (frResult != 0) return 0; + return fParams.frameContentSize; + } + if (version==7) { + ZSTDv07_frameParams fParams; + size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize); + if (frResult != 0) return 0; + return fParams.frameContentSize; + } + return 0; /* should not be possible */ + } +} + MEM_STATIC size_t ZSTD_decompressLegacy( void* dst, size_t dstCapacity, const void* src, size_t compressedSize, - const void* dict,size_t dictSize, - U32 magicNumberLE) + const void* dict,size_t dictSize) { - switch(magicNumberLE) + U32 const version = ZSTD_isLegacy(src, compressedSize); + switch(version) { - case ZSTDv05_MAGICNUMBER : + case 5 : { size_t result; ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx(); if (zd==NULL) return ERROR(memory_allocation); @@ -77,7 +110,7 @@ MEM_STATIC size_t ZSTD_decompressLegacy( ZSTDv05_freeDCtx(zd); return result; } - case ZSTDv06_MAGICNUMBER : + case 6 : { size_t result; ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx(); if (zd==NULL) return ERROR(memory_allocation); @@ -85,6 +118,14 @@ MEM_STATIC size_t ZSTD_decompressLegacy( ZSTDv06_freeDCtx(zd); return result; } + case 7 : + { size_t result; + ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx(); + if (zd==NULL) return ERROR(memory_allocation); + result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); + ZSTDv07_freeDCtx(zd); + return result; + } default : return ERROR(prefix_unknown); } diff --git a/C/zstd/zstd_opt.h b/C/zstd/zstd_opt.h index ef394f19..3a1e9e19 100644 --- a/C/zstd/zstd_opt.h +++ b/C/zstd/zstd_opt.h @@ -134,15 +134,7 @@ FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* ssPtr, U32 litLength, const BY } /* literal Length */ - { static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 16, 17, 17, 18, 18, 19, 19, - 20, 20, 20, 20, 21, 21, 21, 21, - 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24 }; - const BYTE LL_deltaCode = 19; + { const BYTE LL_deltaCode = 19; const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength]; price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode]+1); } @@ -158,15 +150,7 @@ FORCE_INLINE U32 ZSTD_getPrice(seqStore_t* seqStorePtr, U32 litLength, const BYT U32 price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode]+1); /* match Length */ - { static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, - 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 }; - const BYTE ML_deltaCode = 36; + { const BYTE ML_deltaCode = 36; const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength]; price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode]+1); } @@ -185,15 +169,7 @@ MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const B seqStorePtr->litFreq[literals[u]]++; /* literal Length */ - { static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 16, 17, 17, 18, 18, 19, 19, - 20, 20, 20, 20, 21, 21, 21, 21, - 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24 }; - const BYTE LL_deltaCode = 19; + { const BYTE LL_deltaCode = 19; const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength]; seqStorePtr->litLengthFreq[llCode]++; seqStorePtr->litLengthSum++; @@ -206,15 +182,7 @@ MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const B } /* match Length */ - { static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, - 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 }; - const BYTE ML_deltaCode = 36; + { const BYTE ML_deltaCode = 36; const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength]; seqStorePtr->matchLengthFreq[mlCode]++; seqStorePtr->matchLengthSum++; @@ -464,13 +432,14 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx, ZSTD_optimal_t* opt = seqStorePtr->priceTable; ZSTD_match_t* matches = seqStorePtr->matchTable; const BYTE* inr; - U32 offset, rep[ZSTD_REP_INIT]; + U32 offset, rep[ZSTD_REP_NUM]; /* init */ ctx->nextToUpdate3 = ctx->nextToUpdate; ZSTD_rescaleFreqs(seqStorePtr); ip += (ip==prefixStart); - { U32 i; for (i=0; irep[i]; } + { U32 i; for (i=0; irep[i]; } + inr = ip; ZSTD_LOG_BLOCK("%d: COMPBLOCK_OPT_GENERIC srcSz=%d maxSrch=%d mls=%d sufLen=%d\n", (int)(ip-base), (int)srcSize, maxSearches, mls, sufficient_len); @@ -484,7 +453,7 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx, /* check repCode */ { U32 i; - for (i=0; i last_pos || price < opt[mlen].price) @@ -531,7 +500,7 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx, if (last_pos < minMatch) { ip++; continue; } /* initialize opt[0] */ - { U32 i ; for (i=0; i sufficient_len || cur + mlen >= ZSTD_OPT_NUM) { - ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos); best_mlen = mlen; best_off = i; last_pos = cur + 1; + ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos); goto _storeSequence; } - best_off = (i<=1 && opt[cur].mlen != 1) ? 1-i : i; + //best_off = ((i<=1) & (opt[cur].mlen != 1)) ? 1-i : i; + best_off = i - (opt[cur].mlen != 1); + if (opt[cur].mlen == 1) { litlen = opt[cur].litlen; if (cur > litlen) { @@ -692,7 +663,8 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ rep[1] = rep[0]; rep[0] = best_off; } - if (litLength == 0 && offset<=1) offset = 1-offset; + if ((litLength == 0) & (offset==0)) offset = rep[1]; /* protection, but should never happen */ + if ((litLength == 0) & (offset<=2)) offset--; } ZSTD_LOG_ENCODE("%d/%d: ENCODE literals=%d mlen=%d off=%d rep[0]=%d rep[1]=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep[0], (int)rep[1]); @@ -755,12 +727,13 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, const BYTE* inr; /* init */ - U32 offset, rep[ZSTD_REP_INIT]; - { U32 i; for (i=0; irep[i]; } + U32 offset, rep[ZSTD_REP_NUM]; + { U32 i; for (i=0; irep[i]; } ctx->nextToUpdate3 = ctx->nextToUpdate; ZSTD_rescaleFreqs(seqStorePtr); ip += (ip==prefixStart); + inr = ip; ZSTD_LOG_BLOCK("%d: COMPBLOCK_OPT_EXTDICT srcSz=%d maxSrch=%d mls=%d sufLen=%d\n", (int)(ip-base), (int)srcSize, maxSearches, mls, sufficient_len); @@ -776,11 +749,12 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, /* check repCode */ { U32 i; - for (i=0; i= 3) & (repIndex>lowestIndex)) /* intentional overflow */ + if ( (rep[i] <= current) + && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */ && (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) { /* repcode detected we should take it */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -792,7 +766,7 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, goto _storeSequence; } - best_off = (i<=1 && ip == anchor) ? 1-i : i; + best_off = i - (ip==anchor); litlen = opt[0].litlen; do { price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH); @@ -807,7 +781,7 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos); if (!last_pos && !match_num) { ip++; continue; } - { U32 i; for (i=0; i sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) { @@ -878,11 +852,12 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, best_mlen = 0; { U32 i; - for (i=0; i= 3) & (repIndex>lowestIndex)) /* intentional overflow */ + if ( (opt[cur].rep[i] <= current+cur) + && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */ && (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) { /* repcode detected */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -890,12 +865,12 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, ZSTD_LOG_PARSER("%d: Found REP %d/%d mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), i, ZSTD_REP_NUM, mlen, i, opt[cur].rep[i], cur, opt[cur].off); if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) { - ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos); best_mlen = mlen; best_off = i; last_pos = cur + 1; + ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos); goto _storeSequence; } - best_off = (i<=1 && opt[cur].mlen != 1) ? 1-i : i; + best_off = i - (opt[cur].mlen != 1); if (opt[cur].mlen == 1) { litlen = opt[cur].litlen; if (cur > litlen) { @@ -1001,8 +976,9 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ if (offset != 1) rep[2] = rep[1]; rep[1] = rep[0]; rep[0] = best_off; - } - if (litLength == 0 && offset<=1) offset = 1-offset; + } + if ((litLength==0) & (offset==0)) offset = rep[1]; /* protection, but should never happen */ + if ((litLength==0) & (offset<=2)) offset --; } ZSTD_LOG_ENCODE("%d/%d: ENCODE literals=%d mlen=%d off=%d rep[0]=%d rep[1]=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep[0], (int)rep[1]); @@ -1016,7 +992,7 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ ml2 = ZSTD_count_2segments(ip, match, iend, dictEnd, prefixStart); ZSTD_LOG_PARSER("%d: ZSTD_count_2segments=%d offset=%d dictBase=%p dictEnd=%p prefixStart=%p ip=%p match=%p\n", (int)current, (int)ml2, (int)best_off, dictBase, dictEnd, prefixStart, ip, match); } - else ml2 = (U32)ZSTD_count(ip, ip-offset, iend); + else ml2 = (U32)ZSTD_count(ip, ip-best_off, iend); } else ml2 = (U32)ZSTD_count(ip, ip-rep[0], iend); if ((offset >= 8) && (ml2 < mlen || ml2 < minMatch)) { @@ -1033,7 +1009,7 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ } } /* for (cur=0; cur < last_pos; ) */ /* Save reps for next block */ - ctx->savedRep[0] = rep[0]; ctx->savedRep[1] = rep[1]; ctx->savedRep[2] = rep[2]; + { int i; for (i=0; isavedRep[i] = rep[i]; } /* Last Literals */ { size_t lastLLSize = iend - anchor; diff --git a/C/zstd/zstd_v05.c b/C/zstd/zstd_v05.c index d5072479..f3c720fd 100644 --- a/C/zstd/zstd_v05.c +++ b/C/zstd/zstd_v05.c @@ -436,21 +436,6 @@ extern "C" { ***************************************/ #define ZSTDv05_WINDOWLOG_ABSOLUTEMIN 11 -/* from faster to stronger */ -typedef enum { ZSTDv05_fast, ZSTDv05_greedy, ZSTDv05_lazy, ZSTDv05_lazy2, ZSTDv05_btlazy2, ZSTDv05_opt, ZSTDv05_btopt } ZSTDv05_strategy; - -typedef struct -{ - U64 srcSize; /* optional : tells how much bytes are present in the frame. Use 0 if not known. */ - U32 windowLog; /* largest match distance : larger == more compression, more memory needed during decompression */ - U32 contentLog; /* full search segment : larger == more compression, slower, more memory (useless for fast) */ - U32 hashLog; /* dispatch table : larger == faster, more memory */ - U32 searchLog; /* nb of searches : larger == more compression, slower */ - U32 searchLength; /* match length searched : larger == faster decompression, sometimes less compression */ - U32 targetLength; /* acceptable match size for optimal parser (only) : larger == more compression, slower */ - ZSTDv05_strategy strategy; -} ZSTDv05_parameters; - /*-************************************* * Advanced functions @@ -2023,7 +2008,6 @@ extern "C" { ******************************************/ size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */ -size_t HUFv05_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbols decoder */ /* **************************************** @@ -2037,22 +2021,18 @@ HUFv05_decompress() does the following: */ size_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize); size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize); -size_t HUFv05_readDTableX6 (unsigned* DTable, const void* src, size_t srcSize); size_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); size_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); -size_t HUFv05_decompress4X6_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); /* single stream variants */ size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */ -size_t HUFv05_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbol decoder */ size_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); -size_t HUFv05_decompress1X6_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); @@ -2372,9 +2352,6 @@ size_t HUFv05_decompress4X2_usingDTable( const U32 dtLog = DTable[0]; size_t errorCode; - /* Check */ - if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - /* Init */ BITv05_DStream_t bitD1; BITv05_DStream_t bitD2; @@ -2398,6 +2375,9 @@ size_t HUFv05_decompress4X2_usingDTable( BYTE* op4 = opStart4; U32 endSignal; + /* Check */ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + length4 = cSrcSize - (length1 + length2 + length3 + 6); if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ errorCode = BITv05_initDStream(&bitD1, istart1, length1); @@ -2850,376 +2830,6 @@ size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t } -/* ********************************/ -/* quad-symbol decoding */ -/* ********************************/ -typedef struct { BYTE nbBits; BYTE nbBytes; } HUFv05_DDescX6; -typedef union { BYTE byte[4]; U32 sequence; } HUFv05_DSeqX6; - -/* recursive, up to level 3; may benefit from