2016-08-30 10:04:33 -07:00
/**
* Copyright ( c ) 2016 - present , Yann Collet , Facebook , Inc .
* All rights reserved .
*
* This source code is licensed under the BSD - style license found in the
* LICENSE file in the root directory of this source tree . An additional grant
* of patent rights can be found in the PATENTS file in the same directory .
*/
2015-11-11 04:43:58 -08:00
/* ***************************************************************
* Tuning parameters
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
* HEAPMODE :
2016-01-11 03:56:11 -08:00
* Select how default decompression function ZSTD_decompress ( ) will allocate memory ,
* in memory stack ( 0 ) , or in memory heap ( 1 , requires malloc ( ) )
2015-11-11 04:43:58 -08:00
*/
# ifndef ZSTD_HEAPMODE
# define ZSTD_HEAPMODE 1
2016-01-11 03:56:11 -08:00
# endif
2015-11-11 04:43:58 -08:00
/*!
* LEGACY_SUPPORT :
2016-02-02 17:46:46 -08:00
* if set to 1 , ZSTD_decompress ( ) can decode older formats ( v0 .1 + )
2015-11-11 04:43:58 -08:00
*/
# ifndef ZSTD_LEGACY_SUPPORT
2016-01-18 03:03:27 -08:00
# define ZSTD_LEGACY_SUPPORT 0
2015-11-11 04:43:58 -08:00
# endif
2016-08-22 16:34:34 -07:00
/*!
2016-08-23 07:58:10 -07:00
* MAXWINDOWSIZE_DEFAULT :
* maximum window size accepted by DStream , by default .
* Frames requiring more memory will be rejected .
2016-08-22 16:34:34 -07:00
*/
2016-08-23 07:58:10 -07:00
# ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
2016-10-29 03:56:45 -07:00
# define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */
2016-08-22 16:34:34 -07:00
# endif
2016-01-27 15:18:06 -08:00
/*-*******************************************************
2016-02-04 06:28:14 -08:00
* Dependencies
2015-11-11 04:43:58 -08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-06-06 10:52:35 -07:00
# include <string.h> /* memcpy, memmove, memset */
2015-11-11 04:43:58 -08:00
# include "mem.h" /* low level memory routines */
2016-05-31 09:13:56 -07:00
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
# include "xxhash.h" /* XXH64_* */
2016-06-04 15:58:01 -07:00
# define FSE_STATIC_LINKING_ONLY
# include "fse.h"
2016-06-04 15:42:28 -07:00
# define HUF_STATIC_LINKING_ONLY
# include "huf.h"
# include "zstd_internal.h"
2015-11-11 04:43:58 -08:00
2016-06-05 15:26:38 -07:00
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2015-11-11 04:43:58 -08:00
# include "zstd_legacy.h"
# endif
2016-01-27 15:18:06 -08:00
2016-11-28 18:38:52 -08:00
# if defined(_MSC_VER)
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
# define ZSTD_PREFETCH(ptr) _mm_prefetch(ptr, _MM_HINT_T0)
# elif defined(__GNUC__)
# define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
# else
# define ZSTD_PREFETCH(ptr) /* disabled */
# endif
2016-05-12 06:55:26 -07:00
/*-*************************************
* Macros
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define ZSTD_isError ERR_isError /* for inlining */
# define FSE_isError ERR_isError
# define HUF_isError ERR_isError
2016-03-11 16:25:40 -08:00
/*_*******************************************************
2015-11-11 04:43:58 -08:00
* Memory operations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void ZSTD_copy4 ( void * dst , const void * src ) { memcpy ( dst , src , 4 ) ; }
2016-03-11 16:25:40 -08:00
/*-*************************************************************
2015-11-12 06:36:05 -08:00
* Context management
2015-11-11 04:43:58 -08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-11-25 12:09:17 -08:00
typedef enum { ZSTDds_getFrameHeaderSize , ZSTDds_decodeFrameHeader ,
2016-05-31 03:43:46 -07:00
ZSTDds_decodeBlockHeader , ZSTDds_decompressBlock ,
2016-07-27 15:55:43 -07:00
ZSTDds_decompressLastBlock , ZSTDds_checkChecksum ,
2016-05-31 03:43:46 -07:00
ZSTDds_decodeSkippableHeader , ZSTDds_skipFrame } ZSTD_dStage ;
2015-11-25 05:42:45 -08:00
2015-11-11 04:43:58 -08:00
struct ZSTD_DCtx_s
{
2016-09-13 07:52:16 -07:00
const FSE_DTable * LLTptr ;
const FSE_DTable * MLTptr ;
const FSE_DTable * OFTptr ;
const HUF_DTable * HUFptr ;
2016-01-27 15:18:06 -08:00
FSE_DTable LLTable [ FSE_DTABLE_SIZE_U32 ( LLFSELog ) ] ;
2016-09-13 07:52:16 -07:00
FSE_DTable OFTable [ FSE_DTABLE_SIZE_U32 ( OffFSELog ) ] ;
2016-01-27 15:18:06 -08:00
FSE_DTable MLTable [ FSE_DTABLE_SIZE_U32 ( MLFSELog ) ] ;
2016-06-10 17:35:31 -07:00
HUF_DTable hufTable [ HUF_DTABLE_SIZE ( HufLog ) ] ; /* can accommodate HUF_decompress4X */
2015-12-04 08:16:37 -08:00
const void * previousDstEnd ;
const void * base ;
const void * vBase ;
const void * dictEnd ;
2015-11-11 04:43:58 -08:00
size_t expected ;
2016-07-27 02:07:13 -07:00
U32 rep [ ZSTD_REP_NUM ] ;
2016-03-11 12:58:04 -08:00
ZSTD_frameParams fParams ;
2016-07-23 07:31:49 -07:00
blockType_e bType ; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
2015-11-25 05:42:45 -08:00
ZSTD_dStage stage ;
2016-06-10 17:52:42 -07:00
U32 litEntropy ;
U32 fseEntropy ;
XXH64_state_t xxhState ;
size_t headerSize ;
2016-05-28 20:01:04 -07:00
U32 dictID ;
2015-11-11 04:43:58 -08:00
const BYTE * litPtr ;
2016-06-10 17:52:42 -07:00
ZSTD_customMem customMem ;
2015-11-11 04:43:58 -08:00
size_t litSize ;
2016-07-27 15:55:43 -07:00
size_t rleSize ;
2016-07-18 07:52:10 -07:00
BYTE litBuffer [ ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH ] ;
2016-03-11 12:58:04 -08:00
BYTE headerBuffer [ ZSTD_FRAMEHEADERSIZE_MAX ] ;
2016-08-29 09:03:12 -07:00
} ; /* typedef'd to ZSTD_DCtx within "zstd.h" */
2015-11-11 04:43:58 -08:00
2016-10-29 03:56:45 -07:00
size_t ZSTD_sizeof_DCtx ( const ZSTD_DCtx * dctx ) { return ( dctx = = NULL ) ? 0 : sizeof ( ZSTD_DCtx ) ; }
2016-01-27 15:18:06 -08:00
2016-07-11 04:46:25 -07:00
size_t ZSTD_estimateDCtxSize ( void ) { return sizeof ( ZSTD_DCtx ) ; }
2016-01-26 06:58:49 -08:00
size_t ZSTD_decompressBegin ( ZSTD_DCtx * dctx )
2015-11-12 06:36:05 -08:00
{
2016-09-05 10:47:43 -07:00
dctx - > expected = ZSTD_frameHeaderSize_prefix ;
2015-11-25 05:42:45 -08:00
dctx - > stage = ZSTDds_getFrameHeaderSize ;
2015-11-12 06:36:05 -08:00
dctx - > previousDstEnd = NULL ;
dctx - > base = NULL ;
dctx - > vBase = NULL ;
dctx - > dictEnd = NULL ;
2016-09-13 07:52:16 -07:00
dctx - > hufTable [ 0 ] = ( HUF_DTable ) ( ( HufLog ) * 0x1000001 ) ; /* cover both little and big endian */
2016-06-10 17:52:42 -07:00
dctx - > litEntropy = dctx - > fseEntropy = 0 ;
2016-05-28 20:01:04 -07:00
dctx - > dictID = 0 ;
2016-09-06 06:36:19 -07:00
MEM_STATIC_ASSERT ( sizeof ( dctx - > rep ) = = sizeof ( repStartValue ) ) ;
2016-09-13 07:52:16 -07:00
memcpy ( dctx - > rep , repStartValue , sizeof ( repStartValue ) ) ; /* initial repcodes */
dctx - > LLTptr = dctx - > LLTable ;
dctx - > MLTptr = dctx - > MLTable ;
dctx - > OFTptr = dctx - > OFTable ;
dctx - > HUFptr = dctx - > hufTable ;
2015-11-12 06:36:05 -08:00
return 0 ;
}
2016-05-23 07:24:52 -07:00
ZSTD_DCtx * ZSTD_createDCtx_advanced ( ZSTD_customMem customMem )
{
ZSTD_DCtx * dctx ;
2016-08-17 16:40:32 -07:00
if ( ! customMem . customAlloc & & ! customMem . customFree ) customMem = defaultCustomMem ;
if ( ! customMem . customAlloc | | ! customMem . customFree ) return NULL ;
2016-05-23 08:04:23 -07:00
2016-09-06 06:36:19 -07:00
dctx = ( ZSTD_DCtx * ) ZSTD_malloc ( sizeof ( ZSTD_DCtx ) , customMem ) ;
2016-05-23 07:24:52 -07:00
if ( ! dctx ) return NULL ;
2016-08-17 16:40:32 -07:00
memcpy ( & dctx - > customMem , & customMem , sizeof ( customMem ) ) ;
2016-01-26 06:58:49 -08:00
ZSTD_decompressBegin ( dctx ) ;
2015-11-12 06:36:05 -08:00
return dctx ;
}
2016-05-31 15:18:28 -07:00
ZSTD_DCtx * ZSTD_createDCtx ( void )
{
2016-06-03 04:28:20 -07:00
return ZSTD_createDCtx_advanced ( defaultCustomMem ) ;
2016-05-31 15:18:28 -07:00
}
2015-11-12 06:36:05 -08:00
size_t ZSTD_freeDCtx ( ZSTD_DCtx * dctx )
{
2016-06-03 07:36:50 -07:00
if ( dctx = = NULL ) return 0 ; /* support free on NULL */
2016-08-28 21:05:43 -07:00
ZSTD_free ( dctx , dctx - > customMem ) ;
2016-02-04 17:33:10 -08:00
return 0 ; /* reserved as a potential error code in the future */
2015-11-12 06:36:05 -08:00
}
2016-01-26 06:58:49 -08:00
void ZSTD_copyDCtx ( ZSTD_DCtx * dstDCtx , const ZSTD_DCtx * srcDCtx )
{
2016-08-17 16:40:32 -07:00
size_t const workSpaceSize = ( ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH ) + ZSTD_frameHeaderSize_max ;
memcpy ( dstDCtx , srcDCtx , sizeof ( ZSTD_DCtx ) - workSpaceSize ) ; /* no need to copy workspace */
2016-01-26 06:58:49 -08:00
}
2016-09-14 07:14:57 -07:00
static void ZSTD_refDCtx ( ZSTD_DCtx * dstDCtx , const ZSTD_DCtx * srcDCtx )
2016-09-13 07:52:16 -07:00
{
2016-09-14 07:14:57 -07:00
ZSTD_decompressBegin ( dstDCtx ) ; /* init */
2016-10-25 17:47:02 -07:00
if ( srcDCtx ) { /* support refDCtx on NULL */
dstDCtx - > dictEnd = srcDCtx - > dictEnd ;
dstDCtx - > vBase = srcDCtx - > vBase ;
dstDCtx - > base = srcDCtx - > base ;
dstDCtx - > previousDstEnd = srcDCtx - > previousDstEnd ;
dstDCtx - > dictID = srcDCtx - > dictID ;
dstDCtx - > litEntropy = srcDCtx - > litEntropy ;
dstDCtx - > fseEntropy = srcDCtx - > fseEntropy ;
dstDCtx - > LLTptr = srcDCtx - > LLTable ;
dstDCtx - > MLTptr = srcDCtx - > MLTable ;
dstDCtx - > OFTptr = srcDCtx - > OFTable ;
dstDCtx - > HUFptr = srcDCtx - > hufTable ;
dstDCtx - > rep [ 0 ] = srcDCtx - > rep [ 0 ] ;
dstDCtx - > rep [ 1 ] = srcDCtx - > rep [ 1 ] ;
dstDCtx - > rep [ 2 ] = srcDCtx - > rep [ 2 ] ;
}
2016-09-13 07:52:16 -07:00
}
2015-11-12 06:36:05 -08:00
2016-03-11 16:25:40 -08:00
/*-*************************************************************
2015-11-12 06:36:05 -08:00
* Decompression section
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-23 10:28:41 -08:00
2016-11-02 17:30:49 -07:00
/*! ZSTD_isFrame() :
* Tells if the content of ` buffer ` starts with a valid Frame Identifier .
* Note : Frame Identifier is 4 bytes . If ` size < 4 ` , @ return will always be 0.
* Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled .
* Note 3 : Skippable Frame Identifiers are considered valid . */
unsigned ZSTD_isFrame ( const void * buffer , size_t size )
{
if ( size < 4 ) return 0 ;
{ U32 const magic = MEM_readLE32 ( buffer ) ;
if ( magic = = ZSTD_MAGICNUMBER ) return 1 ;
if ( ( magic & 0xFFFFFFF0U ) = = ZSTD_MAGIC_SKIPPABLE_START ) return 1 ;
}
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if ( ZSTD_isLegacy ( buffer , size ) ) return 1 ;
# endif
return 0 ;
}
2016-01-23 10:28:41 -08:00
2016-03-11 16:25:40 -08:00
/** ZSTD_frameHeaderSize() :
2016-09-05 10:47:43 -07:00
* srcSize must be > = ZSTD_frameHeaderSize_prefix .
2016-03-11 16:25:40 -08:00
* @ return : size of the Frame Header */
static size_t ZSTD_frameHeaderSize ( const void * src , size_t srcSize )
2015-11-25 05:42:45 -08:00
{
2016-09-05 10:47:43 -07:00
if ( srcSize < ZSTD_frameHeaderSize_prefix ) return ERROR ( srcSize_wrong ) ;
2016-06-05 15:26:38 -07:00
{ BYTE const fhd = ( ( const BYTE * ) src ) [ 4 ] ;
U32 const dictID = fhd & 3 ;
2016-07-26 10:42:19 -07:00
U32 const singleSegment = ( fhd > > 5 ) & 1 ;
2016-06-05 15:26:38 -07:00
U32 const fcsId = fhd > > 6 ;
2016-09-05 10:47:43 -07:00
return ZSTD_frameHeaderSize_prefix + ! singleSegment + ZSTD_did_fieldSize [ dictID ] + ZSTD_fcs_fieldSize [ fcsId ]
2016-08-17 16:40:32 -07:00
+ ( singleSegment & & ! fcsId ) ;
2016-05-28 20:01:04 -07:00
}
2015-11-25 05:42:45 -08:00
}
2016-03-11 16:25:40 -08:00
/** ZSTD_getFrameParams() :
2016-06-05 15:26:38 -07:00
* decode Frame Header , or require larger ` srcSize ` .
2016-03-11 16:25:40 -08:00
* @ return : 0 , ` fparamsPtr ` is correctly filled ,
2016-03-14 17:33:36 -07:00
* > 0 , ` srcSize ` is too small , result is expected ` srcSize ` ,
2016-03-11 16:25:40 -08:00
* or an error code , which can be tested using ZSTD_isError ( ) */
2016-03-15 04:56:03 -07:00
size_t ZSTD_getFrameParams ( ZSTD_frameParams * fparamsPtr , const void * src , size_t srcSize )
2015-11-25 05:42:45 -08:00
{
2016-03-11 16:25:40 -08:00
const BYTE * ip = ( const BYTE * ) src ;
2016-09-05 10:47:43 -07:00
if ( srcSize < ZSTD_frameHeaderSize_prefix ) return ZSTD_frameHeaderSize_prefix ;
2016-05-31 03:43:46 -07:00
if ( MEM_readLE32 ( src ) ! = ZSTD_MAGICNUMBER ) {
if ( ( MEM_readLE32 ( src ) & 0xFFFFFFF0U ) = = ZSTD_MAGIC_SKIPPABLE_START ) {
if ( srcSize < ZSTD_skippableHeaderSize ) return ZSTD_skippableHeaderSize ; /* magic number + skippable frame length */
2016-06-01 05:44:31 -07:00
memset ( fparamsPtr , 0 , sizeof ( * fparamsPtr ) ) ;
fparamsPtr - > frameContentSize = MEM_readLE32 ( ( const char * ) src + 4 ) ;
2016-06-05 15:26:38 -07:00
fparamsPtr - > windowSize = 0 ; /* windowSize==0 means a frame is skippable */
2016-05-31 03:43:46 -07:00
return 0 ;
}
return ERROR ( prefix_unknown ) ;
}
2016-03-11 16:25:40 -08:00
2016-03-14 17:33:36 -07:00
/* ensure there is enough `srcSize` to fully read/decode frame header */
2016-03-14 17:24:33 -07:00
{ size_t const fhsize = ZSTD_frameHeaderSize ( src , srcSize ) ;
2016-03-11 16:25:40 -08:00
if ( srcSize < fhsize ) return fhsize ; }
2016-06-05 15:26:38 -07:00
{ BYTE const fhdByte = ip [ 4 ] ;
size_t pos = 5 ;
U32 const dictIDSizeCode = fhdByte & 3 ;
U32 const checksumFlag = ( fhdByte > > 2 ) & 1 ;
2016-07-26 10:42:19 -07:00
U32 const singleSegment = ( fhdByte > > 5 ) & 1 ;
2016-06-05 15:26:38 -07:00
U32 const fcsID = fhdByte > > 6 ;
U32 const windowSizeMax = 1U < < ZSTD_WINDOWLOG_MAX ;
U32 windowSize = 0 ;
U32 dictID = 0 ;
U64 frameContentSize = 0 ;
2016-06-16 06:38:51 -07:00
if ( ( fhdByte & 0x08 ) ! = 0 ) return ERROR ( frameParameter_unsupported ) ; /* reserved bits, which must be zero */
2016-07-26 10:42:19 -07:00
if ( ! singleSegment ) {
2016-06-05 15:26:38 -07:00
BYTE const wlByte = ip [ pos + + ] ;
U32 const windowLog = ( wlByte > > 3 ) + ZSTD_WINDOWLOG_ABSOLUTEMIN ;
2016-10-12 17:28:59 -07:00
if ( windowLog > ZSTD_WINDOWLOG_MAX ) return ERROR ( frameParameter_windowTooLarge ) ; /* avoids issue with 1 << windowLog */
2016-06-05 15:26:38 -07:00
windowSize = ( 1U < < windowLog ) ;
windowSize + = ( windowSize > > 3 ) * ( wlByte & 7 ) ;
}
switch ( dictIDSizeCode )
2016-05-28 20:01:04 -07:00
{
default : /* impossible */
2016-06-05 15:26:38 -07:00
case 0 : break ;
case 1 : dictID = ip [ pos ] ; pos + + ; break ;
case 2 : dictID = MEM_readLE16 ( ip + pos ) ; pos + = 2 ; break ;
case 3 : dictID = MEM_readLE32 ( ip + pos ) ; pos + = 4 ; break ;
2016-05-28 20:01:04 -07:00
}
2016-06-05 15:26:38 -07:00
switch ( fcsID )
2016-03-14 17:33:36 -07:00
{
default : /* impossible */
2016-07-26 10:42:19 -07:00
case 0 : if ( singleSegment ) frameContentSize = ip [ pos ] ; break ;
2016-06-05 15:26:38 -07:00
case 1 : frameContentSize = MEM_readLE16 ( ip + pos ) + 256 ; break ;
case 2 : frameContentSize = MEM_readLE32 ( ip + pos ) ; break ;
case 3 : frameContentSize = MEM_readLE64 ( ip + pos ) ; break ;
}
if ( ! windowSize ) windowSize = ( U32 ) frameContentSize ;
2016-10-12 17:28:59 -07:00
if ( windowSize > windowSizeMax ) return ERROR ( frameParameter_windowTooLarge ) ;
2016-06-05 15:26:38 -07:00
fparamsPtr - > frameContentSize = frameContentSize ;
fparamsPtr - > windowSize = windowSize ;
fparamsPtr - > dictID = dictID ;
fparamsPtr - > checksumFlag = checksumFlag ;
}
2015-11-25 05:42:45 -08:00
return 0 ;
}
2016-03-11 16:25:40 -08:00
2016-07-07 04:14:21 -07:00
/** ZSTD_getDecompressedSize() :
* compatible with legacy mode
* @ return : decompressed size if known , 0 otherwise
note : 0 can mean any of the following :
2016-07-20 11:12:24 -07:00
- decompressed size is not present within frame header
2016-07-07 04:14:21 -07:00
- frame header unknown / not supported
2016-07-20 11:12:24 -07:00
- frame header not complete ( ` srcSize ` too small ) */
2016-07-07 05:40:13 -07:00
unsigned long long ZSTD_getDecompressedSize ( const void * src , size_t srcSize )
{
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
if ( ZSTD_isLegacy ( src , srcSize ) ) return ZSTD_getDecompressedSize_legacy ( src , srcSize ) ;
2016-07-07 04:14:21 -07:00
# endif
{ ZSTD_frameParams fparams ;
size_t const frResult = ZSTD_getFrameParams ( & fparams , src , srcSize ) ;
if ( frResult ! = 0 ) return 0 ;
return fparams . frameContentSize ;
}
}
2016-03-11 16:25:40 -08:00
/** ZSTD_decodeFrameHeader() :
2016-10-20 20:11:00 -07:00
* ` headerSize ` must be the size provided by ZSTD_frameHeaderSize ( ) .
2016-03-19 06:14:31 -07:00
* @ return : 0 if success , or an error code , which can be tested using ZSTD_isError ( ) */
2016-10-20 20:11:00 -07:00
static size_t ZSTD_decodeFrameHeader ( ZSTD_DCtx * dctx , const void * src , size_t headerSize )
2015-11-26 03:43:28 -08:00
{
2016-10-20 20:11:00 -07:00
size_t const result = ZSTD_getFrameParams ( & ( dctx - > fParams ) , src , headerSize ) ;
if ( ZSTD_isError ( result ) ) return result ; /* invalid header */
if ( result > 0 ) return ERROR ( srcSize_wrong ) ; /* headerSize too small */
2016-05-30 07:17:33 -07:00
if ( dctx - > fParams . dictID & & ( dctx - > dictID ! = dctx - > fParams . dictID ) ) return ERROR ( dictionary_wrong ) ;
2016-05-31 09:13:56 -07:00
if ( dctx - > fParams . checksumFlag ) XXH64_reset ( & dctx - > xxhState , 0 ) ;
2016-10-20 20:11:00 -07:00
return 0 ;
2015-11-26 03:43:28 -08:00
}
2015-11-11 04:43:58 -08:00
2016-03-19 06:14:31 -07:00
typedef struct
{
2016-07-23 07:31:49 -07:00
blockType_e blockType ;
2016-07-27 15:55:43 -07:00
U32 lastBlock ;
2016-03-19 06:14:31 -07:00
U32 origSize ;
} blockProperties_t ;
/*! ZSTD_getcBlockSize() :
* Provides the size of compressed block from block header ` src ` */
2015-11-11 04:43:58 -08:00
size_t ZSTD_getcBlockSize ( const void * src , size_t srcSize , blockProperties_t * bpPtr )
{
2016-03-19 06:14:31 -07:00
if ( srcSize < ZSTD_blockHeaderSize ) return ERROR ( srcSize_wrong ) ;
2016-07-20 05:58:49 -07:00
{ U32 const cBlockHeader = MEM_readLE24 ( src ) ;
2016-07-27 15:55:43 -07:00
U32 const cSize = cBlockHeader > > 3 ;
bpPtr - > lastBlock = cBlockHeader & 1 ;
bpPtr - > blockType = ( blockType_e ) ( ( cBlockHeader > > 1 ) & 3 ) ;
2016-07-20 05:58:49 -07:00
bpPtr - > origSize = cSize ; /* only useful for RLE */
if ( bpPtr - > blockType = = bt_rle ) return 1 ;
2016-07-27 15:55:43 -07:00
if ( bpPtr - > blockType = = bt_reserved ) return ERROR ( corruption_detected ) ;
2016-07-20 05:58:49 -07:00
return cSize ;
}
2015-11-11 04:43:58 -08:00
}
2016-01-23 10:28:41 -08:00
2016-03-19 06:14:31 -07:00
static size_t ZSTD_copyRawBlock ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-11 04:43:58 -08:00
{
2016-03-19 06:14:31 -07:00
if ( srcSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
2015-11-11 04:43:58 -08:00
memcpy ( dst , src , srcSize ) ;
return srcSize ;
}
2016-07-27 15:55:43 -07:00
static size_t ZSTD_setRleBlock ( void * dst , size_t dstCapacity , const void * src , size_t srcSize , size_t regenSize )
{
if ( srcSize ! = 1 ) return ERROR ( srcSize_wrong ) ;
if ( regenSize > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
memset ( dst , * ( const BYTE * ) src , regenSize ) ;
return regenSize ;
}
2016-02-04 06:28:14 -08:00
/*! ZSTD_decodeLiteralsBlock() :
2015-11-11 12:38:21 -08:00
@ return : nb of bytes read from src ( < srcSize ) */
2015-11-12 06:36:05 -08:00
size_t ZSTD_decodeLiteralsBlock ( ZSTD_DCtx * dctx ,
2015-11-11 04:43:58 -08:00
const void * src , size_t srcSize ) /* note : srcSize < BLOCKSIZE */
{
if ( srcSize < MIN_CBLOCK_SIZE ) return ERROR ( corruption_detected ) ;
2016-07-22 06:04:25 -07:00
{ const BYTE * const istart = ( const BYTE * ) src ;
2016-07-23 07:31:49 -07:00
symbolEncodingType_e const litEncType = ( symbolEncodingType_e ) ( istart [ 0 ] & 3 ) ;
2016-07-22 06:04:25 -07:00
2016-07-23 07:31:49 -07:00
switch ( litEncType )
2016-07-22 06:04:25 -07:00
{
2016-07-23 07:31:49 -07:00
case set_repeat :
2016-07-22 06:04:25 -07:00
if ( dctx - > litEntropy = = 0 ) return ERROR ( dictionary_corrupted ) ;
/* fall-through */
2016-07-23 07:31:49 -07:00
case set_compressed :
2016-07-22 06:04:25 -07:00
if ( srcSize < 5 ) return ERROR ( corruption_detected ) ; /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
{ size_t lhSize , litSize , litCSize ;
U32 singleStream = 0 ;
U32 const lhlCode = ( istart [ 0 ] > > 2 ) & 3 ;
U32 const lhc = MEM_readLE32 ( istart ) ;
switch ( lhlCode )
{
case 0 : case 1 : default : /* note : default is impossible, since lhlCode into [0..3] */
/* 2 - 2 - 10 - 10 */
2016-09-13 07:52:16 -07:00
singleStream = ! lhlCode ;
lhSize = 3 ;
litSize = ( lhc > > 4 ) & 0x3FF ;
litCSize = ( lhc > > 14 ) & 0x3FF ;
break ;
2016-07-22 06:04:25 -07:00
case 2 :
/* 2 - 2 - 14 - 14 */
2016-09-13 07:52:16 -07:00
lhSize = 4 ;
litSize = ( lhc > > 4 ) & 0x3FFF ;
litCSize = lhc > > 18 ;
break ;
2016-07-22 06:04:25 -07:00
case 3 :
/* 2 - 2 - 18 - 18 */
2016-09-13 07:52:16 -07:00
lhSize = 5 ;
litSize = ( lhc > > 4 ) & 0x3FFFF ;
litCSize = ( lhc > > 22 ) + ( istart [ 4 ] < < 10 ) ;
break ;
2016-07-20 11:12:24 -07:00
}
2016-07-22 06:04:25 -07:00
if ( litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX ) return ERROR ( corruption_detected ) ;
if ( litCSize + lhSize > srcSize ) return ERROR ( corruption_detected ) ;
2016-07-23 07:31:49 -07:00
if ( HUF_isError ( ( litEncType = = set_repeat ) ?
2016-07-22 06:04:25 -07:00
( singleStream ?
2016-09-13 07:52:16 -07:00
HUF_decompress1X_usingDTable ( dctx - > litBuffer , litSize , istart + lhSize , litCSize , dctx - > HUFptr ) :
HUF_decompress4X_usingDTable ( dctx - > litBuffer , litSize , istart + lhSize , litCSize , dctx - > HUFptr ) ) :
2016-07-22 06:04:25 -07:00
( singleStream ?
HUF_decompress1X2_DCtx ( dctx - > hufTable , dctx - > litBuffer , litSize , istart + lhSize , litCSize ) :
HUF_decompress4X_hufOnly ( dctx - > hufTable , dctx - > litBuffer , litSize , istart + lhSize , litCSize ) ) ) )
return ERROR ( corruption_detected ) ;
dctx - > litPtr = dctx - > litBuffer ;
dctx - > litSize = litSize ;
dctx - > litEntropy = 1 ;
2016-09-13 07:52:16 -07:00
if ( litEncType = = set_compressed ) dctx - > HUFptr = dctx - > hufTable ;
2016-11-14 11:33:37 -08:00
memset ( dctx - > litBuffer + dctx - > litSize , 0 , WILDCOPY_OVERLENGTH ) ;
2016-07-22 06:04:25 -07:00
return litCSize + lhSize ;
}
2016-07-23 07:31:49 -07:00
case set_basic :
2016-07-22 06:04:25 -07:00
{ size_t litSize , lhSize ;
U32 const lhlCode = ( ( istart [ 0 ] ) > > 2 ) & 3 ;
switch ( lhlCode )
{
case 0 : case 2 : default : /* note : default is impossible, since lhlCode into [0..3] */
lhSize = 1 ;
litSize = istart [ 0 ] > > 3 ;
2016-07-20 11:12:24 -07:00
break ;
2016-07-22 06:04:25 -07:00
case 1 :
lhSize = 2 ;
litSize = MEM_readLE16 ( istart ) > > 4 ;
break ;
case 3 :
lhSize = 3 ;
litSize = MEM_readLE24 ( istart ) > > 4 ;
2016-07-20 11:12:24 -07:00
break ;
}
2016-01-23 10:28:41 -08:00
2016-07-22 06:04:25 -07:00
if ( lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize ) { /* risk reading beyond src buffer with wildcopy */
if ( litSize + lhSize > srcSize ) return ERROR ( corruption_detected ) ;
memcpy ( dctx - > litBuffer , istart + lhSize , litSize ) ;
dctx - > litPtr = dctx - > litBuffer ;
dctx - > litSize = litSize ;
2016-11-14 11:33:37 -08:00
memset ( dctx - > litBuffer + dctx - > litSize , 0 , WILDCOPY_OVERLENGTH ) ;
2016-07-22 06:04:25 -07:00
return lhSize + litSize ;
}
/* direct reference into compressed stream */
dctx - > litPtr = istart + lhSize ;
2015-11-11 04:43:58 -08:00
dctx - > litSize = litSize ;
2016-01-25 08:26:01 -08:00
return lhSize + litSize ;
2015-11-11 04:43:58 -08:00
}
2016-07-22 06:04:25 -07:00
2016-07-23 07:31:49 -07:00
case set_rle :
2016-07-22 06:04:25 -07:00
{ U32 const lhlCode = ( ( istart [ 0 ] ) > > 2 ) & 3 ;
size_t litSize , lhSize ;
switch ( lhlCode )
{
case 0 : case 2 : default : /* note : default is impossible, since lhlCode into [0..3] */
lhSize = 1 ;
litSize = istart [ 0 ] > > 3 ;
break ;
case 1 :
lhSize = 2 ;
litSize = MEM_readLE16 ( istart ) > > 4 ;
break ;
case 3 :
lhSize = 3 ;
litSize = MEM_readLE24 ( istart ) > > 4 ;
if ( srcSize < 4 ) return ERROR ( corruption_detected ) ; /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
break ;
}
if ( litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX ) return ERROR ( corruption_detected ) ;
2016-11-14 17:52:51 -08:00
memset ( dctx - > litBuffer , istart [ lhSize ] , litSize + WILDCOPY_OVERLENGTH ) ;
2016-07-22 06:04:25 -07:00
dctx - > litPtr = dctx - > litBuffer ;
dctx - > litSize = litSize ;
return lhSize + 1 ;
2016-01-23 10:28:41 -08:00
}
2016-07-22 06:04:25 -07:00
default :
return ERROR ( corruption_detected ) ; /* impossible */
2015-11-11 04:43:58 -08:00
}
}
}
2016-09-22 06:57:28 -07:00
typedef union {
FSE_decode_t realData ;
U32 alignedBy4 ;
} FSE_decode_t4 ;
static const FSE_decode_t4 LL_defaultDTable [ ( 1 < < LL_DEFAULTNORMLOG ) + 1 ] = {
{ { LL_DEFAULTNORMLOG , 1 , 1 } } , /* header : tableLog, fastMode, fastMode */
{ { 0 , 0 , 4 } } , /* 0 : base, symbol, bits */
{ { 16 , 0 , 4 } } ,
{ { 32 , 1 , 5 } } ,
{ { 0 , 3 , 5 } } ,
{ { 0 , 4 , 5 } } ,
{ { 0 , 6 , 5 } } ,
{ { 0 , 7 , 5 } } ,
{ { 0 , 9 , 5 } } ,
{ { 0 , 10 , 5 } } ,
{ { 0 , 12 , 5 } } ,
{ { 0 , 14 , 6 } } ,
{ { 0 , 16 , 5 } } ,
{ { 0 , 18 , 5 } } ,
{ { 0 , 19 , 5 } } ,
{ { 0 , 21 , 5 } } ,
{ { 0 , 22 , 5 } } ,
{ { 0 , 24 , 5 } } ,
{ { 32 , 25 , 5 } } ,
{ { 0 , 26 , 5 } } ,
{ { 0 , 27 , 6 } } ,
{ { 0 , 29 , 6 } } ,
{ { 0 , 31 , 6 } } ,
{ { 32 , 0 , 4 } } ,
{ { 0 , 1 , 4 } } ,
{ { 0 , 2 , 5 } } ,
{ { 32 , 4 , 5 } } ,
{ { 0 , 5 , 5 } } ,
{ { 32 , 7 , 5 } } ,
{ { 0 , 8 , 5 } } ,
{ { 32 , 10 , 5 } } ,
{ { 0 , 11 , 5 } } ,
{ { 0 , 13 , 6 } } ,
{ { 32 , 16 , 5 } } ,
{ { 0 , 17 , 5 } } ,
{ { 32 , 19 , 5 } } ,
{ { 0 , 20 , 5 } } ,
{ { 32 , 22 , 5 } } ,
{ { 0 , 23 , 5 } } ,
{ { 0 , 25 , 4 } } ,
{ { 16 , 25 , 4 } } ,
{ { 32 , 26 , 5 } } ,
{ { 0 , 28 , 6 } } ,
{ { 0 , 30 , 6 } } ,
{ { 48 , 0 , 4 } } ,
{ { 16 , 1 , 4 } } ,
{ { 32 , 2 , 5 } } ,
{ { 32 , 3 , 5 } } ,
{ { 32 , 5 , 5 } } ,
{ { 32 , 6 , 5 } } ,
{ { 32 , 8 , 5 } } ,
{ { 32 , 9 , 5 } } ,
{ { 32 , 11 , 5 } } ,
{ { 32 , 12 , 5 } } ,
{ { 0 , 15 , 6 } } ,
{ { 32 , 17 , 5 } } ,
{ { 32 , 18 , 5 } } ,
{ { 32 , 20 , 5 } } ,
{ { 32 , 21 , 5 } } ,
{ { 32 , 23 , 5 } } ,
{ { 32 , 24 , 5 } } ,
{ { 0 , 35 , 6 } } ,
{ { 0 , 34 , 6 } } ,
{ { 0 , 33 , 6 } } ,
{ { 0 , 32 , 6 } } ,
} ; /* LL_defaultDTable */
static const FSE_decode_t4 ML_defaultDTable [ ( 1 < < ML_DEFAULTNORMLOG ) + 1 ] = {
{ { ML_DEFAULTNORMLOG , 1 , 1 } } , /* header : tableLog, fastMode, fastMode */
{ { 0 , 0 , 6 } } , /* 0 : base, symbol, bits */
{ { 0 , 1 , 4 } } ,
{ { 32 , 2 , 5 } } ,
{ { 0 , 3 , 5 } } ,
{ { 0 , 5 , 5 } } ,
{ { 0 , 6 , 5 } } ,
{ { 0 , 8 , 5 } } ,
{ { 0 , 10 , 6 } } ,
{ { 0 , 13 , 6 } } ,
{ { 0 , 16 , 6 } } ,
{ { 0 , 19 , 6 } } ,
{ { 0 , 22 , 6 } } ,
{ { 0 , 25 , 6 } } ,
{ { 0 , 28 , 6 } } ,
{ { 0 , 31 , 6 } } ,
{ { 0 , 33 , 6 } } ,
{ { 0 , 35 , 6 } } ,
{ { 0 , 37 , 6 } } ,
{ { 0 , 39 , 6 } } ,
{ { 0 , 41 , 6 } } ,
{ { 0 , 43 , 6 } } ,
{ { 0 , 45 , 6 } } ,
{ { 16 , 1 , 4 } } ,
{ { 0 , 2 , 4 } } ,
{ { 32 , 3 , 5 } } ,
{ { 0 , 4 , 5 } } ,
{ { 32 , 6 , 5 } } ,
{ { 0 , 7 , 5 } } ,
{ { 0 , 9 , 6 } } ,
{ { 0 , 12 , 6 } } ,
{ { 0 , 15 , 6 } } ,
{ { 0 , 18 , 6 } } ,
{ { 0 , 21 , 6 } } ,
{ { 0 , 24 , 6 } } ,
{ { 0 , 27 , 6 } } ,
{ { 0 , 30 , 6 } } ,
{ { 0 , 32 , 6 } } ,
{ { 0 , 34 , 6 } } ,
{ { 0 , 36 , 6 } } ,
{ { 0 , 38 , 6 } } ,
{ { 0 , 40 , 6 } } ,
{ { 0 , 42 , 6 } } ,
{ { 0 , 44 , 6 } } ,
{ { 32 , 1 , 4 } } ,
{ { 48 , 1 , 4 } } ,
{ { 16 , 2 , 4 } } ,
{ { 32 , 4 , 5 } } ,
{ { 32 , 5 , 5 } } ,
{ { 32 , 7 , 5 } } ,
{ { 32 , 8 , 5 } } ,
{ { 0 , 11 , 6 } } ,
{ { 0 , 14 , 6 } } ,
{ { 0 , 17 , 6 } } ,
{ { 0 , 20 , 6 } } ,
{ { 0 , 23 , 6 } } ,
{ { 0 , 26 , 6 } } ,
{ { 0 , 29 , 6 } } ,
{ { 0 , 52 , 6 } } ,
{ { 0 , 51 , 6 } } ,
{ { 0 , 50 , 6 } } ,
{ { 0 , 49 , 6 } } ,
{ { 0 , 48 , 6 } } ,
{ { 0 , 47 , 6 } } ,
{ { 0 , 46 , 6 } } ,
} ; /* ML_defaultDTable */
static const FSE_decode_t4 OF_defaultDTable [ ( 1 < < OF_DEFAULTNORMLOG ) + 1 ] = {
{ { OF_DEFAULTNORMLOG , 1 , 1 } } , /* header : tableLog, fastMode, fastMode */
{ { 0 , 0 , 5 } } , /* 0 : base, symbol, bits */
{ { 0 , 6 , 4 } } ,
{ { 0 , 9 , 5 } } ,
{ { 0 , 15 , 5 } } ,
{ { 0 , 21 , 5 } } ,
{ { 0 , 3 , 5 } } ,
{ { 0 , 7 , 4 } } ,
{ { 0 , 12 , 5 } } ,
{ { 0 , 18 , 5 } } ,
{ { 0 , 23 , 5 } } ,
{ { 0 , 5 , 5 } } ,
{ { 0 , 8 , 4 } } ,
{ { 0 , 14 , 5 } } ,
{ { 0 , 20 , 5 } } ,
{ { 0 , 2 , 5 } } ,
{ { 16 , 7 , 4 } } ,
{ { 0 , 11 , 5 } } ,
{ { 0 , 17 , 5 } } ,
{ { 0 , 22 , 5 } } ,
{ { 0 , 4 , 5 } } ,
{ { 16 , 8 , 4 } } ,
{ { 0 , 13 , 5 } } ,
{ { 0 , 19 , 5 } } ,
{ { 0 , 1 , 5 } } ,
{ { 16 , 6 , 4 } } ,
{ { 0 , 10 , 5 } } ,
{ { 0 , 16 , 5 } } ,
{ { 0 , 28 , 5 } } ,
{ { 0 , 27 , 5 } } ,
{ { 0 , 26 , 5 } } ,
{ { 0 , 25 , 5 } } ,
{ { 0 , 24 , 5 } } ,
} ; /* OF_defaultDTable */
2016-03-18 14:23:49 -07:00
/*! ZSTD_buildSeqTable() :
@ return : nb bytes read from src ,
or an error code if it fails , testable with ZSTD_isError ( )
*/
2016-09-22 06:57:28 -07:00
static size_t ZSTD_buildSeqTable ( FSE_DTable * DTableSpace , const FSE_DTable * * DTablePtr ,
symbolEncodingType_e type , U32 max , U32 maxLog ,
2016-03-22 17:32:41 -07:00
const void * src , size_t srcSize ,
2016-09-22 06:57:28 -07:00
const FSE_decode_t4 * defaultTable , U32 flagRepeatTable )
2016-03-21 05:24:16 -07:00
{
2016-09-22 06:57:28 -07:00
const void * const tmpPtr = defaultTable ; /* bypass strict aliasing */
2016-03-21 05:24:16 -07:00
switch ( type )
{
2016-07-23 07:31:49 -07:00
case set_rle :
2016-03-21 05:24:16 -07:00
if ( ! srcSize ) return ERROR ( srcSize_wrong ) ;
if ( ( * ( const BYTE * ) src ) > max ) return ERROR ( corruption_detected ) ;
2016-09-22 06:57:28 -07:00
FSE_buildDTable_rle ( DTableSpace , * ( const BYTE * ) src ) ;
* DTablePtr = DTableSpace ;
2016-03-21 05:24:16 -07:00
return 1 ;
2016-07-23 07:31:49 -07:00
case set_basic :
2016-09-22 06:57:28 -07:00
* DTablePtr = ( const FSE_DTable * ) tmpPtr ;
2016-03-22 15:19:28 -07:00
return 0 ;
2016-07-23 07:31:49 -07:00
case set_repeat :
2016-04-09 08:26:22 -07:00
if ( ! flagRepeatTable ) return ERROR ( corruption_detected ) ;
2016-03-22 15:19:28 -07:00
return 0 ;
default : /* impossible */
2016-07-23 07:31:49 -07:00
case set_compressed :
2016-03-22 15:19:28 -07:00
{ U32 tableLog ;
S16 norm [ MaxSeq + 1 ] ;
size_t const headerSize = FSE_readNCount ( norm , & max , & tableLog , src , srcSize ) ;
if ( FSE_isError ( headerSize ) ) return ERROR ( corruption_detected ) ;
if ( tableLog > maxLog ) return ERROR ( corruption_detected ) ;
2016-09-22 06:57:28 -07:00
FSE_buildDTable ( DTableSpace , norm , max , tableLog ) ;
* DTablePtr = DTableSpace ;
2016-03-22 15:19:28 -07:00
return headerSize ;
} }
}
2016-09-13 07:52:16 -07:00
size_t ZSTD_decodeSeqHeaders ( ZSTD_DCtx * dctx , int * nbSeqPtr ,
2016-03-22 15:19:28 -07:00
const void * src , size_t srcSize )
2015-11-11 04:43:58 -08:00
{
const BYTE * const istart = ( const BYTE * const ) src ;
const BYTE * const iend = istart + srcSize ;
2016-03-23 17:27:55 -07:00
const BYTE * ip = istart ;
2015-11-11 04:43:58 -08:00
/* check */
2016-03-18 14:23:49 -07:00
if ( srcSize < MIN_SEQUENCES_SIZE ) return ERROR ( srcSize_wrong ) ;
2015-11-11 04:43:58 -08:00
/* SeqHead */
2016-03-23 17:27:55 -07:00
{ int nbSeq = * ip + + ;
if ( ! nbSeq ) { * nbSeqPtr = 0 ; return 1 ; }
2016-04-01 06:49:41 -07:00
if ( nbSeq > 0x7F ) {
2016-10-18 16:08:52 -07:00
if ( nbSeq = = 0xFF ) {
if ( ip + 2 > iend ) return ERROR ( srcSize_wrong ) ;
2016-03-23 17:27:55 -07:00
nbSeq = MEM_readLE16 ( ip ) + LONGNBSEQ , ip + = 2 ;
2016-10-18 16:08:52 -07:00
} else {
if ( ip > = iend ) return ERROR ( srcSize_wrong ) ;
2016-03-23 17:27:55 -07:00
nbSeq = ( ( nbSeq - 0x80 ) < < 8 ) + * ip + + ;
2016-10-18 16:08:52 -07:00
}
2016-03-23 17:27:55 -07:00
}
* nbSeqPtr = nbSeq ;
2016-03-04 05:45:31 -08:00
}
2016-01-30 15:58:06 -08:00
2016-03-04 05:45:31 -08:00
/* FSE table descriptors */
2016-07-24 09:02:04 -07:00
if ( ip + 4 > iend ) return ERROR ( srcSize_wrong ) ; /* minimum possible size */
2016-07-23 07:31:49 -07:00
{ symbolEncodingType_e const LLtype = ( symbolEncodingType_e ) ( * ip > > 6 ) ;
symbolEncodingType_e const OFtype = ( symbolEncodingType_e ) ( ( * ip > > 4 ) & 3 ) ;
symbolEncodingType_e const MLtype = ( symbolEncodingType_e ) ( ( * ip > > 2 ) & 3 ) ;
2016-03-23 17:27:55 -07:00
ip + + ;
2015-11-11 04:43:58 -08:00
/* Build DTables */
2016-09-22 06:57:28 -07:00
{ size_t const llhSize = ZSTD_buildSeqTable ( dctx - > LLTable , & dctx - > LLTptr ,
LLtype , MaxLL , LLFSELog ,
ip , iend - ip , LL_defaultDTable , dctx - > fseEntropy ) ;
2016-07-04 07:13:11 -07:00
if ( ZSTD_isError ( llhSize ) ) return ERROR ( corruption_detected ) ;
ip + = llhSize ;
2015-11-11 04:43:58 -08:00
}
2016-09-22 06:57:28 -07:00
{ size_t const ofhSize = ZSTD_buildSeqTable ( dctx - > OFTable , & dctx - > OFTptr ,
OFtype , MaxOff , OffFSELog ,
ip , iend - ip , OF_defaultDTable , dctx - > fseEntropy ) ;
2016-07-04 07:13:11 -07:00
if ( ZSTD_isError ( ofhSize ) ) return ERROR ( corruption_detected ) ;
ip + = ofhSize ;
2015-11-11 04:43:58 -08:00
}
2016-09-22 06:57:28 -07:00
{ size_t const mlhSize = ZSTD_buildSeqTable ( dctx - > MLTable , & dctx - > MLTptr ,
MLtype , MaxML , MLFSELog ,
ip , iend - ip , ML_defaultDTable , dctx - > fseEntropy ) ;
2016-07-04 07:13:11 -07:00
if ( ZSTD_isError ( mlhSize ) ) return ERROR ( corruption_detected ) ;
ip + = mlhSize ;
2016-09-22 06:57:28 -07:00
}
}
2015-11-11 04:43:58 -08:00
return ip - istart ;
}
typedef struct {
size_t litLength ;
size_t matchLength ;
2016-01-30 15:58:06 -08:00
size_t offset ;
2016-11-23 15:43:30 -08:00
const BYTE * match ;
2015-11-11 04:43:58 -08:00
} seq_t ;
typedef struct {
BIT_DStream_t DStream ;
FSE_DState_t stateLL ;
FSE_DState_t stateOffb ;
FSE_DState_t stateML ;
2016-07-30 06:32:47 -07:00
size_t prevOffset [ ZSTD_REP_NUM ] ;
2016-11-28 19:59:11 -08:00
const BYTE * base ;
2016-11-29 13:12:24 -08:00
size_t pos ;
2016-11-28 19:59:11 -08:00
iPtrDiff gotoDict ;
2015-11-11 04:43:58 -08:00
} seqState_t ;
2016-02-03 03:53:07 -08:00
2016-11-28 16:11:30 -08:00
static seq_t ZSTD_decodeSequenceLong ( seqState_t * seqState )
2015-11-11 04:43:58 -08:00
{
2016-06-03 06:41:51 -07:00
seq_t seq ;
2016-08-19 18:47:49 -07:00
U32 const llCode = FSE_peekSymbol ( & seqState - > stateLL ) ;
U32 const mlCode = FSE_peekSymbol ( & seqState - > stateML ) ;
U32 const ofCode = FSE_peekSymbol ( & seqState - > stateOffb ) ; /* <= maxOff, by table construction */
2016-03-22 17:54:25 -07:00
U32 const llBits = LL_bits [ llCode ] ;
U32 const mlBits = ML_bits [ mlCode ] ;
2016-03-23 18:31:27 -07:00
U32 const ofBits = ofCode ;
U32 const totalBits = llBits + mlBits + ofBits ;
2016-03-22 17:54:25 -07:00
static const U32 LL_base [ MaxLL + 1 ] = {
2016-03-21 05:24:16 -07:00
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ,
16 , 18 , 20 , 22 , 24 , 28 , 32 , 40 , 48 , 64 , 0x80 , 0x100 , 0x200 , 0x400 , 0x800 , 0x1000 ,
0x2000 , 0x4000 , 0x8000 , 0x10000 } ;
2015-11-11 04:43:58 -08:00
2016-03-22 17:54:25 -07:00
static const U32 ML_base [ MaxML + 1 ] = {
2016-07-05 17:25:44 -07:00
3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 ,
19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 ,
35 , 37 , 39 , 41 , 43 , 47 , 51 , 59 , 67 , 83 , 99 , 0x83 , 0x103 , 0x203 , 0x403 , 0x803 ,
0x1003 , 0x2003 , 0x4003 , 0x8003 , 0x10003 } ;
2016-03-22 17:32:41 -07:00
2016-03-22 17:54:25 -07:00
static const U32 OF_base [ MaxOff + 1 ] = {
2016-07-05 17:25:44 -07:00
0 , 1 , 1 , 5 , 0xD , 0x1D , 0x3D , 0x7D ,
0xFD , 0x1FD , 0x3FD , 0x7FD , 0xFFD , 0x1FFD , 0x3FFD , 0x7FFD ,
0xFFFD , 0x1FFFD , 0x3FFFD , 0x7FFFD , 0xFFFFD , 0x1FFFFD , 0x3FFFFD , 0x7FFFFD ,
2016-07-08 04:13:37 -07:00
0xFFFFFD , 0x1FFFFFD , 0x3FFFFFD , 0x7FFFFFD , 0xFFFFFFD } ;
2016-03-22 17:54:25 -07:00
2016-03-23 06:00:09 -07:00
/* sequence */
2016-04-05 00:34:13 -07:00
{ size_t offset ;
2016-04-05 01:08:25 -07:00
if ( ! ofCode )
offset = 0 ;
else {
2016-08-19 18:47:49 -07:00
offset = OF_base [ ofCode ] + BIT_readBits ( & seqState - > DStream , ofBits ) ; /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
if ( MEM_32bits ( ) ) BIT_reloadDStream ( & seqState - > DStream ) ;
2016-03-17 03:21:00 -07:00
}
2016-04-07 06:24:29 -07:00
2016-07-05 17:25:44 -07:00
if ( ofCode < = 1 ) {
2016-07-30 19:01:57 -07:00
offset + = ( llCode = = 0 ) ;
2016-07-05 17:25:44 -07:00
if ( offset ) {
2016-10-17 17:28:28 -07:00
size_t temp = ( offset = = 3 ) ? seqState - > prevOffset [ 0 ] - 1 : seqState - > prevOffset [ offset ] ;
temp + = ! temp ; /* 0 is not valid; input is corrupted; force offset to 1 */
2016-07-05 17:25:44 -07:00
if ( offset ! = 1 ) seqState - > prevOffset [ 2 ] = seqState - > prevOffset [ 1 ] ;
2016-04-05 01:30:05 -07:00
seqState - > prevOffset [ 1 ] = seqState - > prevOffset [ 0 ] ;
2016-07-30 06:32:47 -07:00
seqState - > prevOffset [ 0 ] = offset = temp ;
2016-04-05 01:08:25 -07:00
} else {
2016-04-05 01:30:05 -07:00
offset = seqState - > prevOffset [ 0 ] ;
2016-04-05 01:08:25 -07:00
}
2016-04-05 01:30:05 -07:00
} else {
seqState - > prevOffset [ 2 ] = seqState - > prevOffset [ 1 ] ;
2016-04-07 06:24:29 -07:00
seqState - > prevOffset [ 1 ] = seqState - > prevOffset [ 0 ] ;
2016-07-30 06:32:47 -07:00
seqState - > prevOffset [ 0 ] = offset ;
2016-04-05 01:08:25 -07:00
}
2016-06-03 06:41:51 -07:00
seq . offset = offset ;
2015-11-11 04:43:58 -08:00
}
2016-08-19 18:47:49 -07:00
seq . matchLength = ML_base [ mlCode ] + ( ( mlCode > 31 ) ? BIT_readBits ( & seqState - > DStream , mlBits ) : 0 ) ; /* <= 16 bits */
if ( MEM_32bits ( ) & & ( mlBits + llBits > 24 ) ) BIT_reloadDStream ( & seqState - > DStream ) ;
2015-11-11 04:43:58 -08:00
2016-08-19 18:47:49 -07:00
seq . litLength = LL_base [ llCode ] + ( ( llCode > 15 ) ? BIT_readBits ( & seqState - > DStream , llBits ) : 0 ) ; /* <= 16 bits */
2016-07-04 09:16:16 -07:00
if ( MEM_32bits ( ) | |
2016-08-19 18:47:49 -07:00
( totalBits > 64 - 7 - ( LLFSELog + MLFSELog + OffFSELog ) ) ) BIT_reloadDStream ( & seqState - > DStream ) ;
2016-01-27 15:18:06 -08:00
2016-11-29 13:12:24 -08:00
{ size_t const pos = seqState - > pos + seq . litLength ;
seq . match = seqState - > base + pos - seq . offset ; /* single memory segment */
if ( seq . offset > pos ) seq . match + = seqState - > gotoDict ; /* separate memory segment */
seqState - > pos = pos + seq . matchLength ;
}
2016-11-23 15:43:30 -08:00
2016-03-22 17:32:41 -07:00
/* ANS state update */
2016-08-19 18:47:49 -07:00
FSE_updateState ( & seqState - > stateLL , & seqState - > DStream ) ; /* <= 9 bits */
FSE_updateState ( & seqState - > stateML , & seqState - > DStream ) ; /* <= 9 bits */
if ( MEM_32bits ( ) ) BIT_reloadDStream ( & seqState - > DStream ) ; /* <= 18 bits */
FSE_updateState ( & seqState - > stateOffb , & seqState - > DStream ) ; /* <= 8 bits */
2016-06-03 06:41:51 -07:00
return seq ;
2015-11-11 04:43:58 -08:00
}
2016-10-21 16:55:26 -07:00
FORCE_NOINLINE
size_t ZSTD_execSequenceLast7 ( BYTE * op ,
BYTE * const oend , seq_t sequence ,
2016-11-14 11:33:37 -08:00
const BYTE * * litPtr , const BYTE * const litLimit ,
2016-10-21 16:55:26 -07:00
const BYTE * const base , const BYTE * const vBase , const BYTE * const dictEnd )
{
BYTE * const oLitEnd = op + sequence . litLength ;
size_t const sequenceLength = sequence . litLength + sequence . matchLength ;
BYTE * const oMatchEnd = op + sequenceLength ; /* risk : address space overflow (32-bits) */
BYTE * const oend_w = oend - WILDCOPY_OVERLENGTH ;
const BYTE * const iLitEnd = * litPtr + sequence . litLength ;
const BYTE * match = oLitEnd - sequence . offset ;
/* check */
if ( oMatchEnd > oend ) return ERROR ( dstSize_tooSmall ) ; /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
2016-11-14 11:33:37 -08:00
if ( iLitEnd > litLimit ) return ERROR ( corruption_detected ) ; /* over-read beyond lit buffer */
2016-10-21 16:55:26 -07:00
if ( oLitEnd < = oend_w ) return ERROR ( GENERIC ) ; /* Precondition */
/* copy literals */
if ( op < oend_w ) {
ZSTD_wildcopy ( op , * litPtr , oend_w - op ) ;
* litPtr + = oend_w - op ;
op = oend_w ;
}
while ( op < oLitEnd ) * op + + = * ( * litPtr ) + + ;
/* copy Match */
if ( sequence . offset > ( size_t ) ( oLitEnd - base ) ) {
/* offset beyond prefix */
if ( sequence . offset > ( size_t ) ( oLitEnd - vBase ) ) return ERROR ( corruption_detected ) ;
match = dictEnd - ( base - match ) ;
if ( match + sequence . matchLength < = dictEnd ) {
memmove ( oLitEnd , match , sequence . matchLength ) ;
return sequenceLength ;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match ;
memmove ( oLitEnd , match , length1 ) ;
op = oLitEnd + length1 ;
sequence . matchLength - = length1 ;
match = base ;
} }
while ( op < oMatchEnd ) * op + + = * match + + ;
return sequenceLength ;
}
2016-05-12 05:06:31 -07:00
FORCE_INLINE
2016-11-28 16:11:30 -08:00
size_t ZSTD_execSequenceLong ( BYTE * op ,
2015-11-19 08:13:19 -08:00
BYTE * const oend , seq_t sequence ,
2016-11-14 11:33:37 -08:00
const BYTE * * litPtr , const BYTE * const litLimit ,
2015-12-04 08:16:37 -08:00
const BYTE * const base , const BYTE * const vBase , const BYTE * const dictEnd )
2015-11-11 04:43:58 -08:00
{
BYTE * const oLitEnd = op + sequence . litLength ;
2016-03-23 17:27:55 -07:00
size_t const sequenceLength = sequence . litLength + sequence . matchLength ;
2015-11-19 08:13:19 -08:00
BYTE * const oMatchEnd = op + sequenceLength ; /* risk : address space overflow (32-bits) */
2016-07-23 16:21:53 -07:00
BYTE * const oend_w = oend - WILDCOPY_OVERLENGTH ;
2016-04-03 11:24:25 -07:00
const BYTE * const iLitEnd = * litPtr + sequence . litLength ;
2016-11-23 15:43:30 -08:00
const BYTE * match = sequence . match ;
2015-11-11 04:43:58 -08:00
/* check */
2016-11-28 15:50:16 -08:00
# if 1
2016-10-21 16:55:26 -07:00
if ( oMatchEnd > oend ) return ERROR ( dstSize_tooSmall ) ; /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
2016-11-14 11:33:37 -08:00
if ( iLitEnd > litLimit ) return ERROR ( corruption_detected ) ; /* over-read beyond lit buffer */
if ( oLitEnd > oend_w ) return ZSTD_execSequenceLast7 ( op , oend , sequence , litPtr , litLimit , base , vBase , dictEnd ) ;
2016-11-28 15:50:16 -08:00
# endif
2015-11-11 04:43:58 -08:00
/* copy Literals */
2016-08-19 17:59:04 -07:00
ZSTD_copy8 ( op , * litPtr ) ;
if ( sequence . litLength > 8 )
ZSTD_wildcopy ( op + 8 , ( * litPtr ) + 8 , sequence . litLength - 8 ) ; /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
2015-11-11 04:43:58 -08:00
op = oLitEnd ;
2016-04-03 11:24:25 -07:00
* litPtr = iLitEnd ; /* update for next sequence */
2015-11-11 04:43:58 -08:00
/* copy Match */
2016-11-28 15:50:16 -08:00
# if 1
2016-01-26 06:58:49 -08:00
if ( sequence . offset > ( size_t ) ( oLitEnd - base ) ) {
2015-11-30 14:13:56 -08:00
/* offset beyond prefix */
2016-03-23 17:27:55 -07:00
if ( sequence . offset > ( size_t ) ( oLitEnd - vBase ) ) return ERROR ( corruption_detected ) ;
2016-01-26 06:58:49 -08:00
if ( match + sequence . matchLength < = dictEnd ) {
2015-12-06 04:18:37 -08:00
memmove ( oLitEnd , match , sequence . matchLength ) ;
2015-11-30 14:13:56 -08:00
return sequenceLength ;
}
/* span extDict & currentPrefixSegment */
2016-03-19 04:12:07 -07:00
{ size_t const length1 = dictEnd - match ;
2015-12-06 04:18:37 -08:00
memmove ( oLitEnd , match , length1 ) ;
2015-11-30 14:13:56 -08:00
op = oLitEnd + length1 ;
sequence . matchLength - = length1 ;
match = base ;
2016-10-10 16:19:21 -07:00
if ( op > oend_w ) {
2016-10-27 16:19:54 -07:00
U32 i ;
for ( i = 0 ; i < sequence . matchLength ; + + i ) op [ i ] = match [ i ] ;
2016-10-10 16:19:21 -07:00
return sequenceLength ;
}
2016-01-27 15:18:06 -08:00
} }
2016-10-10 16:19:21 -07:00
/* Requirement: op <= oend_w */
2016-11-28 15:50:16 -08:00
# endif
2015-11-30 14:13:56 -08:00
/* match within prefix */
2016-01-26 06:58:49 -08:00
if ( sequence . offset < 8 ) {
2015-11-30 14:13:56 -08:00
/* close range match, overlap */
2016-03-23 17:27:55 -07:00
static const U32 dec32table [ ] = { 0 , 1 , 2 , 1 , 4 , 4 , 4 , 4 } ; /* added */
static const int dec64table [ ] = { 8 , 8 , 8 , 7 , 8 , 9 , 10 , 11 } ; /* substracted */
int const sub2 = dec64table [ sequence . offset ] ;
2015-11-30 14:13:56 -08:00
op [ 0 ] = match [ 0 ] ;
op [ 1 ] = match [ 1 ] ;
op [ 2 ] = match [ 2 ] ;
op [ 3 ] = match [ 3 ] ;
match + = dec32table [ sequence . offset ] ;
ZSTD_copy4 ( op + 4 , match ) ;
match - = sub2 ;
2016-01-27 15:18:06 -08:00
} else {
2015-11-30 14:13:56 -08:00
ZSTD_copy8 ( op , match ) ;
}
op + = 8 ; match + = 8 ;
2016-04-06 00:46:01 -07:00
if ( oMatchEnd > oend - ( 16 - MINMATCH ) ) {
2016-06-19 05:27:21 -07:00
if ( op < oend_w ) {
ZSTD_wildcopy ( op , match , oend_w - op ) ;
match + = oend_w - op ;
op = oend_w ;
2015-11-30 14:13:56 -08:00
}
2016-03-19 06:14:31 -07:00
while ( op < oMatchEnd ) * op + + = * match + + ;
2016-01-27 15:18:06 -08:00
} else {
2015-11-30 14:13:56 -08:00
ZSTD_wildcopy ( op , match , sequence . matchLength - 8 ) ; /* works even if matchLength < 8 */
}
return sequenceLength ;
2015-11-11 04:43:58 -08:00
}
2015-11-19 08:13:19 -08:00
2016-11-28 16:11:30 -08:00
static size_t ZSTD_decompressSequencesLong (
2015-11-12 06:36:05 -08:00
ZSTD_DCtx * dctx ,
2015-11-11 04:43:58 -08:00
void * dst , size_t maxDstSize ,
const void * seqStart , size_t seqSize )
{
const BYTE * ip = ( const BYTE * ) seqStart ;
const BYTE * const iend = ip + seqSize ;
BYTE * const ostart = ( BYTE * const ) dst ;
BYTE * const oend = ostart + maxDstSize ;
2016-04-07 17:02:12 -07:00
BYTE * op = ostart ;
2015-11-11 04:43:58 -08:00
const BYTE * litPtr = dctx - > litPtr ;
const BYTE * const litEnd = litPtr + dctx - > litSize ;
2015-12-04 08:16:37 -08:00
const BYTE * const base = ( const BYTE * ) ( dctx - > base ) ;
const BYTE * const vBase = ( const BYTE * ) ( dctx - > vBase ) ;
const BYTE * const dictEnd = ( const BYTE * ) ( dctx - > dictEnd ) ;
2016-04-03 11:24:25 -07:00
int nbSeq ;
2015-11-11 04:43:58 -08:00
/* Build Decoding Tables */
2016-09-13 07:52:16 -07:00
{ size_t const seqHSize = ZSTD_decodeSeqHeaders ( dctx , & nbSeq , ip , seqSize ) ;
2016-04-03 11:24:25 -07:00
if ( ZSTD_isError ( seqHSize ) ) return seqHSize ;
ip + = seqHSize ;
2016-03-21 06:22:38 -07:00
}
2015-11-11 04:43:58 -08:00
/* Regen sequences */
2016-01-30 15:58:06 -08:00
if ( nbSeq ) {
2016-11-28 18:38:52 -08:00
# define STORED_SEQS 4
2016-11-28 16:11:30 -08:00
# define STOSEQ_MASK (STORED_SEQS-1)
2016-11-28 18:38:52 -08:00
# define ADVANCED_SEQS 4
2016-11-28 16:11:30 -08:00
seq_t sequences [ STORED_SEQS ] ;
int const seqAdvance = MIN ( nbSeq , ADVANCED_SEQS ) ;
2016-11-28 15:50:16 -08:00
seqState_t seqState ;
2016-11-28 16:11:30 -08:00
int seqNb ;
2016-11-28 15:50:16 -08:00
dctx - > fseEntropy = 1 ;
{ U32 i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) seqState . prevOffset [ i ] = dctx - > rep [ i ] ; }
2016-11-28 19:59:11 -08:00
seqState . base = base ;
2016-11-29 13:12:24 -08:00
seqState . pos = ( size_t ) ( op - base ) ;
2016-11-28 19:59:11 -08:00
seqState . gotoDict = ( iPtrDiff ) ( dictEnd - base ) ;
2016-11-28 15:50:16 -08:00
CHECK_E ( BIT_initDStream ( & seqState . DStream , ip , iend - ip ) , corruption_detected ) ;
FSE_initDState ( & seqState . stateLL , & seqState . DStream , dctx - > LLTptr ) ;
FSE_initDState ( & seqState . stateOffb , & seqState . DStream , dctx - > OFTptr ) ;
FSE_initDState ( & seqState . stateML , & seqState . DStream , dctx - > MLTptr ) ;
2016-11-28 16:11:30 -08:00
/* prepare in advance */
for ( seqNb = 0 ; ( BIT_reloadDStream ( & seqState . DStream ) < = BIT_DStream_completed ) & & seqNb < seqAdvance ; seqNb + + ) {
sequences [ seqNb ] = ZSTD_decodeSequenceLong ( & seqState ) ;
}
if ( seqNb < seqAdvance ) return ERROR ( corruption_detected ) ;
/* decode and decompress */
for ( ; ( BIT_reloadDStream ( & ( seqState . DStream ) ) < = BIT_DStream_completed ) & & seqNb < nbSeq ; seqNb + + ) {
seq_t const sequence = ZSTD_decodeSequenceLong ( & seqState ) ;
size_t const oneSeqSize = ZSTD_execSequenceLong ( op , oend , sequences [ ( seqNb - ADVANCED_SEQS ) & STOSEQ_MASK ] , & litPtr , litEnd , base , vBase , dictEnd ) ;
if ( ZSTD_isError ( oneSeqSize ) ) return oneSeqSize ;
ZSTD_PREFETCH ( sequence . match ) ;
sequences [ seqNb & STOSEQ_MASK ] = sequence ;
op + = oneSeqSize ;
}
if ( seqNb < nbSeq ) return ERROR ( corruption_detected ) ;
/* finish queue */
seqNb - = seqAdvance ;
for ( ; seqNb < nbSeq ; seqNb + + ) {
size_t const oneSeqSize = ZSTD_execSequenceLong ( op , oend , sequences [ seqNb & STOSEQ_MASK ] , & litPtr , litEnd , base , vBase , dictEnd ) ;
if ( ZSTD_isError ( oneSeqSize ) ) return oneSeqSize ;
op + = oneSeqSize ;
}
2016-11-28 15:50:16 -08:00
/* save reps for next block */
{ U32 i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) dctx - > rep [ i ] = ( U32 ) ( seqState . prevOffset [ i ] ) ; }
}
/* last literal segment */
{ size_t const lastLLSize = litEnd - litPtr ;
if ( lastLLSize > ( size_t ) ( oend - op ) ) return ERROR ( dstSize_tooSmall ) ;
memcpy ( op , litPtr , lastLLSize ) ;
op + = lastLLSize ;
}
return op - ostart ;
}
2016-11-28 16:11:30 -08:00
static seq_t ZSTD_decodeSequence ( seqState_t * seqState )
{
seq_t seq ;
U32 const llCode = FSE_peekSymbol ( & seqState - > stateLL ) ;
U32 const mlCode = FSE_peekSymbol ( & seqState - > stateML ) ;
U32 const ofCode = FSE_peekSymbol ( & seqState - > stateOffb ) ; /* <= maxOff, by table construction */
U32 const llBits = LL_bits [ llCode ] ;
U32 const mlBits = ML_bits [ mlCode ] ;
U32 const ofBits = ofCode ;
U32 const totalBits = llBits + mlBits + ofBits ;
static const U32 LL_base [ MaxLL + 1 ] = {
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ,
16 , 18 , 20 , 22 , 24 , 28 , 32 , 40 , 48 , 64 , 0x80 , 0x100 , 0x200 , 0x400 , 0x800 , 0x1000 ,
0x2000 , 0x4000 , 0x8000 , 0x10000 } ;
static const U32 ML_base [ MaxML + 1 ] = {
3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 ,
19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 ,
35 , 37 , 39 , 41 , 43 , 47 , 51 , 59 , 67 , 83 , 99 , 0x83 , 0x103 , 0x203 , 0x403 , 0x803 ,
0x1003 , 0x2003 , 0x4003 , 0x8003 , 0x10003 } ;
static const U32 OF_base [ MaxOff + 1 ] = {
0 , 1 , 1 , 5 , 0xD , 0x1D , 0x3D , 0x7D ,
0xFD , 0x1FD , 0x3FD , 0x7FD , 0xFFD , 0x1FFD , 0x3FFD , 0x7FFD ,
0xFFFD , 0x1FFFD , 0x3FFFD , 0x7FFFD , 0xFFFFD , 0x1FFFFD , 0x3FFFFD , 0x7FFFFD ,
0xFFFFFD , 0x1FFFFFD , 0x3FFFFFD , 0x7FFFFFD , 0xFFFFFFD } ;
/* sequence */
{ size_t offset ;
if ( ! ofCode )
offset = 0 ;
else {
offset = OF_base [ ofCode ] + BIT_readBits ( & seqState - > DStream , ofBits ) ; /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
if ( MEM_32bits ( ) ) BIT_reloadDStream ( & seqState - > DStream ) ;
}
if ( ofCode < = 1 ) {
offset + = ( llCode = = 0 ) ;
if ( offset ) {
size_t temp = ( offset = = 3 ) ? seqState - > prevOffset [ 0 ] - 1 : seqState - > prevOffset [ offset ] ;
temp + = ! temp ; /* 0 is not valid; input is corrupted; force offset to 1 */
if ( offset ! = 1 ) seqState - > prevOffset [ 2 ] = seqState - > prevOffset [ 1 ] ;
seqState - > prevOffset [ 1 ] = seqState - > prevOffset [ 0 ] ;
seqState - > prevOffset [ 0 ] = offset = temp ;
} else {
offset = seqState - > prevOffset [ 0 ] ;
}
} else {
seqState - > prevOffset [ 2 ] = seqState - > prevOffset [ 1 ] ;
seqState - > prevOffset [ 1 ] = seqState - > prevOffset [ 0 ] ;
seqState - > prevOffset [ 0 ] = offset ;
}
seq . offset = offset ;
}
seq . matchLength = ML_base [ mlCode ] + ( ( mlCode > 31 ) ? BIT_readBits ( & seqState - > DStream , mlBits ) : 0 ) ; /* <= 16 bits */
if ( MEM_32bits ( ) & & ( mlBits + llBits > 24 ) ) BIT_reloadDStream ( & seqState - > DStream ) ;
seq . litLength = LL_base [ llCode ] + ( ( llCode > 15 ) ? BIT_readBits ( & seqState - > DStream , llBits ) : 0 ) ; /* <= 16 bits */
if ( MEM_32bits ( ) | |
( totalBits > 64 - 7 - ( LLFSELog + MLFSELog + OffFSELog ) ) ) BIT_reloadDStream ( & seqState - > DStream ) ;
/* ANS state update */
FSE_updateState ( & seqState - > stateLL , & seqState - > DStream ) ; /* <= 9 bits */
FSE_updateState ( & seqState - > stateML , & seqState - > DStream ) ; /* <= 9 bits */
if ( MEM_32bits ( ) ) BIT_reloadDStream ( & seqState - > DStream ) ; /* <= 18 bits */
FSE_updateState ( & seqState - > stateOffb , & seqState - > DStream ) ; /* <= 8 bits */
return seq ;
}
FORCE_INLINE
size_t ZSTD_execSequence ( BYTE * op ,
BYTE * const oend , seq_t sequence ,
const BYTE * * litPtr , const BYTE * const litLimit ,
const BYTE * const base , const BYTE * const vBase , const BYTE * const dictEnd )
{
BYTE * const oLitEnd = op + sequence . litLength ;
size_t const sequenceLength = sequence . litLength + sequence . matchLength ;
BYTE * const oMatchEnd = op + sequenceLength ; /* risk : address space overflow (32-bits) */
BYTE * const oend_w = oend - WILDCOPY_OVERLENGTH ;
const BYTE * const iLitEnd = * litPtr + sequence . litLength ;
const BYTE * match = oLitEnd - sequence . offset ;
/* check */
if ( oMatchEnd > oend ) return ERROR ( dstSize_tooSmall ) ; /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
if ( iLitEnd > litLimit ) return ERROR ( corruption_detected ) ; /* over-read beyond lit buffer */
if ( oLitEnd > oend_w ) return ZSTD_execSequenceLast7 ( op , oend , sequence , litPtr , litLimit , base , vBase , dictEnd ) ;
/* copy Literals */
ZSTD_copy8 ( op , * litPtr ) ;
if ( sequence . litLength > 8 )
ZSTD_wildcopy ( op + 8 , ( * litPtr ) + 8 , sequence . litLength - 8 ) ; /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
op = oLitEnd ;
* litPtr = iLitEnd ; /* update for next sequence */
/* copy Match */
if ( sequence . offset > ( size_t ) ( oLitEnd - base ) ) {
/* offset beyond prefix */
if ( sequence . offset > ( size_t ) ( oLitEnd - vBase ) ) return ERROR ( corruption_detected ) ;
2016-11-29 13:12:24 -08:00
match + = ( dictEnd - base ) ;
2016-11-28 16:11:30 -08:00
if ( match + sequence . matchLength < = dictEnd ) {
memmove ( oLitEnd , match , sequence . matchLength ) ;
return sequenceLength ;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match ;
memmove ( oLitEnd , match , length1 ) ;
op = oLitEnd + length1 ;
sequence . matchLength - = length1 ;
match = base ;
if ( op > oend_w ) {
U32 i ;
for ( i = 0 ; i < sequence . matchLength ; + + i ) op [ i ] = match [ i ] ;
return sequenceLength ;
}
} }
/* Requirement: op <= oend_w */
/* match within prefix */
if ( sequence . offset < 8 ) {
/* close range match, overlap */
static const U32 dec32table [ ] = { 0 , 1 , 2 , 1 , 4 , 4 , 4 , 4 } ; /* added */
static const int dec64table [ ] = { 8 , 8 , 8 , 7 , 8 , 9 , 10 , 11 } ; /* substracted */
int const sub2 = dec64table [ sequence . offset ] ;
op [ 0 ] = match [ 0 ] ;
op [ 1 ] = match [ 1 ] ;
op [ 2 ] = match [ 2 ] ;
op [ 3 ] = match [ 3 ] ;
match + = dec32table [ sequence . offset ] ;
ZSTD_copy4 ( op + 4 , match ) ;
match - = sub2 ;
} else {
ZSTD_copy8 ( op , match ) ;
}
op + = 8 ; match + = 8 ;
if ( oMatchEnd > oend - ( 16 - MINMATCH ) ) {
if ( op < oend_w ) {
ZSTD_wildcopy ( op , match , oend_w - op ) ;
match + = oend_w - op ;
op = oend_w ;
}
while ( op < oMatchEnd ) * op + + = * match + + ;
} else {
ZSTD_wildcopy ( op , match , sequence . matchLength - 8 ) ; /* works even if matchLength < 8 */
}
return sequenceLength ;
}
static size_t ZSTD_decompressSequences (
2016-11-28 15:50:16 -08:00
ZSTD_DCtx * dctx ,
void * dst , size_t maxDstSize ,
const void * seqStart , size_t seqSize )
{
const BYTE * ip = ( const BYTE * ) seqStart ;
const BYTE * const iend = ip + seqSize ;
BYTE * const ostart = ( BYTE * const ) dst ;
BYTE * const oend = ostart + maxDstSize ;
BYTE * op = ostart ;
const BYTE * litPtr = dctx - > litPtr ;
const BYTE * const litEnd = litPtr + dctx - > litSize ;
const BYTE * const base = ( const BYTE * ) ( dctx - > base ) ;
const BYTE * const vBase = ( const BYTE * ) ( dctx - > vBase ) ;
const BYTE * const dictEnd = ( const BYTE * ) ( dctx - > dictEnd ) ;
int nbSeq ;
/* Build Decoding Tables */
{ size_t const seqHSize = ZSTD_decodeSeqHeaders ( dctx , & nbSeq , ip , seqSize ) ;
if ( ZSTD_isError ( seqHSize ) ) return seqHSize ;
ip + = seqHSize ;
}
/* Regen sequences */
if ( nbSeq ) {
2015-11-11 04:43:58 -08:00
seqState_t seqState ;
2016-06-13 16:49:25 -07:00
dctx - > fseEntropy = 1 ;
2016-07-30 02:43:53 -07:00
{ U32 i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) seqState . prevOffset [ i ] = dctx - > rep [ i ] ; }
2016-09-13 07:52:16 -07:00
CHECK_E ( BIT_initDStream ( & seqState . DStream , ip , iend - ip ) , corruption_detected ) ;
FSE_initDState ( & seqState . stateLL , & seqState . DStream , dctx - > LLTptr ) ;
FSE_initDState ( & seqState . stateOffb , & seqState . DStream , dctx - > OFTptr ) ;
FSE_initDState ( & seqState . stateML , & seqState . DStream , dctx - > MLTptr ) ;
2015-11-11 04:43:58 -08:00
2016-11-28 16:11:30 -08:00
for ( ; ( BIT_reloadDStream ( & ( seqState . DStream ) ) < = BIT_DStream_completed ) & & nbSeq ; ) {
nbSeq - - ;
{ seq_t const sequence = ZSTD_decodeSequence ( & seqState ) ;
size_t const oneSeqSize = ZSTD_execSequence ( op , oend , sequence , & litPtr , litEnd , base , vBase , dictEnd ) ;
if ( ZSTD_isError ( oneSeqSize ) ) return oneSeqSize ;
op + = oneSeqSize ;
} }
2015-11-19 08:13:19 -08:00
2016-11-28 16:11:30 -08:00
/* check if reached exact end */
if ( nbSeq ) return ERROR ( corruption_detected ) ;
2016-06-13 16:49:25 -07:00
/* save reps for next block */
2016-07-30 02:43:53 -07:00
{ U32 i ; for ( i = 0 ; i < ZSTD_REP_NUM ; i + + ) dctx - > rep [ i ] = ( U32 ) ( seqState . prevOffset [ i ] ) ; }
2016-01-30 15:58:06 -08:00
}
2015-11-19 08:13:19 -08:00
2016-01-30 15:58:06 -08:00
/* last literal segment */
2016-03-19 06:14:31 -07:00
{ size_t const lastLLSize = litEnd - litPtr ;
2016-06-19 05:27:21 -07:00
if ( lastLLSize > ( size_t ) ( oend - op ) ) return ERROR ( dstSize_tooSmall ) ;
2016-01-30 15:58:06 -08:00
memcpy ( op , litPtr , lastLLSize ) ;
op + = lastLLSize ;
}
2015-11-11 04:43:58 -08:00
return op - ostart ;
}
2016-01-08 17:00:10 -08:00
static void ZSTD_checkContinuity ( ZSTD_DCtx * dctx , const void * dst )
{
2016-01-26 06:58:49 -08:00
if ( dst ! = dctx - > previousDstEnd ) { /* not contiguous */
2016-01-08 17:00:10 -08:00
dctx - > dictEnd = dctx - > previousDstEnd ;
dctx - > vBase = ( const char * ) dst - ( ( const char * ) ( dctx - > previousDstEnd ) - ( const char * ) ( dctx - > base ) ) ;
dctx - > base = dst ;
dctx - > previousDstEnd = dst ;
}
}
static size_t ZSTD_decompressBlock_internal ( ZSTD_DCtx * dctx ,
2016-02-03 03:39:34 -08:00
void * dst , size_t dstCapacity ,
2015-11-11 04:43:58 -08:00
const void * src , size_t srcSize )
2016-02-03 03:39:34 -08:00
{ /* blockType == blockCompressed */
2015-11-11 04:43:58 -08:00
const BYTE * ip = ( const BYTE * ) src ;
2016-02-03 03:39:34 -08:00
2016-07-18 07:52:10 -07:00
if ( srcSize > = ZSTD_BLOCKSIZE_ABSOLUTEMAX ) return ERROR ( srcSize_wrong ) ;
2015-11-11 04:43:58 -08:00
/* Decode literals sub-block */
2016-04-07 17:02:12 -07:00
{ size_t const litCSize = ZSTD_decodeLiteralsBlock ( dctx , src , srcSize ) ;
if ( ZSTD_isError ( litCSize ) ) return litCSize ;
ip + = litCSize ;
srcSize - = litCSize ;
}
2016-11-28 18:38:52 -08:00
if ( dctx - > fParams . windowSize > 23 )
return ZSTD_decompressSequencesLong ( dctx , dst , dstCapacity , ip , srcSize ) ;
2016-02-03 03:39:34 -08:00
return ZSTD_decompressSequences ( dctx , dst , dstCapacity , ip , srcSize ) ;
2015-11-11 04:43:58 -08:00
}
2016-01-08 17:00:10 -08:00
size_t ZSTD_decompressBlock ( ZSTD_DCtx * dctx ,
2016-02-03 03:39:34 -08:00
void * dst , size_t dstCapacity ,
2016-01-08 17:00:10 -08:00
const void * src , size_t srcSize )
{
2016-06-26 16:31:35 -07:00
size_t dSize ;
2016-01-08 17:00:10 -08:00
ZSTD_checkContinuity ( dctx , dst ) ;
2016-06-26 16:31:35 -07:00
dSize = ZSTD_decompressBlock_internal ( dctx , dst , dstCapacity , src , srcSize ) ;
dctx - > previousDstEnd = ( char * ) dst + dSize ;
return dSize ;
2016-01-08 17:00:10 -08:00
}
2016-07-06 11:30:52 -07:00
/** ZSTD_insertBlock() :
insert ` src ` block into ` dctx ` history . Useful to track uncompressed blocks . */
ZSTDLIB_API size_t ZSTD_insertBlock ( ZSTD_DCtx * dctx , const void * blockStart , size_t blockSize )
{
ZSTD_checkContinuity ( dctx , blockStart ) ;
dctx - > previousDstEnd = ( const char * ) blockStart + blockSize ;
return blockSize ;
}
2016-07-10 18:12:17 -07:00
size_t ZSTD_generateNxBytes ( void * dst , size_t dstCapacity , BYTE byte , size_t length )
2016-06-06 10:52:35 -07:00
{
if ( length > dstCapacity ) return ERROR ( dstSize_tooSmall ) ;
memset ( dst , byte , length ) ;
return length ;
}
2016-05-06 07:43:23 -07:00
/*! ZSTD_decompressFrame() :
* ` dctx ` must be properly initialized */
2016-03-11 12:58:04 -08:00
static size_t ZSTD_decompressFrame ( ZSTD_DCtx * dctx ,
2016-03-19 06:14:31 -07:00
void * dst , size_t dstCapacity ,
2016-01-26 06:58:49 -08:00
const void * src , size_t srcSize )
2015-11-11 04:43:58 -08:00
{
const BYTE * ip = ( const BYTE * ) src ;
BYTE * const ostart = ( BYTE * const ) dst ;
2016-03-19 06:14:31 -07:00
BYTE * const oend = ostart + dstCapacity ;
2016-06-03 06:41:51 -07:00
BYTE * op = ostart ;
2015-11-11 04:43:58 -08:00
size_t remainingSize = srcSize ;
2016-03-19 06:14:31 -07:00
/* check */
if ( srcSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize ) return ERROR ( srcSize_wrong ) ;
/* Frame Header */
2016-09-05 10:47:43 -07:00
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize ( src , ZSTD_frameHeaderSize_prefix ) ;
2015-11-25 05:42:45 -08:00
if ( ZSTD_isError ( frameHeaderSize ) ) return frameHeaderSize ;
if ( srcSize < frameHeaderSize + ZSTD_blockHeaderSize ) return ERROR ( srcSize_wrong ) ;
2016-09-06 06:36:19 -07:00
CHECK_F ( ZSTD_decodeFrameHeader ( dctx , src , frameHeaderSize ) ) ;
2015-11-25 05:42:45 -08:00
ip + = frameHeaderSize ; remainingSize - = frameHeaderSize ;
}
2015-11-11 04:43:58 -08:00
/* Loop on each block */
2016-03-19 06:14:31 -07:00
while ( 1 ) {
2016-06-10 15:23:43 -07:00
size_t decodedSize ;
2016-06-03 06:41:51 -07:00
blockProperties_t blockProperties ;
2016-07-26 10:42:20 -07:00
size_t const cBlockSize = ZSTD_getcBlockSize ( ip , remainingSize , & blockProperties ) ;
2015-11-11 04:43:58 -08:00
if ( ZSTD_isError ( cBlockSize ) ) return cBlockSize ;
ip + = ZSTD_blockHeaderSize ;
remainingSize - = ZSTD_blockHeaderSize ;
if ( cBlockSize > remainingSize ) return ERROR ( srcSize_wrong ) ;
switch ( blockProperties . blockType )
{
case bt_compressed :
2016-01-25 07:54:05 -08:00
decodedSize = ZSTD_decompressBlock_internal ( dctx , op , oend - op , ip , cBlockSize ) ;
2015-11-11 04:43:58 -08:00
break ;
case bt_raw :
2015-11-12 07:19:30 -08:00
decodedSize = ZSTD_copyRawBlock ( op , oend - op , ip , cBlockSize ) ;
2015-11-11 04:43:58 -08:00
break ;
case bt_rle :
2016-07-10 18:12:17 -07:00
decodedSize = ZSTD_generateNxBytes ( op , oend - op , * ip , blockProperties . origSize ) ;
2015-11-11 04:43:58 -08:00
break ;
2016-07-27 15:55:43 -07:00
case bt_reserved :
2015-11-11 04:43:58 -08:00
default :
2016-07-27 15:55:43 -07:00
return ERROR ( corruption_detected ) ;
2015-11-11 04:43:58 -08:00
}
if ( ZSTD_isError ( decodedSize ) ) return decodedSize ;
2016-05-31 15:18:28 -07:00
if ( dctx - > fParams . checksumFlag ) XXH64_update ( & dctx - > xxhState , op , decodedSize ) ;
2015-11-11 04:43:58 -08:00
op + = decodedSize ;
ip + = cBlockSize ;
remainingSize - = cBlockSize ;
2016-07-27 15:55:43 -07:00
if ( blockProperties . lastBlock ) break ;
2015-11-11 04:43:58 -08:00
}
2016-07-27 15:55:43 -07:00
if ( dctx - > fParams . checksumFlag ) { /* Frame content checksum verification */
U32 const checkCalc = ( U32 ) XXH64_digest ( & dctx - > xxhState ) ;
U32 checkRead ;
if ( remainingSize < 4 ) return ERROR ( checksum_wrong ) ;
checkRead = MEM_readLE32 ( ip ) ;
if ( checkRead ! = checkCalc ) return ERROR ( checksum_wrong ) ;
remainingSize - = 4 ;
}
if ( remainingSize ) return ERROR ( srcSize_wrong ) ;
2015-11-11 04:43:58 -08:00
return op - ostart ;
}
2015-12-17 16:26:48 -08:00
2016-01-26 06:58:49 -08:00
size_t ZSTD_decompress_usingDict ( ZSTD_DCtx * dctx ,
2016-03-19 06:14:31 -07:00
void * dst , size_t dstCapacity ,
2016-09-13 07:52:16 -07:00
const void * src , size_t srcSize ,
const void * dict , size_t dictSize )
2016-01-26 06:58:49 -08:00
{
2016-05-06 07:43:23 -07:00
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
2016-07-07 05:40:13 -07:00
if ( ZSTD_isLegacy ( src , srcSize ) ) return ZSTD_decompressLegacy ( dst , dstCapacity , src , srcSize , dict , dictSize ) ;
2016-05-06 07:43:23 -07:00
# endif
2016-01-26 06:58:49 -08:00
ZSTD_decompressBegin_usingDict ( dctx , dict , dictSize ) ;
ZSTD_checkContinuity ( dctx , dst ) ;
2016-03-19 06:14:31 -07:00
return ZSTD_decompressFrame ( dctx , dst , dstCapacity , src , srcSize ) ;
2016-01-26 06:58:49 -08:00
}
2016-03-19 06:14:31 -07:00
size_t ZSTD_decompressDCtx ( ZSTD_DCtx * dctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-12-17 16:26:48 -08:00
{
2016-03-19 06:14:31 -07:00
return ZSTD_decompress_usingDict ( dctx , dst , dstCapacity , src , srcSize , NULL , 0 ) ;
2015-12-17 16:26:48 -08:00
}
2016-03-11 12:58:04 -08:00
2016-03-19 06:14:31 -07:00
size_t ZSTD_decompress ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-11 04:43:58 -08:00
{
2016-01-11 03:56:11 -08:00
# if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
size_t regenSize ;
2016-06-03 06:41:51 -07:00
ZSTD_DCtx * const dctx = ZSTD_createDCtx ( ) ;
2016-01-11 03:56:11 -08:00
if ( dctx = = NULL ) return ERROR ( memory_allocation ) ;
2016-03-19 06:14:31 -07:00
regenSize = ZSTD_decompressDCtx ( dctx , dst , dstCapacity , src , srcSize ) ;
2016-01-11 03:56:11 -08:00
ZSTD_freeDCtx ( dctx ) ;
return regenSize ;
2016-05-06 07:43:23 -07:00
# else /* stack mode */
2015-12-17 16:26:48 -08:00
ZSTD_DCtx dctx ;
2016-03-19 06:14:31 -07:00
return ZSTD_decompressDCtx ( & dctx , dst , dstCapacity , src , srcSize ) ;
2016-01-21 07:04:35 -08:00
# endif
2015-11-11 04:43:58 -08:00
}
2016-08-22 15:30:31 -07:00
/*-**************************************
* Advanced Streaming Decompression API
* Bufferless and synchronous
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-07-28 10:55:09 -07:00
size_t ZSTD_nextSrcSizeToDecompress ( ZSTD_DCtx * dctx ) { return dctx - > expected ; }
2015-11-11 04:43:58 -08:00
2016-07-28 11:30:25 -07:00
ZSTD_nextInputType_e ZSTD_nextInputType ( ZSTD_DCtx * dctx ) {
switch ( dctx - > stage )
{
default : /* should not happen */
case ZSTDds_getFrameHeaderSize :
case ZSTDds_decodeFrameHeader :
return ZSTDnit_frameHeader ;
case ZSTDds_decodeBlockHeader :
return ZSTDnit_blockHeader ;
case ZSTDds_decompressBlock :
return ZSTDnit_block ;
case ZSTDds_decompressLastBlock :
return ZSTDnit_lastBlock ;
case ZSTDds_checkChecksum :
return ZSTDnit_checksum ;
case ZSTDds_decodeSkippableHeader :
case ZSTDds_skipFrame :
return ZSTDnit_skippableFrame ;
}
}
2016-07-28 10:55:09 -07:00
int ZSTD_isSkipFrame ( ZSTD_DCtx * dctx ) { return dctx - > stage = = ZSTDds_skipFrame ; } /* for zbuff */
2016-05-31 03:43:46 -07:00
2016-05-31 09:13:56 -07:00
/** ZSTD_decompressContinue() :
* @ return : nb of bytes generated into ` dst ` ( necessarily < = ` dstCapacity )
* or an error code , which can be tested using ZSTD_isError ( ) */
2016-05-10 05:14:19 -07:00
size_t ZSTD_decompressContinue ( ZSTD_DCtx * dctx , void * dst , size_t dstCapacity , const void * src , size_t srcSize )
2015-11-11 04:43:58 -08:00
{
/* Sanity check */
2016-01-25 07:54:05 -08:00
if ( srcSize ! = dctx - > expected ) return ERROR ( srcSize_wrong ) ;
2016-05-10 05:14:19 -07:00
if ( dstCapacity ) ZSTD_checkContinuity ( dctx , dst ) ;
2015-11-11 04:43:58 -08:00
2016-01-25 07:54:05 -08:00
switch ( dctx - > stage )
2015-11-11 04:43:58 -08:00
{
2015-11-25 05:42:45 -08:00
case ZSTDds_getFrameHeaderSize :
2016-09-05 10:47:43 -07:00
if ( srcSize ! = ZSTD_frameHeaderSize_prefix ) return ERROR ( srcSize_wrong ) ; /* impossible */
if ( ( MEM_readLE32 ( src ) & 0xFFFFFFF0U ) = = ZSTD_MAGIC_SKIPPABLE_START ) { /* skippable frame */
memcpy ( dctx - > headerBuffer , src , ZSTD_frameHeaderSize_prefix ) ;
dctx - > expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix ; /* magic number + skippable frame length */
2016-05-31 03:43:46 -07:00
dctx - > stage = ZSTDds_decodeSkippableHeader ;
return 0 ;
}
2016-09-05 10:47:43 -07:00
dctx - > headerSize = ZSTD_frameHeaderSize ( src , ZSTD_frameHeaderSize_prefix ) ;
2016-05-10 05:14:19 -07:00
if ( ZSTD_isError ( dctx - > headerSize ) ) return dctx - > headerSize ;
2016-09-05 10:47:43 -07:00
memcpy ( dctx - > headerBuffer , src , ZSTD_frameHeaderSize_prefix ) ;
if ( dctx - > headerSize > ZSTD_frameHeaderSize_prefix ) {
dctx - > expected = dctx - > headerSize - ZSTD_frameHeaderSize_prefix ;
2016-05-10 05:14:19 -07:00
dctx - > stage = ZSTDds_decodeFrameHeader ;
return 0 ;
2015-11-11 04:43:58 -08:00
}
2016-05-10 05:14:19 -07:00
dctx - > expected = 0 ; /* not necessary to copy more */
2015-11-25 05:42:45 -08:00
case ZSTDds_decodeFrameHeader :
2016-09-06 06:36:19 -07:00
memcpy ( dctx - > headerBuffer + ZSTD_frameHeaderSize_prefix , src , dctx - > expected ) ;
CHECK_F ( ZSTD_decodeFrameHeader ( dctx , dctx - > headerBuffer , dctx - > headerSize ) ) ;
dctx - > expected = ZSTD_blockHeaderSize ;
dctx - > stage = ZSTDds_decodeBlockHeader ;
return 0 ;
2015-11-25 05:42:45 -08:00
case ZSTDds_decodeBlockHeader :
2016-05-10 05:14:19 -07:00
{ blockProperties_t bp ;
2016-03-23 17:27:55 -07:00
size_t const cBlockSize = ZSTD_getcBlockSize ( src , ZSTD_blockHeaderSize , & bp ) ;
if ( ZSTD_isError ( cBlockSize ) ) return cBlockSize ;
2016-07-27 15:55:43 -07:00
dctx - > expected = cBlockSize ;
dctx - > bType = bp . blockType ;
dctx - > rleSize = bp . origSize ;
if ( cBlockSize ) {
dctx - > stage = bp . lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock ;
return 0 ;
}
/* empty block */
if ( bp . lastBlock ) {
2016-05-31 15:18:28 -07:00
if ( dctx - > fParams . checksumFlag ) {
2016-07-27 15:55:43 -07:00
dctx - > expected = 4 ;
dctx - > stage = ZSTDds_checkChecksum ;
} else {
dctx - > expected = 0 ; /* end of frame */
dctx - > stage = ZSTDds_getFrameHeaderSize ;
2016-05-31 15:18:28 -07:00
}
2016-03-23 17:27:55 -07:00
} else {
2016-07-27 15:55:43 -07:00
dctx - > expected = 3 ; /* go directly to next header */
dctx - > stage = ZSTDds_decodeBlockHeader ;
2015-11-25 05:42:45 -08:00
}
return 0 ;
}
2016-07-27 15:55:43 -07:00
case ZSTDds_decompressLastBlock :
2015-12-04 08:16:37 -08:00
case ZSTDds_decompressBlock :
2016-05-10 05:14:19 -07:00
{ size_t rSize ;
2016-01-25 07:54:05 -08:00
switch ( dctx - > bType )
2015-11-25 05:42:45 -08:00
{
case bt_compressed :
2016-05-10 05:14:19 -07:00
rSize = ZSTD_decompressBlock_internal ( dctx , dst , dstCapacity , src , srcSize ) ;
2015-11-25 05:42:45 -08:00
break ;
case bt_raw :
2016-05-10 05:14:19 -07:00
rSize = ZSTD_copyRawBlock ( dst , dstCapacity , src , srcSize ) ;
2015-11-25 05:42:45 -08:00
break ;
case bt_rle :
2016-07-27 15:55:43 -07:00
rSize = ZSTD_setRleBlock ( dst , dstCapacity , src , srcSize , dctx - > rleSize ) ;
2015-11-25 05:42:45 -08:00
break ;
2016-07-27 15:55:43 -07:00
case bt_reserved : /* should never happen */
2015-11-25 05:42:45 -08:00
default :
2016-07-27 15:55:43 -07:00
return ERROR ( corruption_detected ) ;
2015-11-25 05:42:45 -08:00
}
2016-05-31 15:44:36 -07:00
if ( ZSTD_isError ( rSize ) ) return rSize ;
2016-05-31 15:18:28 -07:00
if ( dctx - > fParams . checksumFlag ) XXH64_update ( & dctx - > xxhState , dst , rSize ) ;
2016-07-27 15:55:43 -07:00
if ( dctx - > stage = = ZSTDds_decompressLastBlock ) { /* end of frame */
if ( dctx - > fParams . checksumFlag ) { /* another round for frame checksum */
2016-07-28 10:55:09 -07:00
dctx - > expected = 4 ;
2016-07-27 15:55:43 -07:00
dctx - > stage = ZSTDds_checkChecksum ;
2016-07-28 10:55:09 -07:00
} else {
dctx - > expected = 0 ; /* ends here */
dctx - > stage = ZSTDds_getFrameHeaderSize ;
2016-07-27 15:55:43 -07:00
}
} else {
dctx - > stage = ZSTDds_decodeBlockHeader ;
dctx - > expected = ZSTD_blockHeaderSize ;
dctx - > previousDstEnd = ( char * ) dst + rSize ;
}
2015-11-25 05:42:45 -08:00
return rSize ;
2015-11-11 04:43:58 -08:00
}
2016-07-27 15:55:43 -07:00
case ZSTDds_checkChecksum :
{ U32 const h32 = ( U32 ) XXH64_digest ( & dctx - > xxhState ) ;
U32 const check32 = MEM_readLE32 ( src ) ; /* srcSize == 4, guaranteed by dctx->expected */
if ( check32 ! = h32 ) return ERROR ( checksum_wrong ) ;
dctx - > expected = 0 ;
dctx - > stage = ZSTDds_getFrameHeaderSize ;
return 0 ;
}
2016-05-31 03:43:46 -07:00
case ZSTDds_decodeSkippableHeader :
2016-09-05 10:47:43 -07:00
{ memcpy ( dctx - > headerBuffer + ZSTD_frameHeaderSize_prefix , src , dctx - > expected ) ;
2016-05-31 03:43:46 -07:00
dctx - > expected = MEM_readLE32 ( dctx - > headerBuffer + 4 ) ;
dctx - > stage = ZSTDds_skipFrame ;
return 0 ;
}
case ZSTDds_skipFrame :
2016-05-31 10:36:51 -07:00
{ dctx - > expected = 0 ;
2016-05-31 03:43:46 -07:00
dctx - > stage = ZSTDds_getFrameHeaderSize ;
return 0 ;
}
2015-11-25 05:42:45 -08:00
default :
return ERROR ( GENERIC ) ; /* impossible */
2015-11-11 04:43:58 -08:00
}
}
2016-06-19 14:06:54 -07:00
static size_t ZSTD_refDictContent ( ZSTD_DCtx * dctx , const void * dict , size_t dictSize )
2015-12-04 08:16:37 -08:00
{
2016-01-25 07:54:05 -08:00
dctx - > dictEnd = dctx - > previousDstEnd ;
dctx - > vBase = ( const char * ) dict - ( ( const char * ) ( dctx - > previousDstEnd ) - ( const char * ) ( dctx - > base ) ) ;
dctx - > base = dict ;
dctx - > previousDstEnd = ( const char * ) dict + dictSize ;
2016-06-19 14:06:54 -07:00
return 0 ;
2015-12-04 08:16:37 -08:00
}
2016-01-25 18:14:20 -08:00
2016-06-15 09:48:51 -07:00
static size_t ZSTD_loadEntropy ( ZSTD_DCtx * dctx , const void * const dict , size_t const dictSize )
2016-01-25 18:14:20 -08:00
{
2016-06-15 05:05:07 -07:00
const BYTE * dictPtr = ( const BYTE * ) dict ;
2016-06-15 16:41:50 -07:00
const BYTE * const dictEnd = dictPtr + dictSize ;
2016-01-27 15:18:06 -08:00
2016-06-08 02:11:02 -07:00
{ size_t const hSize = HUF_readDTableX4 ( dctx - > hufTable , dict , dictSize ) ;
2016-05-31 15:18:28 -07:00
if ( HUF_isError ( hSize ) ) return ERROR ( dictionary_corrupted ) ;
2016-06-15 05:05:07 -07:00
dictPtr + = hSize ;
2016-05-31 15:18:28 -07:00
}
2016-01-27 15:18:06 -08:00
2016-05-06 07:43:23 -07:00
{ short offcodeNCount [ MaxOff + 1 ] ;
Fix buffer overrun in ZSTD_loadEntropy()
The table log set by `FSE_readNCount()` was not checked in
`ZSTD_loadEntropy()`. This caused `FSE_buildDTable(dctx->MLTable, ...)`
to overwrite the beginning of `dctx->hufTable`.
The benchmarks look good, there is no obvious performance regression:
> ./zstds/zstd.opt.0 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 268.2 MB/s , 701.0 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.5 MB/s , 666.9 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 154.9 MB/s , 655.6 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 128.9 MB/s , 648.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 98.4 MB/s , 633.4 MB/s
> ./zstds/zstd.opt.2 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 266.1 MB/s , 703.7 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.0 MB/s , 666.6 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 156.2 MB/s , 656.2 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 133.2 MB/s , 647.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 96.3 MB/s , 633.3 MB/s
2016-10-17 15:49:50 -07:00
U32 offcodeMaxValue = MaxOff , offcodeLog ;
2016-06-15 05:05:07 -07:00
size_t const offcodeHeaderSize = FSE_readNCount ( offcodeNCount , & offcodeMaxValue , & offcodeLog , dictPtr , dictEnd - dictPtr ) ;
2016-05-06 07:43:23 -07:00
if ( FSE_isError ( offcodeHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
Fix buffer overrun in ZSTD_loadEntropy()
The table log set by `FSE_readNCount()` was not checked in
`ZSTD_loadEntropy()`. This caused `FSE_buildDTable(dctx->MLTable, ...)`
to overwrite the beginning of `dctx->hufTable`.
The benchmarks look good, there is no obvious performance regression:
> ./zstds/zstd.opt.0 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 268.2 MB/s , 701.0 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.5 MB/s , 666.9 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 154.9 MB/s , 655.6 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 128.9 MB/s , 648.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 98.4 MB/s , 633.4 MB/s
> ./zstds/zstd.opt.2 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 266.1 MB/s , 703.7 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.0 MB/s , 666.6 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 156.2 MB/s , 656.2 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 133.2 MB/s , 647.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 96.3 MB/s , 633.3 MB/s
2016-10-17 15:49:50 -07:00
if ( offcodeLog > OffFSELog ) return ERROR ( dictionary_corrupted ) ;
2016-09-13 07:52:16 -07:00
CHECK_E ( FSE_buildDTable ( dctx - > OFTable , offcodeNCount , offcodeMaxValue , offcodeLog ) , dictionary_corrupted ) ;
2016-06-15 05:05:07 -07:00
dictPtr + = offcodeHeaderSize ;
2016-05-06 07:43:23 -07:00
}
{ short matchlengthNCount [ MaxML + 1 ] ;
Fix buffer overrun in ZSTD_loadEntropy()
The table log set by `FSE_readNCount()` was not checked in
`ZSTD_loadEntropy()`. This caused `FSE_buildDTable(dctx->MLTable, ...)`
to overwrite the beginning of `dctx->hufTable`.
The benchmarks look good, there is no obvious performance regression:
> ./zstds/zstd.opt.0 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 268.2 MB/s , 701.0 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.5 MB/s , 666.9 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 154.9 MB/s , 655.6 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 128.9 MB/s , 648.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 98.4 MB/s , 633.4 MB/s
> ./zstds/zstd.opt.2 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 266.1 MB/s , 703.7 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.0 MB/s , 666.6 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 156.2 MB/s , 656.2 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 133.2 MB/s , 647.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 96.3 MB/s , 633.3 MB/s
2016-10-17 15:49:50 -07:00
unsigned matchlengthMaxValue = MaxML , matchlengthLog ;
2016-06-15 05:05:07 -07:00
size_t const matchlengthHeaderSize = FSE_readNCount ( matchlengthNCount , & matchlengthMaxValue , & matchlengthLog , dictPtr , dictEnd - dictPtr ) ;
2016-05-06 07:43:23 -07:00
if ( FSE_isError ( matchlengthHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
Fix buffer overrun in ZSTD_loadEntropy()
The table log set by `FSE_readNCount()` was not checked in
`ZSTD_loadEntropy()`. This caused `FSE_buildDTable(dctx->MLTable, ...)`
to overwrite the beginning of `dctx->hufTable`.
The benchmarks look good, there is no obvious performance regression:
> ./zstds/zstd.opt.0 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 268.2 MB/s , 701.0 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.5 MB/s , 666.9 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 154.9 MB/s , 655.6 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 128.9 MB/s , 648.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 98.4 MB/s , 633.4 MB/s
> ./zstds/zstd.opt.2 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 266.1 MB/s , 703.7 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.0 MB/s , 666.6 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 156.2 MB/s , 656.2 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 133.2 MB/s , 647.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 96.3 MB/s , 633.3 MB/s
2016-10-17 15:49:50 -07:00
if ( matchlengthLog > MLFSELog ) return ERROR ( dictionary_corrupted ) ;
2016-09-06 07:38:51 -07:00
CHECK_E ( FSE_buildDTable ( dctx - > MLTable , matchlengthNCount , matchlengthMaxValue , matchlengthLog ) , dictionary_corrupted ) ;
2016-06-15 05:05:07 -07:00
dictPtr + = matchlengthHeaderSize ;
2016-05-06 07:43:23 -07:00
}
{ short litlengthNCount [ MaxLL + 1 ] ;
Fix buffer overrun in ZSTD_loadEntropy()
The table log set by `FSE_readNCount()` was not checked in
`ZSTD_loadEntropy()`. This caused `FSE_buildDTable(dctx->MLTable, ...)`
to overwrite the beginning of `dctx->hufTable`.
The benchmarks look good, there is no obvious performance regression:
> ./zstds/zstd.opt.0 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 268.2 MB/s , 701.0 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.5 MB/s , 666.9 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 154.9 MB/s , 655.6 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 128.9 MB/s , 648.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 98.4 MB/s , 633.4 MB/s
> ./zstds/zstd.opt.2 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 266.1 MB/s , 703.7 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.0 MB/s , 666.6 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 156.2 MB/s , 656.2 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 133.2 MB/s , 647.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 96.3 MB/s , 633.3 MB/s
2016-10-17 15:49:50 -07:00
unsigned litlengthMaxValue = MaxLL , litlengthLog ;
2016-06-15 05:05:07 -07:00
size_t const litlengthHeaderSize = FSE_readNCount ( litlengthNCount , & litlengthMaxValue , & litlengthLog , dictPtr , dictEnd - dictPtr ) ;
2016-05-06 07:43:23 -07:00
if ( FSE_isError ( litlengthHeaderSize ) ) return ERROR ( dictionary_corrupted ) ;
Fix buffer overrun in ZSTD_loadEntropy()
The table log set by `FSE_readNCount()` was not checked in
`ZSTD_loadEntropy()`. This caused `FSE_buildDTable(dctx->MLTable, ...)`
to overwrite the beginning of `dctx->hufTable`.
The benchmarks look good, there is no obvious performance regression:
> ./zstds/zstd.opt.0 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 268.2 MB/s , 701.0 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.5 MB/s , 666.9 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 154.9 MB/s , 655.6 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 128.9 MB/s , 648.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 98.4 MB/s , 633.4 MB/s
> ./zstds/zstd.opt.2 -i10 -b1 -e5 ~/bench/silesia.tar
1#silesia.tar : 211988480 -> 73656930 (2.878), 266.1 MB/s , 703.7 MB/s
2#silesia.tar : 211988480 -> 70162842 (3.021), 199.0 MB/s , 666.6 MB/s
3#silesia.tar : 211988480 -> 66997986 (3.164), 156.2 MB/s , 656.2 MB/s
4#silesia.tar : 211988480 -> 66002591 (3.212), 133.2 MB/s , 647.4 MB/s
5#silesia.tar : 211988480 -> 65008480 (3.261), 96.3 MB/s , 633.3 MB/s
2016-10-17 15:49:50 -07:00
if ( litlengthLog > LLFSELog ) return ERROR ( dictionary_corrupted ) ;
2016-09-06 07:38:51 -07:00
CHECK_E ( FSE_buildDTable ( dctx - > LLTable , litlengthNCount , litlengthMaxValue , litlengthLog ) , dictionary_corrupted ) ;
2016-06-15 05:05:07 -07:00
dictPtr + = litlengthHeaderSize ;
2016-05-06 07:43:23 -07:00
}
2016-01-27 15:18:06 -08:00
2016-06-15 09:48:51 -07:00
if ( dictPtr + 12 > dictEnd ) return ERROR ( dictionary_corrupted ) ;
dctx - > rep [ 0 ] = MEM_readLE32 ( dictPtr + 0 ) ; if ( dctx - > rep [ 0 ] > = dictSize ) return ERROR ( dictionary_corrupted ) ;
dctx - > rep [ 1 ] = MEM_readLE32 ( dictPtr + 4 ) ; if ( dctx - > rep [ 1 ] > = dictSize ) return ERROR ( dictionary_corrupted ) ;
dctx - > rep [ 2 ] = MEM_readLE32 ( dictPtr + 8 ) ; if ( dctx - > rep [ 2 ] > = dictSize ) return ERROR ( dictionary_corrupted ) ;
2016-06-15 05:05:07 -07:00
dictPtr + = 12 ;
2016-06-10 17:52:42 -07:00
dctx - > litEntropy = dctx - > fseEntropy = 1 ;
2016-06-15 05:05:07 -07:00
return dictPtr - ( const BYTE * ) dict ;
2016-01-25 18:14:20 -08:00
}
2016-01-26 06:58:49 -08:00
static size_t ZSTD_decompress_insertDictionary ( ZSTD_DCtx * dctx , const void * dict , size_t dictSize )
2016-01-25 18:14:20 -08:00
{
2016-06-19 14:06:54 -07:00
if ( dictSize < 8 ) return ZSTD_refDictContent ( dctx , dict , dictSize ) ;
2016-05-28 20:01:04 -07:00
{ U32 const magic = MEM_readLE32 ( dict ) ;
if ( magic ! = ZSTD_DICT_MAGIC ) {
2016-06-19 14:06:54 -07:00
return ZSTD_refDictContent ( dctx , dict , dictSize ) ; /* pure content mode */
} }
dctx - > dictID = MEM_readLE32 ( ( const char * ) dict + 4 ) ;
/* load entropy tables */
dict = ( const char * ) dict + 8 ;
dictSize - = 8 ;
{ size_t const eSize = ZSTD_loadEntropy ( dctx , dict , dictSize ) ;
if ( ZSTD_isError ( eSize ) ) return ERROR ( dictionary_corrupted ) ;
dict = ( const char * ) dict + eSize ;
dictSize - = eSize ;
2016-01-25 18:14:20 -08:00
}
2016-06-19 14:06:54 -07:00
/* reference dictionary content */
return ZSTD_refDictContent ( dctx , dict , dictSize ) ;
2016-01-25 18:14:20 -08:00
}
2016-01-26 06:58:49 -08:00
size_t ZSTD_decompressBegin_usingDict ( ZSTD_DCtx * dctx , const void * dict , size_t dictSize )
{
2016-09-06 06:36:19 -07:00
CHECK_F ( ZSTD_decompressBegin ( dctx ) ) ;
2016-09-06 07:38:51 -07:00
if ( dict & & dictSize ) CHECK_E ( ZSTD_decompress_insertDictionary ( dctx , dict , dictSize ) , dictionary_corrupted ) ;
2016-01-26 06:58:49 -08:00
return 0 ;
}
2016-06-06 15:51:51 -07:00
2016-09-14 07:55:44 -07:00
/* ====== ZSTD_DDict ====== */
2016-06-06 15:51:51 -07:00
struct ZSTD_DDict_s {
2016-07-08 10:16:57 -07:00
void * dict ;
size_t dictSize ;
2016-06-06 15:51:51 -07:00
ZSTD_DCtx * refContext ;
2016-08-29 09:03:12 -07:00
} ; /* typedef'd to ZSTD_DDict within "zstd.h" */
2016-06-06 15:51:51 -07:00
ZSTD_DDict * ZSTD_createDDict_advanced ( const void * dict , size_t dictSize , ZSTD_customMem customMem )
{
2016-08-28 21:05:43 -07:00
if ( ! customMem . customAlloc & & ! customMem . customFree ) customMem = defaultCustomMem ;
if ( ! customMem . customAlloc | | ! customMem . customFree ) return NULL ;
2016-06-06 15:51:51 -07:00
2016-08-28 21:05:43 -07:00
{ ZSTD_DDict * const ddict = ( ZSTD_DDict * ) ZSTD_malloc ( sizeof ( ZSTD_DDict ) , customMem ) ;
void * const dictContent = ZSTD_malloc ( dictSize , customMem ) ;
2016-06-06 15:51:51 -07:00
ZSTD_DCtx * const dctx = ZSTD_createDCtx_advanced ( customMem ) ;
if ( ! dictContent | | ! ddict | | ! dctx ) {
2016-08-28 21:05:43 -07:00
ZSTD_free ( dictContent , customMem ) ;
ZSTD_free ( ddict , customMem ) ;
ZSTD_free ( dctx , customMem ) ;
2016-06-06 15:51:51 -07:00
return NULL ;
}
2016-10-12 20:54:42 -07:00
if ( dictSize ) {
memcpy ( dictContent , dict , dictSize ) ;
}
2016-06-06 15:51:51 -07:00
{ size_t const errorCode = ZSTD_decompressBegin_usingDict ( dctx , dictContent , dictSize ) ;
if ( ZSTD_isError ( errorCode ) ) {
2016-08-28 21:05:43 -07:00
ZSTD_free ( dictContent , customMem ) ;
ZSTD_free ( ddict , customMem ) ;
ZSTD_free ( dctx , customMem ) ;
2016-06-06 15:51:51 -07:00
return NULL ;
} }
2016-07-08 10:16:57 -07:00
ddict - > dict = dictContent ;
ddict - > dictSize = dictSize ;
2016-06-06 15:51:51 -07:00
ddict - > refContext = dctx ;
return ddict ;
}
}
/*! ZSTD_createDDict() :
2016-06-19 14:06:54 -07:00
* Create a digested dictionary , ready to start decompression without startup delay .
2016-06-09 15:12:26 -07:00
* ` dict ` can be released after ` ZSTD_DDict ` creation */
2016-06-06 15:51:51 -07:00
ZSTD_DDict * ZSTD_createDDict ( const void * dict , size_t dictSize )
{
ZSTD_customMem const allocator = { NULL , NULL , NULL } ;
return ZSTD_createDDict_advanced ( dict , dictSize , allocator ) ;
}
size_t ZSTD_freeDDict ( ZSTD_DDict * ddict )
{
2016-08-28 21:05:43 -07:00
if ( ddict = = NULL ) return 0 ; /* support free on NULL */
{ ZSTD_customMem const cMem = ddict - > refContext - > customMem ;
ZSTD_freeDCtx ( ddict - > refContext ) ;
ZSTD_free ( ddict - > dict , cMem ) ;
ZSTD_free ( ddict , cMem ) ;
return 0 ;
}
2016-06-06 15:51:51 -07:00
}
2016-09-14 07:55:44 -07:00
size_t ZSTD_sizeof_DDict ( const ZSTD_DDict * ddict )
{
2016-09-14 17:50:27 -07:00
if ( ddict = = NULL ) return 0 ; /* support sizeof on NULL */
2016-09-14 07:55:44 -07:00
return sizeof ( * ddict ) + sizeof ( ddict - > refContext ) + ddict - > dictSize ;
}
2016-06-06 15:51:51 -07:00
/*! ZSTD_decompress_usingDDict() :
* Decompression using a pre - digested Dictionary
2016-06-09 15:12:26 -07:00
* Use dictionary without significant overhead . */
2016-09-14 07:55:44 -07:00
size_t ZSTD_decompress_usingDDict ( ZSTD_DCtx * dctx ,
void * dst , size_t dstCapacity ,
const void * src , size_t srcSize ,
const ZSTD_DDict * ddict )
2016-06-06 15:51:51 -07:00
{
2016-07-06 11:30:52 -07:00
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
2016-07-08 10:22:16 -07:00
if ( ZSTD_isLegacy ( src , srcSize ) ) return ZSTD_decompressLegacy ( dst , dstCapacity , src , srcSize , ddict - > dict , ddict - > dictSize ) ;
2016-07-06 11:30:52 -07:00
# endif
2016-09-14 07:55:44 -07:00
ZSTD_refDCtx ( dctx , ddict - > refContext ) ;
ZSTD_checkContinuity ( dctx , dst ) ;
return ZSTD_decompressFrame ( dctx , dst , dstCapacity , src , srcSize ) ;
2016-06-06 15:51:51 -07:00
}
2016-08-12 04:04:27 -07:00
/*=====================================
* Streaming decompression
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
typedef enum { zdss_init , zdss_loadHeader ,
zdss_read , zdss_load , zdss_flush } ZSTD_dStreamStage ;
/* *** Resource management *** */
struct ZSTD_DStream_s {
2016-09-14 07:14:57 -07:00
ZSTD_DCtx * dctx ;
2016-10-25 17:47:02 -07:00
ZSTD_DDict * ddictLocal ;
const ZSTD_DDict * ddict ;
2016-08-12 04:04:27 -07:00
ZSTD_frameParams fParams ;
ZSTD_dStreamStage stage ;
char * inBuff ;
size_t inBuffSize ;
size_t inPos ;
2016-08-23 07:58:10 -07:00
size_t maxWindowSize ;
2016-08-12 04:04:27 -07:00
char * outBuff ;
size_t outBuffSize ;
size_t outStart ;
size_t outEnd ;
size_t blockSize ;
2016-09-14 07:14:57 -07:00
BYTE headerBuffer [ ZSTD_FRAMEHEADERSIZE_MAX ] ; /* tmp buffer to store frame header */
2016-08-12 04:04:27 -07:00
size_t lhSize ;
ZSTD_customMem customMem ;
2016-08-28 07:43:34 -07:00
void * legacyContext ;
2016-08-28 08:19:47 -07:00
U32 previousLegacyVersion ;
2016-08-28 07:43:34 -07:00
U32 legacyVersion ;
2016-09-09 07:44:16 -07:00
U32 hostageByte ;
2016-08-12 04:04:27 -07:00
} ; /* typedef'd to ZSTD_DStream within "zstd.h" */
ZSTD_DStream * ZSTD_createDStream ( void )
{
return ZSTD_createDStream_advanced ( defaultCustomMem ) ;
}
ZSTD_DStream * ZSTD_createDStream_advanced ( ZSTD_customMem customMem )
{
ZSTD_DStream * zds ;
2016-08-28 21:05:43 -07:00
if ( ! customMem . customAlloc & & ! customMem . customFree ) customMem = defaultCustomMem ;
if ( ! customMem . customAlloc | | ! customMem . customFree ) return NULL ;
2016-08-12 04:04:27 -07:00
2016-08-28 21:05:43 -07:00
zds = ( ZSTD_DStream * ) ZSTD_malloc ( sizeof ( ZSTD_DStream ) , customMem ) ;
2016-08-12 04:04:27 -07:00
if ( zds = = NULL ) return NULL ;
memset ( zds , 0 , sizeof ( ZSTD_DStream ) ) ;
memcpy ( & zds - > customMem , & customMem , sizeof ( ZSTD_customMem ) ) ;
2016-09-14 07:14:57 -07:00
zds - > dctx = ZSTD_createDCtx_advanced ( customMem ) ;
if ( zds - > dctx = = NULL ) { ZSTD_freeDStream ( zds ) ; return NULL ; }
2016-08-12 04:04:27 -07:00
zds - > stage = zdss_init ;
2016-08-23 07:58:10 -07:00
zds - > maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT ;
2016-08-12 04:04:27 -07:00
return zds ;
}
size_t ZSTD_freeDStream ( ZSTD_DStream * zds )
{
if ( zds = = NULL ) return 0 ; /* support free on null */
2016-08-28 21:05:43 -07:00
{ ZSTD_customMem const cMem = zds - > customMem ;
2016-09-14 07:14:57 -07:00
ZSTD_freeDCtx ( zds - > dctx ) ;
2016-10-25 17:47:02 -07:00
ZSTD_freeDDict ( zds - > ddictLocal ) ;
2016-08-28 21:05:43 -07:00
ZSTD_free ( zds - > inBuff , cMem ) ;
ZSTD_free ( zds - > outBuff , cMem ) ;
2016-08-28 07:43:34 -07:00
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
2016-08-28 21:05:43 -07:00
if ( zds - > legacyContext )
ZSTD_freeLegacyStreamContext ( zds - > legacyContext , zds - > previousLegacyVersion ) ;
2016-08-28 07:43:34 -07:00
# endif
2016-08-28 21:05:43 -07:00
ZSTD_free ( zds , cMem ) ;
return 0 ;
}
2016-08-12 04:04:27 -07:00
}
/* *** Initialization *** */
size_t ZSTD_DStreamInSize ( void ) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize ; }
size_t ZSTD_DStreamOutSize ( void ) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX ; }
size_t ZSTD_initDStream_usingDict ( ZSTD_DStream * zds , const void * dict , size_t dictSize )
{
zds - > stage = zdss_loadHeader ;
zds - > lhSize = zds - > inPos = zds - > outStart = zds - > outEnd = 0 ;
2016-10-25 17:47:02 -07:00
ZSTD_freeDDict ( zds - > ddictLocal ) ;
if ( dict ) {
zds - > ddictLocal = ZSTD_createDDict ( dict , dictSize ) ;
if ( zds - > ddictLocal = = NULL ) return ERROR ( memory_allocation ) ;
} else zds - > ddictLocal = NULL ;
zds - > ddict = zds - > ddictLocal ;
2016-08-28 07:43:34 -07:00
zds - > legacyVersion = 0 ;
2016-09-09 07:44:16 -07:00
zds - > hostageByte = 0 ;
2016-09-05 10:47:43 -07:00
return ZSTD_frameHeaderSize_prefix ;
2016-08-12 04:04:27 -07:00
}
size_t ZSTD_initDStream ( ZSTD_DStream * zds )
{
return ZSTD_initDStream_usingDict ( zds , NULL , 0 ) ;
}
2016-10-25 17:47:02 -07:00
size_t ZSTD_initDStream_usingDDict ( ZSTD_DStream * zds , const ZSTD_DDict * ddict ) /**< note : ddict will just be referenced, and must outlive decompression session */
{
size_t const initResult = ZSTD_initDStream ( zds ) ;
zds - > ddict = ddict ;
return initResult ;
}
2016-09-14 07:55:44 -07:00
size_t ZSTD_resetDStream ( ZSTD_DStream * zds )
{
zds - > stage = zdss_loadHeader ;
zds - > lhSize = zds - > inPos = zds - > outStart = zds - > outEnd = 0 ;
zds - > legacyVersion = 0 ;
zds - > hostageByte = 0 ;
return ZSTD_frameHeaderSize_prefix ;
}
2016-08-23 07:58:10 -07:00
size_t ZSTD_setDStreamParameter ( ZSTD_DStream * zds ,
ZSTD_DStreamParameter_e paramType , unsigned paramValue )
{
switch ( paramType )
{
default : return ERROR ( parameter_unknown ) ;
2016-10-14 13:13:13 -07:00
case ZSTDdsp_maxWindowSize : zds - > maxWindowSize = paramValue ? paramValue : ( U32 ) ( - 1 ) ; break ;
2016-08-23 07:58:10 -07:00
}
return 0 ;
}
2016-08-22 16:18:06 -07:00
size_t ZSTD_sizeof_DStream ( const ZSTD_DStream * zds )
2016-08-22 15:30:31 -07:00
{
2016-09-14 17:50:27 -07:00
if ( zds = = NULL ) return 0 ; /* support sizeof on NULL */
2016-10-25 17:47:02 -07:00
return sizeof ( * zds ) + ZSTD_sizeof_DCtx ( zds - > dctx ) + ZSTD_sizeof_DDict ( zds - > ddictLocal ) + zds - > inBuffSize + zds - > outBuffSize ;
2016-08-22 15:30:31 -07:00
}
2016-08-12 04:04:27 -07:00
2016-09-09 07:44:16 -07:00
/* ***** Decompression ***** */
2016-08-12 04:04:27 -07:00
MEM_STATIC size_t ZSTD_limitCopy ( void * dst , size_t dstCapacity , const void * src , size_t srcSize )
{
size_t const length = MIN ( dstCapacity , srcSize ) ;
memcpy ( dst , src , length ) ;
return length ;
}
2016-08-16 16:39:22 -07:00
size_t ZSTD_decompressStream ( ZSTD_DStream * zds , ZSTD_outBuffer * output , ZSTD_inBuffer * input )
2016-08-12 04:04:27 -07:00
{
2016-08-16 16:39:22 -07:00
const char * const istart = ( const char * ) ( input - > src ) + input - > pos ;
const char * const iend = ( const char * ) ( input - > src ) + input - > size ;
2016-08-12 04:04:27 -07:00
const char * ip = istart ;
2016-08-16 16:39:22 -07:00
char * const ostart = ( char * ) ( output - > dst ) + output - > pos ;
char * const oend = ( char * ) ( output - > dst ) + output - > size ;
2016-08-12 04:04:27 -07:00
char * op = ostart ;
U32 someMoreWork = 1 ;
2016-08-28 07:43:34 -07:00
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
if ( zds - > legacyVersion )
2016-08-28 10:00:49 -07:00
return ZSTD_decompressLegacyStream ( zds - > legacyContext , zds - > legacyVersion , output , input ) ;
2016-08-28 07:43:34 -07:00
# endif
2016-08-12 04:04:27 -07:00
while ( someMoreWork ) {
switch ( zds - > stage )
{
case zdss_init :
return ERROR ( init_missing ) ;
case zdss_loadHeader :
2016-08-28 07:43:34 -07:00
{ size_t const hSize = ZSTD_getFrameParams ( & zds - > fParams , zds - > headerBuffer , zds - > lhSize ) ;
if ( ZSTD_isError ( hSize ) )
# if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2016-08-28 08:19:47 -07:00
{ U32 const legacyVersion = ZSTD_isLegacy ( istart , iend - istart ) ;
2016-08-28 07:43:34 -07:00
if ( legacyVersion ) {
2016-10-25 17:47:02 -07:00
const void * const dict = zds - > ddict ? zds - > ddict - > dict : NULL ;
size_t const dictSize = zds - > ddict ? zds - > ddict - > dictSize : 0 ;
2016-09-06 06:36:19 -07:00
CHECK_F ( ZSTD_initLegacyStream ( & zds - > legacyContext , zds - > previousLegacyVersion , legacyVersion ,
2016-10-25 17:47:02 -07:00
dict , dictSize ) ) ;
2016-08-28 08:19:47 -07:00
zds - > legacyVersion = zds - > previousLegacyVersion = legacyVersion ;
return ZSTD_decompressLegacyStream ( zds - > legacyContext , zds - > legacyVersion , output , input ) ;
2016-08-28 07:43:34 -07:00
} else {
return hSize ; /* error */
} }
# else
2016-10-25 17:47:02 -07:00
return hSize ;
2016-08-28 07:43:34 -07:00
# endif
2016-08-12 04:04:27 -07:00
if ( hSize ! = 0 ) { /* need more input */
size_t const toLoad = hSize - zds - > lhSize ; /* if hSize!=0, hSize > zds->lhSize */
if ( toLoad > ( size_t ) ( iend - ip ) ) { /* not enough input to load full header */
memcpy ( zds - > headerBuffer + zds - > lhSize , ip , iend - ip ) ;
zds - > lhSize + = iend - ip ;
2016-08-16 16:39:22 -07:00
input - > pos = input - > size ;
2016-09-05 10:47:43 -07:00
return ( MAX ( ZSTD_frameHeaderSize_min , hSize ) - zds - > lhSize ) + ZSTD_blockHeaderSize ; /* remaining header bytes + next block header */
2016-08-12 04:04:27 -07:00
}
memcpy ( zds - > headerBuffer + zds - > lhSize , ip , toLoad ) ; zds - > lhSize = hSize ; ip + = toLoad ;
break ;
} }
/* Consume header */
2016-10-25 17:47:02 -07:00
{ const ZSTD_DCtx * refContext = zds - > ddict ? zds - > ddict - > refContext : NULL ;
ZSTD_refDCtx ( zds - > dctx , refContext ) ;
}
2016-09-14 07:14:57 -07:00
{ size_t const h1Size = ZSTD_nextSrcSizeToDecompress ( zds - > dctx ) ; /* == ZSTD_frameHeaderSize_prefix */
CHECK_F ( ZSTD_decompressContinue ( zds - > dctx , NULL , 0 , zds - > headerBuffer , h1Size ) ) ;
{ size_t const h2Size = ZSTD_nextSrcSizeToDecompress ( zds - > dctx ) ;
CHECK_F ( ZSTD_decompressContinue ( zds - > dctx , NULL , 0 , zds - > headerBuffer + h1Size , h2Size ) ) ;
2016-08-12 04:04:27 -07:00
} }
zds - > fParams . windowSize = MAX ( zds - > fParams . windowSize , 1U < < ZSTD_WINDOWLOG_ABSOLUTEMIN ) ;
2016-10-14 13:13:13 -07:00
if ( zds - > fParams . windowSize > zds - > maxWindowSize ) return ERROR ( frameParameter_windowTooLarge ) ;
2016-08-12 04:04:27 -07:00
2016-09-09 07:44:16 -07:00
/* Adapt buffer sizes to frame header instructions */
2016-08-12 04:04:27 -07:00
{ size_t const blockSize = MIN ( zds - > fParams . windowSize , ZSTD_BLOCKSIZE_ABSOLUTEMAX ) ;
size_t const neededOutSize = zds - > fParams . windowSize + blockSize ;
zds - > blockSize = blockSize ;
if ( zds - > inBuffSize < blockSize ) {
2016-08-28 21:05:43 -07:00
ZSTD_free ( zds - > inBuff , zds - > customMem ) ;
2016-08-12 04:04:27 -07:00
zds - > inBuffSize = blockSize ;
2016-08-28 21:05:43 -07:00
zds - > inBuff = ( char * ) ZSTD_malloc ( blockSize , zds - > customMem ) ;
2016-08-12 04:04:27 -07:00
if ( zds - > inBuff = = NULL ) return ERROR ( memory_allocation ) ;
}
if ( zds - > outBuffSize < neededOutSize ) {
2016-08-28 21:05:43 -07:00
ZSTD_free ( zds - > outBuff , zds - > customMem ) ;
2016-08-12 04:04:27 -07:00
zds - > outBuffSize = neededOutSize ;
2016-08-28 21:05:43 -07:00
zds - > outBuff = ( char * ) ZSTD_malloc ( neededOutSize , zds - > customMem ) ;
2016-08-12 04:04:27 -07:00
if ( zds - > outBuff = = NULL ) return ERROR ( memory_allocation ) ;
} }
zds - > stage = zdss_read ;
/* pass-through */
case zdss_read :
2016-09-14 07:14:57 -07:00
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress ( zds - > dctx ) ;
2016-08-12 04:04:27 -07:00
if ( neededInSize = = 0 ) { /* end of frame */
zds - > stage = zdss_init ;
someMoreWork = 0 ;
break ;
}
if ( ( size_t ) ( iend - ip ) > = neededInSize ) { /* decode directly from src */
2016-09-14 07:14:57 -07:00
const int isSkipFrame = ZSTD_isSkipFrame ( zds - > dctx ) ;
size_t const decodedSize = ZSTD_decompressContinue ( zds - > dctx ,
2016-08-12 04:04:27 -07:00
zds - > outBuff + zds - > outStart , ( isSkipFrame ? 0 : zds - > outBuffSize - zds - > outStart ) ,
ip , neededInSize ) ;
if ( ZSTD_isError ( decodedSize ) ) return decodedSize ;
ip + = neededInSize ;
if ( ! decodedSize & & ! isSkipFrame ) break ; /* this was just a header */
2016-09-09 07:44:16 -07:00
zds - > outEnd = zds - > outStart + decodedSize ;
2016-08-12 04:04:27 -07:00
zds - > stage = zdss_flush ;
break ;
}
if ( ip = = iend ) { someMoreWork = 0 ; break ; } /* no more input */
zds - > stage = zdss_load ;
/* pass-through */
}
case zdss_load :
2016-09-14 07:14:57 -07:00
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress ( zds - > dctx ) ;
2016-08-12 04:04:27 -07:00
size_t const toLoad = neededInSize - zds - > inPos ; /* should always be <= remaining space within inBuff */
size_t loadedSize ;
if ( toLoad > zds - > inBuffSize - zds - > inPos ) return ERROR ( corruption_detected ) ; /* should never happen */
loadedSize = ZSTD_limitCopy ( zds - > inBuff + zds - > inPos , toLoad , ip , iend - ip ) ;
ip + = loadedSize ;
zds - > inPos + = loadedSize ;
if ( loadedSize < toLoad ) { someMoreWork = 0 ; break ; } /* not enough input, wait for more */
/* decode loaded input */
2016-09-14 07:14:57 -07:00
{ const int isSkipFrame = ZSTD_isSkipFrame ( zds - > dctx ) ;
size_t const decodedSize = ZSTD_decompressContinue ( zds - > dctx ,
2016-08-12 04:04:27 -07:00
zds - > outBuff + zds - > outStart , zds - > outBuffSize - zds - > outStart ,
zds - > inBuff , neededInSize ) ;
if ( ZSTD_isError ( decodedSize ) ) return decodedSize ;
zds - > inPos = 0 ; /* input is consumed */
if ( ! decodedSize & & ! isSkipFrame ) { zds - > stage = zdss_read ; break ; } /* this was just a header */
zds - > outEnd = zds - > outStart + decodedSize ;
zds - > stage = zdss_flush ;
/* pass-through */
} }
case zdss_flush :
{ size_t const toFlushSize = zds - > outEnd - zds - > outStart ;
size_t const flushedSize = ZSTD_limitCopy ( op , oend - op , zds - > outBuff + zds - > outStart , toFlushSize ) ;
op + = flushedSize ;
zds - > outStart + = flushedSize ;
if ( flushedSize = = toFlushSize ) { /* flush completed */
zds - > stage = zdss_read ;
if ( zds - > outStart + zds - > blockSize > zds - > outBuffSize )
zds - > outStart = zds - > outEnd = 0 ;
break ;
}
2016-09-09 07:44:16 -07:00
/* cannot complete flush */
2016-08-12 04:04:27 -07:00
someMoreWork = 0 ;
break ;
}
default : return ERROR ( GENERIC ) ; /* impossible */
} }
/* result */
2016-08-16 16:39:22 -07:00
input - > pos + = ( size_t ) ( ip - istart ) ;
output - > pos + = ( size_t ) ( op - ostart ) ;
2016-09-14 07:14:57 -07:00
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress ( zds - > dctx ) ;
2016-09-09 07:44:16 -07:00
if ( ! nextSrcSizeHint ) { /* frame fully decoded */
if ( zds - > outEnd = = zds - > outStart ) { /* output fully flushed */
if ( zds - > hostageByte ) {
if ( input - > pos > = input - > size ) { zds - > stage = zdss_read ; return 1 ; } /* can't release hostage (not present) */
input - > pos + + ; /* release hostage */
}
return 0 ;
}
if ( ! zds - > hostageByte ) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
input - > pos - - ; /* note : pos > 0, otherwise, impossible to finish reading last block */
zds - > hostageByte = 1 ;
}
return 1 ;
}
2016-09-14 07:14:57 -07:00
nextSrcSizeHint + = ZSTD_blockHeaderSize * ( ZSTD_nextInputType ( zds - > dctx ) = = ZSTDnit_block ) ; /* preload header of next block */
2016-08-12 04:04:27 -07:00
if ( zds - > inPos > nextSrcSizeHint ) return ERROR ( GENERIC ) ; /* should never happen */
nextSrcSizeHint - = zds - > inPos ; /* already loaded*/
return nextSrcSizeHint ;
}
}