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 */
2018-05-15 19:45:22 +02:00
# include "cpu.h"
2017-06-09 03:43:56 +02:00
# 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 ;
2018-05-15 19:45:22 +02:00
void * workspace ;
size_t workspaceSize ;
ZSTD_matchState_t matchState ;
ZSTD_compressedBlockState_t cBlockState ;
ZSTD_compressionParameters cParams ;
ZSTD_customMem customMem ;
U32 dictID ;
2017-07-22 23:46:05 +02:00
} ; /* 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 )
{
2017-07-22 23:46:05 +02:00
ZSTD_STATIC_ASSERT ( zcss_init = = 0 ) ;
ZSTD_STATIC_ASSERT ( ZSTD_CONTENTSIZE_UNKNOWN = = ( 0ULL - 1 ) ) ;
2018-05-15 19:45:22 +02:00
if ( ! customMem . customAlloc ^ ! customMem . customFree ) return NULL ;
{ ZSTD_CCtx * const cctx = ( ZSTD_CCtx * ) ZSTD_calloc ( sizeof ( ZSTD_CCtx ) , customMem ) ;
if ( ! cctx ) return NULL ;
cctx - > customMem = customMem ;
cctx - > requestedParams . compressionLevel = ZSTD_CLEVEL_DEFAULT ;
cctx - > requestedParams . fParams . contentSizeFlag = 1 ;
cctx - > bmi2 = ZSTD_cpuid_bmi2 ( ZSTD_cpuid ( ) ) ;
return cctx ;
}
2017-07-22 23:46:05 +02:00
}
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 ) ;
2018-05-15 19:45:22 +02:00
/* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
if ( cctx - > workSpaceSize < HUF_WORKSPACE_SIZE + 2 * sizeof ( ZSTD_compressedBlockState_t ) ) return NULL ;
2017-10-26 22:41:47 +02:00
assert ( ( ( size_t ) cctx - > workSpace & ( sizeof ( void * ) - 1 ) ) = = 0 ) ; /* ensure correct alignment */
2018-05-15 19:45:22 +02:00
cctx - > blockState . prevCBlock = ( ZSTD_compressedBlockState_t * ) cctx - > workSpace ;
cctx - > blockState . nextCBlock = cctx - > blockState . prevCBlock + 1 ;
{
void * const ptr = cctx - > blockState . nextCBlock + 1 ;
cctx - > entropyWorkspace = ( U32 * ) ptr ;
}
cctx - > bmi2 = ZSTD_cpuid_bmi2 ( ZSTD_cpuid ( ) ) ;
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 */
2018-05-15 19:45:22 +02:00
ZSTD_free ( cctx - > workSpace , cctx - > customMem ) ; cctx - > workSpace = NULL ;
ZSTD_freeCDict ( cctx - > cdictLocal ) ; cctx - > cdictLocal = NULL ;
2017-10-26 22:41:47 +02:00
# ifdef ZSTD_MULTITHREAD
2018-05-15 19:45:22 +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-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 ) ; }
2018-05-15 19:45:22 +02:00
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams (
const ZSTD_CCtx_params * CCtxParams , U64 srcSizeHint , size_t dictSize )
{
ZSTD_compressionParameters cParams = ZSTD_getCParams ( CCtxParams - > compressionLevel , srcSizeHint , dictSize ) ;
if ( CCtxParams - > ldmParams . enableLdm ) cParams . windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG ;
if ( CCtxParams - > cParams . windowLog ) cParams . windowLog = CCtxParams - > cParams . windowLog ;
if ( CCtxParams - > cParams . hashLog ) cParams . hashLog = CCtxParams - > cParams . hashLog ;
if ( CCtxParams - > cParams . chainLog ) cParams . chainLog = CCtxParams - > cParams . chainLog ;
if ( CCtxParams - > cParams . searchLog ) cParams . searchLog = CCtxParams - > cParams . searchLog ;
if ( CCtxParams - > cParams . searchLength ) cParams . searchLength = CCtxParams - > cParams . searchLength ;
if ( CCtxParams - > cParams . targetLength ) cParams . targetLength = CCtxParams - > cParams . targetLength ;
if ( CCtxParams - > cParams . strategy ) cParams . strategy = CCtxParams - > cParams . strategy ;
return cParams ;
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 ;
2018-05-15 19:45:22 +02:00
cctxParams . compressionLevel = ZSTD_CLEVEL_DEFAULT ; /* should not matter, as all cParams are presumed properly defined */
assert ( ! ZSTD_checkCParams ( cParams ) ) ;
cctxParams . fParams . contentSizeFlag = 1 ;
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
params - > fParams . contentSizeFlag = 1 ;
2017-10-26 22:41:47 +02:00
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 ;
}
2018-05-15 19:45:22 +02:00
size_t ZSTD_CCtxParams_reset ( ZSTD_CCtx_params * params )
2017-10-26 22:41:47 +02:00
{
2018-05-15 19:45:22 +02:00
return ZSTD_CCtxParams_init ( params , ZSTD_CLEVEL_DEFAULT ) ;
2017-10-26 22:41:47 +02:00
}
2018-05-15 19:45:22 +02:00
size_t ZSTD_CCtxParams_init ( ZSTD_CCtx_params * cctxParams , int compressionLevel ) {
2017-10-26 22:41:47 +02:00
if ( ! cctxParams ) { return ERROR ( GENERIC ) ; }
memset ( cctxParams , 0 , sizeof ( * cctxParams ) ) ;
cctxParams - > compressionLevel = compressionLevel ;
2018-05-15 19:45:22 +02:00
cctxParams - > fParams . contentSizeFlag = 1 ;
2017-10-26 22:41:47 +02:00
return 0 ;
}
2018-05-15 19:45:22 +02:00
size_t ZSTD_CCtxParams_init_advanced ( ZSTD_CCtx_params * cctxParams , ZSTD_parameters params )
2017-10-26 22:41:47 +02:00
{
if ( ! cctxParams ) { return ERROR ( GENERIC ) ; }
CHECK_F ( ZSTD_checkCParams ( params . cParams ) ) ;
memset ( cctxParams , 0 , sizeof ( * cctxParams ) ) ;
cctxParams - > cParams = params . cParams ;
cctxParams - > fParams = params . fParams ;
2018-05-15 19:45:22 +02:00
cctxParams - > compressionLevel = ZSTD_CLEVEL_DEFAULT ; /* should not matter, as all cParams are presumed properly defined */
assert ( ! ZSTD_checkCParams ( params . cParams ) ) ;
2017-10-26 22:41:47 +02:00
return 0 ;
}
2018-05-15 19:45:22 +02:00
/* ZSTD_assignParamsToCCtxParams() :
* params is presumed valid at this stage */
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
ret . compressionLevel = ZSTD_CLEVEL_DEFAULT ; /* should not matter, as all cParams are presumed properly defined */
assert ( ! ZSTD_checkCParams ( params . cParams ) ) ;
2017-10-26 22:41:47 +02:00
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
} }
2018-05-15 19:45:22 +02:00
static int ZSTD_isUpdateAuthorized ( ZSTD_cParameter param )
{
switch ( param )
{
case ZSTD_p_compressionLevel :
case ZSTD_p_hashLog :
case ZSTD_p_chainLog :
case ZSTD_p_searchLog :
case ZSTD_p_minMatch :
case ZSTD_p_targetLength :
case ZSTD_p_compressionStrategy :
case ZSTD_p_compressLiterals :
return 1 ;
case ZSTD_p_format :
case ZSTD_p_windowLog :
case ZSTD_p_contentSizeFlag :
case ZSTD_p_checksumFlag :
case ZSTD_p_dictIDFlag :
case ZSTD_p_forceMaxWindow :
case ZSTD_p_nbWorkers :
case ZSTD_p_jobSize :
case ZSTD_p_overlapSizeLog :
case ZSTD_p_enableLongDistanceMatching :
case ZSTD_p_ldmHashLog :
case ZSTD_p_ldmMinMatch :
case ZSTD_p_ldmBucketSizeLog :
case ZSTD_p_ldmHashEveryLog :
default :
return 0 ;
}
}
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 ) ;
2018-05-15 19:45:22 +02:00
if ( cctx - > streamStage ! = zcss_init ) {
if ( ZSTD_isUpdateAuthorized ( param ) ) {
cctx - > cParamsChanged = 1 ;
} else {
return ERROR ( stage_wrong ) ;
} }
2017-07-22 23:46:05 +02:00
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 ) ;
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
2017-07-22 23:46:05 +02:00
2018-05-15 19:45:22 +02:00
case ZSTD_p_compressLiterals :
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 ) ;
2018-05-15 19:45:22 +02:00
case ZSTD_p_nbWorkers :
if ( ( value > 0 ) & & 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 :
case ZSTD_p_overlapSizeLog :
return ZSTD_CCtxParam_setParameter ( & cctx - > requestedParams , param , value ) ;
case ZSTD_p_enableLongDistanceMatching :
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
2018-05-15 19:45:22 +02:00
case ZSTD_p_compressionLevel : {
int cLevel = ( int ) value ; /* cast expected to restore negative sign */
if ( cLevel > ZSTD_maxCLevel ( ) ) cLevel = ZSTD_maxCLevel ( ) ;
if ( cLevel ) { /* 0 : does not change current level */
CCtxParams - > disableLiteralCompression = ( cLevel < 0 ) ; /* negative levels disable huffman */
CCtxParams - > compressionLevel = cLevel ;
}
if ( CCtxParams - > compressionLevel > = 0 ) return CCtxParams - > compressionLevel ;
return 0 ; /* return type (size_t) cannot represent negative values */
}
2017-10-26 22:41:47 +02:00
case ZSTD_p_windowLog :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 => use default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_WINDOWLOG_MIN , ZSTD_WINDOWLOG_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > cParams . windowLog = value ;
2018-01-13 13:50:59 +01:00
return CCtxParams - > cParams . windowLog ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_hashLog :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 => use default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > cParams . hashLog = value ;
2018-01-13 13:50:59 +01:00
return CCtxParams - > cParams . hashLog ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_chainLog :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 => use default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_CHAINLOG_MIN , ZSTD_CHAINLOG_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > cParams . chainLog = value ;
2018-01-13 13:50:59 +01:00
return CCtxParams - > cParams . chainLog ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_searchLog :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 => use default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_SEARCHLOG_MIN , ZSTD_SEARCHLOG_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > cParams . searchLog = value ;
2018-01-13 13:50:59 +01:00
return value ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_minMatch :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 => use default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_SEARCHLENGTH_MIN , ZSTD_SEARCHLENGTH_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > cParams . searchLength = value ;
2018-01-13 13:50:59 +01:00
return CCtxParams - > cParams . searchLength ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_targetLength :
2018-05-15 19:45:22 +02:00
/* all values are valid. 0 => use default */
CCtxParams - > cParams . targetLength = value ;
2018-01-13 13:50:59 +01:00
return CCtxParams - > cParams . targetLength ;
2017-07-22 23:46:05 +02:00
case ZSTD_p_compressionStrategy :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 => use default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ( unsigned ) ZSTD_fast , ( unsigned ) ZSTD_btultra ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > cParams . strategy = ( ZSTD_strategy ) value ;
2018-01-13 13:50:59 +01:00
return ( size_t ) CCtxParams - > cParams . strategy ;
2017-07-22 23:46:05 +02:00
2018-05-15 19:45:22 +02:00
case ZSTD_p_compressLiterals :
CCtxParams - > disableLiteralCompression = ! value ;
return ! CCtxParams - > disableLiteralCompression ;
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 ) ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > fParams . noDictIDFlag = ! value ;
2018-01-13 13:50:59 +01:00
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
2018-05-15 19:45:22 +02:00
case ZSTD_p_nbWorkers :
2017-10-26 22:41:47 +02:00
# ifndef ZSTD_MULTITHREAD
2018-05-15 19:45:22 +02:00
if ( value > 0 ) return ERROR ( parameter_unsupported ) ;
return 0 ;
2017-10-26 22:41:47 +02:00
# else
2018-05-15 19:45:22 +02:00
return ZSTDMT_CCtxParam_setNbWorkers ( 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
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
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-05-15 19:45:22 +02:00
CCtxParams - > ldmParams . enableLdm = ( value > 0 ) ;
return CCtxParams - > ldmParams . enableLdm ;
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmHashLog :
2018-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 ==> auto */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_HASHLOG_MIN , ZSTD_HASHLOG_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > ldmParams . hashLog = value ;
2018-01-13 13:50:59 +01:00
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-05-15 19:45:22 +02:00
if ( value > 0 ) /* 0 ==> default */
2018-01-13 13:50:59 +01:00
CLAMPCHECK ( value , ZSTD_LDM_MINMATCH_MIN , ZSTD_LDM_MINMATCH_MAX ) ;
2018-05-15 19:45:22 +02:00
CCtxParams - > ldmParams . minMatchLength = value ;
2018-01-13 13:50:59 +01:00
return CCtxParams - > ldmParams . minMatchLength ;
2017-07-22 23:46:05 +02:00
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmBucketSizeLog :
2018-05-15 19:45:22 +02:00
if ( value > ZSTD_LDM_BUCKETSIZELOG_MAX )
2017-10-26 22:41:47 +02:00
return ERROR ( parameter_outOfBound ) ;
2018-01-13 13:50:59 +01:00
CCtxParams - > ldmParams . bucketSizeLog = value ;
2018-05-15 19:45:22 +02:00
return CCtxParams - > ldmParams . bucketSizeLog ;
2017-10-26 22:41:47 +02:00
case ZSTD_p_ldmHashEveryLog :
2018-05-15 19:45:22 +02:00
if ( value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN )
2017-10-26 22:41:47 +02:00
return ERROR ( parameter_outOfBound ) ;
2018-01-13 13:50:59 +01:00
CCtxParams - > ldmParams . hashEveryLog = value ;
2018-05-15 19:45:22 +02:00
return CCtxParams - > ldmParams . hashEveryLog ;
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 .
2018-05-15 19:45:22 +02:00
* If ZSTDMT is enabled , parameters are pushed to cctx - > mtctx .
* This is possible even if a compression is ongoing .
* In which case , new parameters will be applied on the fly , starting with next compression job .
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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dictLoadMethod_e dictLoadMethod , ZSTD_dictContentType_e dictContentType )
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-05-15 19:45:22 +02:00
ZSTD_getCParamsFromCCtxParams ( & cctx - > requestedParams , cctx - > pledgedSrcSizePlusOne - 1 , dictSize ) ;
2017-07-22 23:46:05 +02:00
cctx - > cdictLocal = ZSTD_createCDict_advanced (
dict , dictSize ,
2018-05-15 19:45:22 +02:00
dictLoadMethod , dictContentType ,
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 (
2018-05-15 19:45:22 +02:00
cctx , dict , dictSize , ZSTD_dlm_byRef , ZSTD_dct_auto ) ;
2017-10-26 22:41:47 +02:00
}
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary ( ZSTD_CCtx * cctx , const void * dict , size_t dictSize )
{
return ZSTD_CCtx_loadDictionary_advanced (
2018-05-15 19:45:22 +02:00
cctx , dict , dictSize , ZSTD_dlm_byCopy , ZSTD_dct_auto ) ;
2017-10-26 22:41:47 +02:00
}
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
{
2018-05-15 19:45:22 +02:00
return ZSTD_CCtx_refPrefix_advanced ( cctx , prefix , prefixSize , ZSTD_dct_rawContent ) ;
2017-10-26 22:41:47 +02:00
}
size_t ZSTD_CCtx_refPrefix_advanced (
2018-05-15 19:45:22 +02:00
ZSTD_CCtx * cctx , const void * prefix , size_t prefixSize , ZSTD_dictContentType_e dictContentType )
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 ;
2018-05-15 19:45:22 +02:00
cctx - > prefixDict . dictContentType = dictContentType ;
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 ) ;
2018-05-15 19:45:22 +02:00
if ( ( U32 ) ( cParams . targetLength ) < ZSTD_TARGETLENGTH_MIN )
return ERROR ( parameter_unsupported ) ;
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 ) ;
2018-05-15 19:45:22 +02:00
if ( ( U32 ) ( cParams . targetLength ) < ZSTD_TARGETLENGTH_MIN ) cParams . targetLength = ZSTD_TARGETLENGTH_MIN ;
2017-07-22 23:46:05 +02:00
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
2018-05-15 19:45:22 +02:00
static size_t ZSTD_sizeof_matchState ( ZSTD_compressionParameters const * cParams , const U32 forCCtx )
{
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 = ( forCCtx & & cParams - > searchLength = = 3 ) ? MIN ( ZSTD_HASHLOG3_MAX , cParams - > windowLog ) : 0 ;
size_t const h3Size = ( ( size_t ) 1 ) < < hashLog3 ;
size_t const tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
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 ) ) ;
size_t const optSpace = ( forCCtx & & ( ( cParams - > strategy = = ZSTD_btopt ) | |
( cParams - > strategy = = ZSTD_btultra ) ) )
? optPotentialSpace
: 0 ;
DEBUGLOG ( 4 , " chainSize: %u - hSize: %u - h3Size: %u " ,
( U32 ) chainSize , ( U32 ) hSize , ( U32 ) h3Size ) ;
return tableSpace + optSpace ;
}
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. */
2018-05-15 19:45:22 +02:00
if ( params - > nbWorkers > 0 ) { return ERROR ( GENERIC ) ; }
2017-10-26 22:41:47 +02:00
{ ZSTD_compressionParameters const cParams =
2018-05-15 19:45:22 +02:00
ZSTD_getCParamsFromCCtxParams ( params , 0 , 0 ) ;
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
size_t const entropySpace = HUF_WORKSPACE_SIZE ;
size_t const blockStateSpace = 2 * sizeof ( ZSTD_compressedBlockState_t ) ;
size_t const matchStateSize = ZSTD_sizeof_matchState ( & cParams , /* forCCtx */ 1 ) ;
2017-10-26 22:41:47 +02:00
2018-05-15 19:45:22 +02:00
size_t const ldmSpace = ZSTD_ldm_getTableSize ( params - > ldmParams ) ;
size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq ( params - > ldmParams , blockSize ) * sizeof ( rawSeq ) ;
2017-06-09 03:43:56 +02:00
2018-05-15 19:45:22 +02:00
size_t const neededSpace = entropySpace + blockStateSpace + tokenSpace +
matchStateSize + ldmSpace + ldmSeqSpace ;
2017-10-26 22:41:47 +02:00
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
}
2018-05-15 19:45:22 +02:00
static size_t ZSTD_estimateCCtxSize_internal ( int compressionLevel )
2017-07-22 23:46:05 +02:00
{
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
2018-05-15 19:45:22 +02:00
size_t ZSTD_estimateCCtxSize ( int compressionLevel )
{
int level ;
size_t memBudget = 0 ;
for ( level = 1 ; level < = compressionLevel ; level + + ) {
size_t const newMB = ZSTD_estimateCCtxSize_internal ( level ) ;
if ( newMB > memBudget ) memBudget = newMB ;
}
return memBudget ;
}
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
{
2018-05-15 19:45:22 +02:00
if ( params - > nbWorkers > 0 ) { return ERROR ( GENERIC ) ; }
2017-10-26 22:41:47 +02:00
{ 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
}
2018-05-15 19:45:22 +02:00
static size_t ZSTD_estimateCStreamSize_internal ( int compressionLevel ) {
2017-07-22 23:46:05 +02:00
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
}
2018-05-15 19:45:22 +02:00
size_t ZSTD_estimateCStreamSize ( int compressionLevel ) {
int level ;
size_t memBudget = 0 ;
for ( level = 1 ; level < = compressionLevel ; level + + ) {
size_t const newMB = ZSTD_estimateCStreamSize_internal ( level ) ;
if ( newMB > memBudget ) memBudget = newMB ;
}
return memBudget ;
}
/* ZSTD_getFrameProgression():
* tells how much data has been consumed ( input ) and produced ( output ) for current frame .
* able to count progression inside worker threads ( non - blocking mode ) .
*/
ZSTD_frameProgression ZSTD_getFrameProgression ( const ZSTD_CCtx * cctx )
{
# ifdef ZSTD_MULTITHREAD
if ( cctx - > appliedParams . nbWorkers > 0 ) {
return ZSTDMT_getFrameProgression ( cctx - > mtctx ) ;
}
# endif
{ ZSTD_frameProgression fp ;
size_t const buffered = ( cctx - > inBuff = = NULL ) ? 0 :
cctx - > inBuffPos - cctx - > inToCompress ;
if ( buffered ) assert ( cctx - > inBuffPos > = cctx - > inToCompress ) ;
assert ( buffered < = ZSTD_BLOCKSIZE_MAX ) ;
fp . ingested = cctx - > consumedSrcSize + buffered ;
fp . consumed = cctx - > consumedSrcSize ;
fp . produced = cctx - > producedCSize ;
return fp ;
} }
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 ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_sufficientBuff: is windowSize2=%u <= wlog1=%u " ,
2018-01-13 13:50:59 +01:00
( U32 ) windowSize2 , cParams2 . windowLog ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_sufficientBuff: is blockSize2=%u <= blockSize1=%u " ,
2018-01-13 13:50:59 +01:00
( 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
}
2018-05-15 19:45:22 +02:00
static void ZSTD_reset_compressedBlockState ( ZSTD_compressedBlockState_t * bs )
{
int i ;
for ( i = 0 ; i < ZSTD_REP_NUM ; + + i )
bs - > rep [ i ] = repStartValue [ i ] ;
bs - > entropy . hufCTable_repeatMode = HUF_repeat_none ;
bs - > entropy . offcode_repeatMode = FSE_repeat_none ;
bs - > entropy . matchlength_repeatMode = FSE_repeat_none ;
bs - > entropy . litlength_repeatMode = FSE_repeat_none ;
}
/*! ZSTD_invalidateMatchState()
* Invalidate all the matches in the match finder tables .
* Requires nextSrc and base to be set ( can be NULL ) .
*/
static void ZSTD_invalidateMatchState ( ZSTD_matchState_t * ms )
{
ZSTD_window_clear ( & ms - > window ) ;
ms - > nextToUpdate = ms - > window . dictLimit + 1 ;
ms - > loadedDictEnd = 0 ;
ms - > opt . litLengthSum = 0 ; /* force reset of btopt stats */
}
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
{
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 ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_continueCCtx: re-use context in place " ) ;
2018-01-13 13:50:59 +01:00
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 ;
2018-05-15 19:45:22 +02:00
cctx - > producedCSize = 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 - > stage = ZSTDcs_init ;
cctx - > dictID = 0 ;
2018-05-15 19:45:22 +02:00
if ( params . ldmParams . enableLdm )
ZSTD_window_clear ( & cctx - > ldmState . window ) ;
ZSTD_referenceExternalSequences ( cctx , NULL , 0 ) ;
ZSTD_invalidateMatchState ( & cctx - > blockState . matchState ) ;
ZSTD_reset_compressedBlockState ( cctx - > blockState . prevCBlock ) ;
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
2018-05-15 19:45:22 +02:00
static void * ZSTD_reset_matchState ( ZSTD_matchState_t * ms , void * ptr , ZSTD_compressionParameters const * cParams , ZSTD_compResetPolicy_e const crp , U32 const forCCtx )
{
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 = ( forCCtx & & cParams - > searchLength = = 3 ) ? MIN ( ZSTD_HASHLOG3_MAX , cParams - > windowLog ) : 0 ;
size_t const h3Size = ( ( size_t ) 1 ) < < hashLog3 ;
size_t const tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ;
ms - > hashLog3 = hashLog3 ;
memset ( & ms - > window , 0 , sizeof ( ms - > window ) ) ;
ZSTD_invalidateMatchState ( ms ) ;
/* opt parser space */
if ( forCCtx & & ( ( cParams - > strategy = = ZSTD_btopt ) | ( cParams - > strategy = = ZSTD_btultra ) ) ) {
DEBUGLOG ( 4 , " reserving optimal parser space " ) ;
ms - > opt . litFreq = ( U32 * ) ptr ;
ms - > opt . litLengthFreq = ms - > opt . litFreq + ( 1 < < Litbits ) ;
ms - > opt . matchLengthFreq = ms - > opt . litLengthFreq + ( MaxLL + 1 ) ;
ms - > opt . offCodeFreq = ms - > opt . matchLengthFreq + ( MaxML + 1 ) ;
ptr = ms - > opt . offCodeFreq + ( MaxOff + 1 ) ;
ms - > opt . matchTable = ( ZSTD_match_t * ) ptr ;
ptr = ms - > opt . matchTable + ZSTD_OPT_NUM + 1 ;
ms - > opt . priceTable = ( ZSTD_optimal_t * ) ptr ;
ptr = ms - > opt . priceTable + ZSTD_OPT_NUM + 1 ;
}
/* table Space */
DEBUGLOG ( 4 , " reset table : %u " , crp ! = ZSTDcrp_noMemset ) ;
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ; /* ensure ptr is properly aligned */
if ( crp ! = ZSTDcrp_noMemset ) memset ( ptr , 0 , tableSpace ) ; /* reset tables only */
ms - > hashTable = ( U32 * ) ( ptr ) ;
ms - > chainTable = ms - > hashTable + hSize ;
ms - > hashTable3 = ms - > chainTable + chainSize ;
ptr = ms - > hashTable3 + h3Size ;
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ;
return ptr ;
}
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-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 */
2018-05-15 19:45:22 +02:00
params . ldmParams . windowLog = params . cParams . windowLog ;
ZSTD_ldm_adjustParameters ( & params . ldmParams , & params . cParams ) ;
2017-10-26 22:41:47 +02:00
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 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 ;
2018-05-15 19:45:22 +02:00
size_t const matchStateSize = ZSTD_sizeof_matchState ( & params . cParams , /* forCCtx */ 1 ) ;
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq ( params . ldmParams , blockSize ) ;
2017-06-09 03:43:56 +02:00
void * ptr ;
/* Check if workSpace is large enough, alloc a new one if needed */
2018-05-15 19:45:22 +02:00
{ size_t const entropySpace = HUF_WORKSPACE_SIZE ;
size_t const blockStateSpace = 2 * sizeof ( ZSTD_compressedBlockState_t ) ;
2017-07-22 23:46:05 +02:00
size_t const bufferSpace = buffInSize + buffOutSize ;
2018-05-15 19:45:22 +02:00
size_t const ldmSpace = ZSTD_ldm_getTableSize ( params . ldmParams ) ;
size_t const ldmSeqSpace = maxNbLdmSeq * sizeof ( rawSeq ) ;
size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
ldmSeqSpace + matchStateSize + tokenSpace +
bufferSpace ;
DEBUGLOG ( 4 , " Need %uKB workspace, including %uKB for match state, and %uKB for buffers " ,
( U32 ) ( neededSpace > > 10 ) , ( U32 ) ( matchStateSize > > 10 ) , ( U32 ) ( bufferSpace > > 10 ) ) ;
DEBUGLOG ( 4 , " windowSize: %u - blockSize: %u " , ( 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 ;
2018-05-15 19:45:22 +02:00
/* Statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
2017-08-27 12:05:17 +02:00
assert ( ( ( size_t ) zc - > workSpace & 3 ) = = 0 ) ; /* ensure correct alignment */
2018-05-15 19:45:22 +02:00
assert ( zc - > workSpaceSize > = 2 * sizeof ( ZSTD_compressedBlockState_t ) ) ;
zc - > blockState . prevCBlock = ( ZSTD_compressedBlockState_t * ) zc - > workSpace ;
zc - > blockState . nextCBlock = zc - > blockState . prevCBlock + 1 ;
ptr = zc - > blockState . nextCBlock + 1 ;
zc - > entropyWorkspace = ( U32 * ) ptr ;
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 ;
2018-05-15 19:45:22 +02:00
zc - > producedCSize = 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 ;
2018-05-15 19:45:22 +02:00
ZSTD_reset_compressedBlockState ( zc - > blockState . prevCBlock ) ;
ptr = zc - > entropyWorkspace + HUF_WORKSPACE_SIZE_U32 ;
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 ;
2018-05-15 19:45:22 +02:00
zc - > ldmSequences = ( rawSeq * ) ptr ;
ptr = zc - > ldmSequences + maxNbLdmSeq ;
zc - > maxNbLdmSequences = maxNbLdmSeq ;
memset ( & zc - > ldmState . window , 0 , sizeof ( zc - > ldmState . window ) ) ;
2017-10-26 22:41:47 +02:00
}
2018-05-15 19:45:22 +02:00
assert ( ( ( size_t ) ptr & 3 ) = = 0 ) ; /* ensure ptr is properly aligned */
2017-10-26 22:41:47 +02:00
2018-05-15 19:45:22 +02:00
ptr = ZSTD_reset_matchState ( & zc - > blockState . matchState , ptr , & params . cParams , crp , /* forCCtx */ 1 ) ;
2017-06-09 03:43:56 +02:00
/* 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 ;
2018-05-15 19:45:22 +02:00
ZSTD_window_clear ( & zc - > ldmState . window ) ;
2017-10-26 22:41:47 +02:00
}
2018-05-15 19:45:22 +02:00
ZSTD_referenceExternalSequences ( zc , NULL , 0 ) ;
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) cctx - > blockState . prevCBlock - > rep [ i ] = 0 ;
assert ( ! ZSTD_window_hasExtDict ( cctx - > blockState . matchState . window ) ) ;
2017-06-09 03:43:56 +02:00
}
2018-05-15 19:45:22 +02:00
static size_t ZSTD_resetCCtx_usingCDict ( ZSTD_CCtx * cctx ,
const ZSTD_CDict * cdict ,
unsigned windowLog ,
ZSTD_frameParameters fParams ,
U64 pledgedSrcSize ,
ZSTD_buffered_policy_e zbuff )
{
{ ZSTD_CCtx_params params = cctx - > requestedParams ;
/* Copy only compression parameters related to tables. */
params . cParams = cdict - > cParams ;
if ( windowLog ) params . cParams . windowLog = windowLog ;
params . fParams = fParams ;
ZSTD_resetCCtx_internal ( cctx , params , pledgedSrcSize ,
ZSTDcrp_noMemset , zbuff ) ;
assert ( cctx - > appliedParams . cParams . strategy = = cdict - > cParams . strategy ) ;
assert ( cctx - > appliedParams . cParams . hashLog = = cdict - > cParams . hashLog ) ;
assert ( cctx - > appliedParams . cParams . chainLog = = cdict - > cParams . chainLog ) ;
}
/* copy tables */
{ size_t const chainSize = ( cdict - > cParams . strategy = = ZSTD_fast ) ? 0 : ( ( size_t ) 1 < < cdict - > cParams . chainLog ) ;
size_t const hSize = ( size_t ) 1 < < cdict - > cParams . hashLog ;
size_t const tableSpace = ( chainSize + hSize ) * sizeof ( U32 ) ;
assert ( ( U32 * ) cctx - > blockState . matchState . chainTable = = ( U32 * ) cctx - > blockState . matchState . hashTable + hSize ) ; /* chainTable must follow hashTable */
assert ( ( U32 * ) cctx - > blockState . matchState . hashTable3 = = ( U32 * ) cctx - > blockState . matchState . chainTable + chainSize ) ;
assert ( ( U32 * ) cdict - > matchState . chainTable = = ( U32 * ) cdict - > matchState . hashTable + hSize ) ; /* chainTable must follow hashTable */
assert ( ( U32 * ) cdict - > matchState . hashTable3 = = ( U32 * ) cdict - > matchState . chainTable + chainSize ) ;
memcpy ( cctx - > blockState . matchState . hashTable , cdict - > matchState . hashTable , tableSpace ) ; /* presumes all tables follow each other */
}
/* Zero the hashTable3, since the cdict never fills it */
{ size_t const h3Size = ( size_t ) 1 < < cctx - > blockState . matchState . hashLog3 ;
assert ( cdict - > matchState . hashLog3 = = 0 ) ;
memset ( cctx - > blockState . matchState . hashTable3 , 0 , h3Size * sizeof ( U32 ) ) ;
}
/* copy dictionary offsets */
{
ZSTD_matchState_t const * srcMatchState = & cdict - > matchState ;
ZSTD_matchState_t * dstMatchState = & cctx - > blockState . matchState ;
dstMatchState - > window = srcMatchState - > window ;
dstMatchState - > nextToUpdate = srcMatchState - > nextToUpdate ;
dstMatchState - > nextToUpdate3 = srcMatchState - > nextToUpdate3 ;
dstMatchState - > loadedDictEnd = srcMatchState - > loadedDictEnd ;
}
cctx - > dictID = cdict - > dictID ;
/* copy block state */
memcpy ( cctx - > blockState . prevCBlock , & cdict - > cBlockState , sizeof ( cdict - > cBlockState ) ) ;
return 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 ,
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 ;
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 ) ;
2018-05-15 19:45:22 +02:00
assert ( dstCCtx - > appliedParams . cParams . windowLog = = srcCCtx - > appliedParams . cParams . windowLog ) ;
assert ( dstCCtx - > appliedParams . cParams . strategy = = srcCCtx - > appliedParams . cParams . strategy ) ;
assert ( dstCCtx - > appliedParams . cParams . hashLog = = srcCCtx - > appliedParams . cParams . hashLog ) ;
assert ( dstCCtx - > appliedParams . cParams . chainLog = = srcCCtx - > appliedParams . cParams . chainLog ) ;
assert ( dstCCtx - > blockState . matchState . hashLog3 = = srcCCtx - > blockState . matchState . hashLog3 ) ;
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 ;
2018-05-15 19:45:22 +02:00
size_t const h3Size = ( size_t ) 1 < < srcCCtx - > blockState . matchState . hashLog3 ;
2017-06-09 03:43:56 +02:00
size_t const tableSpace = ( chainSize + hSize + h3Size ) * sizeof ( U32 ) ;
2018-05-15 19:45:22 +02:00
assert ( ( U32 * ) dstCCtx - > blockState . matchState . chainTable = = ( U32 * ) dstCCtx - > blockState . matchState . hashTable + hSize ) ; /* chainTable must follow hashTable */
assert ( ( U32 * ) dstCCtx - > blockState . matchState . hashTable3 = = ( U32 * ) dstCCtx - > blockState . matchState . chainTable + chainSize ) ;
memcpy ( dstCCtx - > blockState . matchState . hashTable , srcCCtx - > blockState . matchState . hashTable , tableSpace ) ; /* presumes all tables follow each other */
2017-06-09 03:43:56 +02:00
}
/* copy dictionary offsets */
2018-01-13 13:50:59 +01:00
{
2018-05-15 19:45:22 +02:00
ZSTD_matchState_t const * srcMatchState = & srcCCtx - > blockState . matchState ;
ZSTD_matchState_t * dstMatchState = & dstCCtx - > blockState . matchState ;
dstMatchState - > window = srcMatchState - > window ;
dstMatchState - > nextToUpdate = srcMatchState - > nextToUpdate ;
dstMatchState - > nextToUpdate3 = srcMatchState - > nextToUpdate3 ;
dstMatchState - > loadedDictEnd = srcMatchState - > loadedDictEnd ;
2018-01-13 13:50:59 +01:00
}
2018-05-15 19:45:22 +02:00
dstCCtx - > dictID = srcCCtx - > dictID ;
/* copy block state */
memcpy ( dstCCtx - > blockState . prevCBlock , srcCCtx - > blockState . prevCBlock , sizeof ( * srcCCtx - > blockState . prevCBlock ) ) ;
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 ,
2018-05-15 19:45:22 +02:00
fParams , pledgedSrcSize ,
2018-01-13 13:50:59 +01:00
zbuff ) ;
2017-06-09 03:43:56 +02:00
}
2018-05-15 19:45:22 +02:00
# define ZSTD_ROWSIZE 16
2017-06-09 03:43:56 +02:00
/*! ZSTD_reduceTable() :
2018-05-15 19:45:22 +02:00
* reduce table indexes by ` reducerValue ` , or squash to zero .
* PreserveMark preserves " unsorted mark " for btlazy2 strategy .
* It must be set to a clear 0 / 1 value , to remove branch during inlining .
* Presume table size is a multiple of ZSTD_ROWSIZE
* to help auto - vectorization */
FORCE_INLINE_TEMPLATE void
ZSTD_reduceTable_internal ( U32 * const table , U32 const size , U32 const reducerValue , int const preserveMark )
{
int const nbRows = ( int ) size / ZSTD_ROWSIZE ;
int cellNb = 0 ;
int rowNb ;
assert ( ( size & ( ZSTD_ROWSIZE - 1 ) ) = = 0 ) ; /* multiple of ZSTD_ROWSIZE */
assert ( size < ( 1U < < 31 ) ) ; /* can be casted to int */
for ( rowNb = 0 ; rowNb < nbRows ; rowNb + + ) {
int column ;
for ( column = 0 ; column < ZSTD_ROWSIZE ; column + + ) {
if ( preserveMark ) {
U32 const adder = ( table [ cellNb ] = = ZSTD_DUBT_UNSORTED_MARK ) ? reducerValue : 0 ;
table [ cellNb ] + = adder ;
}
if ( table [ cellNb ] < reducerValue ) table [ cellNb ] = 0 ;
else table [ cellNb ] - = reducerValue ;
cellNb + + ;
} }
}
static void ZSTD_reduceTable ( U32 * const table , U32 const size , U32 const reducerValue )
2017-06-09 03:43:56 +02:00
{
2018-05-15 19:45:22 +02:00
ZSTD_reduceTable_internal ( table , size , reducerValue , 0 ) ;
2017-06-09 03:43:56 +02:00
}
2018-05-15 19:45:22 +02:00
static void ZSTD_reduceTable_btlazy2 ( U32 * const table , U32 const size , U32 const reducerValue )
2017-10-26 22:41:47 +02:00
{
2018-05-15 19:45:22 +02:00
ZSTD_reduceTable_internal ( table , size , reducerValue , 1 ) ;
2017-10-26 22:41:47 +02:00
}
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 )
{
2018-05-15 19:45:22 +02:00
ZSTD_matchState_t * const ms = & zc - > blockState . matchState ;
{ U32 const hSize = ( U32 ) 1 < < zc - > appliedParams . cParams . hashLog ;
ZSTD_reduceTable ( ms - > hashTable , hSize , reducerValue ) ;
}
2017-06-09 03:43:56 +02:00
2018-05-15 19:45:22 +02:00
if ( zc - > appliedParams . cParams . strategy ! = ZSTD_fast ) {
U32 const chainSize = ( U32 ) 1 < < zc - > appliedParams . cParams . chainLog ;
if ( zc - > appliedParams . cParams . strategy = = ZSTD_btlazy2 )
ZSTD_reduceTable_btlazy2 ( ms - > chainTable , chainSize , reducerValue ) ;
else
ZSTD_reduceTable ( ms - > chainTable , chainSize , reducerValue ) ;
}
2017-10-26 22:41:47 +02:00
2018-05-15 19:45:22 +02:00
if ( ms - > hashLog3 ) {
U32 const h3Size = ( U32 ) 1 < < ms - > hashLog3 ;
ZSTD_reduceTable ( ms - > hashTable3 , h3Size , reducerValue ) ;
2017-10-26 22:41:47 +02:00
}
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 ; }
2018-05-15 19:45:22 +02:00
static size_t ZSTD_compressLiterals ( ZSTD_entropyCTables_t const * prevEntropy ,
ZSTD_entropyCTables_t * nextEntropy ,
ZSTD_strategy strategy , int disableLiteralCompression ,
2017-06-09 03:43:56 +02:00
void * dst , size_t dstCapacity ,
2018-05-15 19:45:22 +02:00
const void * src , size_t srcSize ,
U32 * workspace , const int bmi2 )
2017-06-09 03:43:56 +02:00
{
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 ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 5 , " ZSTD_compressLiterals (disableLiteralCompression=%i) " ,
disableLiteralCompression ) ;
/* Prepare nextEntropy assuming reusing the existing table */
nextEntropy - > hufCTable_repeatMode = prevEntropy - > hufCTable_repeatMode ;
memcpy ( nextEntropy - > hufCTable , prevEntropy - > hufCTable ,
sizeof ( prevEntropy - > hufCTable ) ) ;
if ( disableLiteralCompression )
return ZSTD_noCompressLiterals ( dst , dstCapacity , src , srcSize ) ;
2017-06-09 03:43:56 +02:00
/* small ? don't even attempt compression (speed opt) */
2018-05-15 19:45:22 +02:00
# define COMPRESS_LITERALS_SIZE_MIN 63
{ size_t const minLitSize = ( prevEntropy - > hufCTable_repeatMode = = HUF_repeat_valid ) ? 6 : COMPRESS_LITERALS_SIZE_MIN ;
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 */
2018-05-15 19:45:22 +02:00
{ HUF_repeat repeat = prevEntropy - > hufCTable_repeatMode ;
2017-08-27 12:05:17 +02:00
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 ,
2018-05-15 19:45:22 +02:00
workspace , HUF_WORKSPACE_SIZE , ( HUF_CElt * ) nextEntropy - > hufCTable , & repeat , preferRepeat , bmi2 )
2017-06-09 03:43:56 +02:00
: HUF_compress4X_repeat ( ostart + lhSize , dstCapacity - lhSize , src , srcSize , 255 , 11 ,
2018-05-15 19:45:22 +02:00
workspace , HUF_WORKSPACE_SIZE , ( HUF_CElt * ) nextEntropy - > hufCTable , & repeat , preferRepeat , bmi2 ) ;
if ( repeat ! = HUF_repeat_none ) {
/* reused the existing table */
hType = set_repeat ;
}
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 ) ) {
2018-05-15 19:45:22 +02:00
memcpy ( nextEntropy - > hufCTable , prevEntropy - > hufCTable , sizeof ( prevEntropy - > hufCTable ) ) ;
2017-06-09 03:43:56 +02:00
return ZSTD_noCompressLiterals ( dst , dstCapacity , src , srcSize ) ;
}
if ( cLitSize = = 1 ) {
2018-05-15 19:45:22 +02:00
memcpy ( nextEntropy - > hufCTable , prevEntropy - > hufCTable , sizeof ( prevEntropy - > hufCTable ) ) ;
2017-06-09 03:43:56 +02:00
return ZSTD_compressRleLiteralsBlock ( dst , dstCapacity , src , srcSize ) ;
}
2018-05-15 19:45:22 +02:00
if ( hType = = set_compressed ) {
/* using a newly constructed table */
nextEntropy - > hufCTable_repeatMode = HUF_repeat_check ;
}
2017-06-09 03:43:56 +02:00
/* 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 ,
2018-05-15 19:45:22 +02:00
FSE_CTable * nextCTable , U32 FSELog , symbolEncodingType_e type ,
2017-08-27 12:05:17 +02:00
U32 * count , U32 max ,
BYTE const * codeTable , size_t nbSeq ,
S16 const * defaultNorm , U32 defaultNormLog , U32 defaultMax ,
2018-05-15 19:45:22 +02:00
FSE_CTable const * prevCTable , size_t prevCTableSize ,
2017-08-27 12:05:17 +02:00
void * workspace , size_t workspaceSize )
{
BYTE * op = ( BYTE * ) dst ;
BYTE const * const oend = op + dstCapacity ;
switch ( type ) {
case set_rle :
* op = codeTable [ 0 ] ;
2018-05-15 19:45:22 +02:00
CHECK_F ( FSE_buildCTable_rle ( nextCTable , ( BYTE ) max ) ) ;
2017-08-27 12:05:17 +02:00
return 1 ;
case set_repeat :
2018-05-15 19:45:22 +02:00
memcpy ( nextCTable , prevCTable , prevCTableSize ) ;
2017-08-27 12:05:17 +02:00
return 0 ;
case set_basic :
2018-05-15 19:45:22 +02:00
CHECK_F ( FSE_buildCTable_wksp ( nextCTable , 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 ;
2018-05-15 19:45:22 +02:00
CHECK_F ( FSE_buildCTable_wksp ( nextCTable , norm , max , tableLog , workspace , workspaceSize ) ) ;
2017-10-26 22:41:47 +02:00
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-05-15 19:45:22 +02:00
FORCE_INLINE_TEMPLATE size_t
ZSTD_encodeSequences_body (
2018-01-13 13:50:59 +01:00
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 ,
2018-05-15 19:45:22 +02:00
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
} }
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 6 , " ZSTD_encodeSequences: flushing ML state with %u bits " , stateMatchLength . stateLog ) ;
2017-10-26 22:41:47 +02:00
FSE_flushCState ( & blockStream , & stateMatchLength ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 6 , " ZSTD_encodeSequences: flushing Off state with %u bits " , stateOffsetBits . stateLog ) ;
2017-10-26 22:41:47 +02:00
FSE_flushCState ( & blockStream , & stateOffsetBits ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 6 , " ZSTD_encodeSequences: flushing LL state with %u bits " , stateLitLength . stateLog ) ;
2017-10-26 22:41:47 +02:00
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
}
}
2018-05-15 19:45:22 +02:00
static size_t
ZSTD_encodeSequences_default (
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 )
{
return ZSTD_encodeSequences_body ( dst , dstCapacity ,
CTable_MatchLength , mlCodeTable ,
CTable_OffsetBits , ofCodeTable ,
CTable_LitLength , llCodeTable ,
sequences , nbSeq , longOffsets ) ;
}
# if DYNAMIC_BMI2
static TARGET_ATTRIBUTE ( " bmi2 " ) size_t
ZSTD_encodeSequences_bmi2 (
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 )
{
return ZSTD_encodeSequences_body ( dst , dstCapacity ,
CTable_MatchLength , mlCodeTable ,
CTable_OffsetBits , ofCodeTable ,
CTable_LitLength , llCodeTable ,
sequences , nbSeq , longOffsets ) ;
}
# endif
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 , int bmi2 )
{
# if DYNAMIC_BMI2
if ( bmi2 ) {
return ZSTD_encodeSequences_bmi2 ( dst , dstCapacity ,
CTable_MatchLength , mlCodeTable ,
CTable_OffsetBits , ofCodeTable ,
CTable_LitLength , llCodeTable ,
sequences , nbSeq , longOffsets ) ;
}
# endif
( void ) bmi2 ;
return ZSTD_encodeSequences_default ( dst , dstCapacity ,
CTable_MatchLength , mlCodeTable ,
CTable_OffsetBits , ofCodeTable ,
CTable_LitLength , llCodeTable ,
sequences , nbSeq , longOffsets ) ;
}
2017-10-26 22:41:47 +02:00
MEM_STATIC size_t ZSTD_compressSequences_internal ( seqStore_t * seqStorePtr ,
2018-05-15 19:45:22 +02:00
ZSTD_entropyCTables_t const * prevEntropy ,
ZSTD_entropyCTables_t * nextEntropy ,
ZSTD_CCtx_params const * cctxParams ,
void * dst , size_t dstCapacity , U32 * workspace ,
const int bmi2 )
2017-06-09 03:43:56 +02:00
{
2018-05-15 19:45:22 +02:00
const int longOffsets = cctxParams - > cParams . windowLog > STREAM_ACCUMULATOR_MIN ;
2017-10-26 22:41:47 +02:00
U32 count [ MaxSeq + 1 ] ;
2018-05-15 19:45:22 +02:00
FSE_CTable * CTable_LitLength = nextEntropy - > litlengthCTable ;
FSE_CTable * CTable_OffsetBits = nextEntropy - > offcodeCTable ;
FSE_CTable * CTable_MatchLength = nextEntropy - > matchlengthCTable ;
2017-10-26 22:41:47 +02:00
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
2018-05-15 19:45:22 +02:00
ZSTD_STATIC_ASSERT ( HUF_WORKSPACE_SIZE > = ( 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 (
2018-05-15 19:45:22 +02:00
prevEntropy , nextEntropy ,
cctxParams - > cParams . strategy , cctxParams - > disableLiteralCompression ,
op , dstCapacity ,
literals , litSize ,
workspace , bmi2 ) ;
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
if ( nbSeq = = 0 ) {
memcpy ( nextEntropy - > litlengthCTable , prevEntropy - > litlengthCTable , sizeof ( prevEntropy - > litlengthCTable ) ) ;
nextEntropy - > litlength_repeatMode = prevEntropy - > litlength_repeatMode ;
memcpy ( nextEntropy - > offcodeCTable , prevEntropy - > offcodeCTable , sizeof ( prevEntropy - > offcodeCTable ) ) ;
nextEntropy - > offcode_repeatMode = prevEntropy - > offcode_repeatMode ;
memcpy ( nextEntropy - > matchlengthCTable , prevEntropy - > matchlengthCTable , sizeof ( prevEntropy - > matchlengthCTable ) ) ;
nextEntropy - > matchlength_repeatMode = prevEntropy - > matchlength_repeatMode ;
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 ;
2018-05-15 19:45:22 +02:00
size_t const mostFrequent = FSE_countFast_wksp ( count , & max , llCodeTable , nbSeq , workspace ) ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " Building LL table " ) ;
2018-05-15 19:45:22 +02:00
nextEntropy - > litlength_repeatMode = prevEntropy - > litlength_repeatMode ;
LLtype = ZSTD_selectEncodingType ( & nextEntropy - > litlength_repeatMode , mostFrequent , nbSeq , LL_defaultNormLog , ZSTD_defaultAllowed ) ;
2017-10-26 22:41:47 +02:00
{ size_t const countSize = ZSTD_buildCTable ( op , oend - op , CTable_LitLength , LLFSELog , ( symbolEncodingType_e ) LLtype ,
count , max , llCodeTable , nbSeq , LL_defaultNorm , LL_defaultNormLog , MaxLL ,
2018-05-15 19:45:22 +02:00
prevEntropy - > litlengthCTable , sizeof ( prevEntropy - > litlengthCTable ) ,
workspace , HUF_WORKSPACE_SIZE ) ;
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
size_t const mostFrequent = FSE_countFast_wksp ( count , & max , ofCodeTable , nbSeq , workspace ) ;
2017-10-26 22:41:47 +02:00
/* 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 " ) ;
2018-05-15 19:45:22 +02:00
nextEntropy - > offcode_repeatMode = prevEntropy - > offcode_repeatMode ;
Offtype = ZSTD_selectEncodingType ( & nextEntropy - > offcode_repeatMode , mostFrequent , nbSeq , OF_defaultNormLog , defaultPolicy ) ;
2017-10-26 22:41:47 +02:00
{ size_t const countSize = ZSTD_buildCTable ( op , oend - op , CTable_OffsetBits , OffFSELog , ( symbolEncodingType_e ) Offtype ,
count , max , ofCodeTable , nbSeq , OF_defaultNorm , OF_defaultNormLog , DefaultMaxOff ,
2018-05-15 19:45:22 +02:00
prevEntropy - > offcodeCTable , sizeof ( prevEntropy - > offcodeCTable ) ,
workspace , HUF_WORKSPACE_SIZE ) ;
2017-10-26 22:41:47 +02:00
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 ;
2018-05-15 19:45:22 +02:00
size_t const mostFrequent = FSE_countFast_wksp ( count , & max , mlCodeTable , nbSeq , workspace ) ;
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 5 , " Building ML table " ) ;
2018-05-15 19:45:22 +02:00
nextEntropy - > matchlength_repeatMode = prevEntropy - > matchlength_repeatMode ;
MLtype = ZSTD_selectEncodingType ( & nextEntropy - > matchlength_repeatMode , mostFrequent , nbSeq , ML_defaultNormLog , ZSTD_defaultAllowed ) ;
2017-10-26 22:41:47 +02:00
{ size_t const countSize = ZSTD_buildCTable ( op , oend - op , CTable_MatchLength , MLFSELog , ( symbolEncodingType_e ) MLtype ,
count , max , mlCodeTable , nbSeq , ML_defaultNorm , ML_defaultNormLog , MaxML ,
2018-05-15 19:45:22 +02:00
prevEntropy - > matchlengthCTable , sizeof ( prevEntropy - > matchlengthCTable ) ,
workspace , HUF_WORKSPACE_SIZE ) ;
2017-10-26 22:41:47 +02:00
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 ,
2018-05-15 19:45:22 +02:00
longOffsets , bmi2 ) ;
2018-01-13 13:50:59 +01:00
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 ,
2018-05-15 19:45:22 +02:00
ZSTD_entropyCTables_t const * prevEntropy ,
ZSTD_entropyCTables_t * nextEntropy ,
ZSTD_CCtx_params const * cctxParams ,
2017-10-26 22:41:47 +02:00
void * dst , size_t dstCapacity ,
2018-05-15 19:45:22 +02:00
size_t srcSize , U32 * workspace , int bmi2 )
2017-06-09 03:43:56 +02:00
{
2018-05-15 19:45:22 +02:00
size_t const cSize = ZSTD_compressSequences_internal (
seqStorePtr , prevEntropy , nextEntropy , cctxParams , dst , dstCapacity ,
workspace , bmi2 ) ;
/* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
* Since we ran out of space , block must be not compressible , so fall back to raw uncompressed block .
2017-10-26 22:41:47 +02:00
*/
2018-05-15 19:45:22 +02:00
if ( ( cSize = = ERROR ( dstSize_tooSmall ) ) & ( srcSize < = dstCapacity ) )
return 0 ; /* block not compressed */
if ( ZSTD_isError ( cSize ) ) return cSize ;
/* Check compressibility */
{ size_t const maxCSize = srcSize - ZSTD_minGain ( srcSize ) ; /* note : fixed formula, maybe should depend on compression level, or strategy */
if ( cSize > = maxCSize ) return 0 ; /* block not compressed */
}
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 .
*/
2018-05-15 19:45:22 +02:00
if ( nextEntropy - > offcode_repeatMode = = FSE_repeat_valid )
nextEntropy - > offcode_repeatMode = FSE_repeat_check ;
2017-06-09 03:43:56 +02:00
2017-10-26 22:41:47 +02:00
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
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 ;
}
2018-05-15 19:45:22 +02:00
static size_t ZSTD_compressBlock_internal ( ZSTD_CCtx * zc ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize )
2017-06-09 03:43:56 +02:00
{
2018-05-15 19:45:22 +02:00
ZSTD_matchState_t * const ms = & zc - > blockState . matchState ;
DEBUGLOG ( 5 , " ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u) " ,
( U32 ) dstCapacity , ms - > window . dictLimit , ms - > nextToUpdate ) ;
if ( srcSize < MIN_CBLOCK_SIZE + ZSTD_blockHeaderSize + 1 ) {
ZSTD_ldm_skipSequences ( & zc - > externSeqStore , srcSize , zc - > appliedParams . cParams . searchLength ) ;
2018-01-13 13:50:59 +01:00
return 0 ; /* don't even attempt compression below a certain srcSize */
2018-05-15 19:45:22 +02:00
}
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 */
2018-05-15 19:45:22 +02:00
{ const BYTE * const base = ms - > window . base ;
2018-01-13 13:50:59 +01:00
const BYTE * const istart = ( const BYTE * ) src ;
const U32 current = ( U32 ) ( istart - base ) ;
2018-05-15 19:45:22 +02:00
if ( current > ms - > nextToUpdate + 384 )
ms - > nextToUpdate = current - MIN ( 192 , ( U32 ) ( current - ms - > nextToUpdate - 384 ) ) ;
2018-01-13 13:50:59 +01:00
}
2018-05-15 19:45:22 +02:00
/* select and store sequences */
{ U32 const extDict = ZSTD_window_hasExtDict ( ms - > window ) ;
size_t lastLLSize ;
{ int i ;
for ( i = 0 ; i < ZSTD_REP_NUM ; + + i )
zc - > blockState . nextCBlock - > rep [ i ] = zc - > blockState . prevCBlock - > rep [ i ] ;
}
if ( zc - > externSeqStore . pos < zc - > externSeqStore . size ) {
assert ( ! zc - > appliedParams . ldmParams . enableLdm ) ;
/* Updates ldmSeqStore.pos */
lastLLSize =
ZSTD_ldm_blockCompress ( & zc - > externSeqStore ,
ms , & zc - > seqStore ,
zc - > blockState . nextCBlock - > rep ,
& zc - > appliedParams . cParams ,
src , srcSize , extDict ) ;
assert ( zc - > externSeqStore . pos < = zc - > externSeqStore . size ) ;
} else if ( zc - > appliedParams . ldmParams . enableLdm ) {
rawSeqStore_t ldmSeqStore = { NULL , 0 , 0 , 0 } ;
ldmSeqStore . seq = zc - > ldmSequences ;
ldmSeqStore . capacity = zc - > maxNbLdmSequences ;
/* Updates ldmSeqStore.size */
CHECK_F ( ZSTD_ldm_generateSequences ( & zc - > ldmState , & ldmSeqStore ,
& zc - > appliedParams . ldmParams ,
src , srcSize ) ) ;
/* Updates ldmSeqStore.pos */
lastLLSize =
ZSTD_ldm_blockCompress ( & ldmSeqStore ,
ms , & zc - > seqStore ,
zc - > blockState . nextCBlock - > rep ,
& zc - > appliedParams . cParams ,
src , srcSize , extDict ) ;
assert ( ldmSeqStore . pos = = ldmSeqStore . size ) ;
} else { /* not long range mode */
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor ( zc - > appliedParams . cParams . strategy , extDict ) ;
lastLLSize = blockCompressor ( ms , & zc - > seqStore , zc - > blockState . nextCBlock - > rep , & zc - > appliedParams . cParams , src , srcSize ) ;
}
{ const BYTE * const lastLiterals = ( const BYTE * ) src + srcSize - lastLLSize ;
ZSTD_storeLastLiterals ( & zc - > seqStore , lastLiterals , lastLLSize ) ;
} }
/* encode sequences and literals */
{ size_t const cSize = ZSTD_compressSequences ( & zc - > seqStore ,
& zc - > blockState . prevCBlock - > entropy , & zc - > blockState . nextCBlock - > entropy ,
& zc - > appliedParams ,
dst , dstCapacity ,
srcSize , zc - > entropyWorkspace , zc - > bmi2 ) ;
if ( ZSTD_isError ( cSize ) | | cSize = = 0 ) return cSize ;
/* confirm repcodes and entropy tables */
{ ZSTD_compressedBlockState_t * const tmp = zc - > blockState . prevCBlock ;
zc - > blockState . prevCBlock = zc - > blockState . nextCBlock ;
zc - > blockState . nextCBlock = tmp ;
}
return cSize ;
2018-01-13 13:50:59 +01:00
}
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 ) {
2018-05-15 19:45:22 +02:00
ZSTD_matchState_t * const ms = & cctx - > blockState . matchState ;
2017-06-09 03:43:56 +02:00
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 ;
2018-05-15 19:45:22 +02:00
if ( ZSTD_window_needOverflowCorrection ( ms - > window , ip + blockSize ) ) {
U32 const cycleLog = ZSTD_cycleLog ( cctx - > appliedParams . cParams . chainLog , cctx - > appliedParams . cParams . strategy ) ;
U32 const correction = ZSTD_window_correctOverflow ( & ms - > window , cycleLog , maxDist , ip ) ;
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 ) ;
2018-05-15 19:45:22 +02:00
2017-06-09 03:43:56 +02:00
ZSTD_reduceIndex ( cctx , correction ) ;
2018-05-15 19:45:22 +02:00
if ( ms - > nextToUpdate < correction ) ms - > nextToUpdate = 0 ;
else ms - > nextToUpdate - = correction ;
ms - > loadedDictEnd = 0 ;
2017-06-09 03:43:56 +02:00
}
2018-05-15 19:45:22 +02:00
ZSTD_window_enforceMaxDist ( & ms - > window , ip + blockSize , maxDist , & ms - > loadedDictEnd ) ;
if ( ms - > nextToUpdate < ms - > window . lowLimit ) ms - > nextToUpdate = ms - > window . lowLimit ;
2017-06-09 03:43:56 +02:00
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 ;
}
2018-05-15 19:45:22 +02:00
/* ZSTD_writeLastEmptyBlock() :
* output an empty Block with end - of - frame mark to complete a frame
* @ return : size of data written into ` dst ` ( = = ZSTD_blockHeaderSize ( defined in zstd_internal . h ) )
* or an error code if ` dstCapcity ` is too small ( < ZSTD_blockHeaderSize )
*/
size_t ZSTD_writeLastEmptyBlock ( void * dst , size_t dstCapacity )
{
if ( dstCapacity < ZSTD_blockHeaderSize ) return ERROR ( dstSize_tooSmall ) ;
{ U32 const cBlockHeader24 = 1 /*lastBlock*/ + ( ( ( U32 ) bt_raw ) < < 1 ) ; /* 0 size */
MEM_writeLE24 ( dst , cBlockHeader24 ) ;
return ZSTD_blockHeaderSize ;
}
}
size_t ZSTD_referenceExternalSequences ( ZSTD_CCtx * cctx , rawSeq * seq , size_t nbSeq )
{
if ( cctx - > stage ! = ZSTDcs_init )
return ERROR ( stage_wrong ) ;
if ( cctx - > appliedParams . ldmParams . enableLdm )
return ERROR ( parameter_unsupported ) ;
cctx - > externSeqStore . seq = seq ;
cctx - > externSeqStore . size = nbSeq ;
cctx - > externSeqStore . capacity = nbSeq ;
cctx - > externSeqStore . pos = 0 ;
return 0 ;
}
2017-06-09 03:43:56 +02:00
static size_t ZSTD_compressContinue_internal ( ZSTD_CCtx * cctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
U32 frame , U32 lastFrameChunk )
{
2018-05-15 19:45:22 +02:00
ZSTD_matchState_t * ms = & cctx - > blockState . matchState ;
2017-06-09 03:43:56 +02:00
size_t fhSize = 0 ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 5 , " ZSTD_compressContinue_internal, stage: %u, srcSize: %u " ,
cctx - > stage , ( U32 ) srcSize ) ;
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 */
2018-05-15 19:45:22 +02:00
if ( ! ZSTD_window_update ( & ms - > window , src , srcSize ) ) {
ms - > nextToUpdate = ms - > window . dictLimit ;
2017-06-09 03:43:56 +02:00
}
2018-05-15 19:45:22 +02:00
if ( cctx - > appliedParams . ldmParams . enableLdm )
ZSTD_window_update ( & cctx - > ldmState . window , src , srcSize ) ;
2017-06-09 03:43:56 +02:00
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 ;
2018-05-15 19:45:22 +02:00
cctx - > producedCSize + = ( cSize + fhSize ) ;
if ( cctx - > appliedParams . fParams . contentSizeFlag ) { /* control src size */
if ( cctx - > consumedSrcSize + 1 > cctx - > pledgedSrcSizePlusOne ) {
DEBUGLOG ( 4 , " error : pledgedSrcSize = %u, while realSrcSize >= %u " ,
( U32 ) cctx - > pledgedSrcSizePlusOne - 1 , ( U32 ) cctx - > consumedSrcSize ) ;
return ERROR ( srcSize_wrong ) ;
}
}
2017-06-09 03:43:56 +02:00
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 )
{
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 5 , " ZSTD_compressContinue (srcSize=%u) " , ( U32 ) srcSize ) ;
2017-06-09 03:43:56 +02:00
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
{
2018-05-15 19:45:22 +02:00
ZSTD_compressionParameters const cParams = cctx - > appliedParams . cParams ;
assert ( ! ZSTD_checkCParams ( cParams ) ) ;
2017-10-26 22:41:47 +02:00
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
*/
2018-05-15 19:45:22 +02:00
static size_t ZSTD_loadDictionaryContent ( ZSTD_matchState_t * ms , ZSTD_CCtx_params const * params , const void * src , size_t srcSize )
2017-06-09 03:43:56 +02:00
{
const BYTE * const ip = ( const BYTE * ) src ;
const BYTE * const iend = ip + srcSize ;
2018-05-15 19:45:22 +02:00
ZSTD_compressionParameters const * cParams = & params - > cParams ;
2017-06-09 03:43:56 +02:00
2018-05-15 19:45:22 +02:00
ZSTD_window_update ( & ms - > window , src , srcSize ) ;
ms - > loadedDictEnd = params - > forceWindow ? 0 : ( U32 ) ( iend - ms - > window . base ) ;
2017-06-09 03:43:56 +02:00
if ( srcSize < = HASH_READ_SIZE ) return 0 ;
2018-05-15 19:45:22 +02:00
switch ( params - > cParams . strategy )
2017-06-09 03:43:56 +02:00
{
case ZSTD_fast :
2018-05-15 19:45:22 +02:00
ZSTD_fillHashTable ( ms , cParams , iend ) ;
2017-06-09 03:43:56 +02:00
break ;
case ZSTD_dfast :
2018-05-15 19:45:22 +02:00
ZSTD_fillDoubleHashTable ( ms , cParams , iend ) ;
2017-06-09 03:43:56 +02:00
break ;
case ZSTD_greedy :
case ZSTD_lazy :
case ZSTD_lazy2 :
if ( srcSize > = HASH_READ_SIZE )
2018-05-15 19:45:22 +02:00
ZSTD_insertAndFindFirstIndex ( ms , cParams , iend - HASH_READ_SIZE ) ;
2017-06-09 03:43:56 +02:00
break ;
2018-05-15 19:45:22 +02:00
case ZSTD_btlazy2 : /* we want the dictionary table fully sorted */
2017-06-09 03:43:56 +02:00
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 )
2018-05-15 19:45:22 +02:00
ZSTD_updateTree ( ms , cParams , iend - HASH_READ_SIZE , iend ) ;
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
}
2018-05-15 19:45:22 +02:00
ms - > nextToUpdate = ( U32 ) ( iend - ms - > window . base ) ;
2017-06-09 03:43:56 +02:00
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() :
2018-05-15 19:45:22 +02:00
* @ return : dictID , or an error code
2017-06-09 03:43:56 +02:00
* assumptions : magic number supposed already checked
* dictSize supposed > 8
*/
2018-05-15 19:45:22 +02:00
static size_t ZSTD_loadZstdDictionary ( ZSTD_compressedBlockState_t * bs , ZSTD_matchState_t * ms , ZSTD_CCtx_params const * params , const void * dict , size_t dictSize , void * workspace )
2017-06-09 03:43:56 +02:00
{
const BYTE * dictPtr = ( const BYTE * ) dict ;
const BYTE * const dictEnd = dictPtr + dictSize ;
short offcodeNCount [ MaxOff + 1 ] ;
unsigned offcodeMaxValue = MaxOff ;
2018-05-15 19:45:22 +02:00
size_t dictID ;
2017-08-27 12:05:17 +02:00
2018-05-15 19:45:22 +02:00
ZSTD_STATIC_ASSERT ( HUF_WORKSPACE_SIZE > = ( 1 < < MAX ( MLFSELog , LLFSELog ) ) ) ;
2017-06-09 03:43:56 +02:00
dictPtr + = 4 ; /* skip magic number */
2018-05-15 19:45:22 +02:00
dictID = params - > 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 ;
2018-05-15 19:45:22 +02:00
size_t const hufHeaderSize = HUF_readCTable ( ( HUF_CElt * ) bs - > 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 */
2018-05-15 19:45:22 +02:00
CHECK_E ( FSE_buildCTable_wksp ( bs - > entropy . offcodeCTable , offcodeNCount , offcodeMaxValue , offcodeLog , workspace , HUF_WORKSPACE_SIZE ) ,
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 ) ) ;
2018-05-15 19:45:22 +02:00
CHECK_E ( FSE_buildCTable_wksp ( bs - > entropy . matchlengthCTable , matchlengthNCount , matchlengthMaxValue , matchlengthLog , workspace , HUF_WORKSPACE_SIZE ) ,
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 ) ) ;
2018-05-15 19:45:22 +02:00
CHECK_E ( FSE_buildCTable_wksp ( bs - > entropy . litlengthCTable , litlengthNCount , litlengthMaxValue , litlengthLog , workspace , HUF_WORKSPACE_SIZE ) ,
2017-06-09 03:43:56 +02:00
dictionary_corrupted ) ;
dictPtr + = litlengthHeaderSize ;
}
if ( dictPtr + 12 > dictEnd ) return ERROR ( dictionary_corrupted ) ;
2018-05-15 19:45:22 +02:00
bs - > rep [ 0 ] = MEM_readLE32 ( dictPtr + 0 ) ;
bs - > rep [ 1 ] = MEM_readLE32 ( dictPtr + 4 ) ;
bs - > 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 + + ) {
2018-05-15 19:45:22 +02:00
if ( bs - > rep [ u ] = = 0 ) return ERROR ( dictionary_corrupted ) ;
if ( bs - > rep [ u ] > dictContentSize ) return ERROR ( dictionary_corrupted ) ;
2017-06-09 03:43:56 +02:00
} }
2018-05-15 19:45:22 +02:00
bs - > entropy . hufCTable_repeatMode = HUF_repeat_valid ;
bs - > entropy . offcode_repeatMode = FSE_repeat_valid ;
bs - > entropy . matchlength_repeatMode = FSE_repeat_valid ;
bs - > entropy . litlength_repeatMode = FSE_repeat_valid ;
CHECK_F ( ZSTD_loadDictionaryContent ( ms , params , dictPtr , dictContentSize ) ) ;
return dictID ;
2017-06-09 03:43:56 +02:00
}
}
/** ZSTD_compress_insertDictionary() :
2018-05-15 19:45:22 +02:00
* @ return : dictID , or an error code */
static size_t ZSTD_compress_insertDictionary ( ZSTD_compressedBlockState_t * bs , ZSTD_matchState_t * ms ,
ZSTD_CCtx_params const * params ,
2017-07-22 23:46:05 +02:00
const void * dict , size_t dictSize ,
2018-05-15 19:45:22 +02:00
ZSTD_dictContentType_e dictContentType ,
void * workspace )
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 ;
2018-05-15 19:45:22 +02:00
ZSTD_reset_compressedBlockState ( bs ) ;
2017-07-22 23:46:05 +02:00
/* dict restricted modes */
2018-05-15 19:45:22 +02:00
if ( dictContentType = = ZSTD_dct_rawContent )
return ZSTD_loadDictionaryContent ( ms , params , dict , dictSize ) ;
2017-06-09 03:43:56 +02:00
2017-07-22 23:46:05 +02:00
if ( MEM_readLE32 ( dict ) ! = ZSTD_MAGIC_DICTIONARY ) {
2018-05-15 19:45:22 +02:00
if ( dictContentType = = ZSTD_dct_auto ) {
2018-01-13 13:50:59 +01:00
DEBUGLOG ( 4 , " raw content dictionary detected " ) ;
2018-05-15 19:45:22 +02:00
return ZSTD_loadDictionaryContent ( ms , params , dict , dictSize ) ;
2017-07-22 23:46:05 +02:00
}
2018-05-15 19:45:22 +02:00
if ( dictContentType = = ZSTD_dct_fullDict )
2017-07-22 23:46:05 +02:00
return ERROR ( dictionary_wrong ) ;
assert ( 0 ) ; /* impossible */
}
/* dict as full zstd dictionary */
2018-05-15 19:45:22 +02:00
return ZSTD_loadZstdDictionary ( bs , ms , params , dict , dictSize , workspace ) ;
2017-06-09 03:43:56 +02:00
}
/*! 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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dictContentType_e dictContentType ,
2017-07-22 23:46:05 +02:00
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 ;
2018-05-15 19:45:22 +02:00
return ZSTD_resetCCtx_usingCDict ( cctx , cdict , params . cParams . windowLog ,
params . fParams , pledgedSrcSize , zbuff ) ;
2017-07-22 23:46:05 +02:00
}
CHECK_F ( ZSTD_resetCCtx_internal ( cctx , params , pledgedSrcSize ,
ZSTDcrp_continue , zbuff ) ) ;
2018-05-15 19:45:22 +02:00
{
size_t const dictID = ZSTD_compress_insertDictionary (
cctx - > blockState . prevCBlock , & cctx - > blockState . matchState ,
& params , dict , dictSize , dictContentType , cctx - > entropyWorkspace ) ;
if ( ZSTD_isError ( dictID ) ) return dictID ;
assert ( dictID < = ( size_t ) ( U32 ) - 1 ) ;
cctx - > dictID = ( U32 ) dictID ;
}
return 0 ;
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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dictContentType_e dictContentType ,
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 ,
2018-05-15 19:45:22 +02:00
dict , dictSize , dictContentType ,
2018-01-13 13:50:59 +01:00
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 ,
2018-05-15 19:45:22 +02:00
dict , dictSize , ZSTD_dct_auto ,
2018-01-13 13:50:59 +01:00
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 )
{
2018-05-15 19:45:22 +02:00
ZSTD_parameters const params = ZSTD_getParams ( compressionLevel , ZSTD_CONTENTSIZE_UNKNOWN , dictSize ) ;
2017-10-26 22:41:47 +02:00
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams ( cctx - > requestedParams , params ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_compressBegin_usingDict (dictSize=%u) " , ( U32 ) dictSize ) ;
return ZSTD_compressBegin_internal ( cctx , dict , dictSize , ZSTD_dct_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 ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " 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 ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_writeEpilogue: write checksum : %08X " , checksum ) ;
2017-06-09 03:43:56 +02:00
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-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_compress_advanced_internal (srcSize:%u) " ,
( U32 ) srcSize ) ;
CHECK_F ( ZSTD_compressBegin_internal ( cctx , dict , dictSize , ZSTD_dct_auto , NULL ,
2017-10-26 22:41:47 +02:00
params , srcSize , ZSTDb_not_buffered ) ) ;
return ZSTD_compressEnd ( cctx , dst , dstCapacity , src , srcSize ) ;
}
2018-05-15 19:45:22 +02:00
size_t ZSTD_compress_usingDict ( ZSTD_CCtx * cctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize ,
2017-06-09 03:43:56 +02:00
const void * dict , size_t dictSize , int compressionLevel )
{
2018-05-15 19:45:22 +02:00
ZSTD_parameters const params = ZSTD_getParams ( compressionLevel , srcSize ? srcSize : 1 , dict ? dictSize : 0 ) ;
ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams ( cctx - > requestedParams , params ) ;
assert ( params . fParams . contentSizeFlag = = 1 ) ;
ZSTD_CCtxParam_setParameter ( & cctxParams , ZSTD_p_compressLiterals , compressionLevel > = 0 ) ;
return ZSTD_compress_advanced_internal ( cctx , dst , dstCapacity , src , srcSize , dict , dictSize , cctxParams ) ;
2017-06-09 03:43:56 +02:00
}
2018-05-15 19:45:22 +02:00
size_t ZSTD_compressCCtx ( ZSTD_CCtx * cctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize , int compressionLevel )
2017-06-09 03:43:56 +02:00
{
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_compressCCtx (srcSize=%u) " , ( U32 ) srcSize ) ;
return ZSTD_compress_usingDict ( cctx , dst , dstCapacity , src , srcSize , NULL , 0 , compressionLevel ) ;
2017-06-09 03:43:56 +02:00
}
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 ) ) ;
2018-05-15 19:45:22 +02:00
return sizeof ( ZSTD_CDict ) + HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState ( & cParams , /* forCCtx */ 0 )
2017-10-26 22:41:47 +02:00
+ ( 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 ) ) ;
2018-05-15 19:45:22 +02:00
return cdict - > workspaceSize + ( cdict - > dictBuffer ? cdict - > dictContentSize : 0 ) + sizeof ( * cdict ) ;
2017-06-09 03:43:56 +02:00
}
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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dictContentType_e dictContentType ,
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters cParams )
{
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 3 , " ZSTD_initCDict_internal, dictContentType %u " , ( U32 ) dictContentType ) ;
assert ( ! ZSTD_checkCParams ( cParams ) ) ;
cdict - > cParams = cParams ;
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 {
2018-05-15 19:45:22 +02:00
void * const internalBuffer = ZSTD_malloc ( dictSize , cdict - > customMem ) ;
2017-07-22 23:46:05 +02:00
cdict - > dictBuffer = internalBuffer ;
cdict - > dictContent = internalBuffer ;
if ( ! internalBuffer ) return ERROR ( memory_allocation ) ;
memcpy ( internalBuffer , dictBuffer , dictSize ) ;
}
cdict - > dictContentSize = dictSize ;
2018-05-15 19:45:22 +02:00
/* Reset the state to no dictionary */
ZSTD_reset_compressedBlockState ( & cdict - > cBlockState ) ;
{ void * const end = ZSTD_reset_matchState (
& cdict - > matchState ,
( U32 * ) cdict - > workspace + HUF_WORKSPACE_SIZE_U32 ,
& cParams , ZSTDcrp_continue , /* forCCtx */ 0 ) ;
assert ( end = = ( char * ) cdict - > workspace + cdict - > workspaceSize ) ;
( void ) end ;
}
/* (Maybe) load the dictionary
* Skips loading the dictionary if it is < = 8 bytes .
*/
{ ZSTD_CCtx_params params ;
memset ( & params , 0 , sizeof ( params ) ) ;
params . compressionLevel = ZSTD_CLEVEL_DEFAULT ;
params . fParams . contentSizeFlag = 1 ;
params . cParams = cParams ;
{ size_t const dictID = ZSTD_compress_insertDictionary (
& cdict - > cBlockState , & cdict - > matchState , & params ,
cdict - > dictContent , cdict - > dictContentSize ,
dictContentType , cdict - > workspace ) ;
if ( ZSTD_isError ( dictID ) ) return dictID ;
assert ( dictID < = ( size_t ) ( U32 ) - 1 ) ;
cdict - > dictID = ( U32 ) dictID ;
}
2017-07-22 23:46:05 +02:00
}
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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dictContentType_e dictContentType ,
2017-06-09 03:43:56 +02:00
ZSTD_compressionParameters cParams , ZSTD_customMem customMem )
{
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 3 , " ZSTD_createCDict_advanced, mode %u " , ( U32 ) dictContentType ) ;
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 ) ;
2018-05-15 19:45:22 +02:00
size_t const workspaceSize = HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState ( & cParams , /* forCCtx */ 0 ) ;
void * const workspace = ZSTD_malloc ( workspaceSize , customMem ) ;
2017-06-09 03:43:56 +02:00
2018-05-15 19:45:22 +02:00
if ( ! cdict | | ! workspace ) {
2017-06-09 03:43:56 +02:00
ZSTD_free ( cdict , customMem ) ;
2018-05-15 19:45:22 +02:00
ZSTD_free ( workspace , customMem ) ;
2017-06-09 03:43:56 +02:00
return NULL ;
}
2018-05-15 19:45:22 +02:00
cdict - > customMem = customMem ;
cdict - > workspace = workspace ;
cdict - > workspaceSize = workspaceSize ;
2017-07-22 23:46:05 +02:00
if ( ZSTD_isError ( ZSTD_initCDict_internal ( cdict ,
dictBuffer , dictSize ,
2018-05-15 19:45:22 +02:00
dictLoadMethod , dictContentType ,
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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dlm_byCopy , ZSTD_dct_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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dlm_byRef , ZSTD_dct_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 */
2018-05-15 19:45:22 +02:00
{ ZSTD_customMem const cMem = cdict - > customMem ;
ZSTD_free ( cdict - > workspace , cMem ) ;
2017-06-09 03:43:56 +02:00
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 .
*/
2018-05-15 19:45:22 +02:00
const ZSTD_CDict * ZSTD_initStaticCDict (
void * workspace , size_t workspaceSize ,
2017-07-22 23:46:05 +02:00
const void * dict , size_t dictSize ,
2017-10-26 22:41:47 +02:00
ZSTD_dictLoadMethod_e dictLoadMethod ,
2018-05-15 19:45:22 +02:00
ZSTD_dictContentType_e dictContentType ,
2017-07-22 23:46:05 +02:00
ZSTD_compressionParameters cParams )
{
2018-05-15 19:45:22 +02:00
size_t const matchStateSize = ZSTD_sizeof_matchState ( & cParams , /* forCCtx */ 0 ) ;
2017-10-26 22:41:47 +02:00
size_t const neededSize = sizeof ( ZSTD_CDict ) + ( dictLoadMethod = = ZSTD_dlm_byRef ? 0 : dictSize )
2018-05-15 19:45:22 +02:00
+ HUF_WORKSPACE_SIZE + matchStateSize ;
2017-07-22 23:46:05 +02:00
ZSTD_CDict * const cdict = ( ZSTD_CDict * ) workspace ;
void * ptr ;
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 ;
}
2018-05-15 19:45:22 +02:00
cdict - > workspace = ptr ;
cdict - > workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize ;
2017-07-22 23:46:05 +02:00
if ( ZSTD_isError ( ZSTD_initCDict_internal ( cdict ,
dict , dictSize ,
2018-05-15 19:45:22 +02:00
ZSTD_dlm_byRef , dictContentType ,
2017-07-22 23:46:05 +02:00
cParams ) ) )
return NULL ;
return cdict ;
}
2018-05-15 19:45:22 +02:00
ZSTD_compressionParameters ZSTD_getCParamsFromCDict ( const ZSTD_CDict * cdict )
{
assert ( cdict ! = NULL ) ;
return cdict - > 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 ) ;
2018-05-15 19:45:22 +02:00
/* Increase window log to fit the entire dictionary and source if the
* source size is known . Limit the increase to 19 , which is the
* window log for compression level 1 with the largest source size .
*/
if ( pledgedSrcSize ! = ZSTD_CONTENTSIZE_UNKNOWN ) {
U32 const limitedSrcSize = ( U32 ) MIN ( pledgedSrcSize , 1U < < 19 ) ;
U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32 ( limitedSrcSize - 1 ) + 1 : 1 ;
params . cParams . windowLog = MAX ( params . cParams . windowLog , limitedSrcLog ) ;
}
2017-06-09 03:43:56 +02:00
params . fParams = fParams ;
2017-07-22 23:46:05 +02:00
return ZSTD_compressBegin_internal ( cctx ,
2018-05-15 19:45:22 +02:00
NULL , 0 , ZSTD_dct_auto ,
2017-07-22 23:46:05 +02:00
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
}
2018-05-15 19:45:22 +02:00
static size_t ZSTD_resetCStream_internal ( ZSTD_CStream * cctx ,
const void * const dict , size_t const dictSize , ZSTD_dictContentType_e const dictContentType ,
2018-01-13 13:50:59 +01:00
const ZSTD_CDict * const cdict ,
ZSTD_CCtx_params const params , unsigned long long const pledgedSrcSize )
2017-06-09 03:43:56 +02:00
{
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 4 , " ZSTD_resetCStream_internal (disableLiteralCompression=%i) " ,
params . disableLiteralCompression ) ;
2017-07-22 23:46:05 +02:00
/* 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
2018-05-15 19:45:22 +02:00
CHECK_F ( ZSTD_compressBegin_internal ( cctx ,
dict , dictSize , dictContentType ,
2018-01-13 13:50:59 +01:00
cdict ,
params , pledgedSrcSize ,
ZSTDb_buffered ) ) ;
2017-06-09 03:43:56 +02:00
2018-05-15 19:45:22 +02:00
cctx - > inToCompress = 0 ;
cctx - > inBuffPos = 0 ;
cctx - > inBuffTarget = cctx - > blockSize
+ ( cctx - > 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 */
cctx - > outBuffContentSize = cctx - > outBuffFlushedSize = 0 ;
cctx - > streamStage = zcss_load ;
cctx - > frameEnded = 0 ;
2017-06-09 03:43:56 +02:00
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 ;
2018-05-15 19:45:22 +02:00
params . cParams = ZSTD_getCParamsFromCCtxParams ( & params , pledgedSrcSize , 0 ) ;
return ZSTD_resetCStream_internal ( zcs , NULL , 0 , ZSTD_dct_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 ,
2018-05-15 19:45:22 +02:00
ZSTD_dlm_byCopy , ZSTD_dct_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-05-15 19:45:22 +02:00
return ZSTD_resetCStream_internal ( zcs , NULL , 0 , ZSTD_dct_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-05-15 19:45:22 +02:00
2018-01-13 13:50:59 +01:00
/* ZSTD_initCStream_advanced() :
2018-05-15 19:45:22 +02:00
* pledgedSrcSize must be exact .
2018-01-13 13:50:59 +01:00
* 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
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. */
2018-05-15 19:45:22 +02:00
{ ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams ( zcs - > requestedParams , params ) ;
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 ( )
2018-05-15 19:45:22 +02:00
* non - static , because can be called from zstdmt_compress . 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 (
2018-05-15 19:45:22 +02:00
& cctx - > requestedParams , cctx - > pledgedSrcSizePlusOne - 1 , 0 /*dictSize*/ ) ;
2017-07-22 23:46:05 +02:00
# ifdef ZSTD_MULTITHREAD
2018-05-15 19:45:22 +02:00
if ( ( cctx - > pledgedSrcSizePlusOne - 1 ) < = ZSTDMT_JOBSIZE_MIN ) {
params . nbWorkers = 0 ; /* do not invoke multi-threading when src size is too small */
}
if ( params . nbWorkers > 0 ) {
/* mt context creation */
if ( cctx - > mtctx = = NULL | | ( params . nbWorkers ! = ZSTDMT_getNbWorkers ( cctx - > mtctx ) ) ) {
DEBUGLOG ( 4 , " ZSTD_compress_generic: creating new mtctx for nbWorkers=%u " ,
params . nbWorkers ) ;
if ( cctx - > mtctx ! = NULL )
DEBUGLOG ( 4 , " ZSTD_compress_generic: previous nbWorkers was %u " ,
ZSTDMT_getNbWorkers ( cctx - > mtctx ) ) ;
2017-10-26 22:41:47 +02:00
ZSTDMT_freeCCtx ( cctx - > mtctx ) ;
2018-05-15 19:45:22 +02:00
cctx - > mtctx = ZSTDMT_createCCtx_advanced ( params . nbWorkers , cctx - > customMem ) ;
2017-10-26 22:41:47 +02:00
if ( cctx - > mtctx = = NULL ) return ERROR ( memory_allocation ) ;
}
2018-05-15 19:45:22 +02:00
/* mt compression */
DEBUGLOG ( 4 , " call ZSTDMT_initCStream_internal as nbWorkers=%u " , params . nbWorkers ) ;
2017-10-26 22:41:47 +02:00
CHECK_F ( ZSTDMT_initCStream_internal (
2018-01-13 13:50:59 +01:00
cctx - > mtctx ,
2018-05-15 19:45:22 +02:00
prefixDict . dict , prefixDict . dictSize , ZSTD_dct_rawContent ,
2018-01-13 13:50:59 +01:00
cctx - > cdict , params , cctx - > pledgedSrcSizePlusOne - 1 ) ) ;
2017-07-22 23:46:05 +02:00
cctx - > streamStage = zcss_load ;
2018-05-15 19:45:22 +02:00
cctx - > appliedParams . nbWorkers = params . nbWorkers ;
2017-07-22 23:46:05 +02:00
} else
# endif
2018-05-15 19:45:22 +02:00
{ CHECK_F ( ZSTD_resetCStream_internal ( cctx ,
prefixDict . dict , prefixDict . dictSize , prefixDict . dictContentType ,
cctx - > cdict ,
params , cctx - > pledgedSrcSizePlusOne - 1 ) ) ;
2018-01-13 13:50:59 +01:00
assert ( cctx - > streamStage = = zcss_load ) ;
2018-05-15 19:45:22 +02:00
assert ( cctx - > appliedParams . nbWorkers = = 0 ) ;
2017-07-22 23:46:05 +02:00
} }
/* compression stage */
# ifdef ZSTD_MULTITHREAD
2018-05-15 19:45:22 +02:00
if ( cctx - > appliedParams . nbWorkers > 0 ) {
if ( cctx - > cParamsChanged ) {
ZSTDMT_updateCParams_whileCompressing ( cctx - > mtctx , & cctx - > requestedParams ) ;
cctx - > cParamsChanged = 0 ;
2017-07-22 23:46:05 +02:00
}
2018-05-15 19:45:22 +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 ;
} }
2017-07-22 23:46:05 +02:00
# 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() :
2018-05-15 19:45:22 +02:00
* @ return : amount of data remaining to flush */
2017-06-09 03:43:56 +02:00
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 */
2018-05-15 19:45:22 +02:00
{ 19 , 12 , 13 , 1 , 6 , 1 , ZSTD_fast } , /* base for negative levels */
{ 19 , 13 , 14 , 1 , 7 , 1 , ZSTD_fast } , /* level 1 */
{ 19 , 15 , 16 , 1 , 6 , 1 , ZSTD_fast } , /* level 2 */
{ 20 , 16 , 17 , 1 , 5 , 8 , ZSTD_dfast } , /* level 3 */
{ 20 , 17 , 18 , 1 , 5 , 8 , ZSTD_dfast } , /* level 4 */
2017-07-22 23:46:05 +02:00
{ 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 */
2018-05-15 19:45:22 +02:00
{ 22 , 21 , 22 , 4 , 5 , 32 , ZSTD_btlazy2 } , /* level 13 */
{ 22 , 21 , 22 , 5 , 5 , 32 , ZSTD_btlazy2 } , /* level 14 */
{ 22 , 22 , 22 , 6 , 5 , 32 , ZSTD_btlazy2 } , /* level 15 */
2018-01-13 13:50:59 +01:00
{ 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 */
2018-05-15 19:45:22 +02:00
{ 18 , 12 , 13 , 1 , 5 , 1 , ZSTD_fast } , /* base for negative levels */
{ 18 , 13 , 14 , 1 , 6 , 1 , ZSTD_fast } , /* level 1 */
2017-06-09 03:43:56 +02:00
{ 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.*/
2018-05-15 19:45:22 +02:00
{ 18 , 18 , 17 , 5 , 4 , 8 , ZSTD_btlazy2 } , /* level 12.*/
{ 18 , 19 , 17 , 7 , 4 , 8 , ZSTD_btlazy2 } , /* level 13 */
2017-06-09 03:43:56 +02:00
{ 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 */
2018-05-15 19:45:22 +02:00
{ 17 , 12 , 12 , 1 , 5 , 1 , ZSTD_fast } , /* level 0 - not used */
{ 17 , 12 , 13 , 1 , 6 , 1 , ZSTD_fast } , /* level 1 */
{ 17 , 13 , 16 , 1 , 5 , 1 , ZSTD_fast } , /* level 2 */
2017-06-09 03:43:56 +02:00
{ 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 */
2018-05-15 19:45:22 +02:00
{ 14 , 12 , 13 , 1 , 5 , 1 , ZSTD_fast } , /* base for negative levels */
{ 14 , 14 , 14 , 1 , 6 , 1 , ZSTD_fast } , /* level 1 */
{ 14 , 14 , 14 , 1 , 4 , 1 , ZSTD_fast } , /* level 2 */
2017-06-09 03:43:56 +02:00
{ 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
} ,
} ;
/*! ZSTD_getCParams() :
2018-05-15 19:45:22 +02:00
* @ return ZSTD_compressionParameters structure for a selected compression level , srcSize and dictSize .
2017-06-09 03:43:56 +02:00
* 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 */
2018-05-15 19:45:22 +02:00
int row = compressionLevel ;
DEBUGLOG ( 5 , " ZSTD_getCParams (cLevel=%i) " , compressionLevel ) ;
if ( compressionLevel = = 0 ) row = ZSTD_CLEVEL_DEFAULT ; /* 0 == default */
if ( compressionLevel < 0 ) row = 0 ; /* entry 0 is baseline for fast mode */
if ( compressionLevel > ZSTD_MAX_CLEVEL ) row = ZSTD_MAX_CLEVEL ;
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters [ tableID ] [ row ] ;
if ( compressionLevel < 0 ) cp . targetLength = ( unsigned ) ( - compressionLevel ) ; /* acceleration factor */
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 ) ;
2018-05-15 19:45:22 +02:00
DEBUGLOG ( 5 , " ZSTD_getParams (cLevel=%i) " , compressionLevel ) ;
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 ;
}