2015-10-22 07:31:46 -07:00
/*
ZSTD HC - High Compression Mode of Zstandard
2016-01-28 08:56:33 -08:00
Copyright ( C ) 2015 - 2016 , Yann Collet .
2015-10-22 07:31:46 -07:00
BSD 2 - Clause License ( http : //www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are
met :
* Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above
copyright notice , this list of conditions and the following disclaimer
in the documentation and / or other materials provided with the
distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
" AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
You can contact the author at :
- Zstd source repository : https : //www.zstd.net
*/
2015-10-30 07:49:48 -07:00
/* *******************************************************
* Compiler specifics
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef _MSC_VER /* Visual Studio */
# define FORCE_INLINE static __forceinline
# include <intrin.h> /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# else
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
# endif
2016-02-11 15:07:30 -08:00
/*-*************************************
2016-02-02 17:46:46 -08:00
* Dependencies
2015-10-22 07:31:46 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-06-04 10:47:02 -07:00
# include <string.h> /* memset */
2015-11-11 12:38:21 -08:00
# include "mem.h"
2016-05-31 09:13:56 -07:00
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
2016-06-04 10:47:02 -07:00
# include "xxhash.h" /* XXH_reset, update, digest */
2016-06-04 15:58:01 -07:00
# define FSE_STATIC_LINKING_ONLY
# include "fse.h"
2016-06-04 15:42:28 -07:00
# define HUF_STATIC_LINKING_ONLY
# include "huf.h"
2016-06-04 10:47:02 -07:00
# include "zstd_internal.h" /* includes zstd.h */
2015-10-22 07:31:46 -07:00
2016-02-11 15:07:30 -08:00
/*-*************************************
2015-11-11 12:38:21 -08:00
* Constants
2015-10-22 07:31:46 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-19 07:18:42 -07:00
static const U32 g_searchStrength = 8 ; /* control skip over incompressible data */
2015-10-22 07:31:46 -07:00
2016-02-11 15:07:30 -08:00
/*-*************************************
2016-01-23 10:28:41 -08:00
* Helper functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t ZSTD_compressBound ( size_t srcSize ) { return FSE_compressBound ( srcSize ) + 12 ; }
2016-06-04 11:17:38 -07:00
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
}
2016-01-23 10:28:41 -08:00
2016-02-11 15:07:30 -08:00
/*-*************************************
2015-11-11 12:38:21 -08:00
* 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 ;
2016-04-07 08:19:00 -07:00
ssPtr - > longLengthID = 0 ;
2015-11-11 12:38:21 -08:00
}
2016-02-11 15:07:30 -08:00
/*-*************************************
2015-11-11 12:38:21 -08:00
* Context memory management
2015-10-22 07:31:46 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-11-11 04:43:58 -08:00
struct ZSTD_CCtx_s
2015-10-22 07:31:46 -07:00
{
2015-11-13 02:27:46 -08:00
const BYTE * nextSrc ; /* next block here to continue on current prefix */
2015-10-22 08:55:40 -07:00
const BYTE * base ; /* All regular indexes relative to this position */
const BYTE * dictBase ; /* extDict indexes relative to this position */
2015-10-22 07:31:46 -07:00
U32 dictLimit ; /* below that point, need extDict */
2015-10-22 08:55:40 -07:00
U32 lowLimit ; /* below that point, no more data */
2015-10-22 07:31:46 -07:00
U32 nextToUpdate ; /* index from which to continue dictionary update */
2016-02-19 01:09:35 -08:00
U32 nextToUpdate3 ; /* index from which to continue dictionary update */
2016-03-23 07:53:38 -07:00
U32 hashLog3 ; /* dispatch table : larger == faster, more memory */
2016-02-02 05:36:49 -08:00
U32 loadedDictEnd ;
2016-04-11 11:12:27 -07:00
U32 stage ; /* 0: created; 1: init,dictLoad; 2:started */
2016-05-28 20:01:04 -07:00
U32 dictID ;
2015-11-11 04:43:58 -08:00
ZSTD_parameters params ;
2015-10-29 10:41:45 -07:00
void * workSpace ;
size_t workSpaceSize ;
2015-12-02 05:00:45 -08:00
size_t blockSize ;
2016-06-05 15:26:38 -07:00
U64 frameContentSize ;
2016-05-31 09:13:56 -07:00
XXH64_state_t xxhState ;
2016-06-02 04:04:18 -07:00
ZSTD_customMem customMem ;
2016-01-07 06:35:18 -08:00
2015-10-29 10:41:45 -07:00
seqStore_t seqStore ; /* sequences storage ptrs */
2015-10-25 06:06:35 -07:00
U32 * hashTable ;
2016-02-19 01:09:35 -08:00
U32 * hashTable3 ;
2016-04-04 04:49:18 -07:00
U32 * chainTable ;
2016-01-25 18:14:20 -08:00
HUF_CElt * hufTable ;
2016-01-27 15:18:06 -08:00
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 ) ] ;
2015-10-22 07:31:46 -07:00
} ;
2015-11-11 04:43:58 -08:00
ZSTD_CCtx * ZSTD_createCCtx ( void )
2015-10-22 07:31:46 -07:00
{
2016-06-03 04:28:20 -07:00
return ZSTD_createCCtx_advanced ( defaultCustomMem ) ;
2016-05-23 06:49:09 -07:00
}
ZSTD_CCtx * ZSTD_createCCtx_advanced ( ZSTD_customMem customMem )
{
2016-05-23 07:24:52 -07:00
ZSTD_CCtx * ctx ;
2016-05-23 08:04:23 -07:00
if ( ! customMem . customAlloc & & ! customMem . customFree )
2016-06-03 04:23:04 -07:00
customMem = defaultCustomMem ;
2016-05-23 06:49:09 -07:00
2016-05-23 08:04:23 -07:00
if ( ! customMem . customAlloc | | ! customMem . customFree )
return NULL ;
2016-06-02 04:04:18 -07:00
ctx = ( ZSTD_CCtx * ) customMem . customAlloc ( customMem . opaque , sizeof ( ZSTD_CCtx ) ) ;
2016-05-23 06:49:09 -07:00
if ( ! ctx ) return NULL ;
memset ( ctx , 0 , sizeof ( ZSTD_CCtx ) ) ;
2016-06-02 04:04:18 -07:00
memcpy ( & ctx - > customMem , & customMem , sizeof ( ZSTD_customMem ) ) ;
2016-05-23 06:49:09 -07:00
return ctx ;
2015-10-22 07:31:46 -07:00
}
2015-11-11 04:43:58 -08:00
size_t ZSTD_freeCCtx ( ZSTD_CCtx * cctx )
2015-10-25 06:06:35 -07:00
{
2016-06-03 07:36:50 -07:00
if ( cctx = = NULL ) return 0 ; /* support free on NULL */
if ( cctx - > workSpace ) cctx - > customMem . customFree ( cctx - > customMem . opaque , cctx - > workSpace ) ;
2016-06-02 04:04:18 -07:00
cctx - > customMem . customFree ( cctx - > customMem . opaque , cctx ) ;
2016-02-04 17:33:10 -08:00
return 0 ; /* reserved as a potential error code in the future */
2015-10-25 06:06:35 -07:00
}
2015-10-22 07:31:46 -07:00
2016-03-26 12:52:14 -07:00
const seqStore_t * ZSTD_getSeqStore ( const ZSTD_CCtx * ctx ) /* hidden interface */
2016-02-11 15:07:30 -08:00
{
2016-03-26 12:52:14 -07:00
return & ( ctx - > seqStore ) ;
2016-02-11 15:07:30 -08:00
}
2015-11-04 03:05:27 -08:00
2016-02-10 04:37:52 -08:00
# define CLAMP(val,min,max) { if (val<min) val=min; else if (val>max) val=max; }
2016-03-30 07:50:44 -07:00
# define CLAMPCHECK(val,min,max) { if ((val<min) || (val>max)) return ERROR(compressionParameter_unsupported); }
/** ZSTD_checkParams() :
ensure param values remain within authorized range .
@ return : 0 , or an error code if one value is beyond authorized range */
2016-03-30 10:48:05 -07:00
size_t ZSTD_checkCParams ( ZSTD_compressionParameters cParams )
2016-03-30 07:50:44 -07:00
{
2016-04-03 19:22:53 -07:00
CLAMPCHECK ( cParams . windowLog , ZSTD_WINDOWLOG_MIN , ZSTD_WINDOWLOG_MAX ) ;
2016-04-04 04:49:18 -07:00
CLAMPCHECK ( cParams . chainLog , ZSTD_CHAINLOG_MIN , ZSTD_CHAINLOG_MAX ) ;
2016-03-30 10:48:05 -07:00
CLAMPCHECK ( cParams . hashLog , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
CLAMPCHECK ( cParams . searchLog , ZSTD_SEARCHLOG_MIN , ZSTD_SEARCHLOG_MAX ) ;
2016-04-06 03:34:42 -07:00
{ U32 const searchLengthMin = ( cParams . strategy = = ZSTD_fast | | cParams . strategy = = ZSTD_greedy ) ? ZSTD_SEARCHLENGTH_MIN + 1 : ZSTD_SEARCHLENGTH_MIN ;
2016-03-30 10:48:05 -07:00
U32 const searchLengthMax = ( cParams . strategy = = ZSTD_fast ) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX - 1 ;
CLAMPCHECK ( cParams . searchLength , searchLengthMin , searchLengthMax ) ; }
CLAMPCHECK ( cParams . targetLength , ZSTD_TARGETLENGTH_MIN , ZSTD_TARGETLENGTH_MAX ) ;
2016-03-30 12:28:15 -07:00
if ( ( U32 ) ( cParams . strategy ) > ( U32 ) ZSTD_btopt ) return ERROR ( compressionParameter_unsupported ) ;
2016-03-30 07:50:44 -07:00
return 0 ;
}
2016-02-10 04:37:52 -08:00
2016-03-30 10:48:05 -07:00
/** ZSTD_checkCParams_advanced() :
temporary work - around , while the compressor compatibility remains limited regarding windowLog < 18 */
size_t ZSTD_checkCParams_advanced ( ZSTD_compressionParameters cParams , U64 srcSize )
{
2016-04-01 09:54:13 -07:00
if ( srcSize > ( 1ULL < < ZSTD_WINDOWLOG_MIN ) ) return ZSTD_checkCParams ( cParams ) ;
2016-03-30 10:48:05 -07:00
if ( cParams . windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN ) return ERROR ( compressionParameter_unsupported ) ;
2016-04-04 04:49:18 -07:00
if ( srcSize < = ( 1ULL < < cParams . windowLog ) ) cParams . windowLog = ZSTD_WINDOWLOG_MIN ; /* fake value - temporary work around */
if ( srcSize < = ( 1ULL < < cParams . chainLog ) ) cParams . chainLog = ZSTD_CHAINLOG_MIN ; /* fake value - temporary work around */
2016-04-01 15:46:40 -07:00
if ( ( srcSize < = ( 1ULL < < cParams . hashLog ) ) & & ( ( U32 ) cParams . strategy < ( U32 ) ZSTD_btlazy2 ) ) cParams . hashLog = ZSTD_HASHLOG_MIN ; /* fake value - temporary work around */
2016-03-30 10:48:05 -07:00
return ZSTD_checkCParams ( cParams ) ;
}
2016-06-01 09:45:34 -07:00
/** ZSTD_adjustCParams() :
optimize cPar for a given input ( ` srcSize ` and ` dictSize ` ) .
2016-03-30 07:50:44 -07:00
mostly downsizing to reduce memory consumption and initialization .
Both ` srcSize ` and ` dictSize ` are optional ( use 0 if unknown ) ,
but if both are 0 , no optimization can be done .
2016-06-01 09:45:34 -07:00
Note : cPar is considered validated at this stage . Use ZSTD_checkParams ( ) to ensure that . */
ZSTD_compressionParameters ZSTD_adjustCParams ( ZSTD_compressionParameters cPar , U64 srcSize , size_t dictSize )
2016-03-30 07:50:44 -07:00
{
2016-06-01 09:45:34 -07:00
if ( srcSize + dictSize = = 0 ) return cPar ; /* no size information available : no adjustment */
2015-11-04 03:05:27 -08:00
2016-03-19 10:08:32 -07:00
/* resize params, to use less memory when necessary */
2016-03-30 11:06:26 -07:00
{ U32 const minSrcSize = ( srcSize = = 0 ) ? 500 : 0 ;
U64 const rSize = srcSize + dictSize + minSrcSize ;
2016-04-04 05:53:16 -07:00
if ( rSize < ( ( U64 ) 1 < < ZSTD_WINDOWLOG_MAX ) ) {
2016-06-04 11:17:38 -07:00
U32 const srcLog = ZSTD_highbit32 ( ( U32 ) ( rSize ) - 1 ) + 1 ;
2016-06-01 09:45:34 -07:00
if ( cPar . windowLog > srcLog ) cPar . windowLog = srcLog ;
2016-03-30 07:50:44 -07:00
} }
2016-06-01 09:45:34 -07:00
if ( cPar . hashLog > cPar . windowLog ) cPar . hashLog = cPar . windowLog ;
{ U32 const btPlus = ( cPar . strategy = = ZSTD_btlazy2 ) | | ( cPar . strategy = = ZSTD_btopt ) ;
U32 const maxChainLog = cPar . windowLog + btPlus ;
if ( cPar . chainLog > maxChainLog ) cPar . chainLog = maxChainLog ; } /* <= ZSTD_CHAINLOG_MAX */
2016-03-19 09:18:00 -07:00
2016-06-01 09:45:34 -07:00
if ( cPar . windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN ) cPar . windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN ; /* required for frame header */
if ( ( cPar . hashLog < ZSTD_HASHLOG_MIN ) & & ( ( U32 ) cPar . strategy > = ( U32 ) ZSTD_btlazy2 ) ) cPar . hashLog = ZSTD_HASHLOG_MIN ; /* required to ensure collision resistance in bt */
return cPar ;
2015-11-04 03:05:27 -08:00
}
2016-03-30 11:42:19 -07:00
size_t ZSTD_sizeofCCtx ( ZSTD_compressionParameters cParams ) /* hidden interface, for paramagrill */
2016-03-19 08:09:09 -07:00
{
ZSTD_CCtx * zc = ZSTD_createCCtx ( ) ;
2016-03-30 11:42:19 -07:00
ZSTD_parameters params ;
2016-05-28 20:01:04 -07:00
memset ( & params , 0 , sizeof ( params ) ) ;
2016-03-30 11:42:19 -07:00
params . cParams = cParams ;
params . fParams . contentSizeFlag = 1 ;
2016-03-30 10:48:05 -07:00
ZSTD_compressBegin_advanced ( zc , NULL , 0 , params , 0 ) ;
2016-03-20 16:07:42 -07:00
{ size_t const ccsize = sizeof ( * zc ) + zc - > workSpaceSize ;
2016-03-19 09:18:00 -07:00
ZSTD_freeCCtx ( zc ) ;
2016-03-20 16:07:42 -07:00
return ccsize ; }
2016-03-08 03:22:11 -08:00
}
2016-04-01 06:48:48 -07:00
/*! ZSTD_resetCCtx_advanced() :
note : ' params ' is expected to be validated */
2015-11-11 04:43:58 -08:00
static size_t ZSTD_resetCCtx_advanced ( ZSTD_CCtx * zc ,
2016-06-05 15:26:38 -07:00
ZSTD_parameters params , U64 frameContentSize , U32 reset )
2016-01-28 08:56:33 -08:00
{ /* note : params considered validated here */
2016-03-30 10:48:05 -07:00
const size_t blockSize = MIN ( ZSTD_BLOCKSIZE_MAX , ( size_t ) 1 < < params . cParams . windowLog ) ;
const U32 divider = ( params . cParams . searchLength = = 3 ) ? 3 : 4 ;
2016-03-07 17:35:34 -08:00
const size_t maxNbSeq = blockSize / divider ;
2016-03-22 15:19:28 -07:00
const size_t tokenSpace = blockSize + 11 * maxNbSeq ;
2016-04-04 04:49:18 -07:00
const size_t chainSize = ( params . cParams . strategy = = ZSTD_fast ) ? 0 : ( 1 < < params . cParams . chainLog ) ;
2016-04-25 06:23:09 -07:00
const size_t hSize = ( ( size_t ) 1 ) < < params . cParams . hashLog ;
2016-06-05 15:26:38 -07:00
const U32 hashLog3 = ( params . cParams . searchLength > 3 ) ? 0 :
( ( ! frameContentSize | | frameContentSize > = 8192 ) ? ZSTD_HASHLOG3_MAX :
( ( frameContentSize > = 2048 ) ? ZSTD_HASHLOG3_MIN + 1 : ZSTD_HASHLOG3_MIN ) ) ;
2016-06-05 15:46:56 -07:00
const size_t h3Size = ( ( size_t ) 1 ) < < hashLog3 ;
2016-04-04 04:49:18 -07:00
const size_t tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
2016-03-02 06:56:24 -08:00
2016-03-19 08:09:09 -07:00
/* Check if workSpace is large enough, alloc a new one if needed */
2016-04-07 06:24:29 -07:00
{ size_t const optSpace = ( ( MaxML + 1 ) + ( MaxLL + 1 ) + ( MaxOff + 1 ) + ( 1 < < Litbits ) ) * sizeof ( U32 )
2016-03-19 08:09:09 -07:00
+ ( ZSTD_OPT_NUM + 1 ) * ( sizeof ( ZSTD_match_t ) + sizeof ( ZSTD_optimal_t ) ) ;
size_t const neededSpace = tableSpace + ( 256 * sizeof ( U32 ) ) /* huffTable */ + tokenSpace
2016-04-04 04:28:28 -07:00
+ ( ( params . cParams . strategy = = ZSTD_btopt ) ? optSpace : 0 ) ;
2016-03-19 08:09:09 -07:00
if ( zc - > workSpaceSize < neededSpace ) {
2016-06-02 04:04:18 -07:00
zc - > customMem . customFree ( zc - > customMem . opaque , zc - > workSpace ) ;
zc - > workSpace = zc - > customMem . customAlloc ( zc - > customMem . opaque , neededSpace ) ;
2016-03-19 08:09:09 -07:00
if ( zc - > workSpace = = NULL ) return ERROR ( memory_allocation ) ;
zc - > workSpaceSize = neededSpace ;
2016-03-19 09:18:00 -07:00
} }
2016-03-19 08:09:09 -07:00
2016-04-11 11:42:31 -07:00
if ( reset ) memset ( zc - > workSpace , 0 , tableSpace ) ; /* reset only tables */
2016-05-31 09:13:56 -07:00
XXH64_reset ( & zc - > xxhState , 0 ) ;
2016-06-05 15:26:38 -07:00
zc - > hashLog3 = hashLog3 ;
2016-06-06 02:07:33 -07:00
zc - > hashTable = ( U32 * ) ( zc - > workSpace ) ;
2016-04-04 04:49:18 -07:00
zc - > chainTable = zc - > hashTable + hSize ;
2016-06-06 02:07:33 -07:00
zc - > hashTable3 = zc - > chainTable + chainSize ;
zc - > seqStore . buffer = zc - > hashTable3 + h3Size ;
2016-01-28 08:56:33 -08:00
zc - > hufTable = ( HUF_CElt * ) zc - > seqStore . buffer ;
zc - > flagStaticTables = 0 ;
2016-03-20 11:14:22 -07:00
zc - > seqStore . buffer = ( ( U32 * ) ( zc - > seqStore . buffer ) ) + 256 ;
2015-10-25 06:06:35 -07:00
2015-11-06 16:13:31 -08:00
zc - > nextToUpdate = 1 ;
2015-11-13 02:27:46 -08:00
zc - > nextSrc = NULL ;
2015-10-29 08:49:43 -07:00
zc - > base = NULL ;
zc - > dictBase = NULL ;
zc - > dictLimit = 0 ;
zc - > lowLimit = 0 ;
2015-10-25 06:06:35 -07:00
zc - > params = params ;
2015-12-02 05:00:45 -08:00
zc - > blockSize = blockSize ;
2016-06-05 15:26:38 -07:00
zc - > frameContentSize = frameContentSize ;
2016-02-10 04:37:52 -08:00
2016-03-30 10:48:05 -07:00
if ( params . cParams . strategy = = ZSTD_btopt ) {
2016-03-23 12:44:12 -07:00
zc - > seqStore . litFreq = ( U32 * ) ( zc - > seqStore . buffer ) ;
2016-03-04 10:17:31 -08:00
zc - > seqStore . litLengthFreq = zc - > seqStore . litFreq + ( 1 < < Litbits ) ;
2016-03-21 05:24:16 -07:00
zc - > seqStore . matchLengthFreq = zc - > seqStore . litLengthFreq + ( MaxLL + 1 ) ;
2016-03-22 15:19:28 -07:00
zc - > seqStore . offCodeFreq = zc - > seqStore . matchLengthFreq + ( MaxML + 1 ) ;
2016-04-07 06:24:29 -07:00
zc - > seqStore . matchTable = ( ZSTD_match_t * ) ( ( void * ) ( zc - > seqStore . offCodeFreq + ( MaxOff + 1 ) ) ) ;
2016-03-04 10:17:31 -08:00
zc - > seqStore . priceTable = ( ZSTD_optimal_t * ) ( ( void * ) ( zc - > seqStore . matchTable + ZSTD_OPT_NUM + 1 ) ) ;
2016-03-23 12:44:12 -07:00
zc - > seqStore . buffer = zc - > seqStore . priceTable + ZSTD_OPT_NUM + 1 ;
2016-03-04 10:17:31 -08:00
zc - > seqStore . litLengthSum = 0 ;
}
2016-03-23 12:44:12 -07:00
zc - > seqStore . offsetStart = ( U32 * ) ( zc - > seqStore . buffer ) ;
zc - > seqStore . litLengthStart = ( U16 * ) ( void * ) ( zc - > seqStore . offsetStart + maxNbSeq ) ;
zc - > seqStore . matchLengthStart = ( U16 * ) ( void * ) ( 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 ;
2016-03-02 11:37:49 -08:00
2016-04-11 11:12:27 -07:00
zc - > stage = 1 ;
2016-05-28 20:01:04 -07:00
zc - > dictID = 0 ;
2016-02-02 05:36:49 -08:00
zc - > loadedDictEnd = 0 ;
2015-10-29 08:49:43 -07:00
2015-10-29 22:40:22 -07:00
return 0 ;
2015-10-22 07:31:46 -07:00
}
2015-10-25 06:06:35 -07:00
2016-03-07 15:03:59 -08:00
/*! ZSTD_copyCCtx() :
* Duplicate an existing context ` srcCCtx ` into another one ` dstCCtx ` .
2016-04-11 11:12:27 -07:00
* Only works during stage 1 ( i . e . after creation , but before first call to ZSTD_compressContinue ( ) ) .
2016-01-26 06:58:49 -08:00
* @ return : 0 , or an error code */
size_t ZSTD_copyCCtx ( ZSTD_CCtx * dstCCtx , const ZSTD_CCtx * srcCCtx )
{
2016-04-11 11:12:27 -07:00
if ( srcCCtx - > stage ! = 1 ) return ERROR ( stage_wrong ) ;
2016-01-26 06:58:49 -08:00
2016-06-02 04:04:18 -07:00
memcpy ( & dstCCtx - > customMem , & srcCCtx - > customMem , sizeof ( ZSTD_customMem ) ) ;
2016-06-05 15:26:38 -07:00
ZSTD_resetCCtx_advanced ( dstCCtx , srcCCtx - > params , srcCCtx - > frameContentSize , 0 ) ;
2016-04-12 10:13:08 -07:00
dstCCtx - > params . fParams . contentSizeFlag = 0 ; /* content size different from the one set during srcCCtx init */
2016-01-26 06:58:49 -08:00
/* copy tables */
2016-04-04 05:54:53 -07:00
{ const size_t chainSize = ( srcCCtx - > params . cParams . strategy = = ZSTD_fast ) ? 0 : ( 1 < < srcCCtx - > params . cParams . chainLog ) ;
2016-04-25 06:23:09 -07:00
const size_t hSize = ( ( size_t ) 1 ) < < srcCCtx - > params . cParams . hashLog ;
2016-06-06 02:07:33 -07:00
const size_t h3Size = ( size_t ) 1 < < srcCCtx - > hashLog3 ;
2016-04-04 05:54:53 -07:00
const size_t tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
2016-03-19 09:18:00 -07:00
memcpy ( dstCCtx - > workSpace , srcCCtx - > workSpace , tableSpace ) ;
}
2016-01-26 06:58:49 -08:00
2016-05-28 20:01:04 -07:00
/* copy dictionary offsets */
2016-03-19 09:18:00 -07:00
dstCCtx - > nextToUpdate = srcCCtx - > nextToUpdate ;
dstCCtx - > nextToUpdate3 = srcCCtx - > nextToUpdate3 ;
dstCCtx - > nextSrc = srcCCtx - > nextSrc ;
dstCCtx - > base = srcCCtx - > base ;
dstCCtx - > dictBase = srcCCtx - > dictBase ;
dstCCtx - > dictLimit = srcCCtx - > dictLimit ;
dstCCtx - > lowLimit = srcCCtx - > lowLimit ;
dstCCtx - > loadedDictEnd = srcCCtx - > loadedDictEnd ;
2016-05-28 20:01:04 -07:00
dstCCtx - > dictID = srcCCtx - > dictID ;
2016-01-26 06:58:49 -08:00
2016-01-27 15:18:06 -08:00
/* copy entropy tables */
dstCCtx - > flagStaticTables = srcCCtx - > flagStaticTables ;
2016-01-28 08:56:33 -08:00
if ( srcCCtx - > flagStaticTables ) {
2016-01-26 06:58:49 -08:00
memcpy ( dstCCtx - > hufTable , srcCCtx - > hufTable , 256 * 4 ) ;
2016-01-27 15:18:06 -08:00
memcpy ( dstCCtx - > litlengthCTable , srcCCtx - > litlengthCTable , sizeof ( dstCCtx - > litlengthCTable ) ) ;
memcpy ( dstCCtx - > matchlengthCTable , srcCCtx - > matchlengthCTable , sizeof ( dstCCtx - > matchlengthCTable ) ) ;
memcpy ( dstCCtx - > offcodeCTable , srcCCtx - > offcodeCTable , sizeof ( dstCCtx - > offcodeCTable ) ) ;
}
2016-01-26 06:58:49 -08:00
return 0 ;
}
2016-03-20 08:20:06 -07:00
/*! ZSTD_reduceTable() :
2016-03-20 16:07:42 -07:00
* reduce table indexes by ` reducerValue ` */
2016-03-20 08:20:06 -07:00
static void ZSTD_reduceTable ( U32 * const table , U32 const size , U32 const reducerValue )
2015-11-13 02:27:46 -08:00
{
2016-03-20 08:20:06 -07:00
U32 u ;
for ( u = 0 ; u < size ; u + + ) {
if ( table [ u ] < reducerValue ) table [ u ] = 0 ;
else table [ u ] - = reducerValue ;
2015-11-13 02:27:46 -08:00
}
}
2016-03-20 08:20:06 -07:00
/*! ZSTD_reduceIndex() :
* rescale all indexes to avoid future overflow ( indexes are U32 ) */
static void ZSTD_reduceIndex ( ZSTD_CCtx * zc , const U32 reducerValue )
{
2016-03-30 10:48:05 -07:00
{ const U32 hSize = 1 < < zc - > params . cParams . hashLog ;
2016-03-20 08:20:06 -07:00
ZSTD_reduceTable ( zc - > hashTable , hSize , reducerValue ) ; }
2016-04-04 04:49:18 -07:00
{ const U32 chainSize = ( zc - > params . cParams . strategy = = ZSTD_fast ) ? 0 : ( 1 < < zc - > params . cParams . chainLog ) ;
ZSTD_reduceTable ( zc - > chainTable , chainSize , reducerValue ) ; }
2016-03-20 08:20:06 -07:00
2016-03-23 07:53:38 -07:00
{ const U32 h3Size = ( zc - > hashLog3 ) ? 1 < < zc - > hashLog3 : 0 ;
2016-03-20 08:20:06 -07:00
ZSTD_reduceTable ( zc - > hashTable3 , h3Size , reducerValue ) ; }
}
2015-11-13 02:27:46 -08:00
2016-01-28 08:56:33 -08:00
/*-*******************************************************
2015-11-11 12:38:21 -08:00
* Block entropic compression
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-13 03:08:40 -07:00
/* Frame format description
Frame Header - [ Block Header - Block ] - Frame End
1 ) Frame Header
2016-06-05 15:26:38 -07:00
- 4 bytes : Magic Number : ZSTD_MAGICNUMBER ( defined within zstd_static . h )
- 1 byte : Frame Header Descriptor
- 1 - 13 bytes : Optional fields
2016-03-13 03:08:40 -07:00
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 descriptor
2016-06-05 15:26:38 -07:00
// old
1 byte - Alloc :
2016-03-13 03:08:40 -07:00
bit 0 - 3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN ( see zstd_internal . h )
2016-06-05 15:26:38 -07:00
bit 4 : reserved for windowLog ( must be zero )
2016-03-13 03:08:40 -07:00
bit 5 : reserved ( must be zero )
bit 6 - 7 : Frame content size : unknown , 1 byte , 2 bytes , 8 bytes
2016-06-05 15:26:38 -07:00
1 byte - checker :
bit 0 - 1 : dictID ( 0 , 1 , 2 or 4 bytes )
bit 2 - 7 : reserved ( must be zero )
// new
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 / 8 th )
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 )
2016-03-13 03:08:40 -07:00
0 : unknown
1 : 0 - 255 bytes
2 : 256 - 65535 + 256
8 : up to 16 exa
*/
2016-01-23 10:28:41 -08:00
/* 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
2016-01-24 19:10:46 -08:00
srcSize < 1 KB = > 3 bytes ( 2 - 2 - 10 - 10 ) = > single stream
2016-01-23 10:28:41 -08:00
srcSize < 1 KB = > 3 bytes ( 2 - 2 - 10 - 10 )
2016-01-24 19:22:03 -08:00
srcSize < 16 KB = > 4 bytes ( 2 - 2 - 14 - 14 )
2016-01-23 10:28:41 -08:00
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
2016-01-24 19:22:03 -08:00
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 < 16 KB = > 4 bytes ( 2 - 2 - 14 - 14 )
else = > 5 bytes ( 2 - 2 - 18 - 18 )
big endian convention
1 - CTable available ( stored into workspace ? )
2016-01-25 18:14:20 -08:00
2 - Small input ( fast heuristic ? Full comparison ? depend on clevel ? )
2016-01-24 19:22:03 -08:00
2016-01-23 10:28:41 -08:00
1.2 ) Literal block content
1.2 .1 ) Huff0 block , using sizes from header
See Huff0 format
2016-01-27 15:18:06 -08:00
1.2 .2 ) Huff0 block , using prepared table
2016-01-23 10:28:41 -08:00
2016-01-27 15:18:06 -08:00
1.2 .3 ) Raw content
2016-01-23 10:28:41 -08:00
2016-01-27 15:18:06 -08:00
1.2 .4 ) single byte
2016-01-23 10:28:41 -08:00
2 ) Sequences section
2016-01-27 15:18:06 -08:00
- 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
2016-01-23 10:28:41 -08:00
*/
2015-11-11 12:38:21 -08:00
2016-03-14 17:24:33 -07:00
size_t ZSTD_noCompressBlock ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-11 12:38:21 -08:00
{
BYTE * const ostart = ( BYTE * const ) dst ;
2016-03-14 17:24:33 -07:00
if ( srcSize + ZSTD_blockHeaderSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
2015-11-11 12:38:21 -08:00
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 */
return ZSTD_blockHeaderSize + srcSize ;
}
2016-03-14 17:24:33 -07:00
static size_t ZSTD_noCompressLiterals ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-11 12:38:21 -08:00
{
BYTE * const ostart = ( BYTE * const ) dst ;
2016-03-18 04:37:45 -07:00
U32 const flSize = 1 + ( srcSize > 31 ) + ( srcSize > 4095 ) ;
2015-11-11 12:38:21 -08:00
2016-03-14 17:24:33 -07:00
if ( srcSize + flSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
2015-11-11 12:38:21 -08:00
2016-01-23 10:28:41 -08:00
switch ( flSize )
{
case 1 : /* 2 - 1 - 5 */
ostart [ 0 ] = ( BYTE ) ( ( IS_RAW < < 6 ) + ( 0 < < 5 ) + srcSize ) ;
break ;
case 2 : /* 2 - 2 - 12 */
ostart [ 0 ] = ( BYTE ) ( ( IS_RAW < < 6 ) + ( 2 < < 4 ) + ( srcSize > > 8 ) ) ;
ostart [ 1 ] = ( BYTE ) srcSize ;
break ;
default : /*note : should not be necessary : flSize is within {1,2,3} */
case 3 : /* 2 - 2 - 20 */
ostart [ 0 ] = ( BYTE ) ( ( IS_RAW < < 6 ) + ( 3 < < 4 ) + ( srcSize > > 16 ) ) ;
ostart [ 1 ] = ( BYTE ) ( srcSize > > 8 ) ;
ostart [ 2 ] = ( BYTE ) srcSize ;
break ;
}
memcpy ( ostart + flSize , src , srcSize ) ;
return srcSize + flSize ;
2015-11-11 12:38:21 -08:00
}
2016-03-14 17:24:33 -07:00
static size_t ZSTD_compressRleLiteralsBlock ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-11 12:38:21 -08:00
{
BYTE * const ostart = ( BYTE * const ) dst ;
2016-03-18 04:37:45 -07:00
U32 const flSize = 1 + ( srcSize > 31 ) + ( srcSize > 4095 ) ;
2016-01-23 10:28:41 -08:00
2016-03-14 17:24:33 -07:00
( void ) dstCapacity ; /* dstCapacity guaranteed to be >=4, hence large enough */
2016-01-23 10:28:41 -08:00
switch ( flSize )
{
case 1 : /* 2 - 1 - 5 */
ostart [ 0 ] = ( BYTE ) ( ( IS_RLE < < 6 ) + ( 0 < < 5 ) + srcSize ) ;
break ;
case 2 : /* 2 - 2 - 12 */
ostart [ 0 ] = ( BYTE ) ( ( IS_RLE < < 6 ) + ( 2 < < 4 ) + ( srcSize > > 8 ) ) ;
ostart [ 1 ] = ( BYTE ) srcSize ;
break ;
2016-03-18 04:37:45 -07:00
default : /*note : should not be necessary : flSize is necessarily within {1,2,3} */
2016-01-23 10:28:41 -08:00
case 3 : /* 2 - 2 - 20 */
ostart [ 0 ] = ( BYTE ) ( ( IS_RLE < < 6 ) + ( 3 < < 4 ) + ( srcSize > > 16 ) ) ;
ostart [ 1 ] = ( BYTE ) ( srcSize > > 8 ) ;
ostart [ 2 ] = ( BYTE ) srcSize ;
break ;
}
2015-11-11 12:38:21 -08:00
2016-01-23 10:28:41 -08:00
ostart [ flSize ] = * ( const BYTE * ) src ;
return flSize + 1 ;
2015-11-11 12:38:21 -08:00
}
2016-01-23 10:28:41 -08:00
2016-03-19 17:09:18 -07:00
static size_t ZSTD_minGain ( size_t srcSize ) { return ( srcSize > > 6 ) + 2 ; }
2015-11-11 12:38:21 -08:00
2016-01-25 18:14:20 -08:00
static size_t ZSTD_compressLiterals ( ZSTD_CCtx * zc ,
2016-03-14 17:24:33 -07:00
void * dst , size_t dstCapacity ,
2015-11-11 12:38:21 -08:00
const void * src , size_t srcSize )
{
2016-03-18 04:37:45 -07:00
size_t const minGain = ZSTD_minGain ( srcSize ) ;
size_t const lhSize = 3 + ( srcSize > = 1 KB ) + ( srcSize > = 16 KB ) ;
2015-11-11 12:38:21 -08:00
BYTE * const ostart = ( BYTE * ) dst ;
2016-01-24 19:10:46 -08:00
U32 singleStream = srcSize < 256 ;
2016-01-25 18:14:20 -08:00
U32 hType = IS_HUF ;
2016-03-18 04:37:45 -07:00
size_t cLitSize ;
2015-11-11 12:38:21 -08:00
2016-03-19 17:09:18 -07:00
/* small ? don't even attempt compression (speed opt) */
# define LITERAL_NOENTROPY 63
{ size_t const minLitSize = zc - > flagStaticTables ? 6 : LITERAL_NOENTROPY ;
if ( srcSize < = minLitSize ) return ZSTD_noCompressLiterals ( dst , dstCapacity , src , srcSize ) ;
}
if ( dstCapacity < lhSize + 1 ) return ERROR ( dstSize_tooSmall ) ; /* not enough space for compression */
2016-01-27 15:18:06 -08:00
if ( zc - > flagStaticTables & & ( lhSize = = 3 ) ) {
2016-01-25 18:14:20 -08:00
hType = IS_PCH ;
singleStream = 1 ;
2016-03-18 04:37:45 -07:00
cLitSize = HUF_compress1X_usingCTable ( ostart + lhSize , dstCapacity - lhSize , src , srcSize , zc - > hufTable ) ;
2016-01-27 15:18:06 -08:00
} else {
2016-03-18 04:37:45 -07:00
cLitSize = singleStream ? HUF_compress1X ( ostart + lhSize , dstCapacity - lhSize , src , srcSize , 255 , 12 )
2016-03-14 17:24:33 -07:00
: HUF_compress2 ( ostart + lhSize , dstCapacity - lhSize , src , srcSize , 255 , 12 ) ;
2016-01-25 18:14:20 -08:00
}
2015-11-11 12:38:21 -08:00
2016-03-18 04:37:45 -07:00
if ( ( cLitSize = = 0 ) | | ( cLitSize > = srcSize - minGain ) )
return ZSTD_noCompressLiterals ( dst , dstCapacity , src , srcSize ) ;
if ( cLitSize = = 1 )
return ZSTD_compressRleLiteralsBlock ( dst , dstCapacity , src , srcSize ) ;
2015-11-11 12:38:21 -08:00
/* Build header */
2016-01-23 10:28:41 -08:00
switch ( lhSize )
2015-11-11 12:38:21 -08:00
{
2016-01-23 10:28:41 -08:00
case 3 : /* 2 - 2 - 10 - 10 */
2016-01-25 18:14:20 -08:00
ostart [ 0 ] = ( BYTE ) ( ( srcSize > > 6 ) + ( singleStream < < 4 ) + ( hType < < 6 ) ) ;
2016-03-18 04:37:45 -07:00
ostart [ 1 ] = ( BYTE ) ( ( srcSize < < 2 ) + ( cLitSize > > 8 ) ) ;
ostart [ 2 ] = ( BYTE ) ( cLitSize ) ;
2016-01-23 10:28:41 -08:00
break ;
case 4 : /* 2 - 2 - 14 - 14 */
2016-01-25 18:14:20 -08:00
ostart [ 0 ] = ( BYTE ) ( ( srcSize > > 10 ) + ( 2 < < 4 ) + ( hType < < 6 ) ) ;
2016-01-23 10:28:41 -08:00
ostart [ 1 ] = ( BYTE ) ( srcSize > > 2 ) ;
2016-03-18 04:37:45 -07:00
ostart [ 2 ] = ( BYTE ) ( ( srcSize < < 6 ) + ( cLitSize > > 8 ) ) ;
ostart [ 3 ] = ( BYTE ) ( cLitSize ) ;
2016-01-23 10:28:41 -08:00
break ;
2016-03-18 04:37:45 -07:00
default : /* should not be necessary, lhSize is only {3,4,5} */
2016-01-23 10:28:41 -08:00
case 5 : /* 2 - 2 - 18 - 18 */
2016-01-25 18:14:20 -08:00
ostart [ 0 ] = ( BYTE ) ( ( srcSize > > 14 ) + ( 3 < < 4 ) + ( hType < < 6 ) ) ;
2016-01-23 10:28:41 -08:00
ostart [ 1 ] = ( BYTE ) ( srcSize > > 6 ) ;
2016-03-18 04:37:45 -07:00
ostart [ 2 ] = ( BYTE ) ( ( srcSize < < 2 ) + ( cLitSize > > 16 ) ) ;
ostart [ 3 ] = ( BYTE ) ( cLitSize > > 8 ) ;
ostart [ 4 ] = ( BYTE ) ( cLitSize ) ;
2016-01-23 10:28:41 -08:00
break ;
2015-11-11 12:38:21 -08:00
}
2016-03-18 04:37:45 -07:00
return lhSize + cLitSize ;
2015-11-11 12:38:21 -08:00
}
2016-03-26 12:52:14 -07:00
void ZSTD_seqToCodes ( const seqStore_t * seqStorePtr , size_t const nbSeq )
{
/* 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 ;
2016-04-07 08:19:00 -07:00
const U16 * const llTable = seqStorePtr - > litLengthStart ;
2016-03-26 12:52:14 -07:00
BYTE * const llCodeTable = seqStorePtr - > llCodeStart ;
size_t u ;
for ( u = 0 ; u < nbSeq ; u + + ) {
2016-04-07 08:19:00 -07:00
U32 const ll = llTable [ u ] ;
2016-06-04 11:17:38 -07:00
llCodeTable [ u ] = ( ll > 63 ) ? ( BYTE ) ZSTD_highbit32 ( ll ) + LL_deltaCode : LL_Code [ ll ] ;
2016-04-07 08:19:00 -07:00
}
if ( seqStorePtr - > longLengthID = = 1 )
llCodeTable [ seqStorePtr - > longLengthPos ] = MaxLL ;
}
2016-03-26 12:52:14 -07:00
/* Offset codes */
{ const U32 * const offsetTable = seqStorePtr - > offsetStart ;
BYTE * const ofCodeTable = seqStorePtr - > offCodeStart ;
size_t u ;
2016-06-04 11:17:38 -07:00
for ( u = 0 ; u < nbSeq ; u + + ) ofCodeTable [ u ] = ( BYTE ) ZSTD_highbit32 ( offsetTable [ u ] ) ;
2016-03-26 12:52:14 -07:00
}
/* ML codes */
{ 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 ;
2016-04-07 08:19:00 -07:00
const U16 * const mlTable = seqStorePtr - > matchLengthStart ;
2016-03-26 12:52:14 -07:00
BYTE * const mlCodeTable = seqStorePtr - > mlCodeStart ;
size_t u ;
for ( u = 0 ; u < nbSeq ; u + + ) {
2016-04-07 08:19:00 -07:00
U32 const ml = mlTable [ u ] ;
2016-06-04 11:17:38 -07:00
mlCodeTable [ u ] = ( ml > 127 ) ? ( BYTE ) ZSTD_highbit32 ( ml ) + ML_deltaCode : ML_Code [ ml ] ;
2016-04-07 08:19:00 -07:00
}
if ( seqStorePtr - > longLengthID = = 2 )
mlCodeTable [ seqStorePtr - > longLengthPos ] = MaxML ;
}
2016-03-26 12:52:14 -07:00
}
2016-01-25 18:14:20 -08:00
size_t ZSTD_compressSequences ( ZSTD_CCtx * zc ,
2016-03-14 17:24:33 -07:00
void * dst , size_t dstCapacity ,
2015-11-11 12:38:21 -08:00
size_t srcSize )
{
2016-01-25 18:14:20 -08:00
const seqStore_t * seqStorePtr = & ( zc - > seqStore ) ;
2015-11-11 12:38:21 -08:00
U32 count [ MaxSeq + 1 ] ;
S16 norm [ MaxSeq + 1 ] ;
2016-01-27 15:18:06 -08:00
FSE_CTable * CTable_LitLength = zc - > litlengthCTable ;
FSE_CTable * CTable_OffsetBits = zc - > offcodeCTable ;
FSE_CTable * CTable_MatchLength = zc - > matchlengthCTable ;
2015-11-11 12:38:21 -08:00
U32 LLtype , Offtype , MLtype ; /* compressed, raw or rle */
2016-03-21 05:24:16 -07:00
U16 * const llTable = seqStorePtr - > litLengthStart ;
2016-03-22 04:14:26 -07:00
U16 * const mlTable = seqStorePtr - > matchLengthStart ;
2015-11-11 12:38:21 -08:00
const U32 * const offsetTable = seqStorePtr - > offsetStart ;
2016-03-20 16:07:42 -07:00
const U32 * const offsetTableEnd = seqStorePtr - > offset ;
2016-03-23 14:31:57 -07:00
BYTE * const ofCodeTable = seqStorePtr - > offCodeStart ;
2016-03-20 11:14:22 -07:00
BYTE * const llCodeTable = seqStorePtr - > llCodeStart ;
2016-03-22 04:14:26 -07:00
BYTE * const mlCodeTable = seqStorePtr - > mlCodeStart ;
2015-11-23 04:34:21 -08:00
BYTE * const ostart = ( BYTE * ) dst ;
2016-03-14 17:24:33 -07:00
BYTE * const oend = ostart + dstCapacity ;
2016-03-18 04:37:45 -07:00
BYTE * op = ostart ;
2016-03-20 16:07:42 -07:00
size_t const nbSeq = offsetTableEnd - offsetTable ;
2015-11-11 12:38:21 -08:00
BYTE * seqHead ;
/* Compress literals */
2016-03-19 17:09:18 -07:00
{ const BYTE * const literals = seqStorePtr - > litStart ;
2016-03-18 04:37:45 -07:00
size_t const litSize = seqStorePtr - > lit - literals ;
2016-03-19 17:09:18 -07:00
size_t const cSize = ZSTD_compressLiterals ( zc , op , dstCapacity , literals , litSize ) ;
2015-11-11 12:38:21 -08:00
if ( ZSTD_isError ( cSize ) ) return cSize ;
op + = cSize ;
}
/* Sequences Header */
2016-03-23 14:31:57 -07:00
if ( ( oend - op ) < 3 /*max nbSeq Size*/ + 1 /*seqHead */ ) return ERROR ( dstSize_tooSmall ) ;
2016-03-04 05:45:31 -08:00
if ( nbSeq < 0x7F ) * op + + = ( BYTE ) nbSeq ;
else if ( nbSeq < LONGNBSEQ ) op [ 0 ] = ( BYTE ) ( ( nbSeq > > 8 ) + 0x80 ) , op [ 1 ] = ( BYTE ) nbSeq , op + = 2 ;
else op [ 0 ] = 0xFF , MEM_writeLE16 ( op + 1 , ( U16 ) ( nbSeq - LONGNBSEQ ) ) , op + = 3 ;
2016-01-30 15:58:06 -08:00
if ( nbSeq = = 0 ) goto _check_compressibility ;
2015-11-11 12:38:21 -08:00
2016-03-22 15:19:28 -07:00
/* seqHead : flags for FSE encoding type */
seqHead = op + + ;
2015-11-11 12:38:21 -08:00
2016-01-27 15:18:06 -08:00
# define MIN_SEQ_FOR_DYNAMIC_FSE 64
# define MAX_SEQ_FOR_STATIC_FSE 1000
2016-03-26 12:52:14 -07:00
/* convert length/distances into codes */
ZSTD_seqToCodes ( seqStorePtr , nbSeq ) ;
2016-03-20 11:14:22 -07:00
2015-11-11 12:38:21 -08:00
/* CTable for Literal Lengths */
2016-03-22 04:14:26 -07:00
{ U32 max = MaxLL ;
size_t const mostFrequent = FSE_countFast ( count , & max , llCodeTable , nbSeq ) ;
if ( ( mostFrequent = = nbSeq ) & & ( nbSeq > 2 ) ) {
* op + + = llCodeTable [ 0 ] ;
FSE_buildCTable_rle ( CTable_LitLength , ( BYTE ) max ) ;
LLtype = FSE_ENCODING_RLE ;
} else if ( ( zc - > flagStaticTables ) & & ( nbSeq < MAX_SEQ_FOR_STATIC_FSE ) ) {
LLtype = FSE_ENCODING_STATIC ;
} 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 ;
} else {
size_t nbSeq_1 = nbSeq ;
const U32 tableLog = FSE_optimalTableLog ( LLFSELog , nbSeq , max ) ;
if ( count [ llCodeTable [ nbSeq - 1 ] ] > 1 ) { count [ llCodeTable [ nbSeq - 1 ] ] - - ; nbSeq_1 - - ; }
FSE_normalizeCount ( norm , tableLog , count , nbSeq_1 , max ) ;
2016-03-22 17:32:41 -07:00
{ size_t const NCountSize = FSE_writeNCount ( op , oend - op , norm , max , tableLog ) ; /* overflow protected */
if ( FSE_isError ( NCountSize ) ) return ERROR ( GENERIC ) ;
op + = NCountSize ; }
2016-03-22 04:14:26 -07:00
FSE_buildCTable ( CTable_LitLength , norm , max , tableLog ) ;
LLtype = FSE_ENCODING_DYNAMIC ;
} }
2015-11-11 12:38:21 -08:00
2016-03-26 12:52:14 -07:00
/* CTable for Offsets */
2016-03-22 04:14:26 -07:00
{ U32 max = MaxOff ;
2016-03-23 14:31:57 -07:00
size_t const mostFrequent = FSE_countFast ( count , & max , ofCodeTable , nbSeq ) ;
2016-03-22 04:14:26 -07:00
if ( ( mostFrequent = = nbSeq ) & & ( nbSeq > 2 ) ) {
2016-03-23 14:31:57 -07:00
* op + + = ofCodeTable [ 0 ] ;
2016-03-22 04:14:26 -07:00
FSE_buildCTable_rle ( CTable_OffsetBits , ( BYTE ) max ) ;
Offtype = FSE_ENCODING_RLE ;
} else if ( ( zc - > flagStaticTables ) & & ( nbSeq < MAX_SEQ_FOR_STATIC_FSE ) ) {
Offtype = FSE_ENCODING_STATIC ;
2016-04-07 06:24:29 -07:00
} else if ( ( nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE ) | | ( mostFrequent < ( nbSeq > > ( OF_defaultNormLog - 1 ) ) ) ) {
FSE_buildCTable ( CTable_OffsetBits , OF_defaultNorm , MaxOff , OF_defaultNormLog ) ;
2016-03-22 04:14:26 -07:00
Offtype = FSE_ENCODING_RAW ;
} else {
size_t nbSeq_1 = nbSeq ;
const U32 tableLog = FSE_optimalTableLog ( OffFSELog , nbSeq , max ) ;
2016-03-23 14:31:57 -07:00
if ( count [ ofCodeTable [ nbSeq - 1 ] ] > 1 ) { count [ ofCodeTable [ nbSeq - 1 ] ] - - ; nbSeq_1 - - ; }
2016-03-22 04:14:26 -07:00
FSE_normalizeCount ( norm , tableLog , count , nbSeq_1 , max ) ;
2016-03-22 17:32:41 -07:00
{ size_t const NCountSize = FSE_writeNCount ( op , oend - op , norm , max , tableLog ) ; /* overflow protected */
if ( FSE_isError ( NCountSize ) ) return ERROR ( GENERIC ) ;
op + = NCountSize ; }
2016-03-22 04:14:26 -07:00
FSE_buildCTable ( CTable_OffsetBits , norm , max , tableLog ) ;
Offtype = FSE_ENCODING_DYNAMIC ;
} }
2015-11-11 12:38:21 -08:00
/* CTable for MatchLengths */
2016-03-22 04:14:26 -07:00
{ U32 max = MaxML ;
size_t const mostFrequent = FSE_countFast ( count , & max , mlCodeTable , nbSeq ) ;
if ( ( mostFrequent = = nbSeq ) & & ( nbSeq > 2 ) ) {
2016-03-23 12:44:12 -07:00
* op + + = * mlCodeTable ;
2016-03-22 04:14:26 -07:00
FSE_buildCTable_rle ( CTable_MatchLength , ( BYTE ) max ) ;
MLtype = FSE_ENCODING_RLE ;
} else if ( ( zc - > flagStaticTables ) & & ( nbSeq < MAX_SEQ_FOR_STATIC_FSE ) ) {
MLtype = FSE_ENCODING_STATIC ;
} 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 ;
} else {
size_t nbSeq_1 = nbSeq ;
const U32 tableLog = FSE_optimalTableLog ( MLFSELog , nbSeq , max ) ;
if ( count [ mlCodeTable [ nbSeq - 1 ] ] > 1 ) { count [ mlCodeTable [ nbSeq - 1 ] ] - - ; nbSeq_1 - - ; }
FSE_normalizeCount ( norm , tableLog , count , nbSeq_1 , max ) ;
{ size_t const NCountSize = FSE_writeNCount ( op , oend - op , norm , max , tableLog ) ; /* overflow protected */
if ( FSE_isError ( NCountSize ) ) return ERROR ( GENERIC ) ;
op + = NCountSize ; }
FSE_buildCTable ( CTable_MatchLength , norm , max , tableLog ) ;
MLtype = FSE_ENCODING_DYNAMIC ;
} }
2015-11-11 12:38:21 -08:00
2016-03-22 15:19:28 -07:00
* seqHead = ( BYTE ) ( ( LLtype < < 6 ) + ( Offtype < < 4 ) + ( MLtype < < 2 ) ) ;
2016-01-27 15:18:06 -08:00
zc - > flagStaticTables = 0 ;
2015-11-11 12:38:21 -08:00
/* Encoding Sequences */
2016-03-19 10:08:32 -07:00
{ BIT_CStream_t blockStream ;
2016-03-18 04:37:45 -07:00
FSE_CState_t stateMatchLength ;
FSE_CState_t stateOffsetBits ;
FSE_CState_t stateLitLength ;
2015-11-11 12:38:21 -08:00
2016-03-18 04:37:45 -07:00
{ size_t const errorCode = BIT_initCStream ( & blockStream , op , oend - op ) ;
2016-03-20 11:14:22 -07:00
if ( ERR_isError ( errorCode ) ) return ERROR ( dstSize_tooSmall ) ; } /* not enough space remaining */
/* first symbols */
2016-03-22 04:14:26 -07:00
FSE_initCState2 ( & stateMatchLength , CTable_MatchLength , mlCodeTable [ nbSeq - 1 ] ) ;
2016-03-23 14:31:57 -07:00
FSE_initCState2 ( & stateOffsetBits , CTable_OffsetBits , ofCodeTable [ nbSeq - 1 ] ) ;
2016-03-20 11:14:22 -07:00
FSE_initCState2 ( & stateLitLength , CTable_LitLength , llCodeTable [ nbSeq - 1 ] ) ;
2016-03-21 05:24:16 -07:00
BIT_addBits ( & blockStream , llTable [ nbSeq - 1 ] , LL_bits [ llCodeTable [ nbSeq - 1 ] ] ) ;
2016-03-26 09:18:11 -07:00
if ( MEM_32bits ( ) ) BIT_flushBits ( & blockStream ) ;
2016-03-23 06:00:09 -07:00
BIT_addBits ( & blockStream , mlTable [ nbSeq - 1 ] , ML_bits [ mlCodeTable [ nbSeq - 1 ] ] ) ;
2016-03-26 09:18:11 -07:00
if ( MEM_32bits ( ) ) BIT_flushBits ( & blockStream ) ;
2016-03-23 18:31:27 -07:00
BIT_addBits ( & blockStream , offsetTable [ nbSeq - 1 ] , ofCodeTable [ nbSeq - 1 ] ) ;
2016-03-20 11:14:22 -07:00
BIT_flushBits ( & blockStream ) ;
2015-11-11 12:38:21 -08:00
2016-03-22 04:14:26 -07:00
{ size_t n ;
for ( n = nbSeq - 2 ; n < nbSeq ; n - - ) { /* intentional underflow */
2016-03-26 09:18:11 -07:00
const BYTE ofCode = ofCodeTable [ n ] ;
2016-03-23 14:31:57 -07:00
const BYTE mlCode = mlCodeTable [ n ] ;
const BYTE llCode = llCodeTable [ n ] ;
const U32 llBits = LL_bits [ llCode ] ;
const U32 mlBits = ML_bits [ mlCode ] ;
2016-03-26 09:18:11 -07:00
const U32 ofBits = ofCode ; /* 32b*/ /* 64b*/
2016-03-22 04:14:26 -07:00
/* (7)*/ /* (7)*/
2016-03-26 09:18:11 -07:00
FSE_encodeSymbol ( & blockStream , & stateOffsetBits , ofCode ) ; /* 15 */ /* 15 */
FSE_encodeSymbol ( & blockStream , & stateMatchLength , mlCode ) ; /* 24 */ /* 24 */
if ( MEM_32bits ( ) ) BIT_flushBits ( & blockStream ) ; /* (7)*/
FSE_encodeSymbol ( & blockStream , & stateLitLength , llCode ) ; /* 16 */ /* 33 */
2016-04-11 07:25:56 -07:00
if ( MEM_32bits ( ) | | ( ofBits + mlBits + llBits > = 64 - 7 - ( LLFSELog + MLFSELog + OffFSELog ) ) )
2016-03-26 09:18:11 -07:00
BIT_flushBits ( & blockStream ) ; /* (7)*/
2016-03-23 14:31:57 -07:00
BIT_addBits ( & blockStream , llTable [ n ] , llBits ) ;
2016-03-26 09:18:11 -07:00
if ( MEM_32bits ( ) & & ( ( llBits + mlBits ) > 24 ) ) BIT_flushBits ( & blockStream ) ;
2016-03-23 14:31:57 -07:00
BIT_addBits ( & blockStream , mlTable [ n ] , mlBits ) ;
2016-03-26 09:18:11 -07:00
if ( MEM_32bits ( ) ) BIT_flushBits ( & blockStream ) ; /* (7)*/
BIT_addBits ( & blockStream , offsetTable [ n ] , ofBits ) ; /* 31 */
BIT_flushBits ( & blockStream ) ; /* (7)*/
2016-03-22 04:14:26 -07:00
} }
2015-11-11 12:38:21 -08:00
FSE_flushCState ( & blockStream , & stateMatchLength ) ;
FSE_flushCState ( & blockStream , & stateOffsetBits ) ;
FSE_flushCState ( & blockStream , & stateLitLength ) ;
2016-03-26 09:18:11 -07:00
{ size_t const streamSize = BIT_closeCStream ( & blockStream ) ;
if ( streamSize = = 0 ) return ERROR ( dstSize_tooSmall ) ; /* not enough space */
op + = streamSize ;
} }
2015-11-11 12:38:21 -08:00
/* check compressibility */
2016-01-30 15:58:06 -08:00
_check_compressibility :
2016-03-22 04:14:26 -07:00
{ size_t const minGain = ZSTD_minGain ( srcSize ) ;
size_t const maxCSize = srcSize - minGain ;
if ( ( size_t ) ( op - ostart ) > = maxCSize ) return 0 ; }
2015-11-11 12:38:21 -08:00
2015-11-23 04:34:21 -08:00
return op - ostart ;
2015-11-11 12:38:21 -08:00
}
2016-03-08 09:24:21 -08:00
/*! ZSTD_storeSeq() :
Store a sequence ( literal length , literals , offset code and match length code ) into seqStore_t .
` offsetCode ` : distance to match , or 0 = = repCode .
` matchCode ` : matchLength - MINMATCH
2015-11-11 12:38:21 -08:00
*/
MEM_STATIC void ZSTD_storeSeq ( seqStore_t * seqStorePtr , size_t litLength , const BYTE * literals , size_t offsetCode , size_t matchCode )
{
2016-02-02 08:30:37 -08:00
#if 0 /* for debug */
2015-11-11 12:38:21 -08:00
static const BYTE * g_start = NULL ;
2016-03-21 05:24:16 -07:00
const U32 pos = ( U32 ) ( literals - g_start ) ;
2015-11-11 12:38:21 -08:00
if ( g_start = = NULL ) g_start = literals ;
2016-05-04 18:01:13 -07:00
if ( ( pos > 2587900 ) & & ( pos < 2588050 ) )
2016-03-26 09:18:11 -07:00
printf ( " Cpos %6u :%5u literals & match %3u bytes at distance %6u \n " ,
2016-03-25 03:43:48 -07:00
pos , ( U32 ) litLength , ( U32 ) matchCode + MINMATCH , ( U32 ) offsetCode ) ;
2015-11-11 12:38:21 -08:00
# endif
2016-05-24 06:36:37 -07:00
ZSTD_statsUpdatePrices ( & seqStorePtr - > stats , litLength , literals , offsetCode , matchCode ) ;
2015-11-11 12:38:21 -08:00
/* copy Literals */
ZSTD_wildcopy ( seqStorePtr - > lit , literals , litLength ) ;
seqStorePtr - > lit + = litLength ;
/* literal Length */
2016-04-07 08:19:00 -07:00
if ( litLength > 0xFFFF ) { seqStorePtr - > longLengthID = 1 ; seqStorePtr - > longLengthPos = ( U32 ) ( seqStorePtr - > litLength - seqStorePtr - > litLengthStart ) ; }
* seqStorePtr - > litLength + + = ( U16 ) litLength ;
2015-11-11 12:38:21 -08:00
/* match offset */
2016-03-23 18:31:27 -07:00
* ( seqStorePtr - > offset + + ) = ( U32 ) offsetCode + 1 ;
2015-11-11 12:38:21 -08:00
/* match Length */
2016-04-07 08:19:00 -07:00
if ( matchCode > 0xFFFF ) { seqStorePtr - > longLengthID = 2 ; seqStorePtr - > longLengthPos = ( U32 ) ( seqStorePtr - > matchLength - seqStorePtr - > matchLengthStart ) ; }
* seqStorePtr - > matchLength + + = ( U16 ) matchCode ;
2015-11-11 12:38:21 -08:00
}
2016-02-11 15:07:30 -08:00
/*-*************************************
2015-11-11 12:38:21 -08:00
* Match length counter
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-11-23 04:34:21 -08:00
static unsigned ZSTD_NbCommonBytes ( register size_t val )
2015-11-11 12:38:21 -08:00
{
2016-01-28 08:56:33 -08:00
if ( MEM_isLittleEndian ( ) ) {
if ( MEM_64bits ( ) ) {
2015-11-11 12:38:21 -08:00
# if defined(_MSC_VER) && defined(_WIN64)
unsigned long r = 0 ;
_BitScanForward64 ( & r , ( U64 ) val ) ;
2015-12-09 00:05:22 -08:00
return ( unsigned ) ( r > > 3 ) ;
2015-11-11 12:38:21 -08:00
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return ( __builtin_ctzll ( ( U64 ) val ) > > 3 ) ;
# else
static const int DeBruijnBytePos [ 64 ] = { 0 , 0 , 0 , 0 , 0 , 1 , 1 , 2 , 0 , 3 , 1 , 3 , 1 , 4 , 2 , 7 , 0 , 2 , 3 , 6 , 1 , 5 , 3 , 5 , 1 , 3 , 4 , 4 , 2 , 5 , 6 , 7 , 7 , 0 , 1 , 2 , 3 , 3 , 4 , 6 , 2 , 6 , 5 , 5 , 3 , 4 , 5 , 6 , 7 , 1 , 2 , 4 , 6 , 4 , 4 , 5 , 7 , 2 , 6 , 5 , 7 , 6 , 7 , 7 } ;
return DeBruijnBytePos [ ( ( U64 ) ( ( val & - ( long long ) val ) * 0x0218A392CDABBD3FULL ) ) > > 58 ] ;
# endif
2016-01-28 08:56:33 -08:00
} else { /* 32 bits */
2015-11-11 12:38:21 -08:00
# if defined(_MSC_VER)
unsigned long r = 0 ;
_BitScanForward ( & r , ( U32 ) val ) ;
2015-12-09 00:05:22 -08:00
return ( unsigned ) ( r > > 3 ) ;
2015-11-11 12:38:21 -08:00
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return ( __builtin_ctz ( ( U32 ) val ) > > 3 ) ;
# else
static const int DeBruijnBytePos [ 32 ] = { 0 , 0 , 3 , 0 , 3 , 1 , 3 , 0 , 3 , 2 , 2 , 1 , 3 , 2 , 0 , 1 , 3 , 3 , 1 , 2 , 2 , 2 , 2 , 0 , 3 , 1 , 2 , 0 , 1 , 0 , 1 , 1 } ;
return DeBruijnBytePos [ ( ( U32 ) ( ( val & - ( S32 ) val ) * 0x077CB531U ) ) > > 27 ] ;
# endif
}
2016-01-28 08:56:33 -08:00
} else { /* Big Endian CPU */
if ( MEM_64bits ( ) ) {
2015-11-11 12:38:21 -08:00
# if defined(_MSC_VER) && defined(_WIN64)
unsigned long r = 0 ;
_BitScanReverse64 ( & r , val ) ;
return ( unsigned ) ( r > > 3 ) ;
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return ( __builtin_clzll ( val ) > > 3 ) ;
# else
unsigned r ;
const unsigned n32 = sizeof ( size_t ) * 4 ; /* calculate this way due to compiler complaining in 32-bits mode */
if ( ! ( val > > n32 ) ) { r = 4 ; } else { r = 0 ; val > > = n32 ; }
if ( ! ( val > > 16 ) ) { r + = 2 ; val > > = 8 ; } else { val > > = 24 ; }
r + = ( ! val ) ;
return r ;
# endif
2016-01-28 08:56:33 -08:00
} else { /* 32 bits */
2015-11-11 12:38:21 -08:00
# if defined(_MSC_VER)
unsigned long r = 0 ;
_BitScanReverse ( & r , ( unsigned long ) val ) ;
return ( unsigned ) ( r > > 3 ) ;
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return ( __builtin_clz ( ( U32 ) val ) > > 3 ) ;
# else
unsigned r ;
if ( ! ( val > > 16 ) ) { r = 2 ; val > > = 8 ; } else { r = 0 ; val > > = 24 ; }
r + = ( ! val ) ;
return r ;
# endif
2016-01-28 08:56:33 -08:00
} }
2015-11-11 12:38:21 -08:00
}
2015-11-23 04:34:21 -08:00
static size_t ZSTD_count ( const BYTE * pIn , const BYTE * pMatch , const BYTE * pInLimit )
2015-11-11 12:38:21 -08:00
{
const BYTE * const pStart = pIn ;
2016-01-27 15:18:06 -08:00
while ( ( pIn < pInLimit - ( sizeof ( size_t ) - 1 ) ) ) {
2016-05-20 02:44:43 -07:00
size_t const diff = MEM_readST ( pMatch ) ^ MEM_readST ( pIn ) ;
2015-11-11 12:38:21 -08:00
if ( ! diff ) { pIn + = sizeof ( size_t ) ; pMatch + = sizeof ( size_t ) ; continue ; }
pIn + = ZSTD_NbCommonBytes ( diff ) ;
return ( size_t ) ( pIn - pStart ) ;
}
if ( MEM_64bits ( ) ) if ( ( pIn < ( pInLimit - 3 ) ) & & ( MEM_read32 ( pMatch ) = = MEM_read32 ( pIn ) ) ) { pIn + = 4 ; pMatch + = 4 ; }
if ( ( pIn < ( pInLimit - 1 ) ) & & ( MEM_read16 ( pMatch ) = = MEM_read16 ( pIn ) ) ) { pIn + = 2 ; pMatch + = 2 ; }
if ( ( pIn < pInLimit ) & & ( * pMatch = = * pIn ) ) pIn + + ;
return ( size_t ) ( pIn - pStart ) ;
}
2016-02-10 21:23:24 -08:00
/** ZSTD_count_2segments() :
2016-02-11 15:07:30 -08:00
* can count match length with ` ip ` & ` match ` in 2 different segments .
2015-11-23 04:34:21 -08:00
* convention : on reaching mEnd , match count continue starting from iStart
*/
static size_t ZSTD_count_2segments ( const BYTE * ip , const BYTE * match , const BYTE * iEnd , const BYTE * mEnd , const BYTE * iStart )
{
2016-05-20 02:44:43 -07:00
const BYTE * const vEnd = MIN ( ip + ( mEnd - match ) , iEnd ) ;
size_t matchLength = ZSTD_count ( ip , match , vEnd ) ;
2015-11-23 04:34:21 -08:00
if ( match + matchLength = = mEnd )
matchLength + = ZSTD_count ( ip + matchLength , iStart , iEnd ) ;
return matchLength ;
}
2015-11-11 12:38:21 -08:00
2016-01-28 08:56:33 -08:00
/*-*************************************
2015-11-11 12:38:21 -08:00
* Hashes
2015-10-22 07:31:46 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-02-19 01:09:35 -08:00
static const U32 prime3bytes = 506832829U ;
static U32 ZSTD_hash3 ( U32 u , U32 h ) { return ( ( u < < ( 32 - 24 ) ) * prime3bytes ) > > ( 32 - h ) ; }
2016-03-07 01:07:08 -08:00
static size_t ZSTD_hash3Ptr ( const void * ptr , U32 h ) { return ZSTD_hash3 ( MEM_readLE32 ( ptr ) , h ) ; }
2016-02-19 01:09:35 -08:00
2015-10-30 07:49:48 -07:00
static const U32 prime4bytes = 2654435761U ;
2016-01-28 08:56:33 -08:00
static U32 ZSTD_hash4 ( U32 u , U32 h ) { return ( u * prime4bytes ) > > ( 32 - h ) ; }
2015-11-11 04:43:58 -08:00
static size_t ZSTD_hash4Ptr ( const void * ptr , U32 h ) { return ZSTD_hash4 ( MEM_read32 ( ptr ) , h ) ; }
2015-10-29 08:49:43 -07:00
2015-10-30 07:49:48 -07:00
static const U64 prime5bytes = 889523592379ULL ;
2016-01-28 08:56:33 -08:00
static size_t ZSTD_hash5 ( U64 u , U32 h ) { return ( size_t ) ( ( ( u < < ( 64 - 40 ) ) * prime5bytes ) > > ( 64 - h ) ) ; }
2016-02-06 19:00:27 -08:00
static size_t ZSTD_hash5Ptr ( const void * p , U32 h ) { return ZSTD_hash5 ( MEM_readLE64 ( p ) , h ) ; }
2015-10-29 08:49:43 -07:00
2015-10-30 07:49:48 -07:00
static const U64 prime6bytes = 227718039650203ULL ;
2016-01-28 08:56:33 -08:00
static size_t ZSTD_hash6 ( U64 u , U32 h ) { return ( size_t ) ( ( ( u < < ( 64 - 48 ) ) * prime6bytes ) > > ( 64 - h ) ) ; }
2016-02-06 19:00:27 -08:00
static size_t ZSTD_hash6Ptr ( const void * p , U32 h ) { return ZSTD_hash6 ( MEM_readLE64 ( p ) , h ) ; }
2015-10-22 07:31:46 -07:00
2015-11-11 12:38:21 -08:00
static const U64 prime7bytes = 58295818150454627ULL ;
2016-01-28 08:56:33 -08:00
static size_t ZSTD_hash7 ( U64 u , U32 h ) { return ( size_t ) ( ( ( u < < ( 64 - 56 ) ) * prime7bytes ) > > ( 64 - h ) ) ; }
2016-02-06 19:00:27 -08:00
static size_t ZSTD_hash7Ptr ( const void * p , U32 h ) { return ZSTD_hash7 ( MEM_readLE64 ( p ) , h ) ; }
2015-11-05 08:32:18 -08:00
2015-11-11 04:43:58 -08:00
static size_t ZSTD_hashPtr ( const void * p , U32 hBits , U32 mls )
2015-10-30 07:49:48 -07:00
{
switch ( mls )
{
default :
2015-11-11 04:43:58 -08:00
case 4 : return ZSTD_hash4Ptr ( p , hBits ) ;
case 5 : return ZSTD_hash5Ptr ( p , hBits ) ;
case 6 : return ZSTD_hash6Ptr ( p , hBits ) ;
case 7 : return ZSTD_hash7Ptr ( p , hBits ) ;
2015-10-30 07:49:48 -07:00
}
}
2016-01-28 08:56:33 -08:00
2016-02-02 05:36:49 -08:00
/*-*************************************
2015-11-05 08:32:18 -08:00
* Fast Scan
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-12-04 08:16:37 -08:00
static void ZSTD_fillHashTable ( ZSTD_CCtx * zc , const void * end , const U32 mls )
{
U32 * const hashTable = zc - > hashTable ;
2016-03-30 10:48:05 -07:00
const U32 hBits = zc - > params . cParams . hashLog ;
2015-12-04 08:16:37 -08:00
const BYTE * const base = zc - > base ;
const BYTE * ip = base + zc - > nextToUpdate ;
2016-02-02 05:36:49 -08:00
const BYTE * const iend = ( ( const BYTE * ) end ) - 8 ;
2016-03-19 07:11:42 -07:00
const size_t fastHashFillStep = 3 ;
2015-12-04 08:16:37 -08:00
2016-01-27 15:18:06 -08:00
while ( ip < = iend ) {
2015-12-04 08:16:37 -08:00
hashTable [ ZSTD_hashPtr ( ip , hBits , mls ) ] = ( U32 ) ( ip - base ) ;
2016-03-19 07:11:42 -07:00
ip + = fastHashFillStep ;
2015-12-04 08:16:37 -08:00
}
}
2015-11-05 08:32:18 -08:00
FORCE_INLINE
2016-01-23 10:28:41 -08:00
void ZSTD_compressBlock_fast_generic ( ZSTD_CCtx * zc ,
2015-11-13 02:27:46 -08:00
const void * src , size_t srcSize ,
const U32 mls )
2015-11-05 08:32:18 -08:00
{
2015-12-04 08:16:37 -08:00
U32 * const hashTable = zc - > hashTable ;
2016-03-30 10:48:05 -07:00
const U32 hBits = zc - > params . cParams . hashLog ;
2015-11-24 05:06:07 -08:00
seqStore_t * seqStorePtr = & ( zc - > seqStore ) ;
const BYTE * const base = zc - > base ;
2015-11-05 08:32:18 -08:00
const BYTE * const istart = ( const BYTE * ) src ;
2015-11-06 01:52:17 -08:00
const BYTE * ip = istart ;
2015-11-05 08:32:18 -08:00
const BYTE * anchor = istart ;
2015-12-29 05:29:08 -08:00
const U32 lowIndex = zc - > dictLimit ;
const BYTE * const lowest = base + lowIndex ;
2015-11-05 08:32:18 -08:00
const BYTE * const iend = istart + srcSize ;
const BYTE * const ilimit = iend - 8 ;
2015-11-13 02:27:46 -08:00
size_t offset_2 = REPCODE_STARTVALUE , offset_1 = REPCODE_STARTVALUE ;
2015-11-05 08:32:18 -08:00
/* init */
2015-11-20 03:03:53 -08:00
ZSTD_resetSeqStore ( seqStorePtr ) ;
2016-01-30 17:04:15 -08:00
if ( ip < lowest + REPCODE_STARTVALUE ) ip = lowest + REPCODE_STARTVALUE ;
2015-11-05 08:32:18 -08:00
/* Main Search Loop */
2016-01-27 15:18:06 -08:00
while ( ip < ilimit ) { /* < instead of <=, because repcode check at (ip+1) */
2015-11-23 04:34:21 -08:00
size_t mlCode ;
2015-11-20 03:03:53 -08:00
size_t offset ;
2015-11-11 04:43:58 -08:00
const size_t h = ZSTD_hashPtr ( ip , hBits , mls ) ;
2015-12-29 05:29:08 -08:00
const U32 matchIndex = hashTable [ h ] ;
const BYTE * match = base + matchIndex ;
2016-01-01 16:16:28 -08:00
const U32 current = ( U32 ) ( ip - base ) ;
hashTable [ h ] = current ; /* update hash table */
2015-11-05 08:32:18 -08:00
2016-01-27 15:18:06 -08:00
if ( MEM_read32 ( ip + 1 - offset_1 ) = = MEM_read32 ( ip + 1 ) ) { /* note : by construction, offset_1 <= current */
2016-04-06 00:46:01 -07:00
mlCode = ZSTD_count ( ip + 1 + EQUAL_READ32 , ip + 1 + EQUAL_READ32 - offset_1 , iend ) + EQUAL_READ32 ;
2015-11-20 03:46:08 -08:00
ip + + ;
2016-04-06 00:46:01 -07:00
ZSTD_storeSeq ( seqStorePtr , ip - anchor , anchor , 0 , mlCode - MINMATCH ) ;
2016-03-16 07:35:14 -07:00
} else {
2015-12-29 05:29:08 -08:00
if ( ( matchIndex < = lowIndex ) | |
2016-01-27 15:18:06 -08:00
( MEM_read32 ( match ) ! = MEM_read32 ( ip ) ) ) {
2015-11-20 03:46:08 -08:00
ip + = ( ( ip - anchor ) > > g_searchStrength ) + 1 ;
continue ;
}
2016-04-06 00:46:01 -07:00
mlCode = ZSTD_count ( ip + EQUAL_READ32 , match + EQUAL_READ32 , iend ) + EQUAL_READ32 ;
2015-11-20 03:46:08 -08:00
offset = ip - match ;
2015-11-23 04:34:21 -08:00
while ( ( ip > anchor ) & & ( match > lowest ) & & ( ip [ - 1 ] = = match [ - 1 ] ) ) { ip - - ; match - - ; mlCode + + ; } /* catch up */
2015-11-20 03:46:08 -08:00
offset_2 = offset_1 ;
offset_1 = offset ;
2016-03-16 07:35:14 -07:00
2016-04-06 00:46:01 -07:00
ZSTD_storeSeq ( seqStorePtr , ip - anchor , anchor , offset + ZSTD_REP_MOVE , mlCode - MINMATCH ) ;
2015-11-20 03:46:08 -08:00
}
/* match found */
2016-04-06 00:46:01 -07:00
ip + = mlCode ;
2015-11-20 03:46:08 -08:00
anchor = ip ;
2016-01-27 15:18:06 -08:00
if ( ip < = ilimit ) {
2015-11-20 03:46:08 -08:00
/* Fill Table */
2016-01-07 06:35:18 -08:00
hashTable [ ZSTD_hashPtr ( base + current + 2 , hBits , mls ) ] = current + 2 ; /* here because current+2 could be > iend-8 */
2015-11-20 03:46:08 -08:00
hashTable [ ZSTD_hashPtr ( ip - 2 , hBits , mls ) ] = ( U32 ) ( ip - 2 - base ) ;
/* check immediate repcode */
while ( ( ip < = ilimit )
2016-01-27 15:18:06 -08:00
& & ( MEM_read32 ( ip ) = = MEM_read32 ( ip - offset_2 ) ) ) {
2015-11-20 03:46:08 -08:00
/* store sequence */
2016-04-06 00:46:01 -07:00
size_t const rlCode = ZSTD_count ( ip + EQUAL_READ32 , ip + EQUAL_READ32 - offset_2 , iend ) + EQUAL_READ32 ;
2016-03-19 10:08:32 -07:00
{ size_t const tmpOff = offset_2 ; offset_2 = offset_1 ; offset_1 = tmpOff ; } /* swap offset_2 <=> offset_1 */
2015-11-20 03:46:08 -08:00
hashTable [ ZSTD_hashPtr ( ip , hBits , mls ) ] = ( U32 ) ( ip - base ) ;
2016-04-06 00:46:01 -07:00
ZSTD_storeSeq ( seqStorePtr , 0 , anchor , 0 , rlCode - MINMATCH ) ;
ip + = rlCode ;
2015-11-20 03:46:08 -08:00
anchor = ip ;
continue ; /* faster when present ... (?) */
2016-01-27 15:18:06 -08:00
} } }
2015-11-05 08:32:18 -08:00
2016-03-19 10:08:32 -07:00
/* Last Literals */
{ size_t const lastLLSize = iend - anchor ;
2015-11-05 08:32:18 -08:00
memcpy ( seqStorePtr - > lit , anchor , lastLLSize ) ;
seqStorePtr - > lit + = lastLLSize ;
}
}
2016-02-10 22:14:25 -08:00
static void ZSTD_compressBlock_fast ( ZSTD_CCtx * ctx ,
2016-01-23 10:28:41 -08:00
const void * src , size_t srcSize )
2015-11-05 08:32:18 -08:00
{
2016-03-30 10:48:05 -07:00
const U32 mls = ctx - > params . cParams . searchLength ;
2015-11-05 08:32:18 -08:00
switch ( mls )
{
default :
case 4 :
2016-01-23 10:28:41 -08:00
ZSTD_compressBlock_fast_generic ( ctx , src , srcSize , 4 ) ; return ;
2015-11-05 08:32:18 -08:00
case 5 :
2016-01-23 10:28:41 -08:00
ZSTD_compressBlock_fast_generic ( ctx , src , srcSize , 5 ) ; return ;
2015-11-05 08:32:18 -08:00
case 6 :
2016-01-23 10:28:41 -08:00
ZSTD_compressBlock_fast_generic ( ctx , src , srcSize , 6 ) ; return ;
2015-11-05 08:32:18 -08:00
case 7 :
2016-01-23 10:28:41 -08:00
ZSTD_compressBlock_fast_generic ( ctx , src , srcSize , 7 ) ; return ;
2015-11-05 08:32:18 -08:00
}
}
2015-10-22 07:31:46 -07:00
2016-02-10 22:14:25 -08:00
static void ZSTD_compressBlock_fast_extDict_generic ( ZSTD_CCtx * ctx ,
2016-01-23 10:28:41 -08:00
const void * src , size_t srcSize ,
const U32 mls )
2015-11-13 02:27:46 -08:00
{
U32 * hashTable = ctx - > hashTable ;
2016-03-30 10:48:05 -07:00
const U32 hBits = ctx - > params . cParams . hashLog ;
2015-11-13 02:27:46 -08:00
seqStore_t * seqStorePtr = & ( ctx - > seqStore ) ;
const BYTE * const base = ctx - > base ;
const BYTE * const dictBase = ctx - > dictBase ;
const BYTE * const istart = ( const BYTE * ) src ;
const BYTE * ip = istart ;
const BYTE * anchor = istart ;
const U32 lowLimit = ctx - > lowLimit ;
2015-11-23 04:34:21 -08:00
const BYTE * const dictStart = dictBase + lowLimit ;
2015-11-13 02:27:46 -08:00
const U32 dictLimit = ctx - > dictLimit ;
2015-11-20 03:03:53 -08:00
const BYTE * const lowPrefixPtr = base + dictLimit ;
const BYTE * const dictEnd = dictBase + dictLimit ;
2015-11-13 02:27:46 -08:00
const BYTE * const iend = istart + srcSize ;
const BYTE * const ilimit = iend - 8 ;
2015-11-17 05:26:54 -08:00
U32 offset_2 = REPCODE_STARTVALUE , offset_1 = REPCODE_STARTVALUE ;
2015-11-13 02:27:46 -08:00
/* init */
ZSTD_resetSeqStore ( seqStorePtr ) ;
2016-01-30 17:04:15 -08:00
/* skip first position to avoid read overflow during repcode match check */
2016-01-27 15:18:06 -08:00
hashTable [ ZSTD_hashPtr ( ip + 0 , hBits , mls ) ] = ( U32 ) ( ip - base + 0 ) ;
2016-01-30 17:04:15 -08:00
ip + = REPCODE_STARTVALUE ;
2015-11-13 02:27:46 -08:00
/* Main Search Loop */
2016-01-27 15:18:06 -08:00
while ( ip < ilimit ) { /* < instead of <=, because (ip+1) */
2015-11-13 02:27:46 -08:00
const size_t h = ZSTD_hashPtr ( ip , hBits , mls ) ;
2015-11-20 03:03:53 -08:00
const U32 matchIndex = hashTable [ h ] ;
2015-11-13 02:27:46 -08:00
const BYTE * matchBase = matchIndex < dictLimit ? dictBase : base ;
2015-11-26 02:43:00 -08:00
const BYTE * match = matchBase + matchIndex ;
2015-11-13 02:27:46 -08:00
const U32 current = ( U32 ) ( ip - base ) ;
2015-11-20 03:03:53 -08:00
const U32 repIndex = current + 1 - offset_1 ;
2015-11-20 03:46:08 -08:00
const BYTE * repBase = repIndex < dictLimit ? dictBase : base ;
2015-11-13 02:27:46 -08:00
const BYTE * repMatch = repBase + repIndex ;
2015-11-23 04:34:21 -08:00
size_t mlCode ;
2015-11-20 03:03:53 -08:00
U32 offset ;
2015-11-13 02:27:46 -08:00
hashTable [ h ] = current ; /* update hash table */
2016-03-20 08:00:00 -07:00
if ( ( ( repIndex > = dictLimit ) | | ( repIndex < = dictLimit - 4 ) )
2016-01-27 15:18:06 -08:00
& & ( MEM_read32 ( repMatch ) = = MEM_read32 ( ip + 1 ) ) ) {
2015-11-20 03:46:08 -08:00
const BYTE * repMatchEnd = repIndex < dictLimit ? dictEnd : iend ;
2016-04-06 00:46:01 -07:00
mlCode = ZSTD_count_2segments ( ip + 1 + EQUAL_READ32 , repMatch + EQUAL_READ32 , iend , repMatchEnd , lowPrefixPtr ) + EQUAL_READ32 ;
2015-11-20 03:03:53 -08:00
ip + + ;
2016-04-06 00:46:01 -07:00
ZSTD_storeSeq ( seqStorePtr , ip - anchor , anchor , 0 , mlCode - MINMATCH ) ;
2016-01-27 15:18:06 -08:00
} else {
2015-11-20 03:46:08 -08:00
if ( ( matchIndex < lowLimit ) | |
2016-03-20 08:00:00 -07:00
( MEM_read32 ( match ) ! = MEM_read32 ( ip ) ) ) {
ip + = ( ( ip - anchor ) > > g_searchStrength ) + 1 ;
continue ;
}
{ const BYTE * matchEnd = matchIndex < dictLimit ? dictEnd : iend ;
2015-11-23 04:34:21 -08:00
const BYTE * lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr ;
2016-04-06 00:46:01 -07:00
mlCode = ZSTD_count_2segments ( ip + EQUAL_READ32 , match + EQUAL_READ32 , iend , matchEnd , lowPrefixPtr ) + EQUAL_READ32 ;
2016-01-27 15:18:06 -08:00
while ( ( ip > anchor ) & & ( match > lowMatchPtr ) & & ( ip [ - 1 ] = = match [ - 1 ] ) ) { ip - - ; match - - ; mlCode + + ; } /* catch up */
2015-11-20 03:46:08 -08:00
offset = current - matchIndex ;
offset_2 = offset_1 ;
offset_1 = offset ;
2016-04-06 00:46:01 -07:00
ZSTD_storeSeq ( seqStorePtr , ip - anchor , anchor , offset + ZSTD_REP_MOVE , mlCode - MINMATCH ) ;
2016-01-27 15:18:06 -08:00
} }
2015-11-20 03:46:08 -08:00
2015-11-23 04:34:21 -08:00
/* found a match : store it */
2016-04-06 00:46:01 -07:00
ip + = mlCode ;
2015-11-20 03:46:08 -08:00
anchor = ip ;
2016-01-27 15:18:06 -08:00
if ( ip < = ilimit ) {
2015-11-26 02:43:00 -08:00
/* Fill Table */
2015-11-23 07:17:21 -08:00
hashTable [ ZSTD_hashPtr ( base + current + 2 , hBits , mls ) ] = current + 2 ;
2015-11-20 03:46:08 -08:00
hashTable [ ZSTD_hashPtr ( ip - 2 , hBits , mls ) ] = ( U32 ) ( ip - 2 - base ) ;
/* check immediate repcode */
2016-01-27 15:18:06 -08:00
while ( ip < = ilimit ) {
2016-04-01 06:48:48 -07:00
U32 const current2 = ( U32 ) ( ip - base ) ;
U32 const repIndex2 = current2 - offset_2 ;
2015-11-20 03:46:08 -08:00
const BYTE * repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2 ;
2015-11-20 03:03:53 -08:00
if ( ( ( repIndex2 < = dictLimit - 4 ) | | ( repIndex2 > = dictLimit ) )
2016-01-27 15:18:06 -08:00
& & ( MEM_read32 ( repMatch2 ) = = MEM_read32 ( ip ) ) ) {
2015-11-23 04:34:21 -08:00
const BYTE * const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend ;
2016-04-06 00:46:01 -07:00
size_t repLength2 = ZSTD_count_2segments ( ip + EQUAL_READ32 , repMatch2 + EQUAL_READ32 , iend , repEnd2 , lowPrefixPtr ) + EQUAL_READ32 ;
2015-11-23 04:34:21 -08:00
U32 tmpOffset = offset_2 ; offset_2 = offset_1 ; offset_1 = tmpOffset ; /* swap offset_2 <=> offset_1 */
2016-04-06 00:46:01 -07:00
ZSTD_storeSeq ( seqStorePtr , 0 , anchor , 0 , repLength2 - MINMATCH ) ;
2015-11-23 04:34:21 -08:00
hashTable [ ZSTD_hashPtr ( ip , hBits , mls ) ] = current2 ;
2016-04-06 00:46:01 -07:00
ip + = repLength2 ;
2015-11-20 03:46:08 -08:00
anchor = ip ;
continue ;
}
2015-11-20 03:03:53 -08:00
break ;
2016-01-27 15:18:06 -08:00
} } }
2015-11-13 02:27:46 -08:00
/* Last Literals */
2016-03-19 10:08:32 -07:00
{ size_t const lastLLSize = iend - anchor ;
2015-11-13 02:27:46 -08:00
memcpy ( seqStorePtr - > lit , anchor , lastLLSize ) ;
seqStorePtr - > lit + = lastLLSize ;
}
}
2016-02-10 22:14:25 -08:00
static void ZSTD_compressBlock_fast_extDict ( ZSTD_CCtx * ctx ,
2015-11-13 02:27:46 -08:00
const void * src , size_t srcSize )
{
2016-03-30 10:48:05 -07:00
const U32 mls = ctx - > params . cParams . searchLength ;
2015-11-13 02:27:46 -08:00
switch ( mls )
{
default :
case 4 :
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_fast_extDict_generic ( ctx , src , srcSize , 4 ) ; return ;
2015-11-13 02:27:46 -08:00
case 5 :
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_fast_extDict_generic ( ctx , src , srcSize , 5 ) ; return ;
2015-11-13 02:27:46 -08:00
case 6 :
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_fast_extDict_generic ( ctx , src , srcSize , 6 ) ; return ;
2015-11-13 02:27:46 -08:00
case 7 :
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_fast_extDict_generic ( ctx , src , srcSize , 7 ) ; return ;
2015-11-13 02:27:46 -08:00
}
}
2016-04-06 03:34:42 -07:00
2016-04-06 08:14:19 -07:00
2016-02-10 21:23:24 -08:00
/*-*************************************
2015-11-03 18:52:54 -08:00
* Binary Tree search
2015-10-22 07:31:46 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-02-10 21:23:24 -08:00
/** ZSTD_insertBt1() : add one or multiple positions to tree.
* ip : assumed < = iend - 8 .
2015-11-23 05:23:47 -08:00
* @ return : nb of positions added */
2015-12-31 22:29:39 -08:00
static U32 ZSTD_insertBt1 ( ZSTD_CCtx * zc , const BYTE * const ip , const U32 mls , const BYTE * const iend , U32 nbCompares ,
U32 extDict )
2015-11-03 18:52:54 -08:00
{
U32 * const hashTable = zc - > hashTable ;
2016-03-30 10:48:05 -07:00
const U32 hashLog = zc - > params . cParams . hashLog ;
2015-11-11 04:43:58 -08:00
const size_t h = ZSTD_hashPtr ( ip , hashLog , mls ) ;
2016-04-04 04:49:18 -07:00
U32 * const bt = zc - > chainTable ;
const U32 btLog = zc - > params . cParams . chainLog - 1 ;
2015-11-03 18:52:54 -08:00
const U32 btMask = ( 1 < < btLog ) - 1 ;
U32 matchIndex = hashTable [ h ] ;
size_t commonLengthSmaller = 0 , commonLengthLarger = 0 ;
const BYTE * const base = zc - > base ;
2015-12-31 22:29:39 -08:00
const BYTE * const dictBase = zc - > dictBase ;
const U32 dictLimit = zc - > dictLimit ;
const BYTE * const dictEnd = dictBase + dictLimit ;
const BYTE * const prefixStart = base + dictLimit ;
2015-11-06 16:13:31 -08:00
const BYTE * match = base + matchIndex ;
2015-12-11 01:44:07 -08:00
const U32 current = ( U32 ) ( ip - base ) ;
2015-11-08 06:08:03 -08:00
const U32 btLow = btMask > = current ? 0 : current - btMask ;
2015-11-03 18:52:54 -08:00
U32 * smallerPtr = bt + 2 * ( current & btMask ) ;
2016-01-16 15:12:55 -08:00
U32 * largerPtr = smallerPtr + 1 ;
2015-11-04 03:05:27 -08:00
U32 dummy32 ; /* to be nullified at the end */
2015-11-23 06:29:15 -08:00
const U32 windowLow = zc - > lowLimit ;
2015-12-31 10:08:44 -08:00
U32 matchEndIdx = current + 8 ;
2016-02-15 08:06:29 -08:00
size_t bestLength = 8 ;
2016-01-21 02:57:45 -08:00
U32 predictedSmall = * ( bt + 2 * ( ( current - 1 ) & btMask ) + 0 ) ;
U32 predictedLarge = * ( bt + 2 * ( ( current - 1 ) & btMask ) + 1 ) ;
predictedSmall + = ( predictedSmall > 0 ) ;
predictedLarge + = ( predictedLarge > 0 ) ;
2015-11-06 16:13:31 -08:00
2015-12-11 01:44:07 -08:00
hashTable [ h ] = current ; /* Update Hash Table */
2015-11-03 18:52:54 -08:00
2016-01-27 15:18:06 -08:00
while ( nbCompares - - & & ( matchIndex > windowLow ) ) {
2015-11-03 18:52:54 -08:00
U32 * nextPtr = bt + 2 * ( matchIndex & btMask ) ;
size_t matchLength = MIN ( commonLengthSmaller , commonLengthLarger ) ; /* guaranteed minimum nb of common bytes */
2016-04-09 11:32:00 -07:00
#if 0 /* note : can create issues when hlog small <= 11 */
2016-02-10 04:37:52 -08:00
const U32 * predictPtr = bt + 2 * ( ( matchIndex - 1 ) & btMask ) ; /* written this way, as bt is a roll buffer */
2016-01-27 15:18:06 -08:00
if ( matchIndex = = predictedSmall ) {
/* no need to check length, result known */
2016-01-16 15:12:55 -08:00
* smallerPtr = matchIndex ;
if ( matchIndex < = btLow ) { smallerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
smallerPtr = nextPtr + 1 ; /* new "smaller" => larger of match */
matchIndex = nextPtr [ 1 ] ; /* new matchIndex larger than previous (closer to current) */
2016-01-21 02:57:45 -08:00
predictedSmall = predictPtr [ 1 ] + ( predictPtr [ 1 ] > 0 ) ;
2016-01-16 15:12:55 -08:00
continue ;
}
2016-01-27 15:18:06 -08:00
if ( matchIndex = = predictedLarge ) {
2016-01-16 15:12:55 -08:00
* largerPtr = matchIndex ;
if ( matchIndex < = btLow ) { largerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
largerPtr = nextPtr ;
matchIndex = nextPtr [ 0 ] ;
2016-01-21 02:57:45 -08:00
predictedLarge = predictPtr [ 0 ] + ( predictPtr [ 0 ] > 0 ) ;
2016-01-16 15:12:55 -08:00
continue ;
}
2016-02-10 21:23:24 -08:00
# endif
2016-01-27 15:18:06 -08:00
if ( ( ! extDict ) | | ( matchIndex + matchLength > = dictLimit ) ) {
2015-12-31 22:29:39 -08:00
match = base + matchIndex ;
if ( match [ matchLength ] = = ip [ matchLength ] )
matchLength + = ZSTD_count ( ip + matchLength + 1 , match + matchLength + 1 , iend ) + 1 ;
2016-01-27 15:18:06 -08:00
} else {
2015-12-31 22:29:39 -08:00
match = dictBase + matchIndex ;
matchLength + = ZSTD_count_2segments ( ip + matchLength , match + matchLength , iend , dictEnd , prefixStart ) ;
if ( matchIndex + matchLength > = dictLimit )
match = base + matchIndex ; /* to prepare for next usage of match[matchLength] */
}
2015-11-03 18:52:54 -08:00
2016-02-15 08:06:29 -08:00
if ( matchLength > bestLength ) {
bestLength = matchLength ;
if ( matchLength > matchEndIdx - matchIndex )
matchEndIdx = matchIndex + ( U32 ) matchLength ;
}
2015-12-29 13:26:09 -08:00
2015-11-04 03:05:27 -08:00
if ( ip + matchLength = = iend ) /* equal : no way to know if inf or sup */
2015-12-31 22:29:39 -08:00
break ; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
2015-11-03 18:52:54 -08:00
2016-01-27 15:18:06 -08:00
if ( match [ matchLength ] < ip [ matchLength ] ) { /* necessarily within correct buffer */
2015-11-03 18:52:54 -08:00
/* match is smaller than current */
* smallerPtr = matchIndex ; /* update smaller idx */
commonLengthSmaller = matchLength ; /* all smaller will now have at least this guaranteed common length */
2015-11-06 16:13:31 -08:00
if ( matchIndex < = btLow ) { smallerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
2015-11-03 18:52:54 -08:00
smallerPtr = nextPtr + 1 ; /* new "smaller" => larger of match */
2015-11-06 16:13:31 -08:00
matchIndex = nextPtr [ 1 ] ; /* new matchIndex larger than previous (closer to current) */
2016-01-27 15:18:06 -08:00
} else {
2015-11-03 18:52:54 -08:00
/* match is larger than current */
* largerPtr = matchIndex ;
commonLengthLarger = matchLength ;
2015-11-06 16:13:31 -08:00
if ( matchIndex < = btLow ) { largerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
2015-11-03 18:52:54 -08:00
largerPtr = nextPtr ;
2015-11-06 16:13:31 -08:00
matchIndex = nextPtr [ 0 ] ;
2016-01-27 15:18:06 -08:00
} }
2015-11-03 18:52:54 -08:00
2015-11-04 03:05:27 -08:00
* smallerPtr = * largerPtr = 0 ;
2016-02-15 08:06:29 -08:00
if ( bestLength > 384 ) return MIN ( 192 , ( U32 ) ( bestLength - 384 ) ) ;
if ( matchEndIdx > current + 8 ) return matchEndIdx - current - 8 ;
return 1 ;
2015-11-03 18:52:54 -08:00
}
2016-02-10 22:14:25 -08:00
static size_t ZSTD_insertBtAndFindBestMatch (
2015-11-11 04:43:58 -08:00
ZSTD_CCtx * zc ,
2015-11-03 18:52:54 -08:00
const BYTE * const ip , const BYTE * const iend ,
size_t * offsetPtr ,
2015-12-31 22:47:58 -08:00
U32 nbCompares , const U32 mls ,
U32 extDict )
2015-11-03 18:52:54 -08:00
{
U32 * const hashTable = zc - > hashTable ;
2016-03-30 10:48:05 -07:00
const U32 hashLog = zc - > params . cParams . hashLog ;
2015-11-11 04:43:58 -08:00
const size_t h = ZSTD_hashPtr ( ip , hashLog , mls ) ;
2016-04-04 04:49:18 -07:00
U32 * const bt = zc - > chainTable ;
const U32 btLog = zc - > params . cParams . chainLog - 1 ;
2015-11-03 18:52:54 -08:00
const U32 btMask = ( 1 < < btLog ) - 1 ;
U32 matchIndex = hashTable [ h ] ;
size_t commonLengthSmaller = 0 , commonLengthLarger = 0 ;
const BYTE * const base = zc - > base ;
2015-12-31 22:47:58 -08:00
const BYTE * const dictBase = zc - > dictBase ;
const U32 dictLimit = zc - > dictLimit ;
const BYTE * const dictEnd = dictBase + dictLimit ;
const BYTE * const prefixStart = base + dictLimit ;
2015-11-03 18:52:54 -08:00
const U32 current = ( U32 ) ( ip - base ) ;
const U32 btLow = btMask > = current ? 0 : current - btMask ;
2015-11-23 06:29:15 -08:00
const U32 windowLow = zc - > lowLimit ;
2015-11-03 18:52:54 -08:00
U32 * smallerPtr = bt + 2 * ( current & btMask ) ;
U32 * largerPtr = bt + 2 * ( current & btMask ) + 1 ;
2015-12-31 10:08:44 -08:00
U32 matchEndIdx = current + 8 ;
2015-11-04 03:05:27 -08:00
U32 dummy32 ; /* to be nullified at the end */
2016-04-07 10:14:09 -07:00
size_t bestLength = 0 ;
2015-11-03 18:52:54 -08:00
2015-12-11 01:44:07 -08:00
hashTable [ h ] = current ; /* Update Hash Table */
2015-11-03 18:52:54 -08:00
2016-01-27 15:18:06 -08:00
while ( nbCompares - - & & ( matchIndex > windowLow ) ) {
2015-11-03 18:52:54 -08:00
U32 * nextPtr = bt + 2 * ( matchIndex & btMask ) ;
size_t matchLength = MIN ( commonLengthSmaller , commonLengthLarger ) ; /* guaranteed minimum nb of common bytes */
2015-12-31 22:47:58 -08:00
const BYTE * match ;
2015-11-03 18:52:54 -08:00
2016-01-27 15:18:06 -08:00
if ( ( ! extDict ) | | ( matchIndex + matchLength > = dictLimit ) ) {
2015-12-31 22:47:58 -08:00
match = base + matchIndex ;
if ( match [ matchLength ] = = ip [ matchLength ] )
matchLength + = ZSTD_count ( ip + matchLength + 1 , match + matchLength + 1 , iend ) + 1 ;
2016-01-27 15:18:06 -08:00
} else {
2015-12-31 22:47:58 -08:00
match = dictBase + matchIndex ;
matchLength + = ZSTD_count_2segments ( ip + matchLength , match + matchLength , iend , dictEnd , prefixStart ) ;
if ( matchIndex + matchLength > = dictLimit )
match = base + matchIndex ; /* to prepare for next usage of match[matchLength] */
}
2015-11-03 18:52:54 -08:00
2016-01-27 15:18:06 -08:00
if ( matchLength > bestLength ) {
2015-12-29 13:26:09 -08:00
if ( matchLength > matchEndIdx - matchIndex )
2015-12-29 14:40:02 -08:00
matchEndIdx = matchIndex + ( U32 ) matchLength ;
2016-06-04 11:17:38 -07:00
if ( ( 4 * ( int ) ( matchLength - bestLength ) ) > ( int ) ( ZSTD_highbit32 ( current - matchIndex + 1 ) - ZSTD_highbit32 ( ( U32 ) offsetPtr [ 0 ] + 1 ) ) )
2016-04-06 03:34:42 -07:00
bestLength = matchLength , * offsetPtr = ZSTD_REP_MOVE + current - matchIndex ;
2015-11-04 03:05:27 -08:00
if ( ip + matchLength = = iend ) /* equal : no way to know if inf or sup */
2015-11-23 04:34:21 -08:00
break ; /* drop, to guarantee consistency (miss a little bit of compression) */
2015-11-03 18:52:54 -08:00
}
2016-01-27 15:18:06 -08:00
if ( match [ matchLength ] < ip [ matchLength ] ) {
2015-11-03 18:52:54 -08:00
/* match is smaller than current */
* smallerPtr = matchIndex ; /* update smaller idx */
commonLengthSmaller = matchLength ; /* all smaller will now have at least this guaranteed common length */
2015-11-23 04:34:21 -08:00
if ( matchIndex < = btLow ) { smallerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
2015-11-04 03:05:27 -08:00
smallerPtr = nextPtr + 1 ; /* new "smaller" => larger of match */
2015-11-23 04:34:21 -08:00
matchIndex = nextPtr [ 1 ] ; /* new matchIndex larger than previous (closer to current) */
2016-01-27 15:18:06 -08:00
} else {
2015-11-03 18:52:54 -08:00
/* match is larger than current */
* largerPtr = matchIndex ;
commonLengthLarger = matchLength ;
2015-11-23 04:34:21 -08:00
if ( matchIndex < = btLow ) { largerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
2015-11-03 18:52:54 -08:00
largerPtr = nextPtr ;
2015-11-23 04:34:21 -08:00
matchIndex = nextPtr [ 0 ] ;
2016-02-10 05:01:49 -08:00
} }
2015-11-03 18:52:54 -08:00
2015-11-04 03:05:27 -08:00
* smallerPtr = * largerPtr = 0 ;
2015-11-03 18:52:54 -08:00
2015-12-31 10:08:44 -08:00
zc - > nextToUpdate = ( matchEndIdx > current + 8 ) ? matchEndIdx - 8 : current + 1 ;
2016-04-07 10:14:09 -07:00
return bestLength ;
2015-11-03 18:52:54 -08:00
}
2016-02-15 08:06:29 -08:00
static void ZSTD_updateTree ( ZSTD_CCtx * zc , const BYTE * const ip , const BYTE * const iend , const U32 nbCompares , const U32 mls )
2016-02-10 22:14:25 -08:00
{
const BYTE * const base = zc - > base ;
const U32 target = ( U32 ) ( ip - base ) ;
U32 idx = zc - > nextToUpdate ;
2016-02-15 08:06:29 -08:00
while ( idx < target )
idx + = ZSTD_insertBt1 ( zc , base + idx , mls , iend , nbCompares , 0 ) ;
2016-02-10 22:14:25 -08:00
}
2016-03-20 08:00:00 -07:00
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
2016-02-10 22:14:25 -08:00
static size_t ZSTD_BtFindBestMatch (
2015-11-11 04:43:58 -08:00
ZSTD_CCtx * zc ,
2015-11-03 18:52:54 -08:00
const BYTE * const ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 mls )
{
2015-12-29 13:26:09 -08:00
if ( ip < zc - > base + zc - > nextToUpdate ) return 0 ; /* skipped area */
2016-02-15 08:06:29 -08:00
ZSTD_updateTree ( zc , ip , iLimit , maxNbAttempts , mls ) ;
2015-12-31 22:47:58 -08:00
return ZSTD_insertBtAndFindBestMatch ( zc , ip , iLimit , offsetPtr , maxNbAttempts , mls , 0 ) ;
2015-11-03 18:52:54 -08:00
}
2016-02-10 05:01:49 -08:00
static size_t ZSTD_BtFindBestMatch_selectMLS (
2015-11-11 04:43:58 -08:00
ZSTD_CCtx * zc , /* Index table will be updated */
2015-11-03 18:52:54 -08:00
const BYTE * ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 matchLengthSearch )
{
switch ( matchLengthSearch )
{
default :
2015-11-11 04:43:58 -08:00
case 4 : return ZSTD_BtFindBestMatch ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 4 ) ;
case 5 : return ZSTD_BtFindBestMatch ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 5 ) ;
case 6 : return ZSTD_BtFindBestMatch ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 6 ) ;
2015-11-03 18:52:54 -08:00
}
}
2016-02-15 08:06:29 -08:00
static void ZSTD_updateTree_extDict ( ZSTD_CCtx * zc , const BYTE * const ip , const BYTE * const iend , const U32 nbCompares , const U32 mls )
{
const BYTE * const base = zc - > base ;
const U32 target = ( U32 ) ( ip - base ) ;
U32 idx = zc - > nextToUpdate ;
while ( idx < target ) idx + = ZSTD_insertBt1 ( zc , base + idx , mls , iend , nbCompares , 1 ) ;
}
2016-04-07 10:14:09 -07:00
2015-11-23 06:29:15 -08:00
/** Tree updater, providing best match */
2016-02-10 22:14:25 -08:00
static size_t ZSTD_BtFindBestMatch_extDict (
2015-11-23 06:29:15 -08:00
ZSTD_CCtx * zc ,
const BYTE * const ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 mls )
{
2015-12-29 13:26:09 -08:00
if ( ip < zc - > base + zc - > nextToUpdate ) return 0 ; /* skipped area */
2016-02-15 08:06:29 -08:00
ZSTD_updateTree_extDict ( zc , ip , iLimit , maxNbAttempts , mls ) ;
2015-12-31 22:47:58 -08:00
return ZSTD_insertBtAndFindBestMatch ( zc , ip , iLimit , offsetPtr , maxNbAttempts , mls , 1 ) ;
2015-11-23 06:29:15 -08:00
}
2016-02-10 22:14:25 -08:00
static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
2015-11-23 06:29:15 -08:00
ZSTD_CCtx * zc , /* Index table will be updated */
const BYTE * ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 matchLengthSearch )
{
switch ( matchLengthSearch )
{
default :
case 4 : return ZSTD_BtFindBestMatch_extDict ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 4 ) ;
case 5 : return ZSTD_BtFindBestMatch_extDict ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 5 ) ;
case 6 : return ZSTD_BtFindBestMatch_extDict ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 6 ) ;
}
}
2015-11-05 08:32:18 -08:00
2016-04-07 10:14:09 -07:00
/* ***********************
* Hash Chain
* * * * * * * * * * * * * * * * * * * * * * * * */
2015-11-05 06:00:24 -08:00
2016-04-07 10:14:09 -07:00
# define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
2015-11-05 06:00:24 -08:00
2016-04-07 06:24:29 -07:00
2016-04-07 10:14:09 -07:00
/* Update chains up to ip (excluded)
Assumption : always within prefix ( ie . not within extDict ) */
FORCE_INLINE
U32 ZSTD_insertAndFindFirstIndex ( ZSTD_CCtx * zc , const BYTE * ip , U32 mls )
{
U32 * const hashTable = zc - > hashTable ;
const U32 hashLog = zc - > params . cParams . hashLog ;
U32 * const chainTable = zc - > chainTable ;
const U32 chainMask = ( 1 < < zc - > params . cParams . chainLog ) - 1 ;
const BYTE * const base = zc - > base ;
const U32 target = ( U32 ) ( ip - base ) ;
U32 idx = zc - > nextToUpdate ;
2015-11-05 06:00:24 -08:00
2016-04-07 10:14:09 -07:00
while ( idx < target ) {
size_t const h = ZSTD_hashPtr ( base + idx , hashLog , mls ) ;
NEXT_IN_CHAIN ( idx , chainMask ) = hashTable [ h ] ;
hashTable [ h ] = idx ;
idx + + ;
2015-11-23 05:37:59 -08:00
}
2016-04-07 10:14:09 -07:00
zc - > nextToUpdate = target ;
return hashTable [ ZSTD_hashPtr ( ip , hashLog , mls ) ] ;
2015-11-23 05:37:59 -08:00
}
2016-04-07 10:14:09 -07:00
FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
size_t ZSTD_HcFindBestMatch_generic (
ZSTD_CCtx * zc , /* Index table will be updated */
const BYTE * const ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 mls , const U32 extDict )
2015-11-05 06:00:24 -08:00
{
2016-04-07 10:14:09 -07:00
U32 * const chainTable = zc - > chainTable ;
const U32 chainSize = ( 1 < < zc - > params . cParams . chainLog ) ;
const U32 chainMask = chainSize - 1 ;
const BYTE * const base = zc - > base ;
const BYTE * const dictBase = zc - > dictBase ;
const U32 dictLimit = zc - > dictLimit ;
2016-04-05 10:01:10 -07:00
const BYTE * const prefixStart = base + dictLimit ;
2016-04-07 10:14:09 -07:00
const BYTE * const dictEnd = dictBase + dictLimit ;
const U32 lowLimit = zc - > lowLimit ;
const U32 current = ( U32 ) ( ip - base ) ;
const U32 minChain = current > chainSize ? current - chainSize : 0 ;
int nbAttempts = maxNbAttempts ;
size_t ml = EQUAL_READ32 - 1 ;
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
/* HC4 match finder */
U32 matchIndex = ZSTD_insertAndFindFirstIndex ( zc , ip , mls ) ;
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
for ( ; ( matchIndex > lowLimit ) & & ( nbAttempts ) ; nbAttempts - - ) {
const BYTE * match ;
size_t currentMl = 0 ;
if ( ( ! extDict ) | | matchIndex > = dictLimit ) {
match = base + matchIndex ;
if ( match [ ml ] = = ip [ ml ] ) /* potentially better */
currentMl = ZSTD_count ( ip , match , iLimit ) ;
} else {
match = dictBase + matchIndex ;
if ( MEM_read32 ( match ) = = MEM_read32 ( ip ) ) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
currentMl = ZSTD_count_2segments ( ip + EQUAL_READ32 , match + EQUAL_READ32 , iLimit , dictEnd , prefixStart ) + EQUAL_READ32 ;
}
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
/* save best solution */
if ( currentMl > ml ) { ml = currentMl ; * offsetPtr = ZSTD_REP_MOVE + current - matchIndex ; if ( ip + currentMl = = iLimit ) break ; /* best possible, and avoid read overflow*/ }
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
if ( matchIndex < = minChain ) break ;
matchIndex = NEXT_IN_CHAIN ( matchIndex , chainMask ) ;
}
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
return ml ;
}
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
ZSTD_CCtx * zc ,
const BYTE * ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 matchLengthSearch )
{
switch ( matchLengthSearch )
{
default :
case 4 : return ZSTD_HcFindBestMatch_generic ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 4 , 0 ) ;
case 5 : return ZSTD_HcFindBestMatch_generic ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 5 , 0 ) ;
case 6 : return ZSTD_HcFindBestMatch_generic ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 6 , 0 ) ;
}
}
2016-04-05 10:01:10 -07:00
2016-04-07 10:14:09 -07:00
FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
ZSTD_CCtx * zc ,
const BYTE * ip , const BYTE * const iLimit ,
size_t * offsetPtr ,
const U32 maxNbAttempts , const U32 matchLengthSearch )
{
switch ( matchLengthSearch )
{
default :
case 4 : return ZSTD_HcFindBestMatch_generic ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 4 , 1 ) ;
case 5 : return ZSTD_HcFindBestMatch_generic ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 5 , 1 ) ;
case 6 : return ZSTD_HcFindBestMatch_generic ( zc , ip , iLimit , offsetPtr , maxNbAttempts , 6 , 1 ) ;
2015-11-05 06:00:24 -08:00
}
}
2016-04-05 10:01:10 -07:00
2015-11-22 04:24:05 -08:00
/* *******************************
2015-11-21 17:53:43 -08:00
* Common parser - lazy strategy
2015-11-22 04:24:05 -08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-11-05 06:00:24 -08:00
FORCE_INLINE
2016-01-23 10:28:41 -08:00
void ZSTD_compressBlock_lazy_generic ( ZSTD_CCtx * ctx ,
const void * src , size_t srcSize ,
2015-11-21 17:42:28 -08:00
const U32 searchMethod , const U32 depth )
2015-11-03 18:52:54 -08:00
{
seqStore_t * seqStorePtr = & ( ctx - > seqStore ) ;
const BYTE * const istart = ( const BYTE * ) src ;
const BYTE * ip = istart ;
const BYTE * anchor = istart ;
const BYTE * const iend = istart + srcSize ;
const BYTE * const ilimit = iend - 8 ;
2015-12-05 00:23:53 -08:00
const BYTE * const base = ctx - > base + ctx - > dictLimit ;
2015-11-03 18:52:54 -08:00
2016-04-09 11:32:00 -07:00
U32 const maxSearches = 1 < < ctx - > params . cParams . searchLog ;
U32 const mls = ctx - > params . cParams . searchLength ;
2015-11-03 18:52:54 -08:00
2015-11-11 04:43:58 -08:00
typedef size_t ( * searchMax_f ) ( ZSTD_CCtx * zc , const BYTE * ip , const BYTE * iLimit ,
2015-11-05 06:00:24 -08:00
size_t * offsetPtr ,
U32 maxNbAttempts , U32 matchLengthSearch ) ;
2015-11-11 04:43:58 -08:00
searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS ;
2015-11-05 06:00:24 -08:00
2015-11-03 18:52:54 -08:00
/* init */
2016-03-18 03:03:43 -07:00
U32 rep [ ZSTD_REP_INIT ] ;
2016-04-08 06:25:32 -07:00
{ U32 i ; for ( i = 0 ; i < ZSTD_REP_INIT ; i + + ) rep [ i ] = REPCODE_STARTVALUE ; }
2016-03-16 04:57:07 -07:00
2016-04-06 03:34:42 -07:00
ctx - > nextToUpdate3 = ctx - > nextToUpdate ;
2015-11-03 18:52:54 -08:00
ZSTD_resetSeqStore ( seqStorePtr ) ;
2015-12-05 00:23:53 -08:00
if ( ( ip - base ) < REPCODE_STARTVALUE ) ip = base + REPCODE_STARTVALUE ;
2015-11-03 18:52:54 -08:00
/* Match Loop */
2016-01-27 15:18:06 -08:00
while ( ip < ilimit ) {
2015-11-21 06:27:35 -08:00
size_t matchLength = 0 ;
size_t offset = 0 ;
2016-04-07 10:14:09 -07:00
const BYTE * start = ip + 1 ;
2015-11-03 18:52:54 -08:00
2015-11-20 03:03:53 -08:00
/* check repCode */
2016-04-07 10:14:09 -07:00
if ( MEM_read32 ( ip + 1 ) = = MEM_read32 ( ip + 1 - rep [ 0 ] ) ) {
2015-11-20 03:03:53 -08:00
/* repcode : we take it */
2016-04-07 10:14:09 -07:00
matchLength = ZSTD_count ( ip + 1 + EQUAL_READ32 , ip + 1 + EQUAL_READ32 - rep [ 0 ] , iend ) + EQUAL_READ32 ;
if ( depth = = 0 ) goto _storeSequence ;
2015-11-03 18:52:54 -08:00
}
2016-03-19 10:08:32 -07:00
/* first search (depth 0) */
{ size_t offsetFound = 99999999 ;
size_t const ml2 = searchMax ( ctx , ip , iend , & offsetFound , maxSearches , mls ) ;
2015-11-23 07:17:21 -08:00
if ( ml2 > matchLength )
matchLength = ml2 , start = ip , offset = offsetFound ;
}
2016-04-07 10:14:09 -07:00
if ( matchLength < EQUAL_READ32 ) {
2015-11-23 07:17:21 -08:00
ip + = ( ( ip - anchor ) > > g_searchStrength ) + 1 ; /* jump faster over incompressible sections */
continue ;
}
2015-11-03 18:52:54 -08:00
/* let's try to find a better solution */
2015-11-21 17:42:28 -08:00
if ( depth > = 1 )
2016-01-27 15:18:06 -08:00
while ( ip < ilimit ) {
2015-11-03 18:52:54 -08:00
ip + + ;
2016-04-07 10:14:09 -07:00
if ( ( offset ) & & ( MEM_read32 ( ip ) = = MEM_read32 ( ip - rep [ 0 ] ) ) ) {
size_t const mlRep = ZSTD_count ( ip + EQUAL_READ32 , ip + EQUAL_READ32 - rep [ 0 ] , iend ) + EQUAL_READ32 ;
2016-03-19 10:08:32 -07:00
int const gain2 = ( int ) ( mlRep * 3 ) ;
2016-06-04 11:17:38 -07:00
int const gain1 = ( int ) ( matchLength * 3 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 1 ) ;
2016-04-07 10:14:09 -07:00
if ( ( mlRep > = EQUAL_READ32 ) & & ( gain2 > gain1 ) )
matchLength = mlRep , offset = 0 , start = ip ;
2015-11-03 18:52:54 -08:00
}
2016-03-19 10:08:32 -07:00
{ size_t offset2 = 99999999 ;
size_t const ml2 = searchMax ( ctx , ip , iend , & offset2 , maxSearches , mls ) ;
2016-06-04 11:17:38 -07:00
int const gain2 = ( int ) ( ml2 * 4 - ZSTD_highbit32 ( ( U32 ) offset2 + 1 ) ) ; /* raw approx */
int const gain1 = ( int ) ( matchLength * 4 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 4 ) ;
2016-04-07 10:14:09 -07:00
if ( ( ml2 > = EQUAL_READ32 ) & & ( gain2 > gain1 ) ) {
2015-11-06 09:44:54 -08:00
matchLength = ml2 , offset = offset2 , start = ip ;
2015-11-03 18:52:54 -08:00
continue ; /* search a better one */
2016-01-27 15:18:06 -08:00
} }
2015-11-03 18:52:54 -08:00
/* let's find an even better one */
2016-01-27 15:18:06 -08:00
if ( ( depth = = 2 ) & & ( ip < ilimit ) ) {
2015-11-03 18:52:54 -08:00
ip + + ;
2016-04-07 10:14:09 -07:00
if ( ( offset ) & & ( MEM_read32 ( ip ) = = MEM_read32 ( ip - rep [ 0 ] ) ) ) {
size_t const ml2 = ZSTD_count ( ip + EQUAL_READ32 , ip + EQUAL_READ32 - rep [ 0 ] , iend ) + EQUAL_READ32 ;
2016-03-19 10:08:32 -07:00
int const gain2 = ( int ) ( ml2 * 4 ) ;
2016-06-04 11:17:38 -07:00
int const gain1 = ( int ) ( matchLength * 4 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 1 ) ;
2016-04-07 10:14:09 -07:00
if ( ( ml2 > = EQUAL_READ32 ) & & ( gain2 > gain1 ) )
matchLength = ml2 , offset = 0 , start = ip ;
2015-11-03 18:52:54 -08:00
}
2016-03-19 10:08:32 -07:00
{ size_t offset2 = 99999999 ;
size_t const ml2 = searchMax ( ctx , ip , iend , & offset2 , maxSearches , mls ) ;
2016-06-04 11:17:38 -07:00
int const gain2 = ( int ) ( ml2 * 4 - ZSTD_highbit32 ( ( U32 ) offset2 + 1 ) ) ; /* raw approx */
int const gain1 = ( int ) ( matchLength * 4 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 7 ) ;
2016-04-07 10:14:09 -07:00
if ( ( ml2 > = EQUAL_READ32 ) & & ( gain2 > gain1 ) ) {
2015-11-06 09:44:54 -08:00
matchLength = ml2 , offset = offset2 , start = ip ;
continue ;
2016-01-27 15:18:06 -08:00
} } }
2015-11-03 18:52:54 -08:00
break ; /* nothing found : store previous solution */
}
2016-02-16 08:41:03 -08:00
/* catch up */
2016-04-07 10:14:09 -07:00
if ( offset ) {
2016-03-18 03:03:43 -07:00
while ( ( start > anchor ) & & ( start > base + offset - ZSTD_REP_MOVE ) & & ( start [ - 1 ] = = start [ - 1 - offset + ZSTD_REP_MOVE ] ) ) /* only search for offset within prefix */
2015-11-08 18:19:33 -08:00
{ start - - ; matchLength + + ; }
2016-04-07 10:14:09 -07:00
rep [ 1 ] = rep [ 0 ] ; rep [ 0 ] = ( U32 ) ( offset - ZSTD_REP_MOVE ) ;
2015-11-08 18:19:33 -08:00
}
/* store sequence */
2016-04-07 10:14:09 -07:00
_storeSequence :
{ size_t const litLength = start - anchor ;
2015-11-03 18:52:54 -08:00
ZSTD_storeSeq ( seqStorePtr , litLength , anchor , offset , matchLength - MINMATCH ) ;
2015-11-08 18:19:33 -08:00
anchor = ip = start + matchLength ;
2015-11-03 18:52:54 -08:00
}
2016-04-07 10:14:09 -07:00
/* check immediate repcode */
while ( ( ip < = ilimit )
& & ( MEM_read32 ( ip ) = = MEM_read32 ( ip - rep [ 1 ] ) ) ) {
/* store sequence */
matchLength = ZSTD_count ( ip + EQUAL_READ32 , ip + EQUAL_READ32 - rep [ 1 ] , iend ) + EQUAL_READ32 ;
offset = rep [ 1 ] ; rep [ 1 ] = rep [ 0 ] ; rep [ 0 ] = ( U32 ) offset ; /* swap repcodes */
ZSTD_storeSeq ( seqStorePtr , 0 , anchor , 0 , matchLength - MINMATCH ) ;
ip + = matchLength ;
anchor = ip ;
continue ; /* faster when present ... (?) */
} }
2015-11-03 18:52:54 -08:00
/* Last Literals */
2016-03-19 10:08:32 -07:00
{ size_t const lastLLSize = iend - anchor ;
2015-11-03 18:52:54 -08:00
memcpy ( seqStorePtr - > lit , anchor , lastLLSize ) ;
seqStorePtr - > lit + = lastLLSize ;
2016-05-24 06:36:37 -07:00
ZSTD_statsUpdatePrices ( & seqStorePtr - > stats , lastLLSize , anchor , 0 , 0 ) ;
2015-11-03 18:52:54 -08:00
}
}
2016-01-31 02:25:48 -08:00
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_btlazy2 ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-10-22 07:31:46 -07:00
{
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_lazy_generic ( ctx , src , srcSize , 1 , 2 ) ;
2015-11-05 06:00:24 -08:00
}
2015-10-22 07:31:46 -07:00
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_lazy2 ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-11-05 06:00:24 -08:00
{
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_lazy_generic ( ctx , src , srcSize , 0 , 2 ) ;
2015-11-05 06:00:24 -08:00
}
2015-10-22 07:31:46 -07:00
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_lazy ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-11-05 06:00:24 -08:00
{
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_lazy_generic ( ctx , src , srcSize , 0 , 1 ) ;
2015-10-22 07:31:46 -07:00
}
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_greedy ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-10-31 04:57:14 -07:00
{
2016-04-07 10:14:09 -07:00
ZSTD_compressBlock_lazy_generic ( ctx , src , srcSize , 0 , 0 ) ;
2015-10-31 04:57:14 -07:00
}
2015-11-21 17:53:43 -08:00
FORCE_INLINE
2016-01-23 10:28:41 -08:00
void ZSTD_compressBlock_lazy_extDict_generic ( ZSTD_CCtx * ctx ,
const void * src , size_t srcSize ,
2015-11-21 17:53:43 -08:00
const U32 searchMethod , const U32 depth )
{
seqStore_t * seqStorePtr = & ( ctx - > seqStore ) ;
const BYTE * const istart = ( const BYTE * ) src ;
const BYTE * ip = istart ;
const BYTE * anchor = istart ;
const BYTE * const iend = istart + srcSize ;
const BYTE * const ilimit = iend - 8 ;
const BYTE * const base = ctx - > base ;
const U32 dictLimit = ctx - > dictLimit ;
const BYTE * const prefixStart = base + dictLimit ;
const BYTE * const dictBase = ctx - > dictBase ;
const BYTE * const dictEnd = dictBase + dictLimit ;
2015-11-24 05:06:07 -08:00
const BYTE * const dictStart = dictBase + ctx - > lowLimit ;
2015-11-21 17:53:43 -08:00
2016-03-30 10:48:05 -07:00
const U32 maxSearches = 1 < < ctx - > params . cParams . searchLog ;
const U32 mls = ctx - > params . cParams . searchLength ;
2015-11-21 17:53:43 -08:00
typedef size_t ( * searchMax_f ) ( ZSTD_CCtx * zc , const BYTE * ip , const BYTE * iLimit ,
size_t * offsetPtr ,
U32 maxNbAttempts , U32 matchLengthSearch ) ;
2015-11-23 06:29:15 -08:00
searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS ;
2015-11-21 17:53:43 -08:00
/* init */
2016-03-18 03:03:43 -07:00
U32 rep [ ZSTD_REP_INIT ] ;
2016-04-08 06:25:32 -07:00
{ U32 i ; for ( i = 0 ; i < ZSTD_REP_INIT ; i + + ) rep [ i ] = REPCODE_STARTVALUE ; }
2016-04-05 09:16:38 -07:00
2016-04-06 03:34:42 -07:00
ctx - > nextToUpdate3 = ctx - > nextToUpdate ;
2015-11-21 17:53:43 -08:00
ZSTD_resetSeqStore ( seqStorePtr ) ;
2015-12-11 01:44:07 -08:00
if ( ( ip - prefixStart ) < REPCODE_STARTVALUE ) ip + = REPCODE_STARTVALUE ;
2015-11-21 17:53:43 -08:00
/* Match Loop */
2016-01-27 15:18:06 -08:00
while ( ip < ilimit ) {
2015-11-21 17:53:43 -08:00
size_t matchLength = 0 ;
size_t offset = 0 ;
2016-04-07 10:14:09 -07:00
const BYTE * start = ip + 1 ;
2015-11-21 17:53:43 -08:00
U32 current = ( U32 ) ( ip - base ) ;
/* check repCode */
2016-04-07 10:14:09 -07:00
{
const U32 repIndex = ( U32 ) ( current + 1 - rep [ 0 ] ) ;
2015-11-21 17:53:43 -08:00
const BYTE * const repBase = repIndex < dictLimit ? dictBase : base ;
const BYTE * const repMatch = repBase + repIndex ;
2015-11-23 04:34:21 -08:00
if ( ( U32 ) ( ( dictLimit - 1 ) - repIndex ) > = 3 ) /* intentional overflow */
2016-04-07 10:14:09 -07:00
if ( MEM_read32 ( ip + 1 ) = = MEM_read32 ( repMatch ) ) {
2015-11-21 17:53:43 -08:00
/* repcode detected we should take it */
const BYTE * const repEnd = repIndex < dictLimit ? dictEnd : iend ;
2016-04-07 10:14:09 -07:00
matchLength = ZSTD_count_2segments ( ip + 1 + EQUAL_READ32 , repMatch + EQUAL_READ32 , iend , repEnd , prefixStart ) + EQUAL_READ32 ;
if ( depth = = 0 ) goto _storeSequence ;
2016-01-27 15:18:06 -08:00
} }
2015-11-21 17:53:43 -08:00
2016-03-19 10:08:32 -07:00
/* first search (depth 0) */
{ size_t offsetFound = 99999999 ;
size_t const ml2 = searchMax ( ctx , ip , iend , & offsetFound , maxSearches , mls ) ;
2015-11-23 07:17:21 -08:00
if ( ml2 > matchLength )
matchLength = ml2 , start = ip , offset = offsetFound ;
}
2016-04-07 10:14:09 -07:00
if ( matchLength < EQUAL_READ32 ) {
2015-11-23 07:17:21 -08:00
ip + = ( ( ip - anchor ) > > g_searchStrength ) + 1 ; /* jump faster over incompressible sections */
continue ;
}
2015-11-21 17:53:43 -08:00
/* let's try to find a better solution */
if ( depth > = 1 )
2016-01-27 15:18:06 -08:00
while ( ip < ilimit ) {
2015-11-21 17:53:43 -08:00
ip + + ;
current + + ;
/* check repCode */
2016-04-07 10:14:09 -07:00
if ( offset ) {
const U32 repIndex = ( U32 ) ( current - rep [ 0 ] ) ;
2015-11-21 17:53:43 -08:00
const BYTE * const repBase = repIndex < dictLimit ? dictBase : base ;
const BYTE * const repMatch = repBase + repIndex ;
2015-11-23 04:34:21 -08:00
if ( ( U32 ) ( ( dictLimit - 1 ) - repIndex ) > = 3 ) /* intentional overflow */
2016-04-07 10:14:09 -07:00
if ( MEM_read32 ( ip ) = = MEM_read32 ( repMatch ) ) {
2015-11-21 17:53:43 -08:00
/* repcode detected */
const BYTE * const repEnd = repIndex < dictLimit ? dictEnd : iend ;
2016-04-07 10:14:09 -07:00
size_t const repLength = ZSTD_count_2segments ( ip + EQUAL_READ32 , repMatch + EQUAL_READ32 , iend , repEnd , prefixStart ) + EQUAL_READ32 ;
2016-03-19 10:08:32 -07:00
int const gain2 = ( int ) ( repLength * 3 ) ;
2016-06-04 11:17:38 -07:00
int const gain1 = ( int ) ( matchLength * 3 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 1 ) ;
2016-04-07 10:14:09 -07:00
if ( ( repLength > = EQUAL_READ32 ) & & ( gain2 > gain1 ) )
matchLength = repLength , offset = 0 , start = ip ;
2016-01-27 15:18:06 -08:00
} }
2015-11-21 17:53:43 -08:00
/* search match, depth 1 */
2016-03-19 10:08:32 -07:00
{ size_t offset2 = 99999999 ;
size_t const ml2 = searchMax ( ctx , ip , iend , & offset2 , maxSearches , mls ) ;
2016-06-04 11:17:38 -07:00
int const gain2 = ( int ) ( ml2 * 4 - ZSTD_highbit32 ( ( U32 ) offset2 + 1 ) ) ; /* raw approx */
int const gain1 = ( int ) ( matchLength * 4 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 4 ) ;
2016-04-07 10:14:09 -07:00
if ( ( ml2 > = EQUAL_READ32 ) & & ( gain2 > gain1 ) ) {
2015-11-21 17:53:43 -08:00
matchLength = ml2 , offset = offset2 , start = ip ;
continue ; /* search a better one */
2016-01-27 15:18:06 -08:00
} }
2015-11-21 17:53:43 -08:00
/* let's find an even better one */
2016-01-27 15:18:06 -08:00
if ( ( depth = = 2 ) & & ( ip < ilimit ) ) {
2015-11-21 17:53:43 -08:00
ip + + ;
current + + ;
/* check repCode */
2016-04-07 10:14:09 -07:00
if ( offset ) {
const U32 repIndex = ( U32 ) ( current - rep [ 0 ] ) ;
2015-11-21 17:53:43 -08:00
const BYTE * const repBase = repIndex < dictLimit ? dictBase : base ;
const BYTE * const repMatch = repBase + repIndex ;
2015-11-23 04:34:21 -08:00
if ( ( U32 ) ( ( dictLimit - 1 ) - repIndex ) > = 3 ) /* intentional overflow */
2016-04-07 10:14:09 -07:00
if ( MEM_read32 ( ip ) = = MEM_read32 ( repMatch ) ) {
2015-11-21 17:53:43 -08:00
/* repcode detected */
const BYTE * const repEnd = repIndex < dictLimit ? dictEnd : iend ;
2016-04-07 10:14:09 -07:00
size_t repLength = ZSTD_count_2segments ( ip + EQUAL_READ32 , repMatch + EQUAL_READ32 , iend , repEnd , prefixStart ) + EQUAL_READ32 ;
int gain2 = ( int ) ( repLength * 4 ) ;
2016-06-04 11:17:38 -07:00
int gain1 = ( int ) ( matchLength * 4 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 1 ) ;
2016-04-07 10:14:09 -07:00
if ( ( repLength > = EQUAL_READ32 ) & & ( gain2 > gain1 ) )
matchLength = repLength , offset = 0 , start = ip ;
2016-01-27 15:18:06 -08:00
} }
2015-11-21 17:53:43 -08:00
/* search match, depth 2 */
2016-03-19 10:08:32 -07:00
{ size_t offset2 = 99999999 ;
size_t const ml2 = searchMax ( ctx , ip , iend , & offset2 , maxSearches , mls ) ;
2016-06-04 11:17:38 -07:00
int const gain2 = ( int ) ( ml2 * 4 - ZSTD_highbit32 ( ( U32 ) offset2 + 1 ) ) ; /* raw approx */
int const gain1 = ( int ) ( matchLength * 4 - ZSTD_highbit32 ( ( U32 ) offset + 1 ) + 7 ) ;
2016-04-07 10:14:09 -07:00
if ( ( ml2 > = EQUAL_READ32 ) & & ( gain2 > gain1 ) ) {
2015-11-21 17:53:43 -08:00
matchLength = ml2 , offset = offset2 , start = ip ;
continue ;
2016-01-27 15:18:06 -08:00
} } }
2015-11-21 17:53:43 -08:00
break ; /* nothing found : store previous solution */
}
/* catch up */
2016-04-07 10:14:09 -07:00
if ( offset ) {
2016-05-31 09:13:56 -07:00
U32 const matchIndex = ( U32 ) ( ( start - base ) - ( offset - ZSTD_REP_MOVE ) ) ;
2015-11-24 05:06:07 -08:00
const BYTE * match = ( matchIndex < dictLimit ) ? dictBase + matchIndex : base + matchIndex ;
const BYTE * const mStart = ( matchIndex < dictLimit ) ? dictStart : prefixStart ;
while ( ( start > anchor ) & & ( match > mStart ) & & ( start [ - 1 ] = = match [ - 1 ] ) ) { start - - ; match - - ; matchLength + + ; } /* catch up */
2016-04-07 10:14:09 -07:00
rep [ 1 ] = rep [ 0 ] ; rep [ 0 ] = ( U32 ) ( offset - ZSTD_REP_MOVE ) ;
2015-11-21 17:53:43 -08:00
}
/* store sequence */
2016-04-07 10:14:09 -07:00
_storeSequence :
{ size_t const litLength = start - anchor ;
2016-04-05 09:16:38 -07:00
ZSTD_storeSeq ( seqStorePtr , litLength , anchor , offset , matchLength - MINMATCH ) ;
anchor = ip = start + matchLength ;
2016-04-07 10:14:09 -07:00
}
/* check immediate repcode */
while ( ip < = ilimit ) {
const U32 repIndex = ( U32 ) ( ( ip - base ) - rep [ 1 ] ) ;
const BYTE * const repBase = repIndex < dictLimit ? dictBase : base ;
const BYTE * const repMatch = repBase + repIndex ;
if ( ( U32 ) ( ( dictLimit - 1 ) - repIndex ) > = 3 ) /* intentional overflow */
if ( MEM_read32 ( ip ) = = MEM_read32 ( repMatch ) ) {
/* repcode detected we should take it */
const BYTE * const repEnd = repIndex < dictLimit ? dictEnd : iend ;
matchLength = ZSTD_count_2segments ( ip + EQUAL_READ32 , repMatch + EQUAL_READ32 , iend , repEnd , prefixStart ) + EQUAL_READ32 ;
offset = rep [ 1 ] ; rep [ 1 ] = rep [ 0 ] ; rep [ 0 ] = ( U32 ) offset ; /* swap offset history */
ZSTD_storeSeq ( seqStorePtr , 0 , anchor , 0 , matchLength - MINMATCH ) ;
ip + = matchLength ;
anchor = ip ;
continue ; /* faster when present ... (?) */
}
break ;
2016-01-27 15:18:06 -08:00
} }
2015-11-21 17:53:43 -08:00
/* Last Literals */
2016-03-20 08:00:00 -07:00
{ size_t const lastLLSize = iend - anchor ;
2015-11-21 17:53:43 -08:00
memcpy ( seqStorePtr - > lit , anchor , lastLLSize ) ;
seqStorePtr - > lit + = lastLLSize ;
}
}
2016-04-07 10:14:09 -07:00
2016-01-23 10:28:41 -08:00
void ZSTD_compressBlock_greedy_extDict ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-11-21 17:53:43 -08:00
{
2016-04-07 10:14:09 -07:00
ZSTD_compressBlock_lazy_extDict_generic ( ctx , src , srcSize , 0 , 0 ) ;
2015-11-21 17:53:43 -08:00
}
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_lazy_extDict ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-11-21 18:12:28 -08:00
{
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_lazy_extDict_generic ( ctx , src , srcSize , 0 , 1 ) ;
2015-11-21 18:12:28 -08:00
}
2015-11-21 17:53:43 -08:00
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_lazy2_extDict ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-11-22 03:22:04 -08:00
{
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_lazy_extDict_generic ( ctx , src , srcSize , 0 , 2 ) ;
2015-11-22 03:22:04 -08:00
}
2016-01-23 10:28:41 -08:00
static void ZSTD_compressBlock_btlazy2_extDict ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2015-11-23 04:34:21 -08:00
{
2016-01-24 19:22:03 -08:00
ZSTD_compressBlock_lazy_extDict_generic ( ctx , src , srcSize , 1 , 2 ) ;
2015-11-23 04:34:21 -08:00
}
2016-04-21 02:08:43 -07:00
/* The optimal parser */
# include "zstd_opt.h"
static void ZSTD_compressBlock_btopt ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
{
ZSTD_compressBlock_opt_generic ( ctx , src , srcSize ) ;
}
2016-02-22 01:06:17 -08:00
static void ZSTD_compressBlock_btopt_extDict ( ZSTD_CCtx * ctx , const void * src , size_t srcSize )
2016-01-31 02:25:48 -08:00
{
2016-04-05 12:03:43 -07:00
ZSTD_compressBlock_opt_extDict_generic ( ctx , src , srcSize ) ;
2016-01-31 02:25:48 -08:00
}
2015-11-21 06:27:35 -08:00
2016-01-23 10:28:41 -08:00
typedef void ( * ZSTD_blockCompressor ) ( ZSTD_CCtx * ctx , const void * src , size_t srcSize ) ;
2015-11-04 03:05:27 -08:00
2016-01-25 18:14:20 -08:00
static ZSTD_blockCompressor ZSTD_selectBlockCompressor ( ZSTD_strategy strat , int extDict )
2015-10-31 04:57:14 -07:00
{
2016-02-22 01:06:17 -08:00
static const ZSTD_blockCompressor blockCompressor [ 2 ] [ 6 ] = {
2016-04-05 14:58:51 -07:00
# if 1
2016-02-22 01:06:17 -08:00
{ ZSTD_compressBlock_fast , ZSTD_compressBlock_greedy , ZSTD_compressBlock_lazy , ZSTD_compressBlock_lazy2 , ZSTD_compressBlock_btlazy2 , ZSTD_compressBlock_btopt } ,
2016-04-05 09:16:38 -07:00
# else
{ ZSTD_compressBlock_fast_extDict , ZSTD_compressBlock_greedy_extDict , ZSTD_compressBlock_lazy_extDict , ZSTD_compressBlock_lazy2_extDict , ZSTD_compressBlock_btlazy2_extDict , ZSTD_compressBlock_btopt_extDict } ,
# endif
2016-02-22 01:06:17 -08:00
{ ZSTD_compressBlock_fast_extDict , ZSTD_compressBlock_greedy_extDict , ZSTD_compressBlock_lazy_extDict , ZSTD_compressBlock_lazy2_extDict , ZSTD_compressBlock_btlazy2_extDict , ZSTD_compressBlock_btopt_extDict }
2015-11-28 17:38:09 -08:00
} ;
return blockCompressor [ extDict ] [ ( U32 ) strat ] ;
2015-10-31 04:57:14 -07:00
}
2016-03-14 17:24:33 -07:00
static size_t ZSTD_compressBlock_internal ( ZSTD_CCtx * zc , void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-04 03:05:27 -08:00
{
2016-03-30 10:48:05 -07:00
ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor ( zc - > params . cParams . strategy , zc - > lowLimit < zc - > dictLimit ) ;
2016-02-02 05:36:49 -08:00
if ( srcSize < MIN_CBLOCK_SIZE + ZSTD_blockHeaderSize + 1 ) return 0 ; /* don't even attempt compression below a certain srcSize */
2016-01-23 10:28:41 -08:00
blockCompressor ( zc , src , srcSize ) ;
2016-03-14 17:24:33 -07:00
return ZSTD_compressSequences ( zc , dst , dstCapacity , srcSize ) ;
2015-11-04 03:05:27 -08:00
}
2016-03-25 02:52:25 -07:00
2016-05-31 09:13:56 -07:00
static size_t ZSTD_compress_generic ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize )
2015-10-22 07:31:46 -07:00
{
2016-05-31 09:13:56 -07:00
size_t blockSize = cctx - > blockSize ;
2015-10-22 07:31:46 -07:00
size_t remaining = srcSize ;
const BYTE * ip = ( const BYTE * ) src ;
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * op = ostart ;
2016-05-31 09:13:56 -07:00
const U32 maxDist = 1 < < cctx - > params . cParams . windowLog ;
ZSTD_stats_t * stats = & cctx - > seqStore . stats ;
2016-03-25 02:52:25 -07:00
ZSTD_statsInit ( stats ) ;
2015-11-01 03:40:22 -08:00
2016-05-31 09:13:56 -07:00
if ( cctx - > params . fParams . checksumFlag )
XXH64_update ( & cctx - > xxhState , src , srcSize ) ;
2016-02-02 05:36:49 -08:00
while ( remaining ) {
2015-11-04 09:19:39 -08:00
size_t cSize ;
2016-06-06 02:07:33 -07:00
ZSTD_statsResetFreqs ( stats ) ; /* debug only */
2015-10-22 07:31:46 -07:00
2016-05-24 06:36:37 -07:00
if ( dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE ) return ERROR ( dstSize_tooSmall ) ; /* not enough space to store compressed block */
2015-11-04 09:19:39 -08:00
if ( remaining < blockSize ) blockSize = remaining ;
2015-11-13 02:27:46 -08:00
2016-05-31 09:13:56 -07:00
if ( ( U32 ) ( ip + blockSize - cctx - > base ) > cctx - > loadedDictEnd + maxDist ) {
2016-03-19 10:08:32 -07:00
/* enforce maxDist */
2016-05-31 09:13:56 -07:00
U32 const newLowLimit = ( U32 ) ( ip + blockSize - cctx - > base ) - maxDist ;
if ( cctx - > lowLimit < newLowLimit ) cctx - > lowLimit = newLowLimit ;
if ( cctx - > dictLimit < cctx - > lowLimit ) cctx - > dictLimit = cctx - > lowLimit ;
2015-11-24 05:06:07 -08:00
}
2015-11-13 02:27:46 -08:00
2016-05-31 09:13:56 -07:00
cSize = ZSTD_compressBlock_internal ( cctx , op + ZSTD_blockHeaderSize , dstCapacity - ZSTD_blockHeaderSize , ip , blockSize ) ;
2016-05-24 06:36:37 -07:00
if ( ZSTD_isError ( cSize ) ) return cSize ;
2015-10-22 07:31:46 -07:00
2016-02-02 05:36:49 -08:00
if ( cSize = = 0 ) { /* block is not compressible */
2016-03-14 17:24:33 -07:00
cSize = ZSTD_noCompressBlock ( op , dstCapacity , ip , blockSize ) ;
2016-05-24 06:36:37 -07:00
if ( ZSTD_isError ( cSize ) ) return cSize ;
2016-02-02 05:36:49 -08:00
} else {
2015-10-22 07:31:46 -07:00
op [ 0 ] = ( BYTE ) ( cSize > > 16 ) ;
op [ 1 ] = ( BYTE ) ( cSize > > 8 ) ;
op [ 2 ] = ( BYTE ) cSize ;
2015-11-19 08:28:35 -08:00
op [ 0 ] + = ( BYTE ) ( bt_compressed < < 6 ) ; /* is a compressed block */
2015-10-22 07:31:46 -07:00
cSize + = 3 ;
}
2015-11-04 09:19:39 -08:00
remaining - = blockSize ;
2016-03-14 17:24:33 -07:00
dstCapacity - = cSize ;
2015-11-04 09:19:39 -08:00
ip + = blockSize ;
2015-10-22 07:31:46 -07:00
op + = cSize ;
}
2016-05-31 09:13:56 -07:00
ZSTD_statsPrint ( stats , cctx - > params . cParams . searchLength ) ;
2015-10-22 07:31:46 -07:00
return op - ostart ;
}
2016-04-12 06:52:33 -07:00
static size_t ZSTD_writeFrameHeader ( void * dst , size_t dstCapacity ,
2016-05-28 20:01:04 -07:00
ZSTD_parameters params , U64 pledgedSrcSize , U32 dictID )
2016-04-12 06:52:33 -07:00
{ BYTE * const op = ( BYTE * ) dst ;
2016-05-28 20:01:04 -07:00
U32 const dictIDSizeCode = ( dictID > 0 ) + ( dictID > = 256 ) + ( dictID > = 65536 ) ; /* 0-3 */
2016-06-06 08:50:07 -07:00
U32 const checksumFlag = params . fParams . checksumFlag > 0 ;
2016-06-05 15:26:38 -07:00
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 ?
( pledgedSrcSize > = 256 ) + ( pledgedSrcSize > = 65536 + 256 ) + ( pledgedSrcSize > = 0xFFFFFFFFU ) : /* 0-3 */
0 ;
BYTE const frameHeaderDecriptionByte = ( BYTE ) ( dictIDSizeCode + ( checksumFlag < < 2 ) + ( directModeFlag < < 5 ) + ( fcsCode < < 6 ) ) ;
2016-05-28 20:01:04 -07:00
size_t pos ;
if ( dstCapacity < ZSTD_frameHeaderSize_max ) return ERROR ( dstSize_tooSmall ) ;
2016-04-12 06:52:33 -07:00
MEM_writeLE32 ( dst , ZSTD_MAGICNUMBER ) ;
2016-06-05 15:26:38 -07:00
op [ 4 ] = frameHeaderDecriptionByte ; pos = 5 ;
if ( ! directModeFlag ) op [ pos + + ] = windowLogByte ;
2016-05-28 20:01:04 -07:00
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 3 : MEM_writeLE32 ( op + pos , dictID ) ; pos + = 4 ; break ;
}
2016-06-05 15:26:38 -07:00
switch ( fcsCode )
2016-04-12 06:52:33 -07:00
{
default : /* impossible */
2016-06-05 15:26:38 -07:00
case 0 : if ( directModeFlag ) 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 ;
2016-05-28 20:01:04 -07:00
case 3 : MEM_writeLE64 ( op + pos , ( U64 ) ( pledgedSrcSize ) ) ; pos + = 8 ; break ;
2016-04-12 06:52:33 -07:00
}
2016-05-28 20:01:04 -07:00
return pos ;
2016-04-12 06:52:33 -07:00
}
2016-01-08 16:08:23 -08:00
static size_t ZSTD_compressContinue_internal ( ZSTD_CCtx * zc ,
2016-03-23 14:31:57 -07:00
void * dst , size_t dstCapacity ,
2016-01-08 16:08:23 -08:00
const void * src , size_t srcSize ,
U32 frame )
2015-10-22 07:31:46 -07:00
{
2015-10-29 08:49:43 -07:00
const BYTE * const ip = ( const BYTE * ) src ;
2016-04-12 06:52:33 -07:00
size_t fhSize = 0 ;
2016-01-07 06:35:18 -08:00
2016-04-11 11:12:27 -07:00
if ( zc - > stage = = 0 ) return ERROR ( stage_wrong ) ;
if ( frame & & ( zc - > stage = = 1 ) ) { /* copy saved header */
2016-06-05 15:26:38 -07:00
fhSize = ZSTD_writeFrameHeader ( dst , dstCapacity , zc - > params , zc - > frameContentSize , zc - > dictID ) ;
2016-04-12 06:52:33 -07:00
if ( ZSTD_isError ( fhSize ) ) return fhSize ;
dstCapacity - = fhSize ;
dst = ( char * ) dst + fhSize ;
2016-04-11 11:12:27 -07:00
zc - > stage = 2 ;
2016-01-07 06:35:18 -08:00
}
2015-10-22 07:31:46 -07:00
2015-12-04 08:16:37 -08:00
/* Check if blocks follow each other */
2016-02-02 05:36:49 -08:00
if ( src ! = zc - > nextSrc ) {
2015-12-04 08:16:37 -08:00
/* not contiguous */
2016-03-19 10:08:32 -07:00
size_t const delta = zc - > nextSrc - ip ;
2015-12-04 08:16:37 -08:00
zc - > lowLimit = zc - > dictLimit ;
zc - > dictLimit = ( U32 ) ( zc - > nextSrc - zc - > base ) ;
zc - > dictBase = zc - > base ;
zc - > base - = delta ;
zc - > nextToUpdate = zc - > dictLimit ;
2015-12-05 00:23:53 -08:00
if ( zc - > dictLimit - zc - > lowLimit < 8 ) zc - > lowLimit = zc - > dictLimit ; /* too small extDict */
2015-12-04 08:16:37 -08:00
}
2015-11-13 02:27:46 -08:00
/* preemptive overflow correction */
2016-02-02 05:36:49 -08:00
if ( zc - > lowLimit > ( 1 < < 30 ) ) {
2016-03-30 10:48:05 -07:00
U32 const btplus = ( zc - > params . cParams . strategy = = ZSTD_btlazy2 ) | | ( zc - > params . cParams . strategy = = ZSTD_btopt ) ;
2016-04-04 04:49:18 -07:00
U32 const chainMask = ( 1 < < ( zc - > params . cParams . chainLog - btplus ) ) - 1 ;
U32 const newLowLimit = zc - > lowLimit & chainMask ; /* preserve position % chainSize */
2016-03-19 10:08:32 -07:00
U32 const correction = zc - > lowLimit - newLowLimit ;
2015-11-24 05:06:07 -08:00
ZSTD_reduceIndex ( zc , correction ) ;
zc - > base + = correction ;
zc - > dictBase + = correction ;
2015-12-11 01:44:07 -08:00
zc - > lowLimit = newLowLimit ;
2015-11-24 05:06:07 -08:00
zc - > dictLimit - = correction ;
if ( zc - > nextToUpdate < correction ) zc - > nextToUpdate = 0 ;
else zc - > nextToUpdate - = correction ;
2015-11-13 02:27:46 -08:00
}
2016-01-08 16:08:23 -08:00
/* if input and dictionary overlap : reduce dictionary (presumed modified by input) */
2016-02-02 05:36:49 -08:00
if ( ( ip + srcSize > zc - > dictBase + zc - > lowLimit ) & & ( ip < zc - > dictBase + zc - > dictLimit ) ) {
2015-11-24 05:06:07 -08:00
zc - > lowLimit = ( U32 ) ( ip + srcSize - zc - > dictBase ) ;
if ( zc - > lowLimit > zc - > dictLimit ) zc - > lowLimit = zc - > dictLimit ;
2015-10-22 07:31:46 -07:00
}
2015-11-24 05:06:07 -08:00
zc - > nextSrc = ip + srcSize ;
2016-03-19 10:08:32 -07:00
{ size_t const cSize = frame ?
2016-03-23 14:31:57 -07:00
ZSTD_compress_generic ( zc , dst , dstCapacity , src , srcSize ) :
ZSTD_compressBlock_internal ( zc , dst , dstCapacity , src , srcSize ) ;
2016-01-07 06:35:18 -08:00
if ( ZSTD_isError ( cSize ) ) return cSize ;
2016-04-12 06:52:33 -07:00
return cSize + fhSize ;
2016-01-07 06:35:18 -08:00
}
2015-10-22 07:31:46 -07:00
}
2016-01-08 16:08:23 -08:00
size_t ZSTD_compressContinue ( ZSTD_CCtx * zc ,
2016-03-23 14:31:57 -07:00
void * dst , size_t dstCapacity ,
2016-01-08 16:08:23 -08:00
const void * src , size_t srcSize )
{
2016-03-23 14:31:57 -07:00
return ZSTD_compressContinue_internal ( zc , dst , dstCapacity , src , srcSize , 1 ) ;
2016-01-08 16:08:23 -08:00
}
2016-03-14 17:24:33 -07:00
size_t ZSTD_compressBlock ( ZSTD_CCtx * zc , void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2016-01-08 16:08:23 -08:00
{
2016-03-16 07:26:51 -07:00
if ( srcSize > ZSTD_BLOCKSIZE_MAX ) return ERROR ( srcSize_wrong ) ;
2016-04-04 12:15:23 -07:00
ZSTD_LOG_BLOCK ( " %p: ZSTD_compressBlock searchLength=%d \n " , zc - > base , zc - > params . cParams . searchLength ) ;
2016-03-14 17:24:33 -07:00
return ZSTD_compressContinue_internal ( zc , dst , dstCapacity , src , srcSize , 0 ) ;
2016-01-08 16:08:23 -08:00
}
2016-01-25 18:14:20 -08:00
static size_t ZSTD_loadDictionaryContent ( ZSTD_CCtx * zc , const void * src , size_t srcSize )
2015-12-04 08:16:37 -08:00
{
const BYTE * const ip = ( const BYTE * ) src ;
const BYTE * const iend = ip + srcSize ;
/* input becomes current prefix */
zc - > lowLimit = zc - > dictLimit ;
zc - > dictLimit = ( U32 ) ( zc - > nextSrc - zc - > base ) ;
zc - > dictBase = zc - > base ;
zc - > base + = ip - zc - > nextSrc ;
zc - > nextToUpdate = zc - > dictLimit ;
2016-02-02 05:36:49 -08:00
zc - > loadedDictEnd = ( U32 ) ( iend - zc - > base ) ;
2015-12-04 08:16:37 -08:00
zc - > nextSrc = iend ;
if ( srcSize < = 8 ) return 0 ;
2016-03-30 10:48:05 -07:00
switch ( zc - > params . cParams . strategy )
2015-12-04 08:16:37 -08:00
{
case ZSTD_fast :
2016-03-30 10:48:05 -07:00
ZSTD_fillHashTable ( zc , iend , zc - > params . cParams . searchLength ) ;
2015-12-04 08:16:37 -08:00
break ;
case ZSTD_greedy :
case ZSTD_lazy :
case ZSTD_lazy2 :
2016-03-30 10:48:05 -07:00
ZSTD_insertAndFindFirstIndex ( zc , iend - 8 , zc - > params . cParams . searchLength ) ;
2015-12-04 08:16:37 -08:00
break ;
case ZSTD_btlazy2 :
2016-02-14 22:21:54 -08:00
case ZSTD_btopt :
2016-03-30 10:48:05 -07:00
ZSTD_updateTree ( zc , iend - 8 , iend , 1 < < zc - > params . cParams . searchLog , zc - > params . cParams . searchLength ) ;
2015-12-04 08:16:37 -08:00
break ;
default :
return ERROR ( GENERIC ) ; /* strategy doesn't exist; impossible */
}
2016-02-02 05:36:49 -08:00
zc - > nextToUpdate = zc - > loadedDictEnd ;
2015-12-04 08:16:37 -08:00
return 0 ;
}
2015-10-22 07:31:46 -07:00
2016-01-25 18:14:20 -08:00
/* Dictionary format :
Magic = = ZSTD_DICT_MAGIC ( 4 bytes )
2016-03-13 03:08:40 -07:00
HUF_writeCTable ( 256 )
2016-01-25 18:14:20 -08:00
Dictionary content
*/
2016-03-13 03:08:40 -07:00
/*! ZSTD_loadDictEntropyStats() :
2016-01-25 18:14:20 -08:00
@ return : size read from dictionary */
static size_t ZSTD_loadDictEntropyStats ( ZSTD_CCtx * zc , const void * dict , size_t dictSize )
{
/* note : magic number already checked */
2016-05-31 09:13:56 -07:00
size_t const dictSizeStart = dictSize ;
{ size_t const hufHeaderSize = HUF_readCTable ( zc - > hufTable , 255 , dict , dictSize ) ;
if ( HUF_isError ( hufHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
zc - > flagStaticTables = 1 ;
dict = ( const char * ) dict + hufHeaderSize ;
dictSize - = hufHeaderSize ;
}
{ short offcodeNCount [ MaxOff + 1 ] ;
unsigned offcodeMaxValue = MaxOff , offcodeLog = OffFSELog ;
size_t const offcodeHeaderSize = FSE_readNCount ( offcodeNCount , & offcodeMaxValue , & offcodeLog , dict , dictSize ) ;
if ( FSE_isError ( offcodeHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
{ size_t const errorCode = FSE_buildCTable ( zc - > offcodeCTable , offcodeNCount , offcodeMaxValue , offcodeLog ) ;
if ( FSE_isError ( errorCode ) ) return ERROR ( dictionary_corrupted ) ; }
dict = ( const char * ) dict + offcodeHeaderSize ;
dictSize - = offcodeHeaderSize ;
}
{ short matchlengthNCount [ MaxML + 1 ] ;
unsigned matchlengthMaxValue = MaxML , matchlengthLog = MLFSELog ;
size_t const matchlengthHeaderSize = FSE_readNCount ( matchlengthNCount , & matchlengthMaxValue , & matchlengthLog , dict , dictSize ) ;
if ( FSE_isError ( matchlengthHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
{ size_t const errorCode = FSE_buildCTable ( zc - > matchlengthCTable , matchlengthNCount , matchlengthMaxValue , matchlengthLog ) ;
if ( FSE_isError ( errorCode ) ) return ERROR ( dictionary_corrupted ) ; }
dict = ( const char * ) dict + matchlengthHeaderSize ;
dictSize - = matchlengthHeaderSize ;
}
{ short litlengthNCount [ MaxLL + 1 ] ;
unsigned litlengthMaxValue = MaxLL , litlengthLog = LLFSELog ;
size_t const litlengthHeaderSize = FSE_readNCount ( litlengthNCount , & litlengthMaxValue , & litlengthLog , dict , dictSize ) ;
if ( FSE_isError ( litlengthHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
{ size_t const errorCode = FSE_buildCTable ( zc - > litlengthCTable , litlengthNCount , litlengthMaxValue , litlengthLog ) ;
if ( FSE_isError ( errorCode ) ) return ERROR ( dictionary_corrupted ) ; }
dictSize - = litlengthHeaderSize ;
}
return ( dictSizeStart - dictSize ) ;
2016-01-25 18:14:20 -08:00
}
2016-03-14 17:24:33 -07:00
/** ZSTD_compress_insertDictionary() :
* @ return : 0 , or an error code */
2016-01-26 07:31:22 -08:00
static size_t ZSTD_compress_insertDictionary ( ZSTD_CCtx * zc , const void * dict , size_t dictSize )
2016-01-25 18:14:20 -08:00
{
2016-05-28 20:01:04 -07:00
if ( ( dict = = NULL ) | | ( dictSize < = 8 ) ) return 0 ;
2016-01-26 06:58:49 -08:00
2016-03-14 17:24:33 -07:00
/* default : dict is pure content */
if ( MEM_readLE32 ( dict ) ! = ZSTD_DICT_MAGIC ) return ZSTD_loadDictionaryContent ( zc , dict , dictSize ) ;
2016-05-28 20:01:04 -07:00
zc - > dictID = zc - > params . fParams . noDictIDFlag ? 0 : MEM_readLE32 ( ( const char * ) dict + 4 ) ;
2016-03-14 17:24:33 -07:00
/* known magic number : dict is parsed for entropy stats and content */
2016-05-28 20:01:04 -07:00
{ size_t const eSize = ZSTD_loadDictEntropyStats ( zc , ( const char * ) dict + 8 /* skip dictHeader */ , dictSize - 8 ) + 8 ;
2016-03-30 07:50:44 -07:00
if ( ZSTD_isError ( eSize ) ) return eSize ;
return ZSTD_loadDictionaryContent ( zc , ( const char * ) dict + eSize , dictSize - eSize ) ;
2016-01-26 06:58:49 -08:00
}
2016-01-07 06:35:18 -08:00
}
2016-04-12 05:14:10 -07:00
2016-04-01 06:48:48 -07:00
/*! ZSTD_compressBegin_internal() :
2016-01-07 06:35:18 -08:00
* @ return : 0 , or an error code */
2016-04-01 06:48:48 -07:00
static size_t ZSTD_compressBegin_internal ( ZSTD_CCtx * zc ,
2016-01-26 07:31:22 -08:00
const void * dict , size_t dictSize ,
2016-03-30 10:48:05 -07:00
ZSTD_parameters params , U64 pledgedSrcSize )
2015-10-22 07:31:46 -07:00
{
2016-06-05 15:26:38 -07:00
size_t const resetError = ZSTD_resetCCtx_advanced ( zc , params , pledgedSrcSize , 1 ) ;
if ( ZSTD_isError ( resetError ) ) return resetError ;
2015-11-13 02:27:46 -08:00
2016-01-26 07:31:22 -08:00
return ZSTD_compress_insertDictionary ( zc , dict , dictSize ) ;
2015-10-22 07:31:46 -07:00
}
2015-10-25 06:06:35 -07:00
2016-04-01 06:48:48 -07:00
/*! ZSTD_compressBegin_advanced() :
* @ return : 0 , or an error code */
2016-06-06 15:51:51 -07:00
size_t ZSTD_compressBegin_advanced ( ZSTD_CCtx * cctx ,
2016-04-01 06:48:48 -07:00
const void * dict , size_t dictSize ,
ZSTD_parameters params , U64 pledgedSrcSize )
{
/* compression parameters verification and optimization */
{ size_t const errorCode = ZSTD_checkCParams_advanced ( params . cParams , pledgedSrcSize ) ;
if ( ZSTD_isError ( errorCode ) ) return errorCode ; }
2016-06-06 15:51:51 -07:00
return ZSTD_compressBegin_internal ( cctx , dict , dictSize , params , pledgedSrcSize ) ;
2016-04-01 06:48:48 -07:00
}
2016-06-06 15:51:51 -07:00
size_t ZSTD_compressBegin_usingDict ( ZSTD_CCtx * cctx , const void * dict , size_t dictSize , int compressionLevel )
2016-01-25 18:14:20 -08:00
{
2016-03-30 10:48:05 -07:00
ZSTD_parameters params ;
2016-05-28 20:01:04 -07:00
memset ( & params , 0 , sizeof ( params ) ) ;
2016-03-30 10:48:05 -07:00
params . cParams = ZSTD_getCParams ( compressionLevel , 0 , dictSize ) ;
2016-06-06 15:51:51 -07:00
ZSTD_LOG_BLOCK ( " %p: ZSTD_compressBegin_usingDict compressionLevel=%d \n " , cctx - > base , compressionLevel ) ;
return ZSTD_compressBegin_internal ( cctx , dict , dictSize , params , 0 ) ;
2016-01-26 07:31:22 -08:00
}
2015-11-25 05:42:45 -08:00
2016-04-04 03:10:00 -07:00
2016-01-26 07:31:22 -08:00
size_t ZSTD_compressBegin ( ZSTD_CCtx * zc , int compressionLevel )
2015-11-25 05:42:45 -08:00
{
2016-03-01 05:14:35 -08:00
ZSTD_LOG_BLOCK ( " %p: ZSTD_compressBegin compressionLevel=%d \n " , zc - > base , compressionLevel ) ;
2016-03-30 10:48:05 -07:00
return ZSTD_compressBegin_usingDict ( zc , NULL , 0 , compressionLevel ) ;
2015-10-25 06:06:35 -07:00
}
2016-03-13 03:08:40 -07:00
/*! ZSTD_compressEnd() :
* Write frame epilogue .
2015-11-25 05:42:45 -08:00
* @ return : nb of bytes written into dst ( or an error code ) */
2016-05-31 09:13:56 -07:00
size_t ZSTD_compressEnd ( ZSTD_CCtx * cctx , void * dst , size_t dstCapacity )
2015-10-29 08:49:43 -07:00
{
BYTE * op = ( BYTE * ) dst ;
2016-04-12 06:52:33 -07:00
size_t fhSize = 0 ;
2015-10-29 08:49:43 -07:00
2016-04-11 11:12:27 -07:00
/* not even init ! */
2016-05-31 09:13:56 -07:00
if ( cctx - > stage = = 0 ) return ERROR ( stage_wrong ) ;
2016-04-11 11:12:27 -07:00
/* special case : empty frame */
2016-05-31 09:13:56 -07:00
if ( cctx - > stage = = 1 ) {
fhSize = ZSTD_writeFrameHeader ( dst , dstCapacity , cctx - > params , 0 , 0 ) ;
2016-04-12 06:52:33 -07:00
if ( ZSTD_isError ( fhSize ) ) return fhSize ;
dstCapacity - = fhSize ;
op + = fhSize ;
2016-05-31 09:13:56 -07:00
cctx - > stage = 2 ;
2016-01-07 06:35:18 -08:00
}
2015-10-29 08:49:43 -07:00
2016-01-07 06:35:18 -08:00
/* frame epilogue */
2016-03-14 17:24:33 -07:00
if ( dstCapacity < 3 ) return ERROR ( dstSize_tooSmall ) ;
2016-05-31 09:13:56 -07:00
{ 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 ;
}
2015-10-29 08:49:43 -07:00
2016-05-31 09:13:56 -07:00
cctx - > stage = 0 ; /* return to "created but not init" status */
2016-04-12 06:52:33 -07:00
return 3 + fhSize ;
2015-10-29 08:49:43 -07:00
}
2016-01-29 18:14:15 -08:00
2016-06-07 03:16:49 -07:00
/*! ZSTD_compress_usingPreparedCCtx() :
* Same as ZSTD_compress_usingDict , but using a reference context ` preparedCCtx ` , where dictionary has been loaded .
* It avoids reloading the dictionary each time .
* ` preparedCCtx ` must have been properly initialized using ZSTD_compressBegin_usingDict ( ) or ZSTD_compressBegin_advanced ( ) .
* Requires 2 contexts : 1 for reference ( preparedCCtx ) which will not be modified , and 1 to run the compression operation ( cctx ) */
static size_t ZSTD_compress_usingPreparedCCtx ( ZSTD_CCtx * cctx , const ZSTD_CCtx * preparedCCtx ,
2016-03-14 17:24:33 -07:00
void * dst , size_t dstCapacity ,
2016-01-29 18:14:15 -08:00
const void * src , size_t srcSize )
{
2016-03-19 10:08:32 -07:00
{ 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 ;
2016-04-07 17:02:12 -07:00
2016-03-19 10:08:32 -07:00
{ size_t const endSize = ZSTD_compressEnd ( cctx , ( char * ) dst + cSize , dstCapacity - cSize ) ;
if ( ZSTD_isError ( endSize ) ) return endSize ;
return cSize + endSize ;
} }
2016-01-29 18:14:15 -08:00
}
2016-03-30 07:50:44 -07:00
static size_t ZSTD_compress_internal ( ZSTD_CCtx * ctx ,
2016-03-14 17:24:33 -07:00
void * dst , size_t dstCapacity ,
2015-11-25 05:42:45 -08:00
const void * src , size_t srcSize ,
2015-12-17 16:26:48 -08:00
const void * dict , size_t dictSize ,
2015-11-25 05:42:45 -08:00
ZSTD_parameters params )
2015-10-22 07:31:46 -07:00
{
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * op = ostart ;
2016-01-26 07:31:22 -08:00
/* Init */
2016-04-01 06:48:48 -07:00
{ size_t const errorCode = ZSTD_compressBegin_internal ( ctx , dict , dictSize , params , srcSize ) ;
2016-03-23 14:31:57 -07:00
if ( ZSTD_isError ( errorCode ) ) return errorCode ; }
2015-10-22 07:31:46 -07:00
/* body (compression) */
2016-03-14 17:24:33 -07:00
{ size_t const oSize = ZSTD_compressContinue ( ctx , op , dstCapacity , src , srcSize ) ;
2016-03-23 14:31:57 -07:00
if ( ZSTD_isError ( oSize ) ) return oSize ;
op + = oSize ;
dstCapacity - = oSize ; }
2015-10-22 07:31:46 -07:00
/* Close frame */
2016-03-14 17:24:33 -07:00
{ size_t const oSize = ZSTD_compressEnd ( ctx , op , dstCapacity ) ;
2016-03-23 14:31:57 -07:00
if ( ZSTD_isError ( oSize ) ) return oSize ;
op + = oSize ; }
2015-10-22 07:31:46 -07:00
return ( op - ostart ) ;
}
2016-03-30 07:50:44 -07:00
size_t ZSTD_compress_advanced ( ZSTD_CCtx * ctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const void * dict , size_t dictSize ,
ZSTD_parameters params )
{
2016-03-30 10:48:05 -07:00
size_t const errorCode = ZSTD_checkCParams_advanced ( params . cParams , srcSize ) ;
2016-03-30 07:50:44 -07:00
if ( ZSTD_isError ( errorCode ) ) return errorCode ;
return ZSTD_compress_internal ( ctx , dst , dstCapacity , src , srcSize , dict , dictSize , params ) ;
}
2016-03-14 17:24:33 -07:00
size_t ZSTD_compress_usingDict ( ZSTD_CCtx * ctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize , const void * dict , size_t dictSize , int compressionLevel )
2015-12-17 16:26:48 -08:00
{
2016-03-30 10:48:05 -07:00
ZSTD_parameters params ;
2016-05-28 20:01:04 -07:00
memset ( & params , 0 , sizeof ( params ) ) ;
2016-03-01 05:14:35 -08:00
ZSTD_LOG_BLOCK ( " %p: ZSTD_compress_usingDict srcSize=%d dictSize=%d compressionLevel=%d \n " , ctx - > base , ( int ) srcSize , ( int ) dictSize , compressionLevel ) ;
2016-03-30 10:48:05 -07:00
params . cParams = ZSTD_getCParams ( compressionLevel , srcSize , dictSize ) ;
params . fParams . contentSizeFlag = 1 ;
2016-03-30 07:50:44 -07:00
return ZSTD_compress_internal ( ctx , dst , dstCapacity , src , srcSize , dict , dictSize , params ) ;
2015-12-17 16:26:48 -08:00
}
2016-03-14 17:24:33 -07:00
size_t ZSTD_compressCCtx ( ZSTD_CCtx * ctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize , int compressionLevel )
2015-10-25 06:06:35 -07:00
{
2016-03-01 05:14:35 -08:00
ZSTD_LOG_BLOCK ( " %p: ZSTD_compressCCtx srcSize=%d compressionLevel=%d \n " , ctx - > base , ( int ) srcSize , compressionLevel ) ;
2016-03-30 07:50:44 -07:00
return ZSTD_compress_usingDict ( ctx , dst , dstCapacity , src , srcSize , NULL , 0 , compressionLevel ) ;
2015-10-25 06:06:35 -07:00
}
2016-03-14 17:24:33 -07:00
size_t ZSTD_compress ( void * dst , size_t dstCapacity , const void * src , size_t srcSize , int compressionLevel )
2015-10-22 07:31:46 -07:00
{
2015-10-29 14:02:40 -07:00
size_t result ;
2015-11-11 04:43:58 -08:00
ZSTD_CCtx ctxBody ;
2015-10-29 10:41:45 -07:00
memset ( & ctxBody , 0 , sizeof ( ctxBody ) ) ;
2016-06-02 04:04:18 -07:00
memcpy ( & ctxBody . customMem , & defaultCustomMem , sizeof ( ZSTD_customMem ) ) ;
2016-03-14 17:24:33 -07:00
result = ZSTD_compressCCtx ( & ctxBody , dst , dstCapacity , src , srcSize , compressionLevel ) ;
2016-06-02 04:04:18 -07:00
ctxBody . customMem . customFree ( ctxBody . customMem . opaque , ctxBody . workSpace ) ; /* can't free ctxBody, since it's on stack; just free heap content */
2015-10-29 14:02:40 -07:00
return result ;
2015-10-22 07:31:46 -07:00
}
2015-12-17 14:50:15 -08:00
2016-01-29 18:14:15 -08:00
2016-06-06 15:51:51 -07:00
/* ===== Dictionary API ===== */
struct ZSTD_CDict_s {
void * dictContent ;
size_t dictContentSize ;
ZSTD_CCtx * refContext ;
} ; /* typedef'd tp ZSTD_CDict within zstd.h */
ZSTD_CDict * ZSTD_createCDict_advanced ( const void * dict , size_t dictSize , ZSTD_parameters params , ZSTD_customMem customMem )
{
if ( ! customMem . customAlloc & & ! customMem . customFree )
customMem = defaultCustomMem ;
if ( ! customMem . customAlloc | | ! customMem . customFree )
return NULL ;
{ ZSTD_CDict * const cdict = ( ZSTD_CDict * ) customMem . customAlloc ( customMem . opaque , sizeof ( * cdict ) ) ;
void * const dictContent = customMem . customAlloc ( customMem . opaque , dictSize ) ;
ZSTD_CCtx * const cctx = ZSTD_createCCtx_advanced ( customMem ) ;
if ( ! dictContent | | ! cdict | | ! cctx ) {
customMem . customFree ( customMem . opaque , dictContent ) ;
customMem . customFree ( customMem . opaque , cdict ) ;
customMem . customFree ( customMem . opaque , cctx ) ;
return NULL ;
}
memcpy ( dictContent , dict , dictSize ) ;
{ size_t const errorCode = ZSTD_compressBegin_advanced ( cctx , dictContent , dictSize , params , 0 ) ;
if ( ZSTD_isError ( errorCode ) ) {
customMem . customFree ( customMem . opaque , dictContent ) ;
customMem . customFree ( customMem . opaque , cdict ) ;
customMem . customFree ( customMem . opaque , cctx ) ;
return NULL ;
} }
cdict - > dictContent = dictContent ;
cdict - > dictContentSize = dictSize ;
cdict - > refContext = cctx ;
return cdict ;
}
}
ZSTD_CDict * ZSTD_createCDict ( const void * dict , size_t dictSize , int compressionLevel )
{
ZSTD_customMem const allocator = { NULL , NULL , NULL } ;
ZSTD_parameters params ;
memset ( & params , 0 , sizeof ( params ) ) ;
params . cParams = ZSTD_getCParams ( compressionLevel , 0 , dictSize ) ;
params . fParams . contentSizeFlag = 1 ;
return ZSTD_createCDict_advanced ( dict , dictSize , params , allocator ) ;
}
size_t ZSTD_freeCDict ( ZSTD_CDict * cdict )
{
ZSTD_freeFunction const cFree = cdict - > refContext - > customMem . customFree ;
void * const opaque = cdict - > refContext - > customMem . opaque ;
ZSTD_freeCCtx ( cdict - > refContext ) ;
cFree ( opaque , cdict - > dictContent ) ;
cFree ( opaque , cdict ) ;
return 0 ;
}
ZSTDLIB_API size_t ZSTD_compress_usingCDict ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const ZSTD_CDict * cdict )
{
return ZSTD_compress_usingPreparedCCtx ( cctx , cdict - > refContext ,
dst , dstCapacity ,
src , srcSize ) ;
}
2016-02-10 04:37:52 -08:00
/*-===== Pre-defined compression levels =====-*/
2016-01-29 18:14:15 -08:00
2016-05-18 03:06:33 -07:00
# define ZSTD_DEFAULT_CLEVEL 1
2016-04-15 04:44:46 -07:00
# define ZSTD_MAX_CLEVEL 22
2016-02-02 17:11:32 -08:00
unsigned ZSTD_maxCLevel ( void ) { return ZSTD_MAX_CLEVEL ; }
2016-03-30 10:48:05 -07:00
static const ZSTD_compressionParameters ZSTD_defaultCParameters [ 4 ] [ ZSTD_MAX_CLEVEL + 1 ] = {
2016-01-29 18:14:15 -08:00
{ /* "default" */
2016-04-09 11:32:00 -07:00
/* W, C, H, S, L, TL, strat */
2016-03-30 10:48:05 -07:00
{ 0 , 0 , 0 , 0 , 0 , 0 , ZSTD_fast } , /* level 0 - never used */
{ 19 , 13 , 14 , 1 , 7 , 4 , ZSTD_fast } , /* level 1 */
{ 19 , 15 , 16 , 1 , 6 , 4 , ZSTD_fast } , /* level 2 */
{ 20 , 18 , 20 , 1 , 6 , 4 , ZSTD_fast } , /* level 3 */
{ 20 , 13 , 17 , 2 , 5 , 4 , ZSTD_greedy } , /* level 4.*/
{ 20 , 15 , 18 , 3 , 5 , 4 , ZSTD_greedy } , /* level 5 */
{ 21 , 16 , 19 , 2 , 5 , 4 , ZSTD_lazy } , /* level 6 */
{ 21 , 17 , 20 , 3 , 5 , 4 , ZSTD_lazy } , /* level 7 */
{ 21 , 18 , 20 , 3 , 5 , 4 , ZSTD_lazy2 } , /* level 8.*/
{ 21 , 20 , 20 , 3 , 5 , 4 , ZSTD_lazy2 } , /* level 9 */
{ 21 , 19 , 21 , 4 , 5 , 4 , ZSTD_lazy2 } , /* level 10 */
{ 22 , 20 , 22 , 4 , 5 , 4 , ZSTD_lazy2 } , /* level 11 */
{ 22 , 20 , 22 , 5 , 5 , 4 , ZSTD_lazy2 } , /* level 12 */
{ 22 , 21 , 22 , 5 , 5 , 4 , ZSTD_lazy2 } , /* level 13 */
{ 22 , 21 , 22 , 6 , 5 , 4 , ZSTD_lazy2 } , /* level 14 */
{ 22 , 21 , 21 , 5 , 5 , 4 , ZSTD_btlazy2 } , /* level 15 */
{ 23 , 22 , 22 , 5 , 5 , 4 , ZSTD_btlazy2 } , /* level 16 */
2016-04-09 11:32:00 -07:00
{ 23 , 23 , 22 , 5 , 5 , 4 , ZSTD_btlazy2 } , /* level 17.*/
{ 23 , 23 , 22 , 6 , 5 , 24 , ZSTD_btopt } , /* level 18.*/
{ 23 , 23 , 22 , 6 , 3 , 48 , ZSTD_btopt } , /* level 19.*/
{ 25 , 26 , 23 , 7 , 3 , 64 , ZSTD_btopt } , /* level 20.*/
{ 26 , 26 , 23 , 7 , 3 , 256 , ZSTD_btopt } , /* level 21.*/
{ 27 , 27 , 25 , 9 , 3 , 512 , ZSTD_btopt } , /* level 22.*/
2016-01-29 18:14:15 -08:00
} ,
{ /* for srcSize <= 256 KB */
2016-03-30 10:48:05 -07:00
/* W, C, H, S, L, T, strat */
{ 0 , 0 , 0 , 0 , 0 , 0 , ZSTD_fast } , /* level 0 */
2016-04-07 17:02:12 -07:00
{ 18 , 13 , 14 , 1 , 6 , 4 , ZSTD_fast } , /* level 1 */
2016-04-08 03:36:19 -07:00
{ 18 , 15 , 17 , 1 , 5 , 4 , ZSTD_fast } , /* level 2 */
{ 18 , 13 , 15 , 1 , 5 , 4 , ZSTD_greedy } , /* level 3.*/
{ 18 , 15 , 17 , 1 , 5 , 4 , ZSTD_greedy } , /* level 4.*/
{ 18 , 16 , 17 , 4 , 5 , 4 , ZSTD_greedy } , /* level 5 */
{ 18 , 17 , 17 , 5 , 5 , 4 , ZSTD_greedy } , /* level 6 */
2016-03-30 10:48:05 -07:00
{ 18 , 17 , 17 , 4 , 4 , 4 , ZSTD_lazy } , /* level 7 */
{ 18 , 17 , 17 , 4 , 4 , 4 , ZSTD_lazy2 } , /* level 8 */
{ 18 , 17 , 17 , 5 , 4 , 4 , ZSTD_lazy2 } , /* level 9 */
{ 18 , 17 , 17 , 6 , 4 , 4 , ZSTD_lazy2 } , /* level 10 */
2016-04-08 03:36:19 -07:00
{ 18 , 18 , 17 , 6 , 4 , 4 , ZSTD_lazy2 } , /* level 11.*/
{ 18 , 18 , 17 , 7 , 4 , 4 , ZSTD_lazy2 } , /* level 12.*/
{ 18 , 19 , 17 , 7 , 4 , 4 , ZSTD_btlazy2 } , /* level 13 */
{ 18 , 18 , 18 , 4 , 4 , 16 , ZSTD_btopt } , /* level 14.*/
{ 18 , 18 , 18 , 8 , 4 , 24 , ZSTD_btopt } , /* level 15.*/
{ 18 , 19 , 18 , 8 , 3 , 48 , ZSTD_btopt } , /* level 16.*/
{ 18 , 19 , 18 , 8 , 3 , 96 , ZSTD_btopt } , /* level 17.*/
{ 18 , 19 , 18 , 9 , 3 , 128 , ZSTD_btopt } , /* level 18.*/
{ 18 , 19 , 18 , 10 , 3 , 256 , ZSTD_btopt } , /* level 19.*/
{ 18 , 19 , 18 , 11 , 3 , 512 , ZSTD_btopt } , /* level 20.*/
{ 18 , 19 , 18 , 12 , 3 , 512 , ZSTD_btopt } , /* level 21.*/
{ 18 , 19 , 18 , 13 , 3 , 512 , ZSTD_btopt } , /* level 22.*/
2016-01-29 18:14:15 -08:00
} ,
{ /* for srcSize <= 128 KB */
2016-03-30 10:48:05 -07:00
/* W, C, H, S, L, T, strat */
{ 0 , 0 , 0 , 0 , 0 , 0 , ZSTD_fast } , /* level 0 - never 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 , 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.*/
{ 17 , 18 , 17 , 7 , 3 , 64 , ZSTD_btopt } , /* level 17.*/
{ 17 , 18 , 17 , 7 , 3 , 256 , ZSTD_btopt } , /* level 18.*/
{ 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.*/
2016-01-29 18:14:15 -08:00
} ,
{ /* for srcSize <= 16 KB */
2016-03-30 10:48:05 -07:00
/* W, C, H, S, L, T, strat */
{ 0 , 0 , 0 , 0 , 0 , 0 , ZSTD_fast } , /* level 0 -- never used */
{ 14 , 14 , 14 , 1 , 4 , 4 , ZSTD_fast } , /* level 1 */
{ 14 , 14 , 15 , 1 , 4 , 4 , ZSTD_fast } , /* level 2 */
{ 14 , 14 , 14 , 4 , 4 , 4 , ZSTD_greedy } , /* level 3.*/
{ 14 , 14 , 14 , 3 , 4 , 4 , ZSTD_lazy } , /* level 4.*/
{ 14 , 14 , 14 , 4 , 4 , 4 , ZSTD_lazy2 } , /* level 5 */
{ 14 , 14 , 14 , 5 , 4 , 4 , ZSTD_lazy2 } , /* level 6 */
{ 14 , 14 , 14 , 6 , 4 , 4 , ZSTD_lazy2 } , /* level 7.*/
{ 14 , 14 , 14 , 7 , 4 , 4 , ZSTD_lazy2 } , /* level 8.*/
{ 14 , 15 , 14 , 6 , 4 , 4 , ZSTD_btlazy2 } , /* level 9.*/
{ 14 , 15 , 14 , 3 , 3 , 6 , ZSTD_btopt } , /* level 10.*/
{ 14 , 15 , 14 , 6 , 3 , 8 , ZSTD_btopt } , /* level 11.*/
{ 14 , 15 , 14 , 6 , 3 , 16 , ZSTD_btopt } , /* level 12.*/
{ 14 , 15 , 14 , 6 , 3 , 24 , ZSTD_btopt } , /* level 13.*/
{ 14 , 15 , 15 , 6 , 3 , 48 , ZSTD_btopt } , /* level 14.*/
{ 14 , 15 , 15 , 6 , 3 , 64 , ZSTD_btopt } , /* level 15.*/
{ 14 , 15 , 15 , 6 , 3 , 96 , ZSTD_btopt } , /* level 16.*/
{ 14 , 15 , 15 , 6 , 3 , 128 , ZSTD_btopt } , /* level 17.*/
{ 14 , 15 , 15 , 6 , 3 , 256 , ZSTD_btopt } , /* level 18.*/
{ 14 , 15 , 15 , 7 , 3 , 256 , ZSTD_btopt } , /* level 19.*/
{ 14 , 15 , 15 , 8 , 3 , 256 , ZSTD_btopt } , /* level 20.*/
{ 14 , 15 , 15 , 9 , 3 , 256 , ZSTD_btopt } , /* level 21.*/
{ 14 , 15 , 15 , 10 , 3 , 256 , ZSTD_btopt } , /* level 22.*/
2016-01-29 18:14:15 -08:00
} ,
} ;
2016-05-18 03:06:33 -07:00
/*! ZSTD_getCParams() :
* @ return ZSTD_compressionParameters structure for a selected compression level , ` srcSize ` and ` dictSize ` .
* Size values are optional , provide 0 if not known or unused */
2016-03-30 10:48:05 -07:00
ZSTD_compressionParameters ZSTD_getCParams ( int compressionLevel , U64 srcSize , size_t dictSize )
2016-01-29 18:14:15 -08:00
{
2016-04-03 19:22:53 -07:00
ZSTD_compressionParameters cp ;
2016-04-04 04:28:28 -07:00
size_t const addedSize = srcSize ? 0 : 500 ;
2016-04-03 19:22:53 -07:00
U64 const rSize = srcSize + dictSize ? srcSize + dictSize + addedSize : ( U64 ) - 1 ;
2016-03-30 10:48:05 -07:00
U32 const tableID = ( rSize < = 256 KB ) + ( rSize < = 128 KB ) + ( rSize < = 16 KB ) ; /* intentional underflow for srcSizeHint == 0 */
2016-05-18 03:06:33 -07:00
if ( compressionLevel < = 0 ) compressionLevel = ZSTD_DEFAULT_CLEVEL ; /* 0 == default; no negative compressionLevel yet */
2016-01-29 18:14:15 -08:00
if ( compressionLevel > ZSTD_MAX_CLEVEL ) compressionLevel = ZSTD_MAX_CLEVEL ;
2016-04-03 19:22:53 -07:00
cp = ZSTD_defaultCParameters [ tableID ] [ compressionLevel ] ;
2016-04-04 04:28:28 -07:00
if ( MEM_32bits ( ) ) { /* auto-correction, for 32-bits mode */
if ( cp . windowLog > ZSTD_WINDOWLOG_MAX ) cp . windowLog = ZSTD_WINDOWLOG_MAX ;
2016-04-04 04:49:18 -07:00
if ( cp . chainLog > ZSTD_CHAINLOG_MAX ) cp . chainLog = ZSTD_CHAINLOG_MAX ;
2016-04-04 04:28:28 -07:00
if ( cp . hashLog > ZSTD_HASHLOG_MAX ) cp . hashLog = ZSTD_HASHLOG_MAX ;
}
2016-06-01 09:45:34 -07:00
cp = ZSTD_adjustCParams ( cp , srcSize , dictSize ) ;
2016-04-03 19:22:53 -07:00
return cp ;
2016-01-29 18:14:15 -08:00
}