2017-08-27 12:05:17 +02:00
/*
2017-06-09 03:43:56 +02:00
* Copyright ( c ) 2016 - present , Yann Collet , Facebook , Inc .
* All rights reserved .
*
2017-08-27 12:05:17 +02:00
* This source code is licensed under both the BSD - style license ( found in the
* LICENSE file in the root directory of this source tree ) and the GPLv2 ( found
* in the COPYING file in the root directory of this source tree ) .
2017-10-26 22:41:47 +02:00
* You may select , at your option , one of the above - listed licenses .
2017-06-09 03:43:56 +02:00
*/
2017-07-22 23:46:05 +02:00
/*-*************************************
* Tuning parameters
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef ZSTD_CLEVEL_DEFAULT
# define ZSTD_CLEVEL_DEFAULT 3
# endif
2017-06-09 03:43:56 +02:00
/*-*************************************
* Dependencies
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <string.h> /* memset */
# include "mem.h"
# define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
# include "fse.h"
# define HUF_STATIC_LINKING_ONLY
# include "huf.h"
2018-01-13 13:50:59 +01:00
# include "zstd_compress_internal.h"
2017-10-26 22:41:47 +02:00
# include "zstd_fast.h"
# include "zstd_double_fast.h"
# include "zstd_lazy.h"
# include "zstd_opt.h"
# include "zstd_ldm.h"
2017-06-09 03:43:56 +02:00
/*-*************************************
* Helper functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t ZSTD_compressBound ( size_t srcSize ) {
2017-10-26 22:41:47 +02:00
return ZSTD_COMPRESSBOUND ( srcSize ) ;
2017-06-09 03:43:56 +02:00
}
/*-*************************************
* Context memory management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-07-22 23:46:05 +02:00
struct ZSTD_CDict_s {
void * dictBuffer ;
const void * dictContent ;
size_t dictContentSize ;
ZSTD_CCtx * refContext ;
} ; /* typedef'd to ZSTD_CDict within "zstd.h" */
2017-06-09 03:43:56 +02:00
ZSTD_CCtx * ZSTD_createCCtx ( void )
{
2017-07-22 23:46:05 +02:00
return ZSTD_createCCtx_advanced ( ZSTD_defaultCMem ) ;
2017-06-09 03:43:56 +02:00
}
ZSTD_CCtx * ZSTD_createCCtx_advanced ( ZSTD_customMem customMem )
{
ZSTD_CCtx * cctx ;
2017-07-22 23:46:05 +02:00
if ( ! customMem . customAlloc ^ ! customMem . customFree ) return NULL ;
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
cctx = ( ZSTD_CCtx * ) ZSTD_calloc ( sizeof ( ZSTD_CCtx ) , customMem ) ;
2017-06-09 03:43:56 +02:00
if ( ! cctx ) return NULL ;
cctx - > customMem = customMem ;
2017-10-26 22:41:47 +02:00
cctx - > requestedParams . compressionLevel = ZSTD_CLEVEL_DEFAULT ;
2018-01-13 13:50:59 +01:00
cctx - > requestedParams . fParams . contentSizeFlag = 1 ;
2017-07-22 23:46:05 +02:00
ZSTD_STATIC_ASSERT ( zcss_init = = 0 ) ;
ZSTD_STATIC_ASSERT ( ZSTD_CONTENTSIZE_UNKNOWN = = ( 0ULL - 1 ) ) ;
return cctx ;
}
ZSTD_CCtx * ZSTD_initStaticCCtx ( void * workspace , size_t workspaceSize )
{
2017-10-26 22:41:47 +02:00
ZSTD_CCtx * const cctx = ( ZSTD_CCtx * ) workspace ;
2017-07-22 23:46:05 +02:00
if ( workspaceSize < = sizeof ( ZSTD_CCtx ) ) return NULL ; /* minimum size */
if ( ( size_t ) workspace & 7 ) return NULL ; /* must be 8-aligned */
memset ( workspace , 0 , workspaceSize ) ; /* may be a bit generous, could memset be smaller ? */
cctx - > staticSize = workspaceSize ;
cctx - > workSpace = ( void * ) ( cctx + 1 ) ;
cctx - > workSpaceSize = workspaceSize - sizeof ( ZSTD_CCtx ) ;
/* entropy space (never moves) */
2017-08-27 12:05:17 +02:00
if ( cctx - > workSpaceSize < sizeof ( ZSTD_entropyCTables_t ) ) return NULL ;
2017-10-26 22:41:47 +02:00
assert ( ( ( size_t ) cctx - > workSpace & ( sizeof ( void * ) - 1 ) ) = = 0 ) ; /* ensure correct alignment */
2017-08-27 12:05:17 +02:00
cctx - > entropy = ( ZSTD_entropyCTables_t * ) cctx - > workSpace ;
2017-07-22 23:46:05 +02:00
2017-06-09 03:43:56 +02:00
return cctx ;
}
size_t ZSTD_freeCCtx ( ZSTD_CCtx * cctx )
{
if ( cctx = = NULL ) return 0 ; /* support free on NULL */
2017-07-22 23:46:05 +02:00
if ( cctx - > staticSize ) return ERROR ( memory_allocation ) ; /* not compatible with static CCtx */
2017-06-09 03:43:56 +02:00
ZSTD_free ( cctx - > workSpace , cctx - > customMem ) ;
2017-07-22 23:46:05 +02:00
cctx - > workSpace = NULL ;
ZSTD_freeCDict ( cctx - > cdictLocal ) ;
cctx - > cdictLocal = NULL ;
2017-10-26 22:41:47 +02:00
# ifdef ZSTD_MULTITHREAD
2017-07-22 23:46:05 +02:00
ZSTDMT_freeCCtx ( cctx - > mtctx ) ;
cctx - > mtctx = NULL ;
2017-10-26 22:41:47 +02:00
# endif
2017-06-09 03:43:56 +02:00
ZSTD_free ( cctx , cctx - > customMem ) ;
return 0 ; /* reserved as a potential error code in the future */
}
2017-10-26 22:41:47 +02:00
static size_t ZSTD_sizeof_mtctx ( const ZSTD_CCtx * cctx )
{
# ifdef ZSTD_MULTITHREAD
return ZSTDMT_sizeof_CCtx ( cctx - > mtctx ) ;
# else
( void ) cctx ;
return 0 ;
# endif
}
2017-06-09 03:43:56 +02:00
size_t ZSTD_sizeof_CCtx ( const ZSTD_CCtx * cctx )
{
if ( cctx = = NULL ) return 0 ; /* support sizeof on NULL */
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 3 , " sizeof(*cctx) : %u " , ( U32 ) sizeof ( * cctx ) ) ;
DEBUGLOG ( 3 , " workSpaceSize (including streaming buffers): %u " , ( U32 ) cctx - > workSpaceSize ) ;
DEBUGLOG ( 3 , " inner cdict : %u " , ( U32 ) ZSTD_sizeof_CDict ( cctx - > cdictLocal ) ) ;
DEBUGLOG ( 3 , " inner MTCTX : %u " , ( U32 ) ZSTD_sizeof_mtctx ( cctx ) ) ;
2017-07-22 23:46:05 +02:00
return sizeof ( * cctx ) + cctx - > workSpaceSize
+ ZSTD_sizeof_CDict ( cctx - > cdictLocal )
2017-10-26 22:41:47 +02:00
+ ZSTD_sizeof_mtctx ( cctx ) ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
size_t ZSTD_sizeof_CStream ( const ZSTD_CStream * zcs )
{
return ZSTD_sizeof_CCtx ( zcs ) ; /* same object */
}
/* private API call, for dictBuilder only */
const seqStore_t * ZSTD_getSeqStore ( const ZSTD_CCtx * ctx ) { return & ( ctx - > seqStore ) ; }
2017-10-26 22:41:47 +02:00
# define ZSTD_CLEVEL_CUSTOM 999
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams (
2018-01-13 13:50:59 +01:00
ZSTD_CCtx_params CCtxParams , U64 srcSizeHint , size_t dictSize )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_getCParamsFromCCtxParams: srcSize = %u, dictSize = %u " ,
( U32 ) srcSizeHint , ( U32 ) dictSize ) ;
return ( CCtxParams . compressionLevel = = ZSTD_CLEVEL_CUSTOM ) ?
CCtxParams . cParams :
ZSTD_getCParams ( CCtxParams . compressionLevel , srcSizeHint , dictSize ) ;
2017-06-09 03:43:56 +02:00
}
2018-01-13 13:50:59 +01:00
static void ZSTD_cLevelToCCtxParams_srcSize ( ZSTD_CCtx_params * CCtxParams , U64 srcSize )
2017-10-26 22:41:47 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_cLevelToCCtxParams_srcSize: srcSize = %u " ,
( U32 ) srcSize ) ;
CCtxParams - > cParams = ZSTD_getCParamsFromCCtxParams ( * CCtxParams , srcSize , 0 ) ;
CCtxParams - > compressionLevel = ZSTD_CLEVEL_CUSTOM ;
2017-10-26 22:41:47 +02:00
}
2017-07-22 23:46:05 +02:00
static void ZSTD_cLevelToCParams ( ZSTD_CCtx * cctx )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_cLevelToCParams: level=%i " , cctx - > requestedParams . compressionLevel ) ;
2017-10-26 22:41:47 +02:00
ZSTD_cLevelToCCtxParams_srcSize (
& cctx - > requestedParams , cctx - > pledgedSrcSizePlusOne - 1 ) ;
}
2018-01-13 13:50:59 +01:00
static void ZSTD_cLevelToCCtxParams ( ZSTD_CCtx_params * CCtxParams )
2017-10-26 22:41:47 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_cLevelToCCtxParams " ) ;
ZSTD_cLevelToCCtxParams_srcSize ( CCtxParams , ZSTD_CONTENTSIZE_UNKNOWN ) ;
2017-10-26 22:41:47 +02:00
}
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams (
ZSTD_compressionParameters cParams )
{
ZSTD_CCtx_params cctxParams ;
memset ( & cctxParams , 0 , sizeof ( cctxParams ) ) ;
cctxParams . cParams = cParams ;
cctxParams . compressionLevel = ZSTD_CLEVEL_CUSTOM ;
return cctxParams ;
}
static ZSTD_CCtx_params * ZSTD_createCCtxParams_advanced (
ZSTD_customMem customMem )
{
ZSTD_CCtx_params * params ;
if ( ! customMem . customAlloc ^ ! customMem . customFree ) return NULL ;
params = ( ZSTD_CCtx_params * ) ZSTD_calloc (
sizeof ( ZSTD_CCtx_params ) , customMem ) ;
if ( ! params ) { return NULL ; }
params - > customMem = customMem ;
params - > compressionLevel = ZSTD_CLEVEL_DEFAULT ;
return params ;
}
ZSTD_CCtx_params * ZSTD_createCCtxParams ( void )
{
return ZSTD_createCCtxParams_advanced ( ZSTD_defaultCMem ) ;
}
size_t ZSTD_freeCCtxParams ( ZSTD_CCtx_params * params )
{
if ( params = = NULL ) { return 0 ; }
ZSTD_free ( params , params - > customMem ) ;
return 0 ;
}
size_t ZSTD_resetCCtxParams ( ZSTD_CCtx_params * params )
{
return ZSTD_initCCtxParams ( params , ZSTD_CLEVEL_DEFAULT ) ;
}
size_t ZSTD_initCCtxParams ( ZSTD_CCtx_params * cctxParams , int compressionLevel ) {
if ( ! cctxParams ) { return ERROR ( GENERIC ) ; }
memset ( cctxParams , 0 , sizeof ( * cctxParams ) ) ;
cctxParams - > compressionLevel = compressionLevel ;
return 0 ;
}
size_t ZSTD_initCCtxParams_advanced ( ZSTD_CCtx_params * cctxParams , ZSTD_parameters params )
{
if ( ! cctxParams ) { return ERROR ( GENERIC ) ; }
CHECK_F ( ZSTD_checkCParams ( params . cParams ) ) ;
memset ( cctxParams , 0 , sizeof ( * cctxParams ) ) ;
cctxParams - > cParams = params . cParams ;
cctxParams - > fParams = params . fParams ;
cctxParams - > compressionLevel = ZSTD_CLEVEL_CUSTOM ;
return 0 ;
}
static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams (
ZSTD_CCtx_params cctxParams , ZSTD_parameters params )
{
ZSTD_CCtx_params ret = cctxParams ;
ret . cParams = params . cParams ;
ret . fParams = params . fParams ;
ret . compressionLevel = ZSTD_CLEVEL_CUSTOM ;
return ret ;
2017-06-09 03:43:56 +02:00
}
2017-08-27 12:05:17 +02:00
# define CLAMPCHECK(val,min,max) { \
if ( ( ( val ) < ( min ) ) | ( ( val ) > ( max ) ) ) { \
return ERROR ( parameter_outOfBound ) ; \
2017-07-22 23:46:05 +02:00
} }
size_t ZSTD_CCtx_setParameter ( ZSTD_CCtx * cctx , ZSTD_cParameter param , unsigned value )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_CCtx_setParameter (%u, %u) " , ( U32 ) param , value ) ;
2017-07-22 23:46:05 +02:00
if ( cctx - > streamStage ! = zcss_init ) return ERROR ( stage_wrong ) ;
switch ( param )
{
2017-10-26 22:41:47 +02:00
case ZSTD_p_format :
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_compressionLevel :
2017-07-22 23:46:05 +02:00
if ( cctx - > cdict ) return ERROR ( stage_wrong ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_windowLog :
case ZSTD_p_hashLog :
case ZSTD_p_chainLog :
case ZSTD_p_searchLog :
case ZSTD_p_minMatch :
case ZSTD_p_targetLength :
case ZSTD_p_compressionStrategy :
if ( cctx - > cdict ) return ERROR ( stage_wrong ) ;
2018-01-13 13:50:59 +01:00
if ( value > 0 ) ZSTD_cLevelToCParams ( cctx ) ; /* Can optimize if srcSize is known */
2017-10-26 22:41:47 +02:00
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_contentSizeFlag :
case ZSTD_p_checksumFlag :
case ZSTD_p_dictIDFlag :
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
2018-01-13 13:50:59 +01:00
* even when referencing into Dictionary content .
2017-10-26 22:41:47 +02:00
* default : 0 when using a CDict , 1 when using a Prefix */
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_nbThreads :
2018-01-13 13:50:59 +01:00
if ( ( value > 1 ) & & cctx - > staticSize ) {
2017-10-26 22:41:47 +02:00
return ERROR ( parameter_unsupported ) ; /* MT not compatible with static alloc */
}
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_jobSize :
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_overlapSizeLog :
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_enableLongDistanceMatching :
if ( cctx - > cdict ) return ERROR ( stage_wrong ) ;
2018-01-13 13:50:59 +01:00
if ( value > 0 ) ZSTD_cLevelToCParams ( cctx ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_ldmHashLog :
case ZSTD_p_ldmMinMatch :
case ZSTD_p_ldmBucketSizeLog :
case ZSTD_p_ldmHashEveryLog :
if ( cctx - > cdict ) return ERROR ( stage_wrong ) ;
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
default : return ERROR ( parameter_unsupported ) ;
}
}
size_t ZSTD_CCtxParam_setParameter (
2018-01-13 13:50:59 +01:00
ZSTD_CCtx_params * CCtxParams , ZSTD_cParameter param , unsigned value )
2017-10-26 22:41:47 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_CCtxParam_setParameter (%u, %u) " , ( U32 ) param , value ) ;
2017-10-26 22:41:47 +02:00
switch ( param )
{
case ZSTD_p_format :
if ( value > ( unsigned ) ZSTD_f_zstd1_magicless )
return ERROR ( parameter_unsupported ) ;
2018-01-13 13:50:59 +01:00
CCtxParams - > format = ( ZSTD_format_e ) value ;
return ( size_t ) CCtxParams - > format ;
2017-10-26 22:41:47 +02:00
case ZSTD_p_compressionLevel :
if ( ( int ) value > ZSTD_maxCLevel ( ) ) value = ZSTD_maxCLevel ( ) ;
2018-01-13 13:50:59 +01:00
if ( value ) /* 0 : does not change current level */
CCtxParams - > compressionLevel = value ;
return CCtxParams - > compressionLevel ;
2017-10-26 22:41:47 +02:00
case ZSTD_p_windowLog :
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_CCtxParam_setParameter: set windowLog=%u " , value ) ;
if ( value ) { /* 0 : does not change current windowLog */
CLAMPCHECK ( value , ZSTD_WINDOWLOG_MIN , ZSTD_WINDOWLOG_MAX ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . windowLog = value ;
}
return CCtxParams - > cParams . windowLog ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_hashLog :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current hashLog */
CLAMPCHECK ( value , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . hashLog = value ;
}
return CCtxParams - > cParams . hashLog ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_chainLog :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current chainLog */
CLAMPCHECK ( value , ZSTD_CHAINLOG_MIN , ZSTD_CHAINLOG_MAX ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . chainLog = value ;
}
return CCtxParams - > cParams . chainLog ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_searchLog :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current searchLog */
CLAMPCHECK ( value , ZSTD_SEARCHLOG_MIN , ZSTD_SEARCHLOG_MAX ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . searchLog = value ;
}
return value ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_minMatch :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current minMatch length */
CLAMPCHECK ( value , ZSTD_SEARCHLENGTH_MIN , ZSTD_SEARCHLENGTH_MAX ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . searchLength = value ;
}
return CCtxParams - > cParams . searchLength ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_targetLength :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current sufficient_len */
CLAMPCHECK ( value , ZSTD_TARGETLENGTH_MIN , ZSTD_TARGETLENGTH_MAX ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . targetLength = value ;
}
return CCtxParams - > cParams . targetLength ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_compressionStrategy :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change currentstrategy */
CLAMPCHECK ( value , ( unsigned ) ZSTD_fast , ( unsigned ) ZSTD_btultra ) ;
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . strategy = ( ZSTD_strategy ) value ;
}
return ( size_t ) CCtxParams - > cParams . strategy ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_contentSizeFlag :
/* Content size written in frame header _when known_ (default:1) */
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " set content size flag = %u " , ( value > 0 ) ) ;
CCtxParams - > fParams . contentSizeFlag = value > 0 ;
return CCtxParams - > fParams . contentSizeFlag ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_checksumFlag :
/* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
2018-01-13 13:50:59 +01:00
CCtxParams - > fParams . checksumFlag = value > 0 ;
return CCtxParams - > fParams . checksumFlag ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " set dictIDFlag = %u " , ( value > 0 ) ) ;
CCtxParams - > fParams . noDictIDFlag = ( value = = 0 ) ;
return ! CCtxParams - > fParams . noDictIDFlag ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_forceMaxWindow :
2018-01-13 13:50:59 +01:00
CCtxParams - > forceWindow = ( value > 0 ) ;
return CCtxParams - > forceWindow ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_nbThreads :
2018-01-13 13:50:59 +01:00
if ( value = = 0 ) return CCtxParams - > nbThreads ;
2017-10-26 22:41:47 +02:00
# ifndef ZSTD_MULTITHREAD
if ( value > 1 ) return ERROR ( parameter_unsupported ) ;
2018-01-13 13:50:59 +01:00
return 1 ;
2017-10-26 22:41:47 +02:00
# else
2018-01-13 13:50:59 +01:00
return ZSTDMT_CCtxParam_setNbThreads ( CCtxParams , value ) ;
2017-10-26 22:41:47 +02:00
# endif
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_jobSize :
# ifndef ZSTD_MULTITHREAD
return ERROR ( parameter_unsupported ) ;
# else
2018-01-13 13:50:59 +01:00
if ( CCtxParams - > nbThreads < = 1 ) return ERROR ( parameter_unsupported ) ;
return ZSTDMT_CCtxParam_setMTCtxParameter ( CCtxParams , ZSTDMT_p_jobSize , value ) ;
2017-10-26 22:41:47 +02:00
# endif
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_overlapSizeLog :
2017-07-22 23:46:05 +02:00
# ifndef ZSTD_MULTITHREAD
2017-10-26 22:41:47 +02:00
return ERROR ( parameter_unsupported ) ;
# else
2018-01-13 13:50:59 +01:00
if ( CCtxParams - > nbThreads < = 1 ) return ERROR ( parameter_unsupported ) ;
return ZSTDMT_CCtxParam_setMTCtxParameter ( CCtxParams , ZSTDMT_p_overlapSectionLog , value ) ;
2017-07-22 23:46:05 +02:00
# endif
2017-10-26 22:41:47 +02:00
case ZSTD_p_enableLongDistanceMatching :
2018-01-13 13:50:59 +01:00
if ( value ) {
ZSTD_cLevelToCCtxParams ( CCtxParams ) ;
CCtxParams - > cParams . windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG ;
2017-07-22 23:46:05 +02:00
}
2018-01-13 13:50:59 +01:00
return ZSTD_ldm_initializeParameters ( & CCtxParams - > ldmParams , value ) ;
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmHashLog :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current ldmHashLog */
CLAMPCHECK ( value , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
CCtxParams - > ldmParams . hashLog = value ;
}
return CCtxParams - > ldmParams . hashLog ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmMinMatch :
2018-01-13 13:50:59 +01:00
if ( value ) { /* 0 : does not change current ldmMinMatch */
CLAMPCHECK ( value , ZSTD_LDM_MINMATCH_MIN , ZSTD_LDM_MINMATCH_MAX ) ;
CCtxParams - > ldmParams . minMatchLength = value ;
}
return CCtxParams - > ldmParams . minMatchLength ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmBucketSizeLog :
if ( value > ZSTD_LDM_BUCKETSIZELOG_MAX ) {
return ERROR ( parameter_outOfBound ) ;
}
2018-01-13 13:50:59 +01:00
CCtxParams - > ldmParams . bucketSizeLog = value ;
return value ;
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmHashEveryLog :
if ( value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN ) {
return ERROR ( parameter_outOfBound ) ;
}
2018-01-13 13:50:59 +01:00
CCtxParams - > ldmParams . hashEveryLog = value ;
return value ;
2017-07-22 23:46:05 +02:00
2017-08-27 12:05:17 +02:00
default : return ERROR ( parameter_unsupported ) ;
2017-07-22 23:46:05 +02:00
}
}
2018-01-13 13:50:59 +01:00
/** ZSTD_CCtx_setParametersUsingCCtxParams() :
* just applies ` params ` into ` cctx `
* no action is performed , parameters are merely stored .
2017-10-26 22:41:47 +02:00
*/
size_t ZSTD_CCtx_setParametersUsingCCtxParams (
ZSTD_CCtx * cctx , const ZSTD_CCtx_params * params )
{
if ( cctx - > streamStage ! = zcss_init ) return ERROR ( stage_wrong ) ;
if ( cctx - > cdict ) return ERROR ( stage_wrong ) ;
2018-01-13 13:50:59 +01:00
cctx - > requestedParams = * params ;
2017-10-26 22:41:47 +02:00
return 0 ;
}
2017-07-22 23:46:05 +02:00
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize ( ZSTD_CCtx * cctx , unsigned long long pledgedSrcSize )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_CCtx_setPledgedSrcSize to %u bytes " , ( U32 ) pledgedSrcSize ) ;
2017-07-22 23:46:05 +02:00
if ( cctx - > streamStage ! = zcss_init ) return ERROR ( stage_wrong ) ;
cctx - > pledgedSrcSizePlusOne = pledgedSrcSize + 1 ;
return 0 ;
}
2017-10-26 22:41:47 +02:00
size_t ZSTD_CCtx_loadDictionary_advanced (
ZSTD_CCtx * cctx , const void * dict , size_t dictSize ,
ZSTD_dictLoadMethod_e dictLoadMethod , ZSTD_dictMode_e dictMode )
2017-07-22 23:46:05 +02:00
{
if ( cctx - > streamStage ! = zcss_init ) return ERROR ( stage_wrong ) ;
if ( cctx - > staticSize ) return ERROR ( memory_allocation ) ; /* no malloc for static CCtx */
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_CCtx_loadDictionary_advanced (size: %u) " , ( U32 ) dictSize ) ;
2017-07-22 23:46:05 +02:00
ZSTD_freeCDict ( cctx - > cdictLocal ) ; /* in case one already exists */
if ( dict = = NULL | | dictSize = = 0 ) { /* no dictionary mode */
cctx - > cdictLocal = NULL ;
cctx - > cdict = NULL ;
} else {
ZSTD_compressionParameters const cParams =
2018-01-13 13:50:59 +01:00
ZSTD_getCParamsFromCCtxParams ( cctx - > requestedParams , cctx - > pledgedSrcSizePlusOne - 1 , dictSize ) ;
2017-07-22 23:46:05 +02:00
cctx - > cdictLocal = ZSTD_createCDict_advanced (
dict , dictSize ,
2017-10-26 22:41:47 +02:00
dictLoadMethod , dictMode ,
2017-07-22 23:46:05 +02:00
cParams , cctx - > customMem ) ;
cctx - > cdict = cctx - > cdictLocal ;
if ( cctx - > cdictLocal = = NULL )
return ERROR ( memory_allocation ) ;
}
return 0 ;
}
2017-10-26 22:41:47 +02:00
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference (
ZSTD_CCtx * cctx , const void * dict , size_t dictSize )
{
return ZSTD_CCtx_loadDictionary_advanced (
cctx , dict , dictSize , ZSTD_dlm_byRef , ZSTD_dm_auto ) ;
}
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary ( ZSTD_CCtx * cctx , const void * dict , size_t dictSize )
{
return ZSTD_CCtx_loadDictionary_advanced (
cctx , dict , dictSize , ZSTD_dlm_byCopy , ZSTD_dm_auto ) ;
}
2017-07-22 23:46:05 +02:00
size_t ZSTD_CCtx_refCDict ( ZSTD_CCtx * cctx , const ZSTD_CDict * cdict )
{
if ( cctx - > streamStage ! = zcss_init ) return ERROR ( stage_wrong ) ;
cctx - > cdict = cdict ;
2017-10-26 22:41:47 +02:00
memset ( & cctx - > prefixDict , 0 , sizeof ( cctx - > prefixDict ) ) ; /* exclusive */
2017-07-22 23:46:05 +02:00
return 0 ;
}
size_t ZSTD_CCtx_refPrefix ( ZSTD_CCtx * cctx , const void * prefix , size_t prefixSize )
2017-10-26 22:41:47 +02:00
{
return ZSTD_CCtx_refPrefix_advanced ( cctx , prefix , prefixSize , ZSTD_dm_rawContent ) ;
}
size_t ZSTD_CCtx_refPrefix_advanced (
ZSTD_CCtx * cctx , const void * prefix , size_t prefixSize , ZSTD_dictMode_e dictMode )
2017-07-22 23:46:05 +02:00
{
if ( cctx - > streamStage ! = zcss_init ) return ERROR ( stage_wrong ) ;
cctx - > cdict = NULL ; /* prefix discards any prior cdict */
2017-10-26 22:41:47 +02:00
cctx - > prefixDict . dict = prefix ;
cctx - > prefixDict . dictSize = prefixSize ;
cctx - > prefixDict . dictMode = dictMode ;
2017-07-22 23:46:05 +02:00
return 0 ;
}
static void ZSTD_startNewCompression ( ZSTD_CCtx * cctx )
{
cctx - > streamStage = zcss_init ;
cctx - > pledgedSrcSizePlusOne = 0 ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
/*! ZSTD_CCtx_reset() :
* Also dumps dictionary */
void ZSTD_CCtx_reset ( ZSTD_CCtx * cctx )
{
ZSTD_startNewCompression ( cctx ) ;
cctx - > cdict = NULL ;
}
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
/** ZSTD_checkCParams() :
control CParam values remain within authorized range .
2017-06-09 03:43:56 +02:00
@ return : 0 , or an error code if one value is beyond authorized range */
size_t ZSTD_checkCParams ( ZSTD_compressionParameters cParams )
{
CLAMPCHECK ( cParams . windowLog , ZSTD_WINDOWLOG_MIN , ZSTD_WINDOWLOG_MAX ) ;
CLAMPCHECK ( cParams . chainLog , ZSTD_CHAINLOG_MIN , ZSTD_CHAINLOG_MAX ) ;
CLAMPCHECK ( cParams . hashLog , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
CLAMPCHECK ( cParams . searchLog , ZSTD_SEARCHLOG_MIN , ZSTD_SEARCHLOG_MAX ) ;
CLAMPCHECK ( cParams . searchLength , ZSTD_SEARCHLENGTH_MIN , ZSTD_SEARCHLENGTH_MAX ) ;
CLAMPCHECK ( cParams . targetLength , ZSTD_TARGETLENGTH_MIN , ZSTD_TARGETLENGTH_MAX ) ;
2017-08-27 12:05:17 +02:00
if ( ( U32 ) ( cParams . strategy ) > ( U32 ) ZSTD_btultra )
return ERROR ( parameter_unsupported ) ;
2017-06-09 03:43:56 +02:00
return 0 ;
}
2017-07-22 23:46:05 +02:00
/** ZSTD_clampCParams() :
* make CParam values within valid range .
* @ return : valid CParams */
static ZSTD_compressionParameters ZSTD_clampCParams ( ZSTD_compressionParameters cParams )
{
# define CLAMP(val,min,max) { \
if ( val < min ) val = min ; \
else if ( val > max ) val = max ; \
}
CLAMP ( cParams . windowLog , ZSTD_WINDOWLOG_MIN , ZSTD_WINDOWLOG_MAX ) ;
CLAMP ( cParams . chainLog , ZSTD_CHAINLOG_MIN , ZSTD_CHAINLOG_MAX ) ;
CLAMP ( cParams . hashLog , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
CLAMP ( cParams . searchLog , ZSTD_SEARCHLOG_MIN , ZSTD_SEARCHLOG_MAX ) ;
CLAMP ( cParams . searchLength , ZSTD_SEARCHLENGTH_MIN , ZSTD_SEARCHLENGTH_MAX ) ;
CLAMP ( cParams . targetLength , ZSTD_TARGETLENGTH_MIN , ZSTD_TARGETLENGTH_MAX ) ;
if ( ( U32 ) ( cParams . strategy ) > ( U32 ) ZSTD_btultra ) cParams . strategy = ZSTD_btultra ;
return cParams ;
}
2017-06-09 03:43:56 +02:00
/** ZSTD_cycleLog() :
* condition for correct operation : hashLog > 1 */
static U32 ZSTD_cycleLog ( U32 hashLog , ZSTD_strategy strat )
{
U32 const btScale = ( ( U32 ) strat > = ( U32 ) ZSTD_btlazy2 ) ;
return hashLog - btScale ;
}
2017-07-22 23:46:05 +02:00
/** ZSTD_adjustCParams_internal() :
2017-06-09 03:43:56 +02:00
optimize ` cPar ` for a given input ( ` srcSize ` and ` dictSize ` ) .
2017-10-26 22:41:47 +02:00
mostly downsizing to reduce memory consumption and initialization latency .
Both ` srcSize ` and ` dictSize ` are optional ( use 0 if unknown ) .
Note : cPar is considered validated at this stage . Use ZSTD_checkCParams ( ) to ensure that condition . */
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters ZSTD_adjustCParams_internal ( ZSTD_compressionParameters cPar , unsigned long long srcSize , size_t dictSize )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
static const U64 minSrcSize = 513 ; /* (1<<9) + 1 */
static const U64 maxWindowResize = 1ULL < < ( ZSTD_WINDOWLOG_MAX - 1 ) ;
2017-07-22 23:46:05 +02:00
assert ( ZSTD_checkCParams ( cPar ) = = 0 ) ;
2017-10-26 22:41:47 +02:00
if ( dictSize & & ( srcSize + 1 < 2 ) /* srcSize unknown */ )
srcSize = minSrcSize ; /* presumed small when there is a dictionary */
else if ( srcSize = = 0 )
srcSize = ZSTD_CONTENTSIZE_UNKNOWN ; /* 0 == unknown : presumed large */
/* resize windowLog if input is small enough, to use less memory */
if ( ( srcSize < maxWindowResize )
& & ( dictSize < maxWindowResize ) ) {
U32 const tSize = ( U32 ) ( srcSize + dictSize ) ;
static U32 const hashSizeMin = 1 < < ZSTD_HASHLOG_MIN ;
U32 const srcLog = ( tSize < hashSizeMin ) ? ZSTD_HASHLOG_MIN :
ZSTD_highbit32 ( tSize - 1 ) + 1 ;
if ( cPar . windowLog > srcLog ) cPar . windowLog = srcLog ;
}
2017-06-09 03:43:56 +02:00
if ( cPar . hashLog > cPar . windowLog ) cPar . hashLog = cPar . windowLog ;
{ U32 const cycleLog = ZSTD_cycleLog ( cPar . chainLog , cPar . strategy ) ;
2017-10-26 22:41:47 +02:00
if ( cycleLog > cPar . windowLog )
cPar . chainLog - = ( cycleLog - cPar . windowLog ) ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
if ( cPar . windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN )
cPar . windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN ; /* required for frame header */
2017-06-09 03:43:56 +02:00
return cPar ;
}
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters ZSTD_adjustCParams ( ZSTD_compressionParameters cPar , unsigned long long srcSize , size_t dictSize )
{
cPar = ZSTD_clampCParams ( cPar ) ;
return ZSTD_adjustCParams_internal ( cPar , srcSize , dictSize ) ;
}
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
size_t ZSTD_estimateCCtxSize_usingCCtxParams ( const ZSTD_CCtx_params * params )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
/* Estimate CCtx size is supported for single-threaded compression only. */
if ( params - > nbThreads > 1 ) { return ERROR ( GENERIC ) ; }
{ ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams ( * params , 0 , 0 ) ;
size_t const blockSize = MIN ( ZSTD_BLOCKSIZE_MAX , ( size_t ) 1 < < cParams . windowLog ) ;
U32 const divider = ( cParams . searchLength = = 3 ) ? 3 : 4 ;
size_t const maxNbSeq = blockSize / divider ;
size_t const tokenSpace = blockSize + 11 * maxNbSeq ;
size_t const chainSize =
( cParams . strategy = = ZSTD_fast ) ? 0 : ( ( size_t ) 1 < < cParams . chainLog ) ;
size_t const hSize = ( ( size_t ) 1 ) < < cParams . hashLog ;
U32 const hashLog3 = ( cParams . searchLength > 3 ) ?
0 : MIN ( ZSTD_HASHLOG3_MAX , cParams . windowLog ) ;
size_t const h3Size = ( ( size_t ) 1 ) < < hashLog3 ;
size_t const entropySpace = sizeof ( ZSTD_entropyCTables_t ) ;
size_t const tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
size_t const optBudget =
( ( MaxML + 1 ) + ( MaxLL + 1 ) + ( MaxOff + 1 ) + ( 1 < < Litbits ) ) * sizeof ( U32 )
+ ( ZSTD_OPT_NUM + 1 ) * ( sizeof ( ZSTD_match_t ) + sizeof ( ZSTD_optimal_t ) ) ;
size_t const optSpace = ( ( cParams . strategy = = ZSTD_btopt ) | | ( cParams . strategy = = ZSTD_btultra ) ) ? optBudget : 0 ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
size_t const ldmSpace = params - > ldmParams . enableLdm ?
ZSTD_ldm_getTableSize ( params - > ldmParams . hashLog ,
params - > ldmParams . bucketSizeLog ) : 0 ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
size_t const neededSpace = entropySpace + tableSpace + tokenSpace +
optSpace + ldmSpace ;
DEBUGLOG ( 5 , " sizeof(ZSTD_CCtx) : %u " , ( U32 ) sizeof ( ZSTD_CCtx ) ) ;
DEBUGLOG ( 5 , " estimate workSpace : %u " , ( U32 ) neededSpace ) ;
return sizeof ( ZSTD_CCtx ) + neededSpace ;
}
}
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
size_t ZSTD_estimateCCtxSize_usingCParams ( ZSTD_compressionParameters cParams )
{
ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams ( cParams ) ;
return ZSTD_estimateCCtxSize_usingCCtxParams ( & params ) ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
size_t ZSTD_estimateCCtxSize ( int compressionLevel )
{
ZSTD_compressionParameters const cParams = ZSTD_getCParams ( compressionLevel , 0 , 0 ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_estimateCCtxSize_usingCParams ( cParams ) ;
2017-07-22 23:46:05 +02:00
}
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
size_t ZSTD_estimateCStreamSize_usingCCtxParams ( const ZSTD_CCtx_params * params )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
if ( params - > nbThreads > 1 ) { return ERROR ( GENERIC ) ; }
{ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams ( params ) ;
size_t const blockSize = MIN ( ZSTD_BLOCKSIZE_MAX , ( size_t ) 1 < < params - > cParams . windowLog ) ;
size_t const inBuffSize = ( ( size_t ) 1 < < params - > cParams . windowLog ) + blockSize ;
size_t const outBuffSize = ZSTD_compressBound ( blockSize ) + 1 ;
size_t const streamingSize = inBuffSize + outBuffSize ;
return CCtxSize + streamingSize ;
}
}
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
size_t ZSTD_estimateCStreamSize_usingCParams ( ZSTD_compressionParameters cParams )
{
ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams ( cParams ) ;
return ZSTD_estimateCStreamSize_usingCCtxParams ( & params ) ;
2017-07-22 23:46:05 +02:00
}
size_t ZSTD_estimateCStreamSize ( int compressionLevel ) {
ZSTD_compressionParameters const cParams = ZSTD_getCParams ( compressionLevel , 0 , 0 ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_estimateCStreamSize_usingCParams ( cParams ) ;
2017-07-22 23:46:05 +02:00
}
2017-10-26 22:41:47 +02:00
static U32 ZSTD_equivalentCParams ( ZSTD_compressionParameters cParams1 ,
ZSTD_compressionParameters cParams2 )
2017-07-22 23:46:05 +02:00
{
2018-01-13 13:50:59 +01:00
return ( cParams1 . hashLog = = cParams2 . hashLog )
2017-07-22 23:46:05 +02:00
& ( cParams1 . chainLog = = cParams2 . chainLog )
& ( cParams1 . strategy = = cParams2 . strategy ) /* opt parser space */
& ( ( cParams1 . searchLength = = 3 ) = = ( cParams2 . searchLength = = 3 ) ) ; /* hashlog3 space */
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
/** The parameters are equivalent if ldm is not enabled in both sets or
* all the parameters are equivalent . */
static U32 ZSTD_equivalentLdmParams ( ldmParams_t ldmParams1 ,
ldmParams_t ldmParams2 )
{
return ( ! ldmParams1 . enableLdm & & ! ldmParams2 . enableLdm ) | |
( ldmParams1 . enableLdm = = ldmParams2 . enableLdm & &
ldmParams1 . hashLog = = ldmParams2 . hashLog & &
ldmParams1 . bucketSizeLog = = ldmParams2 . bucketSizeLog & &
ldmParams1 . minMatchLength = = ldmParams2 . minMatchLength & &
ldmParams1 . hashEveryLog = = ldmParams2 . hashEveryLog ) ;
}
2018-01-13 13:50:59 +01:00
typedef enum { ZSTDb_not_buffered , ZSTDb_buffered } ZSTD_buffered_policy_e ;
/* ZSTD_sufficientBuff() :
* check internal buffers exist for streaming if buffPol = = ZSTDb_buffered .
* Note : they are assumed to be correctly sized if ZSTD_equivalentCParams ( ) = = 1 */
static U32 ZSTD_sufficientBuff ( size_t bufferSize1 , size_t blockSize1 ,
ZSTD_buffered_policy_e buffPol2 ,
ZSTD_compressionParameters cParams2 ,
U64 pledgedSrcSize )
{
size_t const windowSize2 = MAX ( 1 , ( size_t ) MIN ( ( ( U64 ) 1 < < cParams2 . windowLog ) , pledgedSrcSize ) ) ;
size_t const blockSize2 = MIN ( ZSTD_BLOCKSIZE_MAX , windowSize2 ) ;
size_t const neededBufferSize2 = ( buffPol2 = = ZSTDb_buffered ) ? windowSize2 + blockSize2 : 0 ;
DEBUGLOG ( 4 , " ZSTD_sufficientBuff: windowSize2=%u from wlog=%u " ,
( U32 ) windowSize2 , cParams2 . windowLog ) ;
DEBUGLOG ( 4 , " ZSTD_sufficientBuff: blockSize2 %u <=? blockSize1 %u " ,
( U32 ) blockSize2 , ( U32 ) blockSize1 ) ;
return ( blockSize2 < = blockSize1 ) /* seqStore space depends on blockSize */
& ( neededBufferSize2 < = bufferSize1 ) ;
}
2017-10-26 22:41:47 +02:00
/** Equivalence for resetCCtx purposes */
static U32 ZSTD_equivalentParams ( ZSTD_CCtx_params params1 ,
2018-01-13 13:50:59 +01:00
ZSTD_CCtx_params params2 ,
size_t buffSize1 , size_t blockSize1 ,
ZSTD_buffered_policy_e buffPol2 ,
U64 pledgedSrcSize )
2017-10-26 22:41:47 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_equivalentParams: pledgedSrcSize=%u " , ( U32 ) pledgedSrcSize ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_equivalentCParams ( params1 . cParams , params2 . cParams ) & &
2018-01-13 13:50:59 +01:00
ZSTD_equivalentLdmParams ( params1 . ldmParams , params2 . ldmParams ) & &
ZSTD_sufficientBuff ( buffSize1 , blockSize1 , buffPol2 , params2 . cParams , pledgedSrcSize ) ;
2017-10-26 22:41:47 +02:00
}
2017-06-09 03:43:56 +02:00
/*! ZSTD_continueCCtx() :
2017-07-22 23:46:05 +02:00
* reuse CCtx without reset ( note : requires no dictionary ) */
2017-10-26 22:41:47 +02:00
static size_t ZSTD_continueCCtx ( ZSTD_CCtx * cctx , ZSTD_CCtx_params params , U64 pledgedSrcSize )
2017-06-09 03:43:56 +02:00
{
U32 const end = ( U32 ) ( cctx - > nextSrc - cctx - > base ) ;
2018-01-13 13:50:59 +01:00
size_t const windowSize = MAX ( 1 , ( size_t ) MIN ( ( ( U64 ) 1 < < params . cParams . windowLog ) , pledgedSrcSize ) ) ;
size_t const blockSize = MIN ( ZSTD_BLOCKSIZE_MAX , windowSize ) ;
DEBUGLOG ( 4 , " ZSTD_continueCCtx " ) ;
cctx - > blockSize = blockSize ; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
2017-07-22 23:46:05 +02:00
cctx - > appliedParams = params ;
cctx - > pledgedSrcSizePlusOne = pledgedSrcSize + 1 ;
2017-06-09 03:43:56 +02:00
cctx - > consumedSrcSize = 0 ;
2017-07-22 23:46:05 +02:00
if ( pledgedSrcSize = = ZSTD_CONTENTSIZE_UNKNOWN )
cctx - > appliedParams . fParams . contentSizeFlag = 0 ;
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 4 , " pledged content size : %u ; flag : %u " ,
2017-07-22 23:46:05 +02:00
( U32 ) pledgedSrcSize , cctx - > appliedParams . fParams . contentSizeFlag ) ;
2017-06-09 03:43:56 +02:00
cctx - > lowLimit = end ;
cctx - > dictLimit = end ;
cctx - > nextToUpdate = end + 1 ;
cctx - > stage = ZSTDcs_init ;
cctx - > dictID = 0 ;
cctx - > loadedDictEnd = 0 ;
2017-08-27 12:05:17 +02:00
{ int i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) cctx - > seqStore . rep [ i ] = repStartValue [ i ] ; }
cctx - > optState . litLengthSum = 0 ; /* force reset of btopt stats */
2017-06-09 03:43:56 +02:00
XXH64_reset ( & cctx - > xxhState , 0 ) ;
return 0 ;
}
2017-07-22 23:46:05 +02:00
typedef enum { ZSTDcrp_continue , ZSTDcrp_noMemset } ZSTD_compResetPolicy_e ;
2017-06-09 03:43:56 +02:00
/*! ZSTD_resetCCtx_internal() :
2017-07-22 23:46:05 +02:00
note : ` params ` are assumed fully validated at this stage */
static size_t ZSTD_resetCCtx_internal ( ZSTD_CCtx * zc ,
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params params , U64 pledgedSrcSize ,
2017-07-22 23:46:05 +02:00
ZSTD_compResetPolicy_e const crp ,
ZSTD_buffered_policy_e const zbuff )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u " ,
( U32 ) pledgedSrcSize , params . cParams . windowLog ) ;
2017-07-22 23:46:05 +02:00
assert ( ! ZSTD_isError ( ZSTD_checkCParams ( params . cParams ) ) ) ;
if ( crp = = ZSTDcrp_continue ) {
2018-01-13 13:50:59 +01:00
if ( ZSTD_equivalentParams ( zc - > appliedParams , params ,
zc - > inBuffSize , zc - > blockSize ,
zbuff , pledgedSrcSize ) ) {
DEBUGLOG ( 4 , " ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u) " ,
zc - > appliedParams . cParams . windowLog , ( U32 ) zc - > blockSize ) ;
2017-10-26 22:41:47 +02:00
assert ( ! ( params . ldmParams . enableLdm & &
params . ldmParams . hashEveryLog = = ZSTD_LDM_HASHEVERYLOG_NOTSET ) ) ;
2017-08-27 12:05:17 +02:00
zc - > entropy - > hufCTable_repeatMode = HUF_repeat_none ;
zc - > entropy - > offcode_repeatMode = FSE_repeat_none ;
zc - > entropy - > matchlength_repeatMode = FSE_repeat_none ;
zc - > entropy - > litlength_repeatMode = FSE_repeat_none ;
2017-07-22 23:46:05 +02:00
return ZSTD_continueCCtx ( zc , params , pledgedSrcSize ) ;
} }
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_equivalentParams()==0 -> reset CCtx " ) ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
if ( params . ldmParams . enableLdm ) {
/* Adjust long distance matching parameters */
ZSTD_ldm_adjustParameters ( & params . ldmParams , params . cParams . windowLog ) ;
assert ( params . ldmParams . hashLog > = params . ldmParams . bucketSizeLog ) ;
assert ( params . ldmParams . hashEveryLog < 32 ) ;
zc - > ldmState . hashPower =
ZSTD_ldm_getHashPower ( params . ldmParams . minMatchLength ) ;
}
2018-01-13 13:50:59 +01:00
{ size_t const windowSize = MAX ( 1 , ( size_t ) MIN ( ( ( U64 ) 1 < < params . cParams . windowLog ) , pledgedSrcSize ) ) ;
size_t const blockSize = MIN ( ZSTD_BLOCKSIZE_MAX , windowSize ) ;
2017-06-09 03:43:56 +02:00
U32 const divider = ( params . cParams . searchLength = = 3 ) ? 3 : 4 ;
size_t const maxNbSeq = blockSize / divider ;
size_t const tokenSpace = blockSize + 11 * maxNbSeq ;
2017-07-22 23:46:05 +02:00
size_t const chainSize = ( params . cParams . strategy = = ZSTD_fast ) ?
2017-10-26 22:41:47 +02:00
0 : ( ( size_t ) 1 < < params . cParams . chainLog ) ;
2017-06-09 03:43:56 +02:00
size_t const hSize = ( ( size_t ) 1 ) < < params . cParams . hashLog ;
2017-07-22 23:46:05 +02:00
U32 const hashLog3 = ( params . cParams . searchLength > 3 ) ?
0 : MIN ( ZSTD_HASHLOG3_MAX , params . cParams . windowLog ) ;
2017-06-09 03:43:56 +02:00
size_t const h3Size = ( ( size_t ) 1 ) < < hashLog3 ;
size_t const tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
2017-07-22 23:46:05 +02:00
size_t const buffOutSize = ( zbuff = = ZSTDb_buffered ) ? ZSTD_compressBound ( blockSize ) + 1 : 0 ;
2018-01-13 13:50:59 +01:00
size_t const buffInSize = ( zbuff = = ZSTDb_buffered ) ? windowSize + blockSize : 0 ;
2017-06-09 03:43:56 +02:00
void * ptr ;
/* Check if workSpace is large enough, alloc a new one if needed */
2017-08-27 12:05:17 +02:00
{ size_t const entropySpace = sizeof ( ZSTD_entropyCTables_t ) ;
2017-06-09 03:43:56 +02:00
size_t const optPotentialSpace = ( ( MaxML + 1 ) + ( MaxLL + 1 ) + ( MaxOff + 1 ) + ( 1 < < Litbits ) ) * sizeof ( U32 )
+ ( ZSTD_OPT_NUM + 1 ) * ( sizeof ( ZSTD_match_t ) + sizeof ( ZSTD_optimal_t ) ) ;
2017-07-22 23:46:05 +02:00
size_t const optSpace = ( ( params . cParams . strategy = = ZSTD_btopt )
| | ( params . cParams . strategy = = ZSTD_btultra ) ) ?
optPotentialSpace : 0 ;
size_t const bufferSpace = buffInSize + buffOutSize ;
2017-10-26 22:41:47 +02:00
size_t const ldmSpace = params . ldmParams . enableLdm
? ZSTD_ldm_getTableSize ( params . ldmParams . hashLog , params . ldmParams . bucketSizeLog )
: 0 ;
size_t const neededSpace = entropySpace + optSpace + ldmSpace +
tableSpace + tokenSpace + bufferSpace ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " Need %uKB workspace, including %uKB for tables, and %uKB for buffers " ,
( U32 ) ( neededSpace > > 10 ) , ( U32 ) ( tableSpace > > 10 ) , ( U32 ) ( bufferSpace > > 10 ) ) ;
DEBUGLOG ( 4 , " chainSize: %u - hSize: %u - h3Size: %u - windowSize: %u - blockSize: %u " ,
( U32 ) chainSize , ( U32 ) hSize , ( U32 ) h3Size , ( U32 ) windowSize , ( U32 ) blockSize ) ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
if ( zc - > workSpaceSize < neededSpace ) { /* too small : resize */
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " Need to update workSpaceSize from %uK to %uK " ,
( unsigned ) ( zc - > workSpaceSize > > 10 ) ,
( unsigned ) ( neededSpace > > 10 ) ) ;
2017-07-22 23:46:05 +02:00
/* static cctx : no resize, error out */
if ( zc - > staticSize ) return ERROR ( memory_allocation ) ;
2017-06-09 03:43:56 +02:00
zc - > workSpaceSize = 0 ;
ZSTD_free ( zc - > workSpace , zc - > customMem ) ;
zc - > workSpace = ZSTD_malloc ( neededSpace , zc - > customMem ) ;
if ( zc - > workSpace = = NULL ) return ERROR ( memory_allocation ) ;
zc - > workSpaceSize = neededSpace ;
ptr = zc - > workSpace ;
/* entropy space */
2017-08-27 12:05:17 +02:00
assert ( ( ( size_t ) zc - > workSpace & 3 ) = = 0 ) ; /* ensure correct alignment */
assert ( zc - > workSpaceSize > = sizeof ( ZSTD_entropyCTables_t ) ) ;
zc - > entropy = ( ZSTD_entropyCTables_t * ) zc - > workSpace ;
2017-06-09 03:43:56 +02:00
} }
/* init params */
2017-07-22 23:46:05 +02:00
zc - > appliedParams = params ;
zc - > pledgedSrcSizePlusOne = pledgedSrcSize + 1 ;
2017-06-09 03:43:56 +02:00
zc - > consumedSrcSize = 0 ;
2017-07-22 23:46:05 +02:00
if ( pledgedSrcSize = = ZSTD_CONTENTSIZE_UNKNOWN )
zc - > appliedParams . fParams . contentSizeFlag = 0 ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " pledged content size : %u ; flag : %u " ,
2017-07-22 23:46:05 +02:00
( U32 ) pledgedSrcSize , zc - > appliedParams . fParams . contentSizeFlag ) ;
zc - > blockSize = blockSize ;
2017-06-09 03:43:56 +02:00
XXH64_reset ( & zc - > xxhState , 0 ) ;
zc - > stage = ZSTDcs_init ;
zc - > dictID = 0 ;
zc - > loadedDictEnd = 0 ;
2017-08-27 12:05:17 +02:00
zc - > entropy - > hufCTable_repeatMode = HUF_repeat_none ;
zc - > entropy - > offcode_repeatMode = FSE_repeat_none ;
zc - > entropy - > matchlength_repeatMode = FSE_repeat_none ;
zc - > entropy - > litlength_repeatMode = FSE_repeat_none ;
2017-06-09 03:43:56 +02:00
zc - > nextToUpdate = 1 ;
zc - > nextSrc = NULL ;
zc - > base = NULL ;
zc - > dictBase = NULL ;
zc - > dictLimit = 0 ;
zc - > lowLimit = 0 ;
2017-08-27 12:05:17 +02:00
{ int i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) zc - > seqStore . rep [ i ] = repStartValue [ i ] ; }
2017-06-09 03:43:56 +02:00
zc - > hashLog3 = hashLog3 ;
2017-08-27 12:05:17 +02:00
zc - > optState . litLengthSum = 0 ;
2017-06-09 03:43:56 +02:00
2017-08-27 12:05:17 +02:00
ptr = zc - > entropy + 1 ;
2017-06-09 03:43:56 +02:00
/* opt parser space */
2017-07-22 23:46:05 +02:00
if ( ( params . cParams . strategy = = ZSTD_btopt ) | | ( params . cParams . strategy = = ZSTD_btultra ) ) {
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " reserving optimal parser space " ) ;
2017-06-09 03:43:56 +02:00
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ; /* ensure ptr is properly aligned */
2017-08-27 12:05:17 +02:00
zc - > optState . litFreq = ( U32 * ) ptr ;
zc - > optState . litLengthFreq = zc - > optState . litFreq + ( 1 < < Litbits ) ;
zc - > optState . matchLengthFreq = zc - > optState . litLengthFreq + ( MaxLL + 1 ) ;
zc - > optState . offCodeFreq = zc - > optState . matchLengthFreq + ( MaxML + 1 ) ;
ptr = zc - > optState . offCodeFreq + ( MaxOff + 1 ) ;
zc - > optState . matchTable = ( ZSTD_match_t * ) ptr ;
ptr = zc - > optState . matchTable + ZSTD_OPT_NUM + 1 ;
zc - > optState . priceTable = ( ZSTD_optimal_t * ) ptr ;
ptr = zc - > optState . priceTable + ZSTD_OPT_NUM + 1 ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
/* ldm hash table */
/* initialize bucketOffsets table later for pointer alignment */
if ( params . ldmParams . enableLdm ) {
size_t const ldmHSize = ( ( size_t ) 1 ) < < params . ldmParams . hashLog ;
memset ( ptr , 0 , ldmHSize * sizeof ( ldmEntry_t ) ) ;
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ; /* ensure ptr is properly aligned */
zc - > ldmState . hashTable = ( ldmEntry_t * ) ptr ;
ptr = zc - > ldmState . hashTable + ldmHSize ;
}
2017-06-09 03:43:56 +02:00
/* table Space */
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " reset table : %u " , crp ! = ZSTDcrp_noMemset ) ;
2017-06-09 03:43:56 +02:00
if ( crp ! = ZSTDcrp_noMemset ) memset ( ptr , 0 , tableSpace ) ; /* reset tables only */
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ; /* ensure ptr is properly aligned */
zc - > hashTable = ( U32 * ) ( ptr ) ;
zc - > chainTable = zc - > hashTable + hSize ;
zc - > hashTable3 = zc - > chainTable + chainSize ;
ptr = zc - > hashTable3 + h3Size ;
/* sequences storage */
zc - > seqStore . sequencesStart = ( seqDef * ) ptr ;
ptr = zc - > seqStore . sequencesStart + maxNbSeq ;
zc - > seqStore . llCode = ( BYTE * ) ptr ;
zc - > seqStore . mlCode = zc - > seqStore . llCode + maxNbSeq ;
zc - > seqStore . ofCode = zc - > seqStore . mlCode + maxNbSeq ;
zc - > seqStore . litStart = zc - > seqStore . ofCode + maxNbSeq ;
2017-07-22 23:46:05 +02:00
ptr = zc - > seqStore . litStart + blockSize ;
2017-10-26 22:41:47 +02:00
/* ldm bucketOffsets table */
if ( params . ldmParams . enableLdm ) {
size_t const ldmBucketSize =
( ( size_t ) 1 ) < < ( params . ldmParams . hashLog -
params . ldmParams . bucketSizeLog ) ;
memset ( ptr , 0 , ldmBucketSize ) ;
zc - > ldmState . bucketOffsets = ( BYTE * ) ptr ;
ptr = zc - > ldmState . bucketOffsets + ldmBucketSize ;
}
2017-07-22 23:46:05 +02:00
/* buffers */
zc - > inBuffSize = buffInSize ;
zc - > inBuff = ( char * ) ptr ;
zc - > outBuffSize = buffOutSize ;
zc - > outBuff = zc - > inBuff + buffInSize ;
2017-06-09 03:43:56 +02:00
return 0 ;
}
}
/* ZSTD_invalidateRepCodes() :
* ensures next compression will not use repcodes from previous block .
* Note : only works with regular variant ;
* do not use with extDict variant ! */
void ZSTD_invalidateRepCodes ( ZSTD_CCtx * cctx ) {
int i ;
2017-08-27 12:05:17 +02:00
for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) cctx - > seqStore . rep [ i ] = 0 ;
2017-06-09 03:43:56 +02:00
}
/*! ZSTD_copyCCtx_internal() :
* Duplicate an existing context ` srcCCtx ` into another one ` dstCCtx ` .
* Only works during stage ZSTDcs_init ( i . e . after creation , but before first call to ZSTD_compressContinue ( ) ) .
2018-01-13 13:50:59 +01:00
* The " context " , in this case , refers to the hash and chain tables ,
* entropy tables , and dictionary references .
* ` windowLog ` value is enforced if ! = 0 , otherwise value is copied from srcCCtx .
* @ return : 0 , or an error code */
2017-07-22 23:46:05 +02:00
static size_t ZSTD_copyCCtx_internal ( ZSTD_CCtx * dstCCtx ,
const ZSTD_CCtx * srcCCtx ,
2018-01-13 13:50:59 +01:00
unsigned windowLog ,
2017-07-22 23:46:05 +02:00
ZSTD_frameParameters fParams ,
2018-01-13 13:50:59 +01:00
U64 pledgedSrcSize ,
2017-07-22 23:46:05 +02:00
ZSTD_buffered_policy_e zbuff )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
DEBUGLOG ( 5 , " ZSTD_copyCCtx_internal " ) ;
2017-06-09 03:43:56 +02:00
if ( srcCCtx - > stage ! = ZSTDcs_init ) return ERROR ( stage_wrong ) ;
memcpy ( & dstCCtx - > customMem , & srcCCtx - > customMem , sizeof ( ZSTD_customMem ) ) ;
2017-10-26 22:41:47 +02:00
{ ZSTD_CCtx_params params = dstCCtx - > requestedParams ;
/* Copy only compression parameters related to tables. */
params . cParams = srcCCtx - > appliedParams . cParams ;
2018-01-13 13:50:59 +01:00
if ( windowLog ) params . cParams . windowLog = windowLog ;
2017-06-09 03:43:56 +02:00
params . fParams = fParams ;
2017-07-22 23:46:05 +02:00
ZSTD_resetCCtx_internal ( dstCCtx , params , pledgedSrcSize ,
ZSTDcrp_noMemset , zbuff ) ;
2017-06-09 03:43:56 +02:00
}
/* copy tables */
2017-10-26 22:41:47 +02:00
{ size_t const chainSize = ( srcCCtx - > appliedParams . cParams . strategy = = ZSTD_fast ) ? 0 : ( ( size_t ) 1 < < srcCCtx - > appliedParams . cParams . chainLog ) ;
2017-07-22 23:46:05 +02:00
size_t const hSize = ( size_t ) 1 < < srcCCtx - > appliedParams . cParams . hashLog ;
2017-06-09 03:43:56 +02:00
size_t const h3Size = ( size_t ) 1 < < srcCCtx - > hashLog3 ;
size_t const tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
assert ( ( U32 * ) dstCCtx - > chainTable = = ( U32 * ) dstCCtx - > hashTable + hSize ) ; /* chainTable must follow hashTable */
assert ( ( U32 * ) dstCCtx - > hashTable3 = = ( U32 * ) dstCCtx - > chainTable + chainSize ) ;
memcpy ( dstCCtx - > hashTable , srcCCtx - > hashTable , tableSpace ) ; /* presumes all tables follow each other */
}
/* copy dictionary offsets */
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 ;
dstCCtx - > dictID = srcCCtx - > dictID ;
/* copy entropy tables */
2017-08-27 12:05:17 +02:00
memcpy ( dstCCtx - > entropy , srcCCtx - > entropy , sizeof ( ZSTD_entropyCTables_t ) ) ;
2018-01-13 13:50:59 +01:00
/* copy repcodes */
{
int i ;
for ( i = 0 ; i < ZSTD_REP_NUM ; + + i )
dstCCtx - > seqStore . rep [ i ] = srcCCtx - > seqStore . rep [ i ] ;
}
2017-06-09 03:43:56 +02:00
return 0 ;
}
/*! ZSTD_copyCCtx() :
* Duplicate an existing context ` srcCCtx ` into another one ` dstCCtx ` .
* Only works during stage ZSTDcs_init ( i . e . after creation , but before first call to ZSTD_compressContinue ( ) ) .
* pledgedSrcSize = = 0 means " unknown " .
* @ return : 0 , or an error code */
size_t ZSTD_copyCCtx ( ZSTD_CCtx * dstCCtx , const ZSTD_CCtx * srcCCtx , unsigned long long pledgedSrcSize )
{
ZSTD_frameParameters fParams = { 1 /*content*/ , 0 /*checksum*/ , 0 /*noDictID*/ } ;
2017-07-22 23:46:05 +02:00
ZSTD_buffered_policy_e const zbuff = ( ZSTD_buffered_policy_e ) ( srcCCtx - > inBuffSize > 0 ) ;
ZSTD_STATIC_ASSERT ( ( U32 ) ZSTDb_buffered = = 1 ) ;
2018-01-13 13:50:59 +01:00
if ( pledgedSrcSize = = 0 ) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN ;
fParams . contentSizeFlag = ( pledgedSrcSize ! = ZSTD_CONTENTSIZE_UNKNOWN ) ;
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
return ZSTD_copyCCtx_internal ( dstCCtx , srcCCtx ,
0 /*windowLog from srcCCtx*/ , fParams , pledgedSrcSize ,
zbuff ) ;
2017-06-09 03:43:56 +02:00
}
/*! ZSTD_reduceTable() :
* reduce table indexes by ` reducerValue ` */
static void ZSTD_reduceTable ( U32 * const table , U32 const size , U32 const reducerValue )
{
U32 u ;
for ( u = 0 ; u < size ; u + + ) {
if ( table [ u ] < reducerValue ) table [ u ] = 0 ;
else table [ u ] - = reducerValue ;
}
}
2017-10-26 22:41:47 +02:00
/*! ZSTD_ldm_reduceTable() :
* reduce table indexes by ` reducerValue ` */
static void ZSTD_ldm_reduceTable ( ldmEntry_t * const table , U32 const size ,
U32 const reducerValue )
{
U32 u ;
for ( u = 0 ; u < size ; u + + ) {
if ( table [ u ] . offset < reducerValue ) table [ u ] . offset = 0 ;
else table [ u ] . offset - = reducerValue ;
}
}
2017-06-09 03:43:56 +02:00
/*! ZSTD_reduceIndex() :
* rescale all indexes to avoid future overflow ( indexes are U32 ) */
static void ZSTD_reduceIndex ( ZSTD_CCtx * zc , const U32 reducerValue )
{
2017-10-26 22:41:47 +02:00
{ U32 const hSize = ( U32 ) 1 < < zc - > appliedParams . cParams . hashLog ;
2017-06-09 03:43:56 +02:00
ZSTD_reduceTable ( zc - > hashTable , hSize , reducerValue ) ; }
2017-10-26 22:41:47 +02:00
{ U32 const chainSize = ( zc - > appliedParams . cParams . strategy = = ZSTD_fast ) ? 0 : ( ( U32 ) 1 < < zc - > appliedParams . cParams . chainLog ) ;
2017-06-09 03:43:56 +02:00
ZSTD_reduceTable ( zc - > chainTable , chainSize , reducerValue ) ; }
2017-10-26 22:41:47 +02:00
{ U32 const h3Size = ( zc - > hashLog3 ) ? ( U32 ) 1 < < zc - > hashLog3 : 0 ;
2017-06-09 03:43:56 +02:00
ZSTD_reduceTable ( zc - > hashTable3 , h3Size , reducerValue ) ; }
2017-10-26 22:41:47 +02:00
{ if ( zc - > appliedParams . ldmParams . enableLdm ) {
U32 const ldmHSize = ( U32 ) 1 < < zc - > appliedParams . ldmParams . hashLog ;
ZSTD_ldm_reduceTable ( zc - > ldmState . hashTable , ldmHSize , reducerValue ) ;
}
}
2017-06-09 03:43:56 +02:00
}
/*-*******************************************************
* Block entropic compression
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* See doc/zstd_compression_format.md for detailed format description */
size_t ZSTD_noCompressBlock ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
{
if ( srcSize + ZSTD_blockHeaderSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
memcpy ( ( BYTE * ) dst + ZSTD_blockHeaderSize , src , srcSize ) ;
MEM_writeLE24 ( dst , ( U32 ) ( srcSize < < 2 ) + ( U32 ) bt_raw ) ;
return ZSTD_blockHeaderSize + srcSize ;
}
static size_t ZSTD_noCompressLiterals ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
{
BYTE * const ostart = ( BYTE * const ) dst ;
U32 const flSize = 1 + ( srcSize > 31 ) + ( srcSize > 4095 ) ;
if ( srcSize + flSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
switch ( flSize )
{
case 1 : /* 2 - 1 - 5 */
ostart [ 0 ] = ( BYTE ) ( ( U32 ) set_basic + ( srcSize < < 3 ) ) ;
break ;
case 2 : /* 2 - 2 - 12 */
MEM_writeLE16 ( ostart , ( U16 ) ( ( U32 ) set_basic + ( 1 < < 2 ) + ( srcSize < < 4 ) ) ) ;
break ;
case 3 : /* 2 - 2 - 20 */
MEM_writeLE32 ( ostart , ( U32 ) ( ( U32 ) set_basic + ( 3 < < 2 ) + ( srcSize < < 4 ) ) ) ;
break ;
2017-07-22 23:46:05 +02:00
default : /* not necessary : flSize is {1,2,3} */
assert ( 0 ) ;
2017-06-09 03:43:56 +02:00
}
memcpy ( ostart + flSize , src , srcSize ) ;
return srcSize + flSize ;
}
static size_t ZSTD_compressRleLiteralsBlock ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
{
BYTE * const ostart = ( BYTE * const ) dst ;
U32 const flSize = 1 + ( srcSize > 31 ) + ( srcSize > 4095 ) ;
( void ) dstCapacity ; /* dstCapacity already guaranteed to be >=4, hence large enough */
switch ( flSize )
{
case 1 : /* 2 - 1 - 5 */
ostart [ 0 ] = ( BYTE ) ( ( U32 ) set_rle + ( srcSize < < 3 ) ) ;
break ;
case 2 : /* 2 - 2 - 12 */
MEM_writeLE16 ( ostart , ( U16 ) ( ( U32 ) set_rle + ( 1 < < 2 ) + ( srcSize < < 4 ) ) ) ;
break ;
case 3 : /* 2 - 2 - 20 */
MEM_writeLE32 ( ostart , ( U32 ) ( ( U32 ) set_rle + ( 3 < < 2 ) + ( srcSize < < 4 ) ) ) ;
break ;
2017-07-22 23:46:05 +02:00
default : /* not necessary : flSize is {1,2,3} */
assert ( 0 ) ;
2017-06-09 03:43:56 +02:00
}
ostart [ flSize ] = * ( const BYTE * ) src ;
return flSize + 1 ;
}
static size_t ZSTD_minGain ( size_t srcSize ) { return ( srcSize > > 6 ) + 2 ; }
2017-08-27 12:05:17 +02:00
static size_t ZSTD_compressLiterals ( ZSTD_entropyCTables_t * entropy ,
ZSTD_strategy strategy ,
2017-06-09 03:43:56 +02:00
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize )
{
size_t const minGain = ZSTD_minGain ( srcSize ) ;
size_t const lhSize = 3 + ( srcSize > = 1 KB ) + ( srcSize > = 16 KB ) ;
BYTE * const ostart = ( BYTE * ) dst ;
U32 singleStream = srcSize < 256 ;
symbolEncodingType_e hType = set_compressed ;
size_t cLitSize ;
/* small ? don't even attempt compression (speed opt) */
# define LITERAL_NOENTROPY 63
2017-08-27 12:05:17 +02:00
{ size_t const minLitSize = entropy - > hufCTable_repeatMode = = HUF_repeat_valid ? 6 : LITERAL_NOENTROPY ;
2017-06-09 03:43:56 +02:00
if ( srcSize < = minLitSize ) return ZSTD_noCompressLiterals ( dst , dstCapacity , src , srcSize ) ;
}
if ( dstCapacity < lhSize + 1 ) return ERROR ( dstSize_tooSmall ) ; /* not enough space for compression */
2017-08-27 12:05:17 +02:00
{ HUF_repeat repeat = entropy - > hufCTable_repeatMode ;
int const preferRepeat = strategy < ZSTD_lazy ? srcSize < = 1024 : 0 ;
2017-06-09 03:43:56 +02:00
if ( repeat = = HUF_repeat_valid & & lhSize = = 3 ) singleStream = 1 ;
cLitSize = singleStream ? HUF_compress1X_repeat ( ostart + lhSize , dstCapacity - lhSize , src , srcSize , 255 , 11 ,
2017-08-27 12:05:17 +02:00
entropy - > workspace , sizeof ( entropy - > workspace ) , ( HUF_CElt * ) entropy - > hufCTable , & repeat , preferRepeat )
2017-06-09 03:43:56 +02:00
: HUF_compress4X_repeat ( ostart + lhSize , dstCapacity - lhSize , src , srcSize , 255 , 11 ,
2017-08-27 12:05:17 +02:00
entropy - > workspace , sizeof ( entropy - > workspace ) , ( HUF_CElt * ) entropy - > hufCTable , & repeat , preferRepeat ) ;
2017-06-09 03:43:56 +02:00
if ( repeat ! = HUF_repeat_none ) { hType = set_repeat ; } /* reused the existing table */
2017-08-27 12:05:17 +02:00
else { entropy - > hufCTable_repeatMode = HUF_repeat_check ; } /* now have a table to reuse */
2017-06-09 03:43:56 +02:00
}
2017-08-27 12:05:17 +02:00
if ( ( cLitSize = = 0 ) | ( cLitSize > = srcSize - minGain ) | ERR_isError ( cLitSize ) ) {
entropy - > hufCTable_repeatMode = HUF_repeat_none ;
2017-06-09 03:43:56 +02:00
return ZSTD_noCompressLiterals ( dst , dstCapacity , src , srcSize ) ;
}
if ( cLitSize = = 1 ) {
2017-08-27 12:05:17 +02:00
entropy - > hufCTable_repeatMode = HUF_repeat_none ;
2017-06-09 03:43:56 +02:00
return ZSTD_compressRleLiteralsBlock ( dst , dstCapacity , src , srcSize ) ;
}
/* Build header */
switch ( lhSize )
{
case 3 : /* 2 - 2 - 10 - 10 */
{ U32 const lhc = hType + ( ( ! singleStream ) < < 2 ) + ( ( U32 ) srcSize < < 4 ) + ( ( U32 ) cLitSize < < 14 ) ;
MEM_writeLE24 ( ostart , lhc ) ;
break ;
}
case 4 : /* 2 - 2 - 14 - 14 */
{ U32 const lhc = hType + ( 2 < < 2 ) + ( ( U32 ) srcSize < < 4 ) + ( ( U32 ) cLitSize < < 18 ) ;
MEM_writeLE32 ( ostart , lhc ) ;
break ;
}
case 5 : /* 2 - 2 - 18 - 18 */
{ U32 const lhc = hType + ( 3 < < 2 ) + ( ( U32 ) srcSize < < 4 ) + ( ( U32 ) cLitSize < < 22 ) ;
MEM_writeLE32 ( ostart , lhc ) ;
ostart [ 4 ] = ( BYTE ) ( cLitSize > > 10 ) ;
break ;
}
2018-01-13 13:50:59 +01:00
default : /* not possible : lhSize is {3,4,5} */
2017-07-22 23:46:05 +02:00
assert ( 0 ) ;
2017-06-09 03:43:56 +02:00
}
return lhSize + cLitSize ;
}
void ZSTD_seqToCodes ( const seqStore_t * seqStorePtr )
{
const seqDef * const sequences = seqStorePtr - > sequencesStart ;
BYTE * const llCodeTable = seqStorePtr - > llCode ;
BYTE * const ofCodeTable = seqStorePtr - > ofCode ;
BYTE * const mlCodeTable = seqStorePtr - > mlCode ;
U32 const nbSeq = ( U32 ) ( seqStorePtr - > sequences - seqStorePtr - > sequencesStart ) ;
U32 u ;
for ( u = 0 ; u < nbSeq ; u + + ) {
U32 const llv = sequences [ u ] . litLength ;
U32 const mlv = sequences [ u ] . matchLength ;
2018-01-13 13:50:59 +01:00
llCodeTable [ u ] = ( BYTE ) ZSTD_LLcode ( llv ) ;
2017-06-09 03:43:56 +02:00
ofCodeTable [ u ] = ( BYTE ) ZSTD_highbit32 ( sequences [ u ] . offset ) ;
2018-01-13 13:50:59 +01:00
mlCodeTable [ u ] = ( BYTE ) ZSTD_MLcode ( mlv ) ;
2017-06-09 03:43:56 +02:00
}
if ( seqStorePtr - > longLengthID = = 1 )
llCodeTable [ seqStorePtr - > longLengthPos ] = MaxLL ;
if ( seqStorePtr - > longLengthID = = 2 )
mlCodeTable [ seqStorePtr - > longLengthPos ] = MaxML ;
}
2017-10-26 22:41:47 +02:00
typedef enum {
ZSTD_defaultDisallowed = 0 ,
ZSTD_defaultAllowed = 1
} ZSTD_defaultPolicy_e ;
2018-01-13 13:50:59 +01:00
MEM_STATIC
symbolEncodingType_e ZSTD_selectEncodingType (
2017-10-26 22:41:47 +02:00
FSE_repeat * repeatMode , size_t const mostFrequent , size_t nbSeq ,
U32 defaultNormLog , ZSTD_defaultPolicy_e const isDefaultAllowed )
2017-08-27 12:05:17 +02:00
{
# define MIN_SEQ_FOR_DYNAMIC_FSE 64
# define MAX_SEQ_FOR_STATIC_FSE 1000
2017-10-26 22:41:47 +02:00
ZSTD_STATIC_ASSERT ( ZSTD_defaultDisallowed = = 0 & & ZSTD_defaultAllowed ! = 0 ) ;
if ( ( mostFrequent = = nbSeq ) & & ( ! isDefaultAllowed | | nbSeq > 2 ) ) {
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " Selected set_rle " ) ;
2017-10-26 22:41:47 +02:00
/* Prefer set_basic over set_rle when there are 2 or less symbols,
* since RLE uses 1 byte , but set_basic uses 5 - 6 bits per symbol .
* If basic encoding isn ' t possible , always choose RLE .
*/
2017-08-27 12:05:17 +02:00
* repeatMode = FSE_repeat_check ;
return set_rle ;
}
2018-01-13 13:50:59 +01:00
if ( isDefaultAllowed
& & ( * repeatMode = = FSE_repeat_valid ) & & ( nbSeq < MAX_SEQ_FOR_STATIC_FSE ) ) {
DEBUGLOG ( 5 , " Selected set_repeat " ) ;
2017-08-27 12:05:17 +02:00
return set_repeat ;
}
2018-01-13 13:50:59 +01:00
if ( isDefaultAllowed
& & ( ( nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE ) | | ( mostFrequent < ( nbSeq > > ( defaultNormLog - 1 ) ) ) ) ) {
DEBUGLOG ( 5 , " Selected set_basic " ) ;
/* The format allows default tables to be repeated, but it isn't useful.
* When using simple heuristics to select encoding type , we don ' t want
* to confuse these tables with dictionaries . When running more careful
* analysis , we don ' t need to waste time checking both repeating tables
* and default tables .
*/
* repeatMode = FSE_repeat_none ;
2017-08-27 12:05:17 +02:00
return set_basic ;
}
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " Selected set_compressed " ) ;
2017-08-27 12:05:17 +02:00
* repeatMode = FSE_repeat_check ;
return set_compressed ;
}
2018-01-13 13:50:59 +01:00
MEM_STATIC
size_t ZSTD_buildCTable ( void * dst , size_t dstCapacity ,
2017-08-27 12:05:17 +02:00
FSE_CTable * CTable , U32 FSELog , symbolEncodingType_e type ,
U32 * count , U32 max ,
BYTE const * codeTable , size_t nbSeq ,
S16 const * defaultNorm , U32 defaultNormLog , U32 defaultMax ,
void * workspace , size_t workspaceSize )
{
BYTE * op = ( BYTE * ) dst ;
BYTE const * const oend = op + dstCapacity ;
switch ( type ) {
case set_rle :
* op = codeTable [ 0 ] ;
CHECK_F ( FSE_buildCTable_rle ( CTable , ( BYTE ) max ) ) ;
return 1 ;
case set_repeat :
return 0 ;
case set_basic :
2018-01-13 13:50:59 +01:00
CHECK_F ( FSE_buildCTable_wksp ( CTable , defaultNorm , defaultMax , defaultNormLog , workspace , workspaceSize ) ) ; /* note : could be pre-calculated */
2017-08-27 12:05:17 +02:00
return 0 ;
2017-10-26 22:41:47 +02:00
case set_compressed : {
S16 norm [ MaxSeq + 1 ] ;
size_t nbSeq_1 = nbSeq ;
const U32 tableLog = FSE_optimalTableLog ( FSELog , nbSeq , max ) ;
if ( count [ codeTable [ nbSeq - 1 ] ] > 1 ) {
count [ codeTable [ nbSeq - 1 ] ] - - ;
nbSeq_1 - - ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
assert ( nbSeq_1 > 1 ) ;
CHECK_F ( 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 NCountSize ;
CHECK_F ( FSE_buildCTable_wksp ( CTable , norm , max , tableLog , workspace , workspaceSize ) ) ;
return NCountSize ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
}
default : return assert ( 0 ) , ERROR ( GENERIC ) ;
}
}
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
MEM_STATIC
size_t ZSTD_encodeSequences (
void * dst , size_t dstCapacity ,
FSE_CTable const * CTable_MatchLength , BYTE const * mlCodeTable ,
FSE_CTable const * CTable_OffsetBits , BYTE const * ofCodeTable ,
FSE_CTable const * CTable_LitLength , BYTE const * llCodeTable ,
seqDef const * sequences , size_t nbSeq , int longOffsets )
2017-10-26 22:41:47 +02:00
{
BIT_CStream_t blockStream ;
FSE_CState_t stateMatchLength ;
FSE_CState_t stateOffsetBits ;
FSE_CState_t stateLitLength ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
CHECK_E ( BIT_initCStream ( & blockStream , dst , dstCapacity ) , dstSize_tooSmall ) ; /* not enough space remaining */
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
/* first symbols */
FSE_initCState2 ( & stateMatchLength , CTable_MatchLength , mlCodeTable [ nbSeq - 1 ] ) ;
FSE_initCState2 ( & stateOffsetBits , CTable_OffsetBits , ofCodeTable [ nbSeq - 1 ] ) ;
FSE_initCState2 ( & stateLitLength , CTable_LitLength , llCodeTable [ nbSeq - 1 ] ) ;
BIT_addBits ( & blockStream , sequences [ nbSeq - 1 ] . litLength , LL_bits [ llCodeTable [ nbSeq - 1 ] ] ) ;
if ( MEM_32bits ( ) ) BIT_flushBits ( & blockStream ) ;
BIT_addBits ( & blockStream , sequences [ nbSeq - 1 ] . matchLength , ML_bits [ mlCodeTable [ nbSeq - 1 ] ] ) ;
if ( MEM_32bits ( ) ) BIT_flushBits ( & blockStream ) ;
if ( longOffsets ) {
U32 const ofBits = ofCodeTable [ nbSeq - 1 ] ;
int const extraBits = ofBits - MIN ( ofBits , STREAM_ACCUMULATOR_MIN - 1 ) ;
if ( extraBits ) {
BIT_addBits ( & blockStream , sequences [ nbSeq - 1 ] . offset , extraBits ) ;
BIT_flushBits ( & blockStream ) ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
BIT_addBits ( & blockStream , sequences [ nbSeq - 1 ] . offset > > extraBits ,
ofBits - extraBits ) ;
} else {
BIT_addBits ( & blockStream , sequences [ nbSeq - 1 ] . offset , ofCodeTable [ nbSeq - 1 ] ) ;
}
BIT_flushBits ( & blockStream ) ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
{ size_t n ;
for ( n = nbSeq - 2 ; n < nbSeq ; n - - ) { /* intentional underflow */
BYTE const llCode = llCodeTable [ n ] ;
BYTE const ofCode = ofCodeTable [ n ] ;
BYTE const mlCode = mlCodeTable [ n ] ;
U32 const llBits = LL_bits [ llCode ] ;
2018-01-13 13:50:59 +01:00
U32 const ofBits = ofCode ;
2017-10-26 22:41:47 +02:00
U32 const mlBits = ML_bits [ mlCode ] ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 6 , " encoding: litlen:%2u - matchlen:%2u - offCode:%7u " ,
sequences [ n ] . litLength ,
sequences [ n ] . matchLength + MINMATCH ,
sequences [ n ] . offset ) ; /* 32b*/ /* 64b*/
2017-10-26 22:41:47 +02:00
/* (7)*/ /* (7)*/
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 */
if ( MEM_32bits ( ) | | ( ofBits + mlBits + llBits > = 64 - 7 - ( LLFSELog + MLFSELog + OffFSELog ) ) )
BIT_flushBits ( & blockStream ) ; /* (7)*/
BIT_addBits ( & blockStream , sequences [ n ] . litLength , llBits ) ;
if ( MEM_32bits ( ) & & ( ( llBits + mlBits ) > 24 ) ) BIT_flushBits ( & blockStream ) ;
BIT_addBits ( & blockStream , sequences [ n ] . matchLength , mlBits ) ;
if ( MEM_32bits ( ) | | ( ofBits + mlBits + llBits > 56 ) ) BIT_flushBits ( & blockStream ) ;
if ( longOffsets ) {
int const extraBits = ofBits - MIN ( ofBits , STREAM_ACCUMULATOR_MIN - 1 ) ;
if ( extraBits ) {
BIT_addBits ( & blockStream , sequences [ n ] . offset , extraBits ) ;
BIT_flushBits ( & blockStream ) ; /* (7)*/
}
BIT_addBits ( & blockStream , sequences [ n ] . offset > > extraBits ,
ofBits - extraBits ) ; /* 31 */
} else {
BIT_addBits ( & blockStream , sequences [ n ] . offset , ofBits ) ; /* 31 */
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
BIT_flushBits ( & blockStream ) ; /* (7)*/
2017-06-09 03:43:56 +02:00
} }
2017-10-26 22:41:47 +02:00
FSE_flushCState ( & blockStream , & stateMatchLength ) ;
FSE_flushCState ( & blockStream , & stateOffsetBits ) ;
FSE_flushCState ( & blockStream , & stateLitLength ) ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
{ size_t const streamSize = BIT_closeCStream ( & blockStream ) ;
if ( streamSize = = 0 ) return ERROR ( dstSize_tooSmall ) ; /* not enough space */
return streamSize ;
2017-06-09 03:43:56 +02:00
}
}
2017-10-26 22:41:47 +02:00
MEM_STATIC size_t ZSTD_compressSequences_internal ( seqStore_t * seqStorePtr ,
ZSTD_entropyCTables_t * entropy ,
ZSTD_compressionParameters const * cParams ,
void * dst , size_t dstCapacity )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
const int longOffsets = cParams - > windowLog > STREAM_ACCUMULATOR_MIN ;
U32 count [ MaxSeq + 1 ] ;
FSE_CTable * CTable_LitLength = entropy - > litlengthCTable ;
FSE_CTable * CTable_OffsetBits = entropy - > offcodeCTable ;
FSE_CTable * CTable_MatchLength = entropy - > matchlengthCTable ;
U32 LLtype , Offtype , MLtype ; /* compressed, raw or rle */
const seqDef * const sequences = seqStorePtr - > sequencesStart ;
const BYTE * const ofCodeTable = seqStorePtr - > ofCode ;
const BYTE * const llCodeTable = seqStorePtr - > llCode ;
const BYTE * const mlCodeTable = seqStorePtr - > mlCode ;
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * const oend = ostart + dstCapacity ;
BYTE * op = ostart ;
size_t const nbSeq = seqStorePtr - > sequences - seqStorePtr - > sequencesStart ;
BYTE * seqHead ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
ZSTD_STATIC_ASSERT ( sizeof ( entropy - > workspace ) > = ( 1 < < MAX ( MLFSELog , LLFSELog ) ) ) ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
/* Compress literals */
{ const BYTE * const literals = seqStorePtr - > litStart ;
size_t const litSize = seqStorePtr - > lit - literals ;
size_t const cSize = ZSTD_compressLiterals (
entropy , cParams - > strategy , op , dstCapacity , literals , litSize ) ;
if ( ZSTD_isError ( cSize ) )
return cSize ;
2018-01-13 13:50:59 +01:00
assert ( cSize < = dstCapacity ) ;
2017-10-26 22:41:47 +02:00
op + = cSize ;
}
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
/* Sequences Header */
2018-01-13 13:50:59 +01:00
if ( ( oend - op ) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/ ) return ERROR ( dstSize_tooSmall ) ;
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 ;
2017-10-26 22:41:47 +02:00
if ( nbSeq = = 0 ) return op - ostart ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
/* seqHead : flags for FSE encoding type */
seqHead = op + + ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
/* convert length/distances into codes */
ZSTD_seqToCodes ( seqStorePtr ) ;
2018-01-13 13:50:59 +01:00
/* build CTable for Literal Lengths */
2017-10-26 22:41:47 +02:00
{ U32 max = MaxLL ;
size_t const mostFrequent = FSE_countFast_wksp ( count , & max , llCodeTable , nbSeq , entropy - > workspace ) ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " Building LL table " ) ;
2017-10-26 22:41:47 +02:00
LLtype = ZSTD_selectEncodingType ( & entropy - > litlength_repeatMode , mostFrequent , nbSeq , LL_defaultNormLog , ZSTD_defaultAllowed ) ;
{ size_t const countSize = ZSTD_buildCTable ( op , oend - op , CTable_LitLength , LLFSELog , ( symbolEncodingType_e ) LLtype ,
count , max , llCodeTable , nbSeq , LL_defaultNorm , LL_defaultNormLog , MaxLL ,
entropy - > workspace , sizeof ( entropy - > workspace ) ) ;
if ( ZSTD_isError ( countSize ) ) return countSize ;
op + = countSize ;
} }
2018-01-13 13:50:59 +01:00
/* build CTable for Offsets */
2017-10-26 22:41:47 +02:00
{ U32 max = MaxOff ;
size_t const mostFrequent = FSE_countFast_wksp ( count , & max , ofCodeTable , nbSeq , entropy - > workspace ) ;
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
2018-01-13 13:50:59 +01:00
ZSTD_defaultPolicy_e const defaultPolicy = ( max < = DefaultMaxOff ) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed ;
DEBUGLOG ( 5 , " Building OF table " ) ;
2017-10-26 22:41:47 +02:00
Offtype = ZSTD_selectEncodingType ( & entropy - > offcode_repeatMode , mostFrequent , nbSeq , OF_defaultNormLog , defaultPolicy ) ;
{ size_t const countSize = ZSTD_buildCTable ( op , oend - op , CTable_OffsetBits , OffFSELog , ( symbolEncodingType_e ) Offtype ,
count , max , ofCodeTable , nbSeq , OF_defaultNorm , OF_defaultNormLog , DefaultMaxOff ,
entropy - > workspace , sizeof ( entropy - > workspace ) ) ;
if ( ZSTD_isError ( countSize ) ) return countSize ;
op + = countSize ;
} }
2018-01-13 13:50:59 +01:00
/* build CTable for MatchLengths */
2017-10-26 22:41:47 +02:00
{ U32 max = MaxML ;
size_t const mostFrequent = FSE_countFast_wksp ( count , & max , mlCodeTable , nbSeq , entropy - > workspace ) ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " Building ML table " ) ;
2017-10-26 22:41:47 +02:00
MLtype = ZSTD_selectEncodingType ( & entropy - > matchlength_repeatMode , mostFrequent , nbSeq , ML_defaultNormLog , ZSTD_defaultAllowed ) ;
{ size_t const countSize = ZSTD_buildCTable ( op , oend - op , CTable_MatchLength , MLFSELog , ( symbolEncodingType_e ) MLtype ,
count , max , mlCodeTable , nbSeq , ML_defaultNorm , ML_defaultNormLog , MaxML ,
entropy - > workspace , sizeof ( entropy - > workspace ) ) ;
if ( ZSTD_isError ( countSize ) ) return countSize ;
op + = countSize ;
} }
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
* seqHead = ( BYTE ) ( ( LLtype < < 6 ) + ( Offtype < < 4 ) + ( MLtype < < 2 ) ) ;
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
{ size_t const bitstreamSize = ZSTD_encodeSequences (
op , oend - op ,
CTable_MatchLength , mlCodeTable ,
CTable_OffsetBits , ofCodeTable ,
CTable_LitLength , llCodeTable ,
sequences , nbSeq ,
longOffsets ) ;
if ( ZSTD_isError ( bitstreamSize ) ) return bitstreamSize ;
op + = bitstreamSize ;
2017-10-26 22:41:47 +02:00
}
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
return op - ostart ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
MEM_STATIC size_t ZSTD_compressSequences ( seqStore_t * seqStorePtr ,
ZSTD_entropyCTables_t * entropy ,
ZSTD_compressionParameters const * cParams ,
void * dst , size_t dstCapacity ,
size_t srcSize )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
size_t const cSize = ZSTD_compressSequences_internal ( seqStorePtr , entropy , cParams ,
dst , dstCapacity ) ;
/* If the srcSize <= dstCapacity, then there is enough space to write a
* raw uncompressed block . Since we ran out of space , the block must not
* be compressible , so fall back to a raw uncompressed block .
*/
2018-01-13 13:50:59 +01:00
int const uncompressibleError = ( cSize = = ERROR ( dstSize_tooSmall ) ) & & ( srcSize < = dstCapacity ) ;
2017-10-26 22:41:47 +02:00
if ( ZSTD_isError ( cSize ) & & ! uncompressibleError )
return cSize ;
2018-01-13 13:50:59 +01:00
/* We check that dictionaries have offset codes available for the first
* block . After the first block , the offcode table might not have large
* enough codes to represent the offsets in the data .
*/
if ( entropy - > offcode_repeatMode = = FSE_repeat_valid )
entropy - > offcode_repeatMode = FSE_repeat_check ;
2017-10-26 22:41:47 +02:00
/* Check compressibility */
2018-01-13 13:50:59 +01:00
{ size_t const minGain = ZSTD_minGain ( srcSize ) ; /* note : fixed formula, maybe should depend on compression level, or strategy */
size_t const maxCSize = srcSize - minGain ;
if ( cSize > = maxCSize | | uncompressibleError ) {
entropy - > hufCTable_repeatMode = HUF_repeat_none ;
entropy - > offcode_repeatMode = FSE_repeat_none ;
entropy - > matchlength_repeatMode = FSE_repeat_none ;
entropy - > litlength_repeatMode = FSE_repeat_none ;
return 0 ; /* block not compressed */
} }
2017-10-26 22:41:47 +02:00
assert ( ! ZSTD_isError ( cSize ) ) ;
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
/* block is compressed => confirm repcodes in history */
2017-10-26 22:41:47 +02:00
{ int i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) seqStorePtr - > rep [ i ] = seqStorePtr - > repToConfirm [ i ] ; }
return cSize ;
}
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
/* ZSTD_selectBlockCompressor() :
2017-10-26 22:41:47 +02:00
* Not static , but internal use only ( used by long distance matcher )
2017-07-22 23:46:05 +02:00
* assumption : strat is a valid strategy */
2017-10-26 22:41:47 +02:00
typedef size_t ( * ZSTD_blockCompressor ) ( ZSTD_CCtx * ctx , const void * src , size_t srcSize ) ;
ZSTD_blockCompressor ZSTD_selectBlockCompressor ( ZSTD_strategy strat , int extDict )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
static const ZSTD_blockCompressor blockCompressor [ 2 ] [ ( unsigned ) ZSTD_btultra + 1 ] = {
{ ZSTD_compressBlock_fast /* default for 0 */ ,
ZSTD_compressBlock_fast , ZSTD_compressBlock_doubleFast , ZSTD_compressBlock_greedy ,
2017-06-09 03:43:56 +02:00
ZSTD_compressBlock_lazy , ZSTD_compressBlock_lazy2 , ZSTD_compressBlock_btlazy2 ,
2017-07-22 23:46:05 +02:00
ZSTD_compressBlock_btopt , ZSTD_compressBlock_btultra } ,
{ ZSTD_compressBlock_fast_extDict /* default for 0 */ ,
ZSTD_compressBlock_fast_extDict , ZSTD_compressBlock_doubleFast_extDict , ZSTD_compressBlock_greedy_extDict ,
2017-06-09 03:43:56 +02:00
ZSTD_compressBlock_lazy_extDict , ZSTD_compressBlock_lazy2_extDict , ZSTD_compressBlock_btlazy2_extDict ,
2017-07-22 23:46:05 +02:00
ZSTD_compressBlock_btopt_extDict , ZSTD_compressBlock_btultra_extDict }
2017-06-09 03:43:56 +02:00
} ;
2017-07-22 23:46:05 +02:00
ZSTD_STATIC_ASSERT ( ( unsigned ) ZSTD_fast = = 1 ) ;
2018-01-13 13:50:59 +01:00
2017-07-22 23:46:05 +02:00
assert ( ( U32 ) strat > = ( U32 ) ZSTD_fast ) ;
assert ( ( U32 ) strat < = ( U32 ) ZSTD_btultra ) ;
return blockCompressor [ extDict ! = 0 ] [ ( U32 ) strat ] ;
2017-06-09 03:43:56 +02:00
}
2017-10-26 22:41:47 +02:00
static void ZSTD_storeLastLiterals ( seqStore_t * seqStorePtr ,
const BYTE * anchor , size_t lastLLSize )
{
memcpy ( seqStorePtr - > lit , anchor , lastLLSize ) ;
seqStorePtr - > lit + = lastLLSize ;
}
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
static void ZSTD_resetSeqStore ( seqStore_t * ssPtr )
{
ssPtr - > lit = ssPtr - > litStart ;
ssPtr - > sequences = ssPtr - > sequencesStart ;
ssPtr - > longLengthID = 0 ;
}
2017-06-09 03:43:56 +02:00
static size_t ZSTD_compressBlock_internal ( ZSTD_CCtx * zc , void * dst , size_t dstCapacity , const void * src , size_t srcSize )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " ZSTD_compressBlock_internal : dstCapacity = %u " , ( U32 ) dstCapacity ) ;
if ( srcSize < MIN_CBLOCK_SIZE + ZSTD_blockHeaderSize + 1 )
return 0 ; /* don't even attempt compression below a certain srcSize */
2017-06-09 03:43:56 +02:00
ZSTD_resetSeqStore ( & ( zc - > seqStore ) ) ;
2017-10-26 22:41:47 +02:00
2018-01-13 13:50:59 +01:00
/* limited update after a very long match */
{ const BYTE * const base = zc - > base ;
const BYTE * const istart = ( const BYTE * ) src ;
const U32 current = ( U32 ) ( istart - base ) ;
if ( current > zc - > nextToUpdate + 384 )
zc - > nextToUpdate = current - MIN ( 192 , ( U32 ) ( current - zc - > nextToUpdate - 384 ) ) ;
}
/* find and store sequences */
{ U32 const extDict = zc - > lowLimit < zc - > dictLimit ;
const ZSTD_blockCompressor blockCompressor =
zc - > appliedParams . ldmParams . enableLdm
? ( extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm )
: ZSTD_selectBlockCompressor ( zc - > appliedParams . cParams . strategy , extDict ) ;
size_t const lastLLSize = blockCompressor ( zc , src , srcSize ) ;
const BYTE * const anchor = ( const BYTE * ) src + srcSize - lastLLSize ;
ZSTD_storeLastLiterals ( & zc - > seqStore , anchor , lastLLSize ) ;
}
/* encode */
2017-08-27 12:05:17 +02:00
return ZSTD_compressSequences ( & zc - > seqStore , zc - > entropy , & zc - > appliedParams . cParams , dst , dstCapacity , srcSize ) ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
/*! ZSTD_compress_frameChunk() :
2017-06-09 03:43:56 +02:00
* Compress a chunk of data into one or multiple blocks .
* All blocks will be terminated , all input will be consumed .
* Function will issue an error if there is not enough ` dstCapacity ` to hold the compressed content .
* Frame is supposed already started ( header already produced )
* @ return : compressed size , or an error code
*/
2017-07-22 23:46:05 +02:00
static size_t ZSTD_compress_frameChunk ( ZSTD_CCtx * cctx ,
2017-06-09 03:43:56 +02:00
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
U32 lastFrameChunk )
{
size_t blockSize = cctx - > blockSize ;
size_t remaining = srcSize ;
const BYTE * ip = ( const BYTE * ) src ;
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * op = ostart ;
2017-10-26 22:41:47 +02:00
U32 const maxDist = ( U32 ) 1 < < cctx - > appliedParams . cParams . windowLog ;
2018-01-13 13:50:59 +01:00
assert ( cctx - > appliedParams . cParams . windowLog < = 31 ) ;
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " ZSTD_compress_frameChunk (blockSize=%u) " , ( U32 ) blockSize ) ;
2017-07-22 23:46:05 +02:00
if ( cctx - > appliedParams . fParams . checksumFlag & & srcSize )
2017-06-09 03:43:56 +02:00
XXH64_update ( & cctx - > xxhState , src , srcSize ) ;
while ( remaining ) {
U32 const lastBlock = lastFrameChunk & ( blockSize > = remaining ) ;
if ( dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE )
return ERROR ( dstSize_tooSmall ) ; /* not enough space to store compressed block */
if ( remaining < blockSize ) blockSize = remaining ;
2017-10-26 22:41:47 +02:00
/* preemptive overflow correction:
* 1. correction is large enough :
* lowLimit > ( 3 < < 29 ) = = > current > 3 < < 29 + 1 < < windowLog - blockSize
* 1 < < windowLog < = newCurrent < 1 < < chainLog + 1 < < windowLog
*
* current - newCurrent
* > ( 3 < < 29 + 1 < < windowLog - blockSize ) - ( 1 < < windowLog + 1 < < chainLog )
* > ( 3 < < 29 - blockSize ) - ( 1 < < chainLog )
* > ( 3 < < 29 - blockSize ) - ( 1 < < 30 ) ( NOTE : chainLog < = 30 )
* > 1 < < 29 - 1 < < 17
*
* 2. ( ip + blockSize - cctx - > base ) doesn ' t overflow :
* In 32 bit mode we limit windowLog to 30 so we don ' t get
* differences larger than 1 < < 31 - 1.
* 3. cctx - > lowLimit < 1 < < 32 :
* windowLog < = 31 = = > 3 < < 29 + 1 < < windowLog < 7 < < 29 < 1 < < 32.
*/
2017-06-09 03:43:56 +02:00
if ( cctx - > lowLimit > ( 3U < < 29 ) ) {
2017-10-26 22:41:47 +02:00
U32 const cycleMask = ( ( U32 ) 1 < < ZSTD_cycleLog ( cctx - > appliedParams . cParams . chainLog , cctx - > appliedParams . cParams . strategy ) ) - 1 ;
2017-06-09 03:43:56 +02:00
U32 const current = ( U32 ) ( ip - cctx - > base ) ;
2017-10-26 22:41:47 +02:00
U32 const newCurrent = ( current & cycleMask ) + ( ( U32 ) 1 < < cctx - > appliedParams . cParams . windowLog ) ;
2017-06-09 03:43:56 +02:00
U32 const correction = current - newCurrent ;
2017-10-26 22:41:47 +02:00
ZSTD_STATIC_ASSERT ( ZSTD_CHAINLOG_MAX < = 30 ) ;
ZSTD_STATIC_ASSERT ( ZSTD_WINDOWLOG_MAX_32 < = 30 ) ;
ZSTD_STATIC_ASSERT ( ZSTD_WINDOWLOG_MAX < = 31 ) ;
assert ( current > newCurrent ) ;
assert ( correction > 1 < < 28 ) ; /* Loose bound, should be about 1<<29 */
2017-06-09 03:43:56 +02:00
ZSTD_reduceIndex ( cctx , correction ) ;
cctx - > base + = correction ;
cctx - > dictBase + = correction ;
cctx - > lowLimit - = correction ;
cctx - > dictLimit - = correction ;
if ( cctx - > nextToUpdate < correction ) cctx - > nextToUpdate = 0 ;
else cctx - > nextToUpdate - = correction ;
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 4 , " Correction of 0x%x bytes to lowLimit=0x%x \n " , correction , cctx - > lowLimit ) ;
2017-06-09 03:43:56 +02:00
}
2018-01-13 13:50:59 +01:00
/* enforce maxDist */
2017-06-09 03:43:56 +02:00
if ( ( U32 ) ( ip + blockSize - cctx - > base ) > cctx - > loadedDictEnd + maxDist ) {
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 ;
}
2018-01-13 13:50:59 +01:00
{ size_t cSize = ZSTD_compressBlock_internal ( cctx ,
op + ZSTD_blockHeaderSize , dstCapacity - ZSTD_blockHeaderSize ,
ip , blockSize ) ;
if ( ZSTD_isError ( cSize ) ) return cSize ;
if ( cSize = = 0 ) { /* block is not compressible */
U32 const cBlockHeader24 = lastBlock + ( ( ( U32 ) bt_raw ) < < 1 ) + ( U32 ) ( blockSize < < 3 ) ;
if ( blockSize + ZSTD_blockHeaderSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
MEM_writeLE32 ( op , cBlockHeader24 ) ; /* 4th byte will be overwritten */
memcpy ( op + ZSTD_blockHeaderSize , ip , blockSize ) ;
cSize = ZSTD_blockHeaderSize + blockSize ;
} else {
U32 const cBlockHeader24 = lastBlock + ( ( ( U32 ) bt_compressed ) < < 1 ) + ( U32 ) ( cSize < < 3 ) ;
MEM_writeLE24 ( op , cBlockHeader24 ) ;
cSize + = ZSTD_blockHeaderSize ;
}
2017-06-09 03:43:56 +02:00
2018-01-13 13:50:59 +01:00
ip + = blockSize ;
assert ( remaining > = blockSize ) ;
remaining - = blockSize ;
op + = cSize ;
assert ( dstCapacity > = cSize ) ;
dstCapacity - = cSize ;
DEBUGLOG ( 5 , " ZSTD_compress_frameChunk: adding a block of size %u " ,
( U32 ) cSize ) ;
} }
2017-06-09 03:43:56 +02:00
if ( lastFrameChunk & & ( op > ostart ) ) cctx - > stage = ZSTDcs_ending ;
return op - ostart ;
}
static size_t ZSTD_writeFrameHeader ( void * dst , size_t dstCapacity ,
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params params , U64 pledgedSrcSize , U32 dictID )
2017-06-09 03:43:56 +02:00
{ BYTE * const op = ( BYTE * ) dst ;
U32 const dictIDSizeCodeLength = ( dictID > 0 ) + ( dictID > = 256 ) + ( dictID > = 65536 ) ; /* 0-3 */
U32 const dictIDSizeCode = params . fParams . noDictIDFlag ? 0 : dictIDSizeCodeLength ; /* 0-3 */
U32 const checksumFlag = params . fParams . checksumFlag > 0 ;
2017-10-26 22:41:47 +02:00
U32 const windowSize = ( U32 ) 1 < < params . cParams . windowLog ;
2017-06-09 03:43:56 +02:00
U32 const singleSegment = params . fParams . contentSizeFlag & & ( windowSize > = pledgedSrcSize ) ;
BYTE const windowLogByte = ( BYTE ) ( ( params . cParams . windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN ) < < 3 ) ;
U32 const fcsCode = params . fParams . contentSizeFlag ?
2017-07-22 23:46:05 +02:00
( pledgedSrcSize > = 256 ) + ( pledgedSrcSize > = 65536 + 256 ) + ( pledgedSrcSize > = 0xFFFFFFFFU ) : 0 ; /* 0-3 */
2017-06-09 03:43:56 +02:00
BYTE const frameHeaderDecriptionByte = ( BYTE ) ( dictIDSizeCode + ( checksumFlag < < 2 ) + ( singleSegment < < 5 ) + ( fcsCode < < 6 ) ) ;
2017-10-26 22:41:47 +02:00
size_t pos = 0 ;
2017-06-09 03:43:56 +02:00
if ( dstCapacity < ZSTD_frameHeaderSize_max ) return ERROR ( dstSize_tooSmall ) ;
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 4 , " ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u " ,
2017-07-22 23:46:05 +02:00
! params . fParams . noDictIDFlag , dictID , dictIDSizeCode ) ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
if ( params . format = = ZSTD_f_zstd1 ) {
MEM_writeLE32 ( dst , ZSTD_MAGICNUMBER ) ;
pos = 4 ;
}
op [ pos + + ] = frameHeaderDecriptionByte ;
2017-06-09 03:43:56 +02:00
if ( ! singleSegment ) op [ pos + + ] = windowLogByte ;
switch ( dictIDSizeCode )
{
2017-07-22 23:46:05 +02:00
default : assert ( 0 ) ; /* impossible */
2017-06-09 03:43:56 +02:00
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 ;
}
switch ( fcsCode )
{
2017-07-22 23:46:05 +02:00
default : assert ( 0 ) ; /* impossible */
2017-06-09 03:43:56 +02:00
case 0 : if ( singleSegment ) op [ pos + + ] = ( BYTE ) ( pledgedSrcSize ) ; break ;
case 1 : MEM_writeLE16 ( op + pos , ( U16 ) ( pledgedSrcSize - 256 ) ) ; pos + = 2 ; break ;
case 2 : MEM_writeLE32 ( op + pos , ( U32 ) ( pledgedSrcSize ) ) ; pos + = 4 ; break ;
case 3 : MEM_writeLE64 ( op + pos , ( U64 ) ( pledgedSrcSize ) ) ; pos + = 8 ; break ;
}
return pos ;
}
static size_t ZSTD_compressContinue_internal ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
U32 frame , U32 lastFrameChunk )
{
const BYTE * const ip = ( const BYTE * ) src ;
size_t fhSize = 0 ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " ZSTD_compressContinue_internal, stage: %u " , cctx - > stage ) ;
2017-06-09 03:43:56 +02:00
if ( cctx - > stage = = ZSTDcs_created ) return ERROR ( stage_wrong ) ; /* missing init (ZSTD_compressBegin) */
if ( frame & & ( cctx - > stage = = ZSTDcs_init ) ) {
2017-07-22 23:46:05 +02:00
fhSize = ZSTD_writeFrameHeader ( dst , dstCapacity , cctx - > appliedParams ,
2017-10-26 22:41:47 +02:00
cctx - > pledgedSrcSizePlusOne - 1 , cctx - > dictID ) ;
2017-06-09 03:43:56 +02:00
if ( ZSTD_isError ( fhSize ) ) return fhSize ;
dstCapacity - = fhSize ;
dst = ( char * ) dst + fhSize ;
cctx - > stage = ZSTDcs_ongoing ;
}
2018-01-13 13:50:59 +01:00
if ( ! srcSize ) return fhSize ; /* do not generate an empty block if no input */
2017-06-09 03:43:56 +02:00
/* Check if blocks follow each other */
if ( src ! = cctx - > nextSrc ) {
/* not contiguous */
2018-01-13 13:50:59 +01:00
size_t const distanceFromBase = ( size_t ) ( cctx - > nextSrc - cctx - > base ) ;
2017-06-09 03:43:56 +02:00
cctx - > lowLimit = cctx - > dictLimit ;
2018-01-13 13:50:59 +01:00
assert ( distanceFromBase = = ( size_t ) ( U32 ) distanceFromBase ) ; /* should never overflow */
cctx - > dictLimit = ( U32 ) distanceFromBase ;
2017-06-09 03:43:56 +02:00
cctx - > dictBase = cctx - > base ;
2018-01-13 13:50:59 +01:00
cctx - > base = ip - distanceFromBase ;
2017-06-09 03:43:56 +02:00
cctx - > nextToUpdate = cctx - > dictLimit ;
if ( cctx - > dictLimit - cctx - > lowLimit < HASH_READ_SIZE ) cctx - > lowLimit = cctx - > dictLimit ; /* too small extDict */
}
2018-01-13 13:50:59 +01:00
cctx - > nextSrc = ip + srcSize ;
2017-06-09 03:43:56 +02:00
/* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
if ( ( ip + srcSize > cctx - > dictBase + cctx - > lowLimit ) & ( ip < cctx - > dictBase + cctx - > dictLimit ) ) {
ptrdiff_t const highInputIdx = ( ip + srcSize ) - cctx - > dictBase ;
U32 const lowLimitMax = ( highInputIdx > ( ptrdiff_t ) cctx - > dictLimit ) ? cctx - > dictLimit : ( U32 ) highInputIdx ;
cctx - > lowLimit = lowLimitMax ;
}
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " ZSTD_compressContinue_internal (blockSize=%u) " , ( U32 ) cctx - > blockSize ) ;
{ size_t const cSize = frame ?
2017-07-22 23:46:05 +02:00
ZSTD_compress_frameChunk ( cctx , dst , dstCapacity , src , srcSize , lastFrameChunk ) :
2017-06-09 03:43:56 +02:00
ZSTD_compressBlock_internal ( cctx , dst , dstCapacity , src , srcSize ) ;
if ( ZSTD_isError ( cSize ) ) return cSize ;
cctx - > consumedSrcSize + = srcSize ;
return cSize + fhSize ;
2018-01-13 13:50:59 +01:00
}
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_compressContinue ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize )
{
return ZSTD_compressContinue_internal ( cctx , dst , dstCapacity , src , srcSize , 1 /* frame mode */ , 0 /* last chunk */ ) ;
}
2017-07-22 23:46:05 +02:00
size_t ZSTD_getBlockSize ( const ZSTD_CCtx * cctx )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams ( cctx - > appliedParams , 0 , 0 ) ;
return MIN ( ZSTD_BLOCKSIZE_MAX , ( U32 ) 1 < < cParams . windowLog ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_compressBlock ( ZSTD_CCtx * cctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize )
{
2017-07-22 23:46:05 +02:00
size_t const blockSizeMax = ZSTD_getBlockSize ( cctx ) ;
2017-06-09 03:43:56 +02:00
if ( srcSize > blockSizeMax ) return ERROR ( srcSize_wrong ) ;
return ZSTD_compressContinue_internal ( cctx , dst , dstCapacity , src , srcSize , 0 /* frame mode */ , 0 /* last chunk */ ) ;
}
/*! ZSTD_loadDictionaryContent() :
* @ return : 0 , or an error code
*/
static size_t ZSTD_loadDictionaryContent ( ZSTD_CCtx * zc , const void * src , size_t srcSize )
{
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 ;
2018-01-13 13:50:59 +01:00
zc - > base = ip - zc - > dictLimit ;
2017-06-09 03:43:56 +02:00
zc - > nextToUpdate = zc - > dictLimit ;
2017-10-26 22:41:47 +02:00
zc - > loadedDictEnd = zc - > appliedParams . forceWindow ? 0 : ( U32 ) ( iend - zc - > base ) ;
2017-06-09 03:43:56 +02:00
zc - > nextSrc = iend ;
if ( srcSize < = HASH_READ_SIZE ) return 0 ;
2017-07-22 23:46:05 +02:00
switch ( zc - > appliedParams . cParams . strategy )
2017-06-09 03:43:56 +02:00
{
case ZSTD_fast :
2017-07-22 23:46:05 +02:00
ZSTD_fillHashTable ( zc , iend , zc - > appliedParams . cParams . searchLength ) ;
2017-06-09 03:43:56 +02:00
break ;
case ZSTD_dfast :
2017-07-22 23:46:05 +02:00
ZSTD_fillDoubleHashTable ( zc , iend , zc - > appliedParams . cParams . searchLength ) ;
2017-06-09 03:43:56 +02:00
break ;
case ZSTD_greedy :
case ZSTD_lazy :
case ZSTD_lazy2 :
if ( srcSize > = HASH_READ_SIZE )
2017-07-22 23:46:05 +02:00
ZSTD_insertAndFindFirstIndex ( zc , iend - HASH_READ_SIZE , zc - > appliedParams . cParams . searchLength ) ;
2017-06-09 03:43:56 +02:00
break ;
case ZSTD_btlazy2 :
case ZSTD_btopt :
2017-07-22 23:46:05 +02:00
case ZSTD_btultra :
2017-06-09 03:43:56 +02:00
if ( srcSize > = HASH_READ_SIZE )
2017-10-26 22:41:47 +02:00
ZSTD_updateTree ( zc , iend - HASH_READ_SIZE , iend , ( U32 ) 1 < < zc - > appliedParams . cParams . searchLog , zc - > appliedParams . cParams . searchLength ) ;
2017-06-09 03:43:56 +02:00
break ;
default :
2017-07-22 23:46:05 +02:00
assert ( 0 ) ; /* not possible : not a valid strategy id */
2017-06-09 03:43:56 +02:00
}
zc - > nextToUpdate = ( U32 ) ( iend - zc - > base ) ;
return 0 ;
}
/* Dictionaries that assign zero probability to symbols that show up causes problems
when FSE encoding . Refuse dictionaries that assign zero probability to symbols
that we may encounter during compression .
NOTE : This behavior is not standard and could be improved in the future . */
static size_t ZSTD_checkDictNCount ( short * normalizedCounter , unsigned dictMaxSymbolValue , unsigned maxSymbolValue ) {
U32 s ;
if ( dictMaxSymbolValue < maxSymbolValue ) return ERROR ( dictionary_corrupted ) ;
for ( s = 0 ; s < = maxSymbolValue ; + + s ) {
if ( normalizedCounter [ s ] = = 0 ) return ERROR ( dictionary_corrupted ) ;
}
return 0 ;
}
/* Dictionary format :
* See :
* https : //github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
*/
/*! ZSTD_loadZstdDictionary() :
* @ return : 0 , or an error code
* assumptions : magic number supposed already checked
* dictSize supposed > 8
*/
static size_t ZSTD_loadZstdDictionary ( ZSTD_CCtx * cctx , const void * dict , size_t dictSize )
{
const BYTE * dictPtr = ( const BYTE * ) dict ;
const BYTE * const dictEnd = dictPtr + dictSize ;
short offcodeNCount [ MaxOff + 1 ] ;
unsigned offcodeMaxValue = MaxOff ;
2017-08-27 12:05:17 +02:00
ZSTD_STATIC_ASSERT ( sizeof ( cctx - > entropy - > workspace ) > = ( 1 < < MAX ( MLFSELog , LLFSELog ) ) ) ;
2017-06-09 03:43:56 +02:00
dictPtr + = 4 ; /* skip magic number */
2017-07-22 23:46:05 +02:00
cctx - > dictID = cctx - > appliedParams . fParams . noDictIDFlag ? 0 : MEM_readLE32 ( dictPtr ) ;
2017-06-09 03:43:56 +02:00
dictPtr + = 4 ;
2017-10-26 22:41:47 +02:00
{ unsigned maxSymbolValue = 255 ;
size_t const hufHeaderSize = HUF_readCTable ( ( HUF_CElt * ) cctx - > entropy - > hufCTable , & maxSymbolValue , dictPtr , dictEnd - dictPtr ) ;
2017-06-09 03:43:56 +02:00
if ( HUF_isError ( hufHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
2017-10-26 22:41:47 +02:00
if ( maxSymbolValue < 255 ) return ERROR ( dictionary_corrupted ) ;
2017-06-09 03:43:56 +02:00
dictPtr + = hufHeaderSize ;
}
{ unsigned offcodeLog ;
size_t const offcodeHeaderSize = FSE_readNCount ( offcodeNCount , & offcodeMaxValue , & offcodeLog , dictPtr , dictEnd - dictPtr ) ;
if ( FSE_isError ( offcodeHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
if ( offcodeLog > OffFSELog ) return ERROR ( dictionary_corrupted ) ;
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
2017-08-27 12:05:17 +02:00
CHECK_E ( FSE_buildCTable_wksp ( cctx - > entropy - > offcodeCTable , offcodeNCount , offcodeMaxValue , offcodeLog , cctx - > entropy - > workspace , sizeof ( cctx - > entropy - > workspace ) ) ,
2017-06-09 03:43:56 +02:00
dictionary_corrupted ) ;
dictPtr + = offcodeHeaderSize ;
}
{ short matchlengthNCount [ MaxML + 1 ] ;
unsigned matchlengthMaxValue = MaxML , matchlengthLog ;
size_t const matchlengthHeaderSize = FSE_readNCount ( matchlengthNCount , & matchlengthMaxValue , & matchlengthLog , dictPtr , dictEnd - dictPtr ) ;
if ( FSE_isError ( matchlengthHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
if ( matchlengthLog > MLFSELog ) return ERROR ( dictionary_corrupted ) ;
/* Every match length code must have non-zero probability */
CHECK_F ( ZSTD_checkDictNCount ( matchlengthNCount , matchlengthMaxValue , MaxML ) ) ;
2017-08-27 12:05:17 +02:00
CHECK_E ( FSE_buildCTable_wksp ( cctx - > entropy - > matchlengthCTable , matchlengthNCount , matchlengthMaxValue , matchlengthLog , cctx - > entropy - > workspace , sizeof ( cctx - > entropy - > workspace ) ) ,
2017-06-09 03:43:56 +02:00
dictionary_corrupted ) ;
dictPtr + = matchlengthHeaderSize ;
}
{ short litlengthNCount [ MaxLL + 1 ] ;
unsigned litlengthMaxValue = MaxLL , litlengthLog ;
size_t const litlengthHeaderSize = FSE_readNCount ( litlengthNCount , & litlengthMaxValue , & litlengthLog , dictPtr , dictEnd - dictPtr ) ;
if ( FSE_isError ( litlengthHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
if ( litlengthLog > LLFSELog ) return ERROR ( dictionary_corrupted ) ;
/* Every literal length code must have non-zero probability */
CHECK_F ( ZSTD_checkDictNCount ( litlengthNCount , litlengthMaxValue , MaxLL ) ) ;
2017-08-27 12:05:17 +02:00
CHECK_E ( FSE_buildCTable_wksp ( cctx - > entropy - > litlengthCTable , litlengthNCount , litlengthMaxValue , litlengthLog , cctx - > entropy - > workspace , sizeof ( cctx - > entropy - > workspace ) ) ,
2017-06-09 03:43:56 +02:00
dictionary_corrupted ) ;
dictPtr + = litlengthHeaderSize ;
}
if ( dictPtr + 12 > dictEnd ) return ERROR ( dictionary_corrupted ) ;
2017-08-27 12:05:17 +02:00
cctx - > seqStore . rep [ 0 ] = MEM_readLE32 ( dictPtr + 0 ) ;
cctx - > seqStore . rep [ 1 ] = MEM_readLE32 ( dictPtr + 4 ) ;
cctx - > seqStore . rep [ 2 ] = MEM_readLE32 ( dictPtr + 8 ) ;
2017-06-09 03:43:56 +02:00
dictPtr + = 12 ;
{ size_t const dictContentSize = ( size_t ) ( dictEnd - dictPtr ) ;
U32 offcodeMax = MaxOff ;
if ( dictContentSize < = ( ( U32 ) - 1 ) - 128 KB ) {
U32 const maxOffset = ( U32 ) dictContentSize + 128 KB ; /* The maximum offset that must be supported */
offcodeMax = ZSTD_highbit32 ( maxOffset ) ; /* Calculate minimum offset code required to represent maxOffset */
}
/* All offset values <= dictContentSize + 128 KB must be representable */
CHECK_F ( ZSTD_checkDictNCount ( offcodeNCount , offcodeMaxValue , MIN ( offcodeMax , MaxOff ) ) ) ;
/* All repCodes must be <= dictContentSize and != 0*/
{ U32 u ;
for ( u = 0 ; u < 3 ; u + + ) {
2017-08-27 12:05:17 +02:00
if ( cctx - > seqStore . rep [ u ] = = 0 ) return ERROR ( dictionary_corrupted ) ;
if ( cctx - > seqStore . rep [ u ] > dictContentSize ) return ERROR ( dictionary_corrupted ) ;
2017-06-09 03:43:56 +02:00
} }
2017-08-27 12:05:17 +02:00
cctx - > entropy - > hufCTable_repeatMode = HUF_repeat_valid ;
cctx - > entropy - > offcode_repeatMode = FSE_repeat_valid ;
cctx - > entropy - > matchlength_repeatMode = FSE_repeat_valid ;
cctx - > entropy - > litlength_repeatMode = FSE_repeat_valid ;
2017-06-09 03:43:56 +02:00
return ZSTD_loadDictionaryContent ( cctx , dictPtr , dictContentSize ) ;
}
}
/** ZSTD_compress_insertDictionary() :
* @ return : 0 , or an error code */
2017-07-22 23:46:05 +02:00
static size_t ZSTD_compress_insertDictionary ( ZSTD_CCtx * cctx ,
const void * dict , size_t dictSize ,
ZSTD_dictMode_e dictMode )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compress_insertDictionary (dictSize=%u) " , ( U32 ) dictSize ) ;
2017-06-09 03:43:56 +02:00
if ( ( dict = = NULL ) | | ( dictSize < = 8 ) ) return 0 ;
2017-07-22 23:46:05 +02:00
/* dict restricted modes */
if ( dictMode = = ZSTD_dm_rawContent )
2017-06-09 03:43:56 +02:00
return ZSTD_loadDictionaryContent ( cctx , dict , dictSize ) ;
2017-07-22 23:46:05 +02:00
if ( MEM_readLE32 ( dict ) ! = ZSTD_MAGIC_DICTIONARY ) {
if ( dictMode = = ZSTD_dm_auto ) {
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " raw content dictionary detected " ) ;
2017-07-22 23:46:05 +02:00
return ZSTD_loadDictionaryContent ( cctx , dict , dictSize ) ;
}
if ( dictMode = = ZSTD_dm_fullDict )
return ERROR ( dictionary_wrong ) ;
assert ( 0 ) ; /* impossible */
}
/* dict as full zstd dictionary */
2017-06-09 03:43:56 +02:00
return ZSTD_loadZstdDictionary ( cctx , dict , dictSize ) ;
}
/*! ZSTD_compressBegin_internal() :
2017-07-22 23:46:05 +02:00
* @ return : 0 , or an error code */
2018-01-13 13:50:59 +01:00
size_t ZSTD_compressBegin_internal ( ZSTD_CCtx * cctx ,
2017-06-09 03:43:56 +02:00
const void * dict , size_t dictSize ,
2017-07-22 23:46:05 +02:00
ZSTD_dictMode_e dictMode ,
const ZSTD_CDict * cdict ,
2018-01-13 13:50:59 +01:00
ZSTD_CCtx_params params , U64 pledgedSrcSize ,
ZSTD_buffered_policy_e zbuff )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compressBegin_internal: wlog=%u " , params . cParams . windowLog ) ;
2017-07-22 23:46:05 +02:00
/* params are supposed to be fully validated at this point */
2017-06-09 03:43:56 +02:00
assert ( ! ZSTD_isError ( ZSTD_checkCParams ( params . cParams ) ) ) ;
2017-07-22 23:46:05 +02:00
assert ( ! ( ( dict ) & & ( cdict ) ) ) ; /* either dict or cdict, not both */
if ( cdict & & cdict - > dictContentSize > 0 ) {
2018-01-13 13:50:59 +01:00
cctx - > requestedParams = params ;
2017-07-22 23:46:05 +02:00
return ZSTD_copyCCtx_internal ( cctx , cdict - > refContext ,
2018-01-13 13:50:59 +01:00
params . cParams . windowLog , params . fParams , pledgedSrcSize ,
2017-07-22 23:46:05 +02:00
zbuff ) ;
}
CHECK_F ( ZSTD_resetCCtx_internal ( cctx , params , pledgedSrcSize ,
ZSTDcrp_continue , zbuff ) ) ;
return ZSTD_compress_insertDictionary ( cctx , dict , dictSize , dictMode ) ;
2017-06-09 03:43:56 +02:00
}
2018-01-13 13:50:59 +01:00
size_t ZSTD_compressBegin_advanced_internal ( ZSTD_CCtx * cctx ,
2017-10-26 22:41:47 +02:00
const void * dict , size_t dictSize ,
ZSTD_dictMode_e dictMode ,
2018-01-13 13:50:59 +01:00
const ZSTD_CDict * cdict ,
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params params ,
unsigned long long pledgedSrcSize )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compressBegin_advanced_internal: wlog=%u " , params . cParams . windowLog ) ;
2017-10-26 22:41:47 +02:00
/* compression parameters verification and optimization */
CHECK_F ( ZSTD_checkCParams ( params . cParams ) ) ;
2018-01-13 13:50:59 +01:00
return ZSTD_compressBegin_internal ( cctx ,
dict , dictSize , dictMode ,
cdict ,
2017-10-26 22:41:47 +02:00
params , pledgedSrcSize ,
ZSTDb_not_buffered ) ;
}
2017-06-09 03:43:56 +02:00
/*! ZSTD_compressBegin_advanced() :
* @ return : 0 , or an error code */
size_t ZSTD_compressBegin_advanced ( ZSTD_CCtx * cctx ,
const void * dict , size_t dictSize ,
ZSTD_parameters params , unsigned long long pledgedSrcSize )
{
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams ( cctx - > requestedParams , params ) ;
2018-01-13 13:50:59 +01:00
return ZSTD_compressBegin_advanced_internal ( cctx ,
dict , dictSize , ZSTD_dm_auto ,
NULL /*cdict*/ ,
cctxParams , pledgedSrcSize ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_compressBegin_usingDict ( ZSTD_CCtx * cctx , const void * dict , size_t dictSize , int compressionLevel )
{
ZSTD_parameters const params = ZSTD_getParams ( compressionLevel , 0 , dictSize ) ;
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams ( cctx - > requestedParams , params ) ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compressBegin_usingDict " ) ;
2017-07-22 23:46:05 +02:00
return ZSTD_compressBegin_internal ( cctx , dict , dictSize , ZSTD_dm_auto , NULL ,
2018-01-13 13:50:59 +01:00
cctxParams , ZSTD_CONTENTSIZE_UNKNOWN , ZSTDb_not_buffered ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_compressBegin ( ZSTD_CCtx * cctx , int compressionLevel )
{
return ZSTD_compressBegin_usingDict ( cctx , NULL , 0 , compressionLevel ) ;
}
/*! ZSTD_writeEpilogue() :
* Ends a frame .
* @ return : nb of bytes written into dst ( or an error code ) */
static size_t ZSTD_writeEpilogue ( ZSTD_CCtx * cctx , void * dst , size_t dstCapacity )
{
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * op = ostart ;
size_t fhSize = 0 ;
2017-07-22 23:46:05 +02:00
DEBUGLOG ( 5 , " ZSTD_writeEpilogue " ) ;
2017-06-09 03:43:56 +02:00
if ( cctx - > stage = = ZSTDcs_created ) return ERROR ( stage_wrong ) ; /* init missing */
/* special case : empty frame */
if ( cctx - > stage = = ZSTDcs_init ) {
2017-07-22 23:46:05 +02:00
fhSize = ZSTD_writeFrameHeader ( dst , dstCapacity , cctx - > appliedParams , 0 , 0 ) ;
2017-06-09 03:43:56 +02:00
if ( ZSTD_isError ( fhSize ) ) return fhSize ;
dstCapacity - = fhSize ;
op + = fhSize ;
cctx - > stage = ZSTDcs_ongoing ;
}
if ( cctx - > stage ! = ZSTDcs_ending ) {
/* write one last empty block, make it the "last" block */
U32 const cBlockHeader24 = 1 /* last block */ + ( ( ( U32 ) bt_raw ) < < 1 ) + 0 ;
if ( dstCapacity < 4 ) return ERROR ( dstSize_tooSmall ) ;
MEM_writeLE32 ( op , cBlockHeader24 ) ;
op + = ZSTD_blockHeaderSize ;
dstCapacity - = ZSTD_blockHeaderSize ;
}
2017-07-22 23:46:05 +02:00
if ( cctx - > appliedParams . fParams . checksumFlag ) {
2017-06-09 03:43:56 +02:00
U32 const checksum = ( U32 ) XXH64_digest ( & cctx - > xxhState ) ;
if ( dstCapacity < 4 ) return ERROR ( dstSize_tooSmall ) ;
MEM_writeLE32 ( op , checksum ) ;
op + = 4 ;
}
cctx - > stage = ZSTDcs_created ; /* return to "created but no init" status */
return op - ostart ;
}
size_t ZSTD_compressEnd ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize )
{
size_t endResult ;
2017-07-22 23:46:05 +02:00
size_t const cSize = ZSTD_compressContinue_internal ( cctx ,
dst , dstCapacity , src , srcSize ,
1 /* frame mode */ , 1 /* last chunk */ ) ;
2017-06-09 03:43:56 +02:00
if ( ZSTD_isError ( cSize ) ) return cSize ;
endResult = ZSTD_writeEpilogue ( cctx , ( char * ) dst + cSize , dstCapacity - cSize ) ;
if ( ZSTD_isError ( endResult ) ) return endResult ;
2017-07-22 23:46:05 +02:00
if ( cctx - > appliedParams . fParams . contentSizeFlag ) { /* control src size */
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 4 , " end of frame : controlling src size " ) ;
2017-07-22 23:46:05 +02:00
if ( cctx - > pledgedSrcSizePlusOne ! = cctx - > consumedSrcSize + 1 ) {
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 4 , " error : pledgedSrcSize = %u, while realSrcSize = %u " ,
2017-07-22 23:46:05 +02:00
( U32 ) cctx - > pledgedSrcSizePlusOne - 1 , ( U32 ) cctx - > consumedSrcSize ) ;
return ERROR ( srcSize_wrong ) ;
} }
2017-06-09 03:43:56 +02:00
return cSize + endResult ;
}
static size_t ZSTD_compress_internal ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const void * dict , size_t dictSize ,
ZSTD_parameters params )
{
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams ( cctx - > requestedParams , params ) ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compress_internal " ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_compress_advanced_internal ( cctx ,
dst , dstCapacity ,
src , srcSize ,
dict , dictSize ,
cctxParams ) ;
2017-06-09 03:43:56 +02: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 )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compress_advanced " ) ;
2017-06-09 03:43:56 +02:00
CHECK_F ( ZSTD_checkCParams ( params . cParams ) ) ;
return ZSTD_compress_internal ( ctx , dst , dstCapacity , src , srcSize , dict , dictSize , params ) ;
}
2017-10-26 22:41:47 +02:00
/* Internal */
size_t ZSTD_compress_advanced_internal (
ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const void * dict , size_t dictSize ,
ZSTD_CCtx_params params )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compress_advanced_internal " ) ;
2017-10-26 22:41:47 +02:00
CHECK_F ( ZSTD_compressBegin_internal ( cctx , dict , dictSize , ZSTD_dm_auto , NULL ,
params , srcSize , ZSTDb_not_buffered ) ) ;
return ZSTD_compressEnd ( cctx , dst , dstCapacity , src , srcSize ) ;
}
2017-06-09 03:43:56 +02: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 )
{
2018-01-13 13:50:59 +01:00
ZSTD_parameters params = ZSTD_getParams ( compressionLevel , srcSize ? srcSize : 1 , dict ? dictSize : 0 ) ;
2017-06-09 03:43:56 +02:00
params . fParams . contentSizeFlag = 1 ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compress_usingDict (level=%i, srcSize=%u, dictSize=%u) " ,
compressionLevel , ( U32 ) srcSize , ( U32 ) dictSize ) ;
2017-06-09 03:43:56 +02:00
return ZSTD_compress_internal ( ctx , dst , dstCapacity , src , srcSize , dict , dictSize , params ) ;
}
size_t ZSTD_compressCCtx ( ZSTD_CCtx * ctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize , int compressionLevel )
{
return ZSTD_compress_usingDict ( ctx , dst , dstCapacity , src , srcSize , NULL , 0 , compressionLevel ) ;
}
size_t ZSTD_compress ( void * dst , size_t dstCapacity , const void * src , size_t srcSize , int compressionLevel )
{
size_t result ;
ZSTD_CCtx ctxBody ;
memset ( & ctxBody , 0 , sizeof ( ctxBody ) ) ;
2017-07-22 23:46:05 +02:00
ctxBody . customMem = ZSTD_defaultCMem ;
2017-06-09 03:43:56 +02:00
result = ZSTD_compressCCtx ( & ctxBody , dst , dstCapacity , src , srcSize , compressionLevel ) ;
2017-07-22 23:46:05 +02:00
ZSTD_free ( ctxBody . workSpace , ZSTD_defaultCMem ) ; /* can't free ctxBody itself, as it's on stack; free only heap content */
2017-06-09 03:43:56 +02:00
return result ;
}
/* ===== Dictionary API ===== */
2017-07-22 23:46:05 +02:00
/*! ZSTD_estimateCDictSize_advanced() :
* Estimate amount of memory that will be needed to create a dictionary with following arguments */
2017-10-26 22:41:47 +02:00
size_t ZSTD_estimateCDictSize_advanced (
size_t dictSize , ZSTD_compressionParameters cParams ,
ZSTD_dictLoadMethod_e dictLoadMethod )
2017-07-22 23:46:05 +02:00
{
DEBUGLOG ( 5 , " sizeof(ZSTD_CDict) : %u " , ( U32 ) sizeof ( ZSTD_CDict ) ) ;
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 5 , " CCtx estimate : %u " ,
( U32 ) ZSTD_estimateCCtxSize_usingCParams ( cParams ) ) ;
return sizeof ( ZSTD_CDict ) + ZSTD_estimateCCtxSize_usingCParams ( cParams )
+ ( dictLoadMethod = = ZSTD_dlm_byRef ? 0 : dictSize ) ;
2017-07-22 23:46:05 +02:00
}
size_t ZSTD_estimateCDictSize ( size_t dictSize , int compressionLevel )
{
ZSTD_compressionParameters const cParams = ZSTD_getCParams ( compressionLevel , 0 , dictSize ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_estimateCDictSize_advanced ( dictSize , cParams , ZSTD_dlm_byCopy ) ;
2017-07-22 23:46:05 +02:00
}
2017-06-09 03:43:56 +02:00
size_t ZSTD_sizeof_CDict ( const ZSTD_CDict * cdict )
{
if ( cdict = = NULL ) return 0 ; /* support sizeof on NULL */
2017-07-22 23:46:05 +02:00
DEBUGLOG ( 5 , " sizeof(*cdict) : %u " , ( U32 ) sizeof ( * cdict ) ) ;
DEBUGLOG ( 5 , " ZSTD_sizeof_CCtx : %u " , ( U32 ) ZSTD_sizeof_CCtx ( cdict - > refContext ) ) ;
2017-06-09 03:43:56 +02:00
return ZSTD_sizeof_CCtx ( cdict - > refContext ) + ( cdict - > dictBuffer ? cdict - > dictContentSize : 0 ) + sizeof ( * cdict ) ;
}
2017-07-22 23:46:05 +02:00
static size_t ZSTD_initCDict_internal (
ZSTD_CDict * cdict ,
const void * dictBuffer , size_t dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dictLoadMethod_e dictLoadMethod ,
ZSTD_dictMode_e dictMode ,
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters cParams )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 3 , " ZSTD_initCDict_internal, mode %u " , ( U32 ) dictMode ) ;
2017-10-26 22:41:47 +02:00
if ( ( dictLoadMethod = = ZSTD_dlm_byRef ) | | ( ! dictBuffer ) | | ( ! dictSize ) ) {
2017-07-22 23:46:05 +02:00
cdict - > dictBuffer = NULL ;
cdict - > dictContent = dictBuffer ;
} else {
void * const internalBuffer = ZSTD_malloc ( dictSize , cdict - > refContext - > customMem ) ;
cdict - > dictBuffer = internalBuffer ;
cdict - > dictContent = internalBuffer ;
if ( ! internalBuffer ) return ERROR ( memory_allocation ) ;
memcpy ( internalBuffer , dictBuffer , dictSize ) ;
}
cdict - > dictContentSize = dictSize ;
2017-10-26 22:41:47 +02:00
{ ZSTD_CCtx_params cctxParams = cdict - > refContext - > requestedParams ;
cctxParams . cParams = cParams ;
2017-07-22 23:46:05 +02:00
CHECK_F ( ZSTD_compressBegin_internal ( cdict - > refContext ,
cdict - > dictContent , dictSize , dictMode ,
NULL ,
2017-10-26 22:41:47 +02:00
cctxParams , ZSTD_CONTENTSIZE_UNKNOWN ,
2017-07-22 23:46:05 +02:00
ZSTDb_not_buffered ) ) ;
}
return 0 ;
}
ZSTD_CDict * ZSTD_createCDict_advanced ( const void * dictBuffer , size_t dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dictLoadMethod_e dictLoadMethod ,
ZSTD_dictMode_e dictMode ,
2017-06-09 03:43:56 +02:00
ZSTD_compressionParameters cParams , ZSTD_customMem customMem )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 3 , " ZSTD_createCDict_advanced, mode %u " , ( U32 ) dictMode ) ;
2017-07-22 23:46:05 +02:00
if ( ! customMem . customAlloc ^ ! customMem . customFree ) return NULL ;
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
{ ZSTD_CDict * const cdict = ( ZSTD_CDict * ) ZSTD_malloc ( sizeof ( ZSTD_CDict ) , customMem ) ;
2017-06-09 03:43:56 +02:00
ZSTD_CCtx * const cctx = ZSTD_createCCtx_advanced ( customMem ) ;
if ( ! cdict | | ! cctx ) {
ZSTD_free ( cdict , customMem ) ;
ZSTD_freeCCtx ( cctx ) ;
return NULL ;
}
2017-07-22 23:46:05 +02:00
cdict - > refContext = cctx ;
if ( ZSTD_isError ( ZSTD_initCDict_internal ( cdict ,
dictBuffer , dictSize ,
2017-10-26 22:41:47 +02:00
dictLoadMethod , dictMode ,
2017-07-22 23:46:05 +02:00
cParams ) ) ) {
ZSTD_freeCDict ( cdict ) ;
return NULL ;
2017-06-09 03:43:56 +02:00
}
return cdict ;
}
}
ZSTD_CDict * ZSTD_createCDict ( const void * dict , size_t dictSize , int compressionLevel )
{
ZSTD_compressionParameters cParams = ZSTD_getCParams ( compressionLevel , 0 , dictSize ) ;
2017-07-22 23:46:05 +02:00
return ZSTD_createCDict_advanced ( dict , dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dlm_byCopy , ZSTD_dm_auto ,
2017-07-22 23:46:05 +02:00
cParams , ZSTD_defaultCMem ) ;
2017-06-09 03:43:56 +02:00
}
ZSTD_CDict * ZSTD_createCDict_byReference ( const void * dict , size_t dictSize , int compressionLevel )
{
ZSTD_compressionParameters cParams = ZSTD_getCParams ( compressionLevel , 0 , dictSize ) ;
2017-07-22 23:46:05 +02:00
return ZSTD_createCDict_advanced ( dict , dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dlm_byRef , ZSTD_dm_auto ,
2017-07-22 23:46:05 +02:00
cParams , ZSTD_defaultCMem ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_freeCDict ( ZSTD_CDict * cdict )
{
if ( cdict = = NULL ) return 0 ; /* support free on NULL */
{ ZSTD_customMem const cMem = cdict - > refContext - > customMem ;
ZSTD_freeCCtx ( cdict - > refContext ) ;
ZSTD_free ( cdict - > dictBuffer , cMem ) ;
ZSTD_free ( cdict , cMem ) ;
return 0 ;
}
}
2017-07-22 23:46:05 +02:00
/*! ZSTD_initStaticCDict_advanced() :
* Generate a digested dictionary in provided memory area .
* workspace : The memory area to emplace the dictionary into .
* Provided pointer must 8 - bytes aligned .
* It must outlive dictionary usage .
* workspaceSize : Use ZSTD_estimateCDictSize ( )
* to determine how large workspace must be .
* cParams : use ZSTD_getCParams ( ) to transform a compression level
* into its relevants cParams .
* @ return : pointer to ZSTD_CDict * , or NULL if error ( size too small )
* Note : there is no corresponding " free " function .
* Since workspace was allocated externally , it must be freed externally .
*/
ZSTD_CDict * ZSTD_initStaticCDict ( void * workspace , size_t workspaceSize ,
const void * dict , size_t dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dictLoadMethod_e dictLoadMethod ,
ZSTD_dictMode_e dictMode ,
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters cParams )
{
2017-10-26 22:41:47 +02:00
size_t const cctxSize = ZSTD_estimateCCtxSize_usingCParams ( cParams ) ;
size_t const neededSize = sizeof ( ZSTD_CDict ) + ( dictLoadMethod = = ZSTD_dlm_byRef ? 0 : dictSize )
2017-07-22 23:46:05 +02:00
+ cctxSize ;
ZSTD_CDict * const cdict = ( ZSTD_CDict * ) workspace ;
void * ptr ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " (size_t)workspace & 7 : %u " , ( U32 ) ( size_t ) workspace & 7 ) ;
2017-07-22 23:46:05 +02:00
if ( ( size_t ) workspace & 7 ) return NULL ; /* 8-aligned */
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " (workspaceSize < neededSize) : (%u < %u) => %u " ,
2017-07-22 23:46:05 +02:00
( U32 ) workspaceSize , ( U32 ) neededSize , ( U32 ) ( workspaceSize < neededSize ) ) ;
if ( workspaceSize < neededSize ) return NULL ;
2017-10-26 22:41:47 +02:00
if ( dictLoadMethod = = ZSTD_dlm_byCopy ) {
2017-07-22 23:46:05 +02:00
memcpy ( cdict + 1 , dict , dictSize ) ;
dict = cdict + 1 ;
ptr = ( char * ) workspace + sizeof ( ZSTD_CDict ) + dictSize ;
} else {
ptr = cdict + 1 ;
}
cdict - > refContext = ZSTD_initStaticCCtx ( ptr , cctxSize ) ;
if ( ZSTD_isError ( ZSTD_initCDict_internal ( cdict ,
dict , dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dlm_byRef , dictMode ,
2017-07-22 23:46:05 +02:00
cParams ) ) )
return NULL ;
return cdict ;
}
2017-10-26 22:41:47 +02:00
ZSTD_compressionParameters ZSTD_getCParamsFromCDict ( const ZSTD_CDict * cdict ) {
return cdict - > refContext - > appliedParams . cParams ;
2017-06-09 03:43:56 +02:00
}
/* ZSTD_compressBegin_usingCDict_advanced() :
* cdict must be ! = NULL */
size_t ZSTD_compressBegin_usingCDict_advanced (
ZSTD_CCtx * const cctx , const ZSTD_CDict * const cdict ,
ZSTD_frameParameters const fParams , unsigned long long const pledgedSrcSize )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compressBegin_usingCDict_advanced " ) ;
2017-07-22 23:46:05 +02:00
if ( cdict = = NULL ) return ERROR ( dictionary_wrong ) ;
2017-10-26 22:41:47 +02:00
{ ZSTD_CCtx_params params = cctx - > requestedParams ;
params . cParams = ZSTD_getCParamsFromCDict ( cdict ) ;
2017-06-09 03:43:56 +02:00
params . fParams = fParams ;
2017-07-22 23:46:05 +02:00
return ZSTD_compressBegin_internal ( cctx ,
NULL , 0 , ZSTD_dm_auto ,
cdict ,
params , pledgedSrcSize ,
ZSTDb_not_buffered ) ;
2017-06-09 03:43:56 +02:00
}
}
/* ZSTD_compressBegin_usingCDict() :
* pledgedSrcSize = 0 means " unknown "
* if pledgedSrcSize > 0 , it will enable contentSizeFlag */
size_t ZSTD_compressBegin_usingCDict ( ZSTD_CCtx * cctx , const ZSTD_CDict * cdict )
{
ZSTD_frameParameters const fParams = { 0 /*content*/ , 0 /*checksum*/ , 0 /*noDictID*/ } ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_compressBegin_usingCDict : dictIDFlag == %u " , ! fParams . noDictIDFlag ) ;
2017-06-09 03:43:56 +02:00
return ZSTD_compressBegin_usingCDict_advanced ( cctx , cdict , fParams , 0 ) ;
}
size_t ZSTD_compress_usingCDict_advanced ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const ZSTD_CDict * cdict , ZSTD_frameParameters fParams )
{
CHECK_F ( ZSTD_compressBegin_usingCDict_advanced ( cctx , cdict , fParams , srcSize ) ) ; /* will check if cdict != NULL */
return ZSTD_compressEnd ( cctx , dst , dstCapacity , src , srcSize ) ;
}
/*! ZSTD_compress_usingCDict() :
* Compression using a digested Dictionary .
* Faster startup than ZSTD_compress_usingDict ( ) , recommended when same dictionary is used multiple times .
* Note that compression parameters are decided at CDict creation time
* while frame parameters are hardcoded */
size_t ZSTD_compress_usingCDict ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const ZSTD_CDict * cdict )
{
ZSTD_frameParameters const fParams = { 1 /*content*/ , 0 /*checksum*/ , 0 /*noDictID*/ } ;
return ZSTD_compress_usingCDict_advanced ( cctx , dst , dstCapacity , src , srcSize , cdict , fParams ) ;
}
/* ******************************************************************
* Streaming
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ZSTD_CStream * ZSTD_createCStream ( void )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 3 , " ZSTD_createCStream " ) ;
2017-07-22 23:46:05 +02:00
return ZSTD_createCStream_advanced ( ZSTD_defaultCMem ) ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
ZSTD_CStream * ZSTD_initStaticCStream ( void * workspace , size_t workspaceSize )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
return ZSTD_initStaticCCtx ( workspace , workspaceSize ) ;
}
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
ZSTD_CStream * ZSTD_createCStream_advanced ( ZSTD_customMem customMem )
{ /* CStream and CCtx are now same object */
return ZSTD_createCCtx_advanced ( customMem ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_freeCStream ( ZSTD_CStream * zcs )
{
2017-07-22 23:46:05 +02:00
return ZSTD_freeCCtx ( zcs ) ; /* same object */
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
2017-06-09 03:43:56 +02:00
/*====== Initialization ======*/
2017-07-22 23:46:05 +02:00
size_t ZSTD_CStreamInSize ( void ) { return ZSTD_BLOCKSIZE_MAX ; }
2017-06-09 03:43:56 +02:00
size_t ZSTD_CStreamOutSize ( void )
{
2017-07-22 23:46:05 +02:00
return ZSTD_compressBound ( ZSTD_BLOCKSIZE_MAX ) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
static size_t ZSTD_resetCStream_internal ( ZSTD_CStream * zcs ,
2018-01-13 13:50:59 +01:00
const void * const dict , size_t const dictSize , ZSTD_dictMode_e const dictMode ,
const ZSTD_CDict * const cdict ,
ZSTD_CCtx_params const params , unsigned long long const pledgedSrcSize )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
DEBUGLOG ( 4 , " ZSTD_resetCStream_internal " ) ;
/* params are supposed to be fully validated at this point */
assert ( ! ZSTD_isError ( ZSTD_checkCParams ( params . cParams ) ) ) ;
assert ( ! ( ( dict ) & & ( cdict ) ) ) ; /* either dict or cdict, not both */
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
CHECK_F ( ZSTD_compressBegin_internal ( zcs ,
2018-01-13 13:50:59 +01:00
dict , dictSize , dictMode ,
cdict ,
params , pledgedSrcSize ,
ZSTDb_buffered ) ) ;
2017-06-09 03:43:56 +02:00
zcs - > inToCompress = 0 ;
zcs - > inBuffPos = 0 ;
2018-01-13 13:50:59 +01:00
zcs - > inBuffTarget = zcs - > blockSize
+ ( zcs - > blockSize = = pledgedSrcSize ) ; /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
2017-06-09 03:43:56 +02:00
zcs - > outBuffContentSize = zcs - > outBuffFlushedSize = 0 ;
2017-07-22 23:46:05 +02:00
zcs - > streamStage = zcss_load ;
2017-06-09 03:43:56 +02:00
zcs - > frameEnded = 0 ;
return 0 ; /* ready to go */
}
2018-01-13 13:50:59 +01:00
/* ZSTD_resetCStream():
* pledgedSrcSize = = 0 means " unknown " */
2017-06-09 03:43:56 +02:00
size_t ZSTD_resetCStream ( ZSTD_CStream * zcs , unsigned long long pledgedSrcSize )
{
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params params = zcs - > requestedParams ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_resetCStream: pledgedSrcSize = %u " , ( U32 ) pledgedSrcSize ) ;
if ( pledgedSrcSize = = 0 ) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN ;
params . fParams . contentSizeFlag = 1 ;
2017-10-26 22:41:47 +02:00
params . cParams = ZSTD_getCParamsFromCCtxParams ( params , pledgedSrcSize , 0 ) ;
return ZSTD_resetCStream_internal ( zcs , NULL , 0 , ZSTD_dm_auto , zcs - > cdict , params , pledgedSrcSize ) ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
/*! ZSTD_initCStream_internal() :
2018-01-13 13:50:59 +01:00
* Note : for lib / compress only . Used by zstdmt_compress . c .
2017-07-22 23:46:05 +02:00
* Assumption 1 : params are valid
* Assumption 2 : either dict , or cdict , is defined , not both */
size_t ZSTD_initCStream_internal ( ZSTD_CStream * zcs ,
const void * dict , size_t dictSize , const ZSTD_CDict * cdict ,
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params params , unsigned long long pledgedSrcSize )
2017-06-09 03:43:56 +02:00
{
2017-10-26 22:41:47 +02:00
DEBUGLOG ( 4 , " ZSTD_initCStream_internal " ) ;
2017-06-09 03:43:56 +02:00
assert ( ! ZSTD_isError ( ZSTD_checkCParams ( params . cParams ) ) ) ;
2017-07-22 23:46:05 +02:00
assert ( ! ( ( dict ) & & ( cdict ) ) ) ; /* either dict or cdict, not both */
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
if ( dict & & dictSize > = 8 ) {
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " loading dictionary of size %u " , ( U32 ) dictSize ) ;
2017-07-22 23:46:05 +02:00
if ( zcs - > staticSize ) { /* static CCtx : never uses malloc */
/* incompatible with internal cdict creation */
return ERROR ( memory_allocation ) ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
ZSTD_freeCDict ( zcs - > cdictLocal ) ;
zcs - > cdictLocal = ZSTD_createCDict_advanced ( dict , dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dlm_byCopy , ZSTD_dm_auto ,
2017-07-22 23:46:05 +02:00
params . cParams , zcs - > customMem ) ;
zcs - > cdict = zcs - > cdictLocal ;
if ( zcs - > cdictLocal = = NULL ) return ERROR ( memory_allocation ) ;
} else {
if ( cdict ) {
2018-01-13 13:50:59 +01:00
params . cParams = ZSTD_getCParamsFromCDict ( cdict ) ; /* cParams are enforced from cdict; it includes windowLog */
2017-07-22 23:46:05 +02:00
}
ZSTD_freeCDict ( zcs - > cdictLocal ) ;
zcs - > cdictLocal = NULL ;
zcs - > cdict = cdict ;
2017-06-09 03:43:56 +02:00
}
2018-01-13 13:50:59 +01:00
params . compressionLevel = ZSTD_CLEVEL_CUSTOM ; /* enforce usage of cParams, instead of a dynamic derivation from cLevel (but does that happen ?) */
2017-07-22 23:46:05 +02:00
zcs - > requestedParams = params ;
2017-10-26 22:41:47 +02:00
return ZSTD_resetCStream_internal ( zcs , NULL , 0 , ZSTD_dm_auto , zcs - > cdict , params , pledgedSrcSize ) ;
2017-06-09 03:43:56 +02:00
}
/* ZSTD_initCStream_usingCDict_advanced() :
* same as ZSTD_initCStream_usingCDict ( ) , with control over frame parameters */
2017-07-22 23:46:05 +02:00
size_t ZSTD_initCStream_usingCDict_advanced ( ZSTD_CStream * zcs ,
const ZSTD_CDict * cdict ,
ZSTD_frameParameters fParams ,
unsigned long long pledgedSrcSize )
2018-01-13 13:50:59 +01:00
{
DEBUGLOG ( 4 , " ZSTD_initCStream_usingCDict_advanced " ) ;
if ( ! cdict ) return ERROR ( dictionary_wrong ) ; /* cannot handle NULL cdict (does not know what to do) */
2017-10-26 22:41:47 +02:00
{ ZSTD_CCtx_params params = zcs - > requestedParams ;
params . cParams = ZSTD_getCParamsFromCDict ( cdict ) ;
2017-06-09 03:43:56 +02:00
params . fParams = fParams ;
2017-07-22 23:46:05 +02:00
return ZSTD_initCStream_internal ( zcs ,
NULL , 0 , cdict ,
params , pledgedSrcSize ) ;
2017-06-09 03:43:56 +02:00
}
}
/* note : cdict must outlive compression session */
size_t ZSTD_initCStream_usingCDict ( ZSTD_CStream * zcs , const ZSTD_CDict * cdict )
{
2018-01-13 13:50:59 +01:00
ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */ , 0 /* checksum */ , 0 /* hideDictID */ } ;
DEBUGLOG ( 4 , " ZSTD_initCStream_usingCDict " ) ;
return ZSTD_initCStream_usingCDict_advanced ( zcs , cdict , fParams , ZSTD_CONTENTSIZE_UNKNOWN ) ; /* note : will check that cdict != NULL */
2017-06-09 03:43:56 +02:00
}
2018-01-13 13:50:59 +01:00
/* ZSTD_initCStream_advanced() :
* pledgedSrcSize must be correct .
* if srcSize is not known at init time , use value ZSTD_CONTENTSIZE_UNKNOWN .
* dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy . */
2017-06-09 03:43:56 +02:00
size_t ZSTD_initCStream_advanced ( ZSTD_CStream * zcs ,
const void * dict , size_t dictSize ,
ZSTD_parameters params , unsigned long long pledgedSrcSize )
{
2018-01-13 13:50:59 +01:00
ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams ( zcs - > requestedParams , params ) ;
DEBUGLOG ( 4 , " ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u " ,
( U32 ) pledgedSrcSize , params . fParams . contentSizeFlag ) ;
2017-06-09 03:43:56 +02:00
CHECK_F ( ZSTD_checkCParams ( params . cParams ) ) ;
2018-01-13 13:50:59 +01:00
if ( ( pledgedSrcSize = = 0 ) & & ( params . fParams . contentSizeFlag = = 0 ) ) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN ; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
return ZSTD_initCStream_internal ( zcs , dict , dictSize , NULL /*cdict*/ , cctxParams , pledgedSrcSize ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_initCStream_usingDict ( ZSTD_CStream * zcs , const void * dict , size_t dictSize , int compressionLevel )
{
ZSTD_parameters const params = ZSTD_getParams ( compressionLevel , 0 , dictSize ) ;
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams ( zcs - > requestedParams , params ) ;
2018-01-13 13:50:59 +01:00
return ZSTD_initCStream_internal ( zcs , dict , dictSize , NULL , cctxParams , ZSTD_CONTENTSIZE_UNKNOWN ) ;
2017-06-09 03:43:56 +02:00
}
2018-01-13 13:50:59 +01:00
size_t ZSTD_initCStream_srcSize ( ZSTD_CStream * zcs , int compressionLevel , unsigned long long pss )
2017-06-09 03:43:56 +02:00
{
2018-01-13 13:50:59 +01:00
U64 const pledgedSrcSize = ( pss = = 0 ) ? ZSTD_CONTENTSIZE_UNKNOWN : pss ; /* temporary : 0 interpreted as "unknown" during transition period. Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. `0` will be interpreted as "empty" in the future */
2017-10-26 22:41:47 +02:00
ZSTD_parameters const params = ZSTD_getParams ( compressionLevel , pledgedSrcSize , 0 ) ;
2018-01-13 13:50:59 +01:00
ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams ( zcs - > requestedParams , params ) ;
2017-10-26 22:41:47 +02:00
return ZSTD_initCStream_internal ( zcs , NULL , 0 , NULL , cctxParams , pledgedSrcSize ) ;
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_initCStream ( ZSTD_CStream * zcs , int compressionLevel )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_initCStream " ) ;
return ZSTD_initCStream_srcSize ( zcs , compressionLevel , ZSTD_CONTENTSIZE_UNKNOWN ) ;
2017-06-09 03:43:56 +02:00
}
/*====== Compression ======*/
2017-07-22 23:46:05 +02:00
MEM_STATIC size_t ZSTD_limitCopy ( void * dst , size_t dstCapacity ,
const void * src , size_t srcSize )
2017-06-09 03:43:56 +02:00
{
size_t const length = MIN ( dstCapacity , srcSize ) ;
2017-07-22 23:46:05 +02:00
if ( length ) memcpy ( dst , src , length ) ;
2017-06-09 03:43:56 +02:00
return length ;
}
2017-07-22 23:46:05 +02:00
/** ZSTD_compressStream_generic():
* internal function for all * compressStream * ( ) variants and * compress_generic ( )
2017-10-26 22:41:47 +02:00
* non - static , because can be called from zstdmt . c
2017-07-22 23:46:05 +02:00
* @ return : hint size for next input */
size_t ZSTD_compressStream_generic ( ZSTD_CStream * zcs ,
ZSTD_outBuffer * output ,
ZSTD_inBuffer * input ,
ZSTD_EndDirective const flushMode )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
const char * const istart = ( const char * ) input - > src ;
const char * const iend = istart + input - > size ;
const char * ip = istart + input - > pos ;
char * const ostart = ( char * ) output - > dst ;
char * const oend = ostart + output - > size ;
char * op = ostart + output - > pos ;
2017-06-09 03:43:56 +02:00
U32 someMoreWork = 1 ;
2017-07-22 23:46:05 +02:00
/* check expectations */
DEBUGLOG ( 5 , " ZSTD_compressStream_generic, flush=%u " , ( U32 ) flushMode ) ;
assert ( zcs - > inBuff ! = NULL ) ;
2018-01-13 13:50:59 +01:00
assert ( zcs - > inBuffSize > 0 ) ;
assert ( zcs - > outBuff ! = NULL ) ;
assert ( zcs - > outBuffSize > 0 ) ;
2017-07-22 23:46:05 +02:00
assert ( output - > pos < = output - > size ) ;
assert ( input - > pos < = input - > size ) ;
2017-06-09 03:43:56 +02:00
while ( someMoreWork ) {
2017-07-22 23:46:05 +02:00
switch ( zcs - > streamStage )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
case zcss_init :
/* call ZSTD_initCStream() first ! */
return ERROR ( init_missing ) ;
2017-06-09 03:43:56 +02:00
case zcss_load :
2017-07-22 23:46:05 +02:00
if ( ( flushMode = = ZSTD_e_end )
& & ( ( size_t ) ( oend - op ) > = ZSTD_compressBound ( iend - ip ) ) /* enough dstCapacity */
& & ( zcs - > inBuffPos = = 0 ) ) {
/* shortcut to compression pass directly into output buffer */
size_t const cSize = ZSTD_compressEnd ( zcs ,
op , oend - op , ip , iend - ip ) ;
DEBUGLOG ( 4 , " ZSTD_compressEnd : %u " , ( U32 ) cSize ) ;
if ( ZSTD_isError ( cSize ) ) return cSize ;
ip = iend ;
op + = cSize ;
zcs - > frameEnded = 1 ;
ZSTD_startNewCompression ( zcs ) ;
someMoreWork = 0 ; break ;
}
/* complete loading into inBuffer */
2017-06-09 03:43:56 +02:00
{ size_t const toLoad = zcs - > inBuffTarget - zcs - > inBuffPos ;
2017-07-22 23:46:05 +02:00
size_t const loaded = ZSTD_limitCopy (
zcs - > inBuff + zcs - > inBuffPos , toLoad ,
ip , iend - ip ) ;
2017-06-09 03:43:56 +02:00
zcs - > inBuffPos + = loaded ;
ip + = loaded ;
2017-07-22 23:46:05 +02:00
if ( ( flushMode = = ZSTD_e_continue )
& & ( zcs - > inBuffPos < zcs - > inBuffTarget ) ) {
/* not enough input to fill full block : stop here */
someMoreWork = 0 ; break ;
}
if ( ( flushMode = = ZSTD_e_flush )
& & ( zcs - > inBuffPos = = zcs - > inToCompress ) ) {
/* empty */
someMoreWork = 0 ; break ;
}
}
2017-06-09 03:43:56 +02:00
/* compress current block (note : this stage cannot be stopped in the middle) */
2017-07-22 23:46:05 +02:00
DEBUGLOG ( 5 , " stream compression stage (flushMode==%u) " , flushMode ) ;
2017-06-09 03:43:56 +02:00
{ void * cDst ;
size_t cSize ;
size_t const iSize = zcs - > inBuffPos - zcs - > inToCompress ;
size_t oSize = oend - op ;
2017-07-22 23:46:05 +02:00
unsigned const lastBlock = ( flushMode = = ZSTD_e_end ) & & ( ip = = iend ) ;
2017-06-09 03:43:56 +02:00
if ( oSize > = ZSTD_compressBound ( iSize ) )
2017-07-22 23:46:05 +02:00
cDst = op ; /* compress into output buffer, to skip flush stage */
2017-06-09 03:43:56 +02:00
else
cDst = zcs - > outBuff , oSize = zcs - > outBuffSize ;
2017-07-22 23:46:05 +02:00
cSize = lastBlock ?
ZSTD_compressEnd ( zcs , cDst , oSize ,
zcs - > inBuff + zcs - > inToCompress , iSize ) :
ZSTD_compressContinue ( zcs , cDst , oSize ,
zcs - > inBuff + zcs - > inToCompress , iSize ) ;
2017-06-09 03:43:56 +02:00
if ( ZSTD_isError ( cSize ) ) return cSize ;
2017-07-22 23:46:05 +02:00
zcs - > frameEnded = lastBlock ;
2017-06-09 03:43:56 +02:00
/* prepare next block */
zcs - > inBuffTarget = zcs - > inBuffPos + zcs - > blockSize ;
if ( zcs - > inBuffTarget > zcs - > inBuffSize )
2017-07-22 23:46:05 +02:00
zcs - > inBuffPos = 0 , zcs - > inBuffTarget = zcs - > blockSize ;
DEBUGLOG ( 5 , " inBuffTarget:%u / inBuffSize:%u " ,
( U32 ) zcs - > inBuffTarget , ( U32 ) zcs - > inBuffSize ) ;
if ( ! lastBlock )
assert ( zcs - > inBuffTarget < = zcs - > inBuffSize ) ;
2017-06-09 03:43:56 +02:00
zcs - > inToCompress = zcs - > inBuffPos ;
2017-07-22 23:46:05 +02:00
if ( cDst = = op ) { /* no need to flush */
op + = cSize ;
if ( zcs - > frameEnded ) {
DEBUGLOG ( 5 , " Frame completed directly in outBuffer " ) ;
someMoreWork = 0 ;
ZSTD_startNewCompression ( zcs ) ;
}
break ;
}
2017-06-09 03:43:56 +02:00
zcs - > outBuffContentSize = cSize ;
zcs - > outBuffFlushedSize = 0 ;
2017-07-22 23:46:05 +02:00
zcs - > streamStage = zcss_flush ; /* pass-through to flush stage */
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
/* fall-through */
2017-06-09 03:43:56 +02:00
case zcss_flush :
2017-07-22 23:46:05 +02:00
DEBUGLOG ( 5 , " flush stage " ) ;
2017-06-09 03:43:56 +02:00
{ size_t const toFlush = zcs - > outBuffContentSize - zcs - > outBuffFlushedSize ;
2017-07-22 23:46:05 +02:00
size_t const flushed = ZSTD_limitCopy ( op , oend - op ,
zcs - > outBuff + zcs - > outBuffFlushedSize , toFlush ) ;
DEBUGLOG ( 5 , " toFlush: %u into %u ==> flushed: %u " ,
( U32 ) toFlush , ( U32 ) ( oend - op ) , ( U32 ) flushed ) ;
2017-06-09 03:43:56 +02:00
op + = flushed ;
zcs - > outBuffFlushedSize + = flushed ;
2017-07-22 23:46:05 +02:00
if ( toFlush ! = flushed ) {
/* flush not fully completed, presumably because dst is too small */
assert ( op = = oend ) ;
someMoreWork = 0 ;
break ;
}
2017-06-09 03:43:56 +02:00
zcs - > outBuffContentSize = zcs - > outBuffFlushedSize = 0 ;
2017-07-22 23:46:05 +02:00
if ( zcs - > frameEnded ) {
DEBUGLOG ( 5 , " Frame completed on flush " ) ;
someMoreWork = 0 ;
ZSTD_startNewCompression ( zcs ) ;
break ;
}
zcs - > streamStage = zcss_load ;
2017-06-09 03:43:56 +02:00
break ;
}
2017-07-22 23:46:05 +02:00
default : /* impossible */
assert ( 0 ) ;
2017-06-09 03:43:56 +02:00
}
}
2017-07-22 23:46:05 +02:00
input - > pos = ip - istart ;
output - > pos = op - ostart ;
2017-06-09 03:43:56 +02:00
if ( zcs - > frameEnded ) return 0 ;
{ size_t hintInSize = zcs - > inBuffTarget - zcs - > inBuffPos ;
if ( hintInSize = = 0 ) hintInSize = zcs - > blockSize ;
return hintInSize ;
}
}
size_t ZSTD_compressStream ( ZSTD_CStream * zcs , ZSTD_outBuffer * output , ZSTD_inBuffer * input )
{
2017-07-22 23:46:05 +02:00
/* check conditions */
if ( output - > pos > output - > size ) return ERROR ( GENERIC ) ;
if ( input - > pos > input - > size ) return ERROR ( GENERIC ) ;
return ZSTD_compressStream_generic ( zcs , output , input , ZSTD_e_continue ) ;
}
size_t ZSTD_compress_generic ( ZSTD_CCtx * cctx ,
ZSTD_outBuffer * output ,
ZSTD_inBuffer * input ,
ZSTD_EndDirective endOp )
{
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " ZSTD_compress_generic, endOp=%u " , ( U32 ) endOp ) ;
2017-07-22 23:46:05 +02:00
/* check conditions */
if ( output - > pos > output - > size ) return ERROR ( GENERIC ) ;
if ( input - > pos > input - > size ) return ERROR ( GENERIC ) ;
assert ( cctx ! = NULL ) ;
/* transparent initialization stage */
if ( cctx - > streamStage = = zcss_init ) {
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params params = cctx - > requestedParams ;
2018-01-13 13:50:59 +01:00
ZSTD_prefixDict const prefixDict = cctx - > prefixDict ;
2017-10-26 22:41:47 +02:00
memset ( & cctx - > prefixDict , 0 , sizeof ( cctx - > prefixDict ) ) ; /* single usage */
assert ( prefixDict . dict = = NULL | | cctx - > cdict = = NULL ) ; /* only one can be set */
DEBUGLOG ( 4 , " ZSTD_compress_generic : transparent init stage " ) ;
2018-01-13 13:50:59 +01:00
if ( endOp = = ZSTD_e_end ) cctx - > pledgedSrcSizePlusOne = input - > size + 1 ; /* auto-fix pledgedSrcSize */
params . cParams = ZSTD_getCParamsFromCCtxParams (
cctx - > requestedParams , cctx - > pledgedSrcSizePlusOne - 1 , 0 /*dictSize*/ ) ;
2017-07-22 23:46:05 +02:00
# ifdef ZSTD_MULTITHREAD
2018-01-13 13:50:59 +01:00
if ( ( cctx - > pledgedSrcSizePlusOne - 1 ) < = ZSTDMT_JOBSIZE_MIN )
params . nbThreads = 1 ; /* do not invoke multi-threading when src size is too small */
2017-10-26 22:41:47 +02:00
if ( params . nbThreads > 1 ) {
2018-01-13 13:50:59 +01:00
if ( cctx - > mtctx = = NULL | | ( params . nbThreads ! = ZSTDMT_getNbThreads ( cctx - > mtctx ) ) ) {
DEBUGLOG ( 4 , " ZSTD_compress_generic: creating new mtctx for nbThreads=%u (previous: %u) " ,
params . nbThreads , ZSTDMT_getNbThreads ( cctx - > mtctx ) ) ;
2017-10-26 22:41:47 +02:00
ZSTDMT_freeCCtx ( cctx - > mtctx ) ;
cctx - > mtctx = ZSTDMT_createCCtx_advanced ( params . nbThreads , cctx - > customMem ) ;
if ( cctx - > mtctx = = NULL ) return ERROR ( memory_allocation ) ;
}
DEBUGLOG ( 4 , " call ZSTDMT_initCStream_internal as nbThreads=%u " , params . nbThreads ) ;
CHECK_F ( ZSTDMT_initCStream_internal (
2018-01-13 13:50:59 +01:00
cctx - > mtctx ,
prefixDict . dict , prefixDict . dictSize , ZSTD_dm_rawContent ,
cctx - > cdict , params , cctx - > pledgedSrcSizePlusOne - 1 ) ) ;
2017-07-22 23:46:05 +02:00
cctx - > streamStage = zcss_load ;
2017-10-26 22:41:47 +02:00
cctx - > appliedParams . nbThreads = params . nbThreads ;
2017-07-22 23:46:05 +02:00
} else
# endif
2018-01-13 13:50:59 +01:00
{ CHECK_F ( ZSTD_resetCStream_internal (
2017-10-26 22:41:47 +02:00
cctx , prefixDict . dict , prefixDict . dictSize ,
prefixDict . dictMode , cctx - > cdict , params ,
cctx - > pledgedSrcSizePlusOne - 1 ) ) ;
2018-01-13 13:50:59 +01:00
assert ( cctx - > streamStage = = zcss_load ) ;
assert ( cctx - > appliedParams . nbThreads < = 1 ) ;
2017-07-22 23:46:05 +02:00
} }
/* compression stage */
# ifdef ZSTD_MULTITHREAD
2017-10-26 22:41:47 +02:00
if ( cctx - > appliedParams . nbThreads > 1 ) {
2017-07-22 23:46:05 +02:00
size_t const flushMin = ZSTDMT_compressStream_generic ( cctx - > mtctx , output , input , endOp ) ;
if ( ZSTD_isError ( flushMin )
| | ( endOp = = ZSTD_e_end & & flushMin = = 0 ) ) { /* compression completed */
ZSTD_startNewCompression ( cctx ) ;
}
return flushMin ;
}
# endif
CHECK_F ( ZSTD_compressStream_generic ( cctx , output , input , endOp ) ) ;
DEBUGLOG ( 5 , " completed ZSTD_compress_generic " ) ;
return cctx - > outBuffContentSize - cctx - > outBuffFlushedSize ; /* remaining to flush */
}
size_t ZSTD_compress_generic_simpleArgs (
ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity , size_t * dstPos ,
const void * src , size_t srcSize , size_t * srcPos ,
ZSTD_EndDirective endOp )
{
ZSTD_outBuffer output = { dst , dstCapacity , * dstPos } ;
ZSTD_inBuffer input = { src , srcSize , * srcPos } ;
/* ZSTD_compress_generic() will check validity of dstPos and srcPos */
size_t const cErr = ZSTD_compress_generic ( cctx , & output , & input , endOp ) ;
* dstPos = output . pos ;
* srcPos = input . pos ;
return cErr ;
2017-06-09 03:43:56 +02:00
}
/*====== Finalize ======*/
/*! ZSTD_flushStream() :
* @ return : amount of data remaining to flush */
size_t ZSTD_flushStream ( ZSTD_CStream * zcs , ZSTD_outBuffer * output )
{
2017-07-22 23:46:05 +02:00
ZSTD_inBuffer input = { NULL , 0 , 0 } ;
if ( output - > pos > output - > size ) return ERROR ( GENERIC ) ;
CHECK_F ( ZSTD_compressStream_generic ( zcs , output , & input , ZSTD_e_flush ) ) ;
return zcs - > outBuffContentSize - zcs - > outBuffFlushedSize ; /* remaining to flush */
2017-06-09 03:43:56 +02:00
}
size_t ZSTD_endStream ( ZSTD_CStream * zcs , ZSTD_outBuffer * output )
{
2017-07-22 23:46:05 +02:00
ZSTD_inBuffer input = { NULL , 0 , 0 } ;
if ( output - > pos > output - > size ) return ERROR ( GENERIC ) ;
CHECK_F ( ZSTD_compressStream_generic ( zcs , output , & input , ZSTD_e_end ) ) ;
{ size_t const lastBlockSize = zcs - > frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE ;
size_t const checksumSize = zcs - > frameEnded ? 0 : zcs - > appliedParams . fParams . checksumFlag * 4 ;
size_t const toFlush = zcs - > outBuffContentSize - zcs - > outBuffFlushedSize + lastBlockSize + checksumSize ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_endStream : remaining to flush : %u " , ( U32 ) toFlush ) ;
2017-07-22 23:46:05 +02:00
return toFlush ;
2017-06-09 03:43:56 +02:00
}
}
/*-===== Pre-defined compression levels =====-*/
# define ZSTD_MAX_CLEVEL 22
int ZSTD_maxCLevel ( void ) { return ZSTD_MAX_CLEVEL ; }
static const ZSTD_compressionParameters ZSTD_defaultCParameters [ 4 ] [ ZSTD_MAX_CLEVEL + 1 ] = {
2017-07-22 23:46:05 +02:00
{ /* "default" - guarantees a monotonically increasing memory budget */
2017-06-09 03:43:56 +02:00
/* W, C, H, S, L, TL, strat */
{ 18 , 12 , 12 , 1 , 7 , 16 , ZSTD_fast } , /* level 0 - never used */
{ 19 , 13 , 14 , 1 , 7 , 16 , ZSTD_fast } , /* level 1 */
{ 19 , 15 , 16 , 1 , 6 , 16 , ZSTD_fast } , /* level 2 */
2017-07-22 23:46:05 +02:00
{ 20 , 16 , 17 , 1 , 5 , 16 , ZSTD_dfast } , /* level 3 */
{ 20 , 17 , 18 , 1 , 5 , 16 , ZSTD_dfast } , /* level 4 */
{ 20 , 17 , 18 , 2 , 5 , 16 , ZSTD_greedy } , /* level 5 */
{ 21 , 17 , 19 , 2 , 5 , 16 , ZSTD_lazy } , /* level 6 */
{ 21 , 18 , 19 , 3 , 5 , 16 , ZSTD_lazy } , /* level 7 */
2017-06-09 03:43:56 +02:00
{ 21 , 18 , 20 , 3 , 5 , 16 , ZSTD_lazy2 } , /* level 8 */
2017-07-22 23:46:05 +02:00
{ 21 , 19 , 20 , 3 , 5 , 16 , ZSTD_lazy2 } , /* level 9 */
2017-06-09 03:43:56 +02:00
{ 21 , 19 , 21 , 4 , 5 , 16 , ZSTD_lazy2 } , /* level 10 */
{ 22 , 20 , 22 , 4 , 5 , 16 , ZSTD_lazy2 } , /* level 11 */
{ 22 , 20 , 22 , 5 , 5 , 16 , ZSTD_lazy2 } , /* level 12 */
{ 22 , 21 , 22 , 5 , 5 , 16 , ZSTD_lazy2 } , /* level 13 */
{ 22 , 21 , 22 , 6 , 5 , 16 , ZSTD_lazy2 } , /* level 14 */
2018-01-13 13:50:59 +01:00
{ 22 , 21 , 22 , 4 , 5 , 16 , ZSTD_btlazy2 } , /* level 15 */
{ 22 , 21 , 22 , 4 , 5 , 48 , ZSTD_btopt } , /* level 16 */
{ 23 , 22 , 22 , 4 , 4 , 48 , ZSTD_btopt } , /* level 17 */
{ 23 , 22 , 22 , 5 , 3 , 64 , ZSTD_btopt } , /* level 18 */
{ 23 , 23 , 22 , 7 , 3 , 128 , ZSTD_btopt } , /* level 19 */
{ 25 , 25 , 23 , 7 , 3 , 128 , ZSTD_btultra } , /* level 20 */
2017-07-22 23:46:05 +02:00
{ 26 , 26 , 24 , 7 , 3 , 256 , ZSTD_btultra } , /* level 21 */
{ 27 , 27 , 25 , 9 , 3 , 512 , ZSTD_btultra } , /* level 22 */
2017-06-09 03:43:56 +02:00
} ,
{ /* for srcSize <= 256 KB */
/* W, C, H, S, L, T, strat */
{ 0 , 0 , 0 , 0 , 0 , 0 , ZSTD_fast } , /* level 0 - not used */
{ 18 , 13 , 14 , 1 , 6 , 8 , ZSTD_fast } , /* level 1 */
{ 18 , 14 , 13 , 1 , 5 , 8 , ZSTD_dfast } , /* level 2 */
{ 18 , 16 , 15 , 1 , 5 , 8 , ZSTD_dfast } , /* level 3 */
{ 18 , 15 , 17 , 1 , 5 , 8 , ZSTD_greedy } , /* level 4.*/
{ 18 , 16 , 17 , 4 , 5 , 8 , ZSTD_greedy } , /* level 5.*/
{ 18 , 16 , 17 , 3 , 5 , 8 , ZSTD_lazy } , /* level 6.*/
{ 18 , 17 , 17 , 4 , 4 , 8 , ZSTD_lazy } , /* level 7 */
{ 18 , 17 , 17 , 4 , 4 , 8 , ZSTD_lazy2 } , /* level 8 */
{ 18 , 17 , 17 , 5 , 4 , 8 , ZSTD_lazy2 } , /* level 9 */
{ 18 , 17 , 17 , 6 , 4 , 8 , ZSTD_lazy2 } , /* level 10 */
{ 18 , 18 , 17 , 6 , 4 , 8 , ZSTD_lazy2 } , /* level 11.*/
{ 18 , 18 , 17 , 7 , 4 , 8 , ZSTD_lazy2 } , /* level 12.*/
{ 18 , 19 , 17 , 6 , 4 , 8 , ZSTD_btlazy2 } , /* level 13 */
{ 18 , 18 , 18 , 4 , 4 , 16 , ZSTD_btopt } , /* level 14.*/
{ 18 , 18 , 18 , 4 , 3 , 16 , ZSTD_btopt } , /* level 15.*/
{ 18 , 19 , 18 , 6 , 3 , 32 , ZSTD_btopt } , /* level 16.*/
{ 18 , 19 , 18 , 8 , 3 , 64 , ZSTD_btopt } , /* level 17.*/
{ 18 , 19 , 18 , 9 , 3 , 128 , ZSTD_btopt } , /* level 18.*/
{ 18 , 19 , 18 , 10 , 3 , 256 , ZSTD_btopt } , /* level 19.*/
2017-07-22 23:46:05 +02:00
{ 18 , 19 , 18 , 11 , 3 , 512 , ZSTD_btultra } , /* level 20.*/
{ 18 , 19 , 18 , 12 , 3 , 512 , ZSTD_btultra } , /* level 21.*/
{ 18 , 19 , 18 , 13 , 3 , 512 , ZSTD_btultra } , /* level 22.*/
2017-06-09 03:43:56 +02:00
} ,
{ /* for srcSize <= 128 KB */
/* W, C, H, S, L, T, strat */
{ 17 , 12 , 12 , 1 , 7 , 8 , ZSTD_fast } , /* level 0 - not used */
{ 17 , 12 , 13 , 1 , 6 , 8 , ZSTD_fast } , /* level 1 */
{ 17 , 13 , 16 , 1 , 5 , 8 , ZSTD_fast } , /* level 2 */
{ 17 , 16 , 16 , 2 , 5 , 8 , ZSTD_dfast } , /* level 3 */
{ 17 , 13 , 15 , 3 , 4 , 8 , ZSTD_greedy } , /* level 4 */
{ 17 , 15 , 17 , 4 , 4 , 8 , ZSTD_greedy } , /* level 5 */
{ 17 , 16 , 17 , 3 , 4 , 8 , ZSTD_lazy } , /* level 6 */
{ 17 , 15 , 17 , 4 , 4 , 8 , ZSTD_lazy2 } , /* level 7 */
{ 17 , 17 , 17 , 4 , 4 , 8 , ZSTD_lazy2 } , /* level 8 */
{ 17 , 17 , 17 , 5 , 4 , 8 , ZSTD_lazy2 } , /* level 9 */
{ 17 , 17 , 17 , 6 , 4 , 8 , ZSTD_lazy2 } , /* level 10 */
{ 17 , 17 , 17 , 7 , 4 , 8 , ZSTD_lazy2 } , /* level 11 */
{ 17 , 17 , 17 , 8 , 4 , 8 , ZSTD_lazy2 } , /* level 12 */
{ 17 , 18 , 17 , 6 , 4 , 8 , ZSTD_btlazy2 } , /* level 13.*/
{ 17 , 17 , 17 , 7 , 3 , 8 , ZSTD_btopt } , /* level 14.*/
{ 17 , 17 , 17 , 7 , 3 , 16 , ZSTD_btopt } , /* level 15.*/
{ 17 , 18 , 17 , 7 , 3 , 32 , ZSTD_btopt } , /* level 16.*/
{ 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.*/
2017-07-22 23:46:05 +02:00
{ 17 , 18 , 17 , 9 , 3 , 256 , ZSTD_btultra } , /* level 20.*/
{ 17 , 18 , 17 , 10 , 3 , 256 , ZSTD_btultra } , /* level 21.*/
{ 17 , 18 , 17 , 11 , 3 , 512 , ZSTD_btultra } , /* level 22.*/
2017-06-09 03:43:56 +02:00
} ,
{ /* for srcSize <= 16 KB */
/* W, C, H, S, L, T, strat */
{ 14 , 12 , 12 , 1 , 7 , 6 , ZSTD_fast } , /* level 0 - not used */
{ 14 , 14 , 14 , 1 , 6 , 6 , ZSTD_fast } , /* level 1 */
{ 14 , 14 , 14 , 1 , 4 , 6 , ZSTD_fast } , /* level 2 */
{ 14 , 14 , 14 , 1 , 4 , 6 , ZSTD_dfast } , /* level 3.*/
{ 14 , 14 , 14 , 4 , 4 , 6 , ZSTD_greedy } , /* level 4.*/
{ 14 , 14 , 14 , 3 , 4 , 6 , ZSTD_lazy } , /* level 5.*/
{ 14 , 14 , 14 , 4 , 4 , 6 , ZSTD_lazy2 } , /* level 6 */
{ 14 , 14 , 14 , 5 , 4 , 6 , ZSTD_lazy2 } , /* level 7 */
{ 14 , 14 , 14 , 6 , 4 , 6 , ZSTD_lazy2 } , /* level 8.*/
{ 14 , 15 , 14 , 6 , 4 , 6 , 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.*/
2017-07-22 23:46:05 +02:00
{ 14 , 15 , 15 , 8 , 3 , 256 , ZSTD_btultra } , /* level 20.*/
{ 14 , 15 , 15 , 9 , 3 , 256 , ZSTD_btultra } , /* level 21.*/
{ 14 , 15 , 15 , 10 , 3 , 256 , ZSTD_btultra } , /* level 22.*/
2017-06-09 03:43:56 +02:00
} ,
} ;
2017-07-22 23:46:05 +02:00
# if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
/* This function just controls
* the monotonic memory budget increase of ZSTD_defaultCParameters [ 0 ] .
* Run once , on first ZSTD_getCParams ( ) usage , if ZSTD_DEBUG is enabled
*/
MEM_STATIC void ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget ( void )
{
int level ;
for ( level = 1 ; level < ZSTD_maxCLevel ( ) ; level + + ) {
ZSTD_compressionParameters const c1 = ZSTD_defaultCParameters [ 0 ] [ level ] ;
ZSTD_compressionParameters const c2 = ZSTD_defaultCParameters [ 0 ] [ level + 1 ] ;
assert ( c1 . windowLog < = c2 . windowLog ) ;
# define ZSTD_TABLECOST(h,c) ((1<<(h)) + (1<<(c)))
assert ( ZSTD_TABLECOST ( c1 . hashLog , c1 . chainLog ) < = ZSTD_TABLECOST ( c2 . hashLog , c2 . chainLog ) ) ;
}
}
# endif
2017-06-09 03:43:56 +02: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 */
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters ZSTD_getCParams ( int compressionLevel , unsigned long long srcSizeHint , size_t dictSize )
2017-06-09 03:43:56 +02:00
{
2017-07-22 23:46:05 +02:00
size_t const addedSize = srcSizeHint ? 0 : 500 ;
U64 const rSize = srcSizeHint + dictSize ? srcSizeHint + dictSize + addedSize : ( U64 ) - 1 ;
2017-06-09 03:43:56 +02:00
U32 const tableID = ( rSize < = 256 KB ) + ( rSize < = 128 KB ) + ( rSize < = 16 KB ) ; /* intentional underflow for srcSizeHint == 0 */
2017-07-22 23:46:05 +02:00
# if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
static int g_monotonicTest = 1 ;
if ( g_monotonicTest ) {
ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget ( ) ;
g_monotonicTest = 0 ;
2017-06-09 03:43:56 +02:00
}
2017-07-22 23:46:05 +02:00
# endif
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " ZSTD_getCParams: cLevel=%i, srcSize=%u, dictSize=%u => table %u " ,
compressionLevel , ( U32 ) srcSizeHint , ( U32 ) dictSize , tableID ) ;
2017-07-22 23:46:05 +02:00
if ( compressionLevel < = 0 ) compressionLevel = ZSTD_CLEVEL_DEFAULT ; /* 0 == default; no negative compressionLevel yet */
if ( compressionLevel > ZSTD_MAX_CLEVEL ) compressionLevel = ZSTD_MAX_CLEVEL ;
{ ZSTD_compressionParameters const cp = ZSTD_defaultCParameters [ tableID ] [ compressionLevel ] ;
return ZSTD_adjustCParams_internal ( cp , srcSizeHint , dictSize ) ; }
2017-10-26 22:41:47 +02:00
2017-06-09 03:43:56 +02:00
}
/*! ZSTD_getParams() :
* same as ZSTD_getCParams ( ) , but @ return a ` ZSTD_parameters ` object ( instead of ` ZSTD_compressionParameters ` ) .
* All fields of ` ZSTD_frameParameters ` are set to default ( 0 ) */
2017-07-22 23:46:05 +02:00
ZSTD_parameters ZSTD_getParams ( int compressionLevel , unsigned long long srcSizeHint , size_t dictSize ) {
2017-06-09 03:43:56 +02:00
ZSTD_parameters params ;
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters const cParams = ZSTD_getCParams ( compressionLevel , srcSizeHint , dictSize ) ;
2017-06-09 03:43:56 +02:00
memset ( & params , 0 , sizeof ( params ) ) ;
params . cParams = cParams ;
2018-01-13 13:50:59 +01:00
params . fParams . contentSizeFlag = 1 ;
2017-06-09 03:43:56 +02:00
return params ;
}