2015-10-18 14:18:32 -07:00
/* ******************************************************************
2016-04-22 03:43:18 -07:00
Huffman decoder , part of New Generation Entropy library
2016-03-19 21:40:39 -07:00
Copyright ( C ) 2013 - 2016 , Yann Collet .
2015-10-18 14:18:32 -07:00
BSD 2 - Clause License ( http : //www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are
met :
* Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above
copyright notice , this list of conditions and the following disclaimer
in the documentation and / or other materials provided with the
distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
" AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
You can contact the author at :
2016-04-22 03:43:18 -07:00
- FSE + HUF source repository : https : //github.com/Cyan4973/FiniteStateEntropy
2015-10-18 14:18:32 -07:00
- Public forum : https : //groups.google.com/forum/#!forum/lz4c
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-05 16:58:37 -08:00
/* **************************************************************
2015-10-18 14:18:32 -07:00
* Compiler specifics
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ )
/* inline is defined */
# elif defined(_MSC_VER)
# define inline __inline
# else
# define inline /* disable inline */
# endif
# ifdef _MSC_VER /* Visual Studio */
# define FORCE_INLINE static __forceinline
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# else
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
# endif
2016-01-05 16:58:37 -08:00
/* **************************************************************
2015-10-18 14:18:32 -07:00
* Includes
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <string.h> /* memcpy, memset */
# include "bitstream.h"
# include "fse.h" /* header compression */
2016-06-04 15:42:28 -07:00
# define HUF_STATIC_LINKING_ONLY
# include "huf.h"
2015-10-18 14:18:32 -07:00
2016-01-05 16:58:37 -08:00
/* **************************************************************
2015-10-18 14:18:32 -07:00
* Error Management
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-05 16:58:37 -08:00
# define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1 / (int)(!!(c)) }; } /* use only *after* variable declarations */
2015-10-18 14:18:32 -07:00
2016-01-24 19:10:46 -08:00
/*-***************************/
/* single-symbol decoding */
/*-***************************/
2016-06-08 02:11:02 -07:00
typedef struct { BYTE maxTableLog ; BYTE currentTableLog ; } DTableDesc ;
typedef struct { BYTE byte ; BYTE nbBits ; } HUF_DEltX2 ; /* single-symbol decoding */
2015-10-18 14:18:32 -07:00
2016-06-08 02:11:02 -07:00
size_t HUF_readDTableX2 ( HUF_DTable * DTable , const void * src , size_t srcSize )
2015-10-18 14:18:32 -07:00
{
2016-05-20 05:36:36 -07:00
BYTE huffWeight [ HUF_SYMBOLVALUE_MAX + 1 ] ;
U32 rankVal [ HUF_TABLELOG_ABSOLUTEMAX + 1 ] ; /* large enough for values from 0 to 16 */
2015-10-18 14:18:32 -07:00
U32 tableLog = 0 ;
2016-01-05 16:58:37 -08:00
size_t iSize ;
2015-10-18 14:18:32 -07:00
U32 nbSymbols = 0 ;
U32 n ;
U32 nextRankStart ;
2016-01-05 16:58:37 -08:00
void * const dtPtr = DTable + 1 ;
HUF_DEltX2 * const dt = ( HUF_DEltX2 * ) dtPtr ;
2016-06-08 02:11:02 -07:00
DTableDesc dtd ;
2015-10-18 14:18:32 -07:00
2016-06-08 02:11:02 -07:00
HUF_STATIC_ASSERT ( sizeof ( HUF_DEltX2 ) = = sizeof ( HUF_DTable ) ) ; /* if compilation fails here, assertion is false */
memcpy ( & dtd , DTable , sizeof ( dtd ) ) ;
2015-10-18 14:18:32 -07:00
//memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */
2016-05-20 05:36:36 -07:00
iSize = HUF_readStats ( huffWeight , HUF_SYMBOLVALUE_MAX + 1 , rankVal , & nbSymbols , & tableLog , src , srcSize ) ;
2015-10-18 14:18:32 -07:00
if ( HUF_isError ( iSize ) ) return iSize ;
/* check result */
2016-06-08 02:11:02 -07:00
if ( tableLog > dtd . maxTableLog ) return ERROR ( tableLog_tooLarge ) ; /* DTable is too small */
dtd . currentTableLog = ( BYTE ) tableLog ; /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */
memcpy ( DTable , & dtd , sizeof ( dtd ) ) ;
2015-10-18 14:18:32 -07:00
/* Prepare ranks */
nextRankStart = 0 ;
2016-05-06 07:55:27 -07:00
for ( n = 1 ; n < tableLog + 1 ; n + + ) {
2015-10-18 14:18:32 -07:00
U32 current = nextRankStart ;
nextRankStart + = ( rankVal [ n ] < < ( n - 1 ) ) ;
rankVal [ n ] = current ;
}
/* fill DTable */
2016-01-28 06:39:52 -08:00
for ( n = 0 ; n < nbSymbols ; n + + ) {
2015-10-18 14:18:32 -07:00
const U32 w = huffWeight [ n ] ;
const U32 length = ( 1 < < w ) > > 1 ;
U32 i ;
HUF_DEltX2 D ;
D . byte = ( BYTE ) n ; D . nbBits = ( BYTE ) ( tableLog + 1 - w ) ;
for ( i = rankVal [ w ] ; i < rankVal [ w ] + length ; i + + )
dt [ i ] = D ;
rankVal [ w ] + = length ;
}
return iSize ;
}
2016-03-19 21:40:39 -07:00
2015-10-18 14:18:32 -07:00
static BYTE HUF_decodeSymbolX2 ( BIT_DStream_t * Dstream , const HUF_DEltX2 * dt , const U32 dtLog )
{
2016-03-19 21:40:39 -07:00
const size_t val = BIT_lookBitsFast ( Dstream , dtLog ) ; /* note : dtLog >= 1 */
const BYTE c = dt [ val ] . byte ;
BIT_skipBits ( Dstream , dt [ val ] . nbBits ) ;
return c ;
2015-10-18 14:18:32 -07:00
}
# define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
* ptr + + = HUF_decodeSymbolX2 ( DStreamPtr , dt , dtLog )
# define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
2016-05-20 05:36:36 -07:00
if ( MEM_64bits ( ) | | ( HUF_TABLELOG_MAX < = 12 ) ) \
2015-10-18 14:18:32 -07:00
HUF_DECODE_SYMBOLX2_0 ( ptr , DStreamPtr )
# define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
2015-10-21 02:01:09 -07:00
if ( MEM_64bits ( ) ) \
2015-10-18 14:18:32 -07:00
HUF_DECODE_SYMBOLX2_0 ( ptr , DStreamPtr )
static inline size_t HUF_decodeStreamX2 ( BYTE * p , BIT_DStream_t * const bitDPtr , BYTE * const pEnd , const HUF_DEltX2 * const dt , const U32 dtLog )
{
BYTE * const pStart = p ;
/* up to 4 symbols at a time */
2016-01-28 06:39:52 -08:00
while ( ( BIT_reloadDStream ( bitDPtr ) = = BIT_DStream_unfinished ) & & ( p < = pEnd - 4 ) ) {
2015-10-18 14:18:32 -07:00
HUF_DECODE_SYMBOLX2_2 ( p , bitDPtr ) ;
HUF_DECODE_SYMBOLX2_1 ( p , bitDPtr ) ;
HUF_DECODE_SYMBOLX2_2 ( p , bitDPtr ) ;
HUF_DECODE_SYMBOLX2_0 ( p , bitDPtr ) ;
}
/* closer to the end */
while ( ( BIT_reloadDStream ( bitDPtr ) = = BIT_DStream_unfinished ) & & ( p < pEnd ) )
HUF_DECODE_SYMBOLX2_0 ( p , bitDPtr ) ;
/* no more data to retrieve from bitstream, hence no need to reload */
while ( p < pEnd )
HUF_DECODE_SYMBOLX2_0 ( p , bitDPtr ) ;
return pEnd - pStart ;
}
size_t HUF_decompress1X2_usingDTable (
void * dst , size_t dstSize ,
const void * cSrc , size_t cSrcSize ,
2016-06-08 02:11:02 -07:00
const HUF_DTable * DTable )
2015-10-18 14:18:32 -07:00
{
BYTE * op = ( BYTE * ) dst ;
BYTE * const oend = op + dstSize ;
2016-01-05 16:58:37 -08:00
const void * dtPtr = DTable ;
const HUF_DEltX2 * const dt = ( ( const HUF_DEltX2 * ) dtPtr ) + 1 ;
2015-10-18 14:18:32 -07:00
BIT_DStream_t bitD ;
2016-06-08 02:11:02 -07:00
DTableDesc dtd ;
U32 dtLog ;
memcpy ( & dtd , DTable , sizeof ( dtd ) ) ;
dtLog = dtd . currentTableLog ;
2016-03-19 21:40:39 -07:00
{ size_t const errorCode = BIT_initDStream ( & bitD , cSrc , cSrcSize ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
2015-10-18 14:18:32 -07:00
HUF_decodeStreamX2 ( op , & bitD , oend , dt , dtLog ) ;
/* check */
if ( ! BIT_endOfDStream ( & bitD ) ) return ERROR ( corruption_detected ) ;
return dstSize ;
}
size_t HUF_decompress1X2 ( void * dst , size_t dstSize , const void * cSrc , size_t cSrcSize )
{
2016-05-20 05:36:36 -07:00
HUF_CREATE_STATIC_DTABLEX2 ( DTable , HUF_TABLELOG_MAX ) ;
2015-10-18 14:18:32 -07:00
const BYTE * ip = ( const BYTE * ) cSrc ;
2016-03-19 21:40:39 -07:00
size_t const errorCode = HUF_readDTableX2 ( DTable , cSrc , cSrcSize ) ;
2015-10-18 14:18:32 -07:00
if ( HUF_isError ( errorCode ) ) return errorCode ;
if ( errorCode > = cSrcSize ) return ERROR ( srcSize_wrong ) ;
ip + = errorCode ;
cSrcSize - = errorCode ;
return HUF_decompress1X2_usingDTable ( dst , dstSize , ip , cSrcSize , DTable ) ;
}
size_t HUF_decompress4X2_usingDTable (
void * dst , size_t dstSize ,
const void * cSrc , size_t cSrcSize ,
2016-06-08 02:11:02 -07:00
const HUF_DTable * DTable )
2015-10-18 14:18:32 -07:00
{
2016-01-28 06:39:52 -08:00
/* Check */
2016-02-19 08:33:43 -08:00
if ( cSrcSize < 10 ) return ERROR ( corruption_detected ) ; /* strict minimum : jump table + 1 byte per stream */
2016-03-19 21:40:39 -07:00
{ const BYTE * const istart = ( const BYTE * ) cSrc ;
2016-02-19 08:33:43 -08:00
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * const oend = ostart + dstSize ;
const void * const dtPtr = DTable ;
const HUF_DEltX2 * const dt = ( ( const HUF_DEltX2 * ) dtPtr ) + 1 ;
2015-10-18 14:18:32 -07:00
2016-02-19 08:33:43 -08:00
/* Init */
BIT_DStream_t bitD1 ;
BIT_DStream_t bitD2 ;
BIT_DStream_t bitD3 ;
BIT_DStream_t bitD4 ;
2016-06-08 02:11:02 -07:00
size_t const length1 = MEM_readLE16 ( istart ) ;
size_t const length2 = MEM_readLE16 ( istart + 2 ) ;
size_t const length3 = MEM_readLE16 ( istart + 4 ) ;
size_t const length4 = cSrcSize - ( length1 + length2 + length3 + 6 ) ;
2016-02-19 08:33:43 -08:00
const BYTE * const istart1 = istart + 6 ; /* jumpTable */
const BYTE * const istart2 = istart1 + length1 ;
const BYTE * const istart3 = istart2 + length2 ;
const BYTE * const istart4 = istart3 + length3 ;
const size_t segmentSize = ( dstSize + 3 ) / 4 ;
BYTE * const opStart2 = ostart + segmentSize ;
BYTE * const opStart3 = opStart2 + segmentSize ;
BYTE * const opStart4 = opStart3 + segmentSize ;
BYTE * op1 = ostart ;
BYTE * op2 = opStart2 ;
BYTE * op3 = opStart3 ;
BYTE * op4 = opStart4 ;
U32 endSignal ;
2016-06-08 02:11:02 -07:00
DTableDesc dtd ;
U32 dtLog ;
memcpy ( & dtd , DTable , sizeof ( dtd ) ) ;
dtLog = dtd . currentTableLog ;
2015-10-18 14:18:32 -07:00
2016-02-19 08:33:43 -08:00
if ( length4 > cSrcSize ) return ERROR ( corruption_detected ) ; /* overflow */
2016-06-08 02:11:02 -07:00
{ size_t const errorCode = BIT_initDStream ( & bitD1 , istart1 , length1 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
{ size_t const errorCode = BIT_initDStream ( & bitD2 , istart2 , length2 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
{ size_t const errorCode = BIT_initDStream ( & bitD3 , istart3 , length3 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
{ size_t const errorCode = BIT_initDStream ( & bitD4 , istart4 , length4 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
2016-02-19 08:33:43 -08:00
/* 16-32 symbols per loop (4-8 symbols per stream) */
2015-10-18 14:18:32 -07:00
endSignal = BIT_reloadDStream ( & bitD1 ) | BIT_reloadDStream ( & bitD2 ) | BIT_reloadDStream ( & bitD3 ) | BIT_reloadDStream ( & bitD4 ) ;
2016-02-19 08:33:43 -08:00
for ( ; ( endSignal = = BIT_DStream_unfinished ) & & ( op4 < ( oend - 7 ) ) ; ) {
HUF_DECODE_SYMBOLX2_2 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX2_2 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX2_2 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX2_2 ( op4 , & bitD4 ) ;
HUF_DECODE_SYMBOLX2_1 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX2_1 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX2_1 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX2_1 ( op4 , & bitD4 ) ;
HUF_DECODE_SYMBOLX2_2 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX2_2 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX2_2 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX2_2 ( op4 , & bitD4 ) ;
HUF_DECODE_SYMBOLX2_0 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX2_0 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX2_0 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX2_0 ( op4 , & bitD4 ) ;
endSignal = BIT_reloadDStream ( & bitD1 ) | BIT_reloadDStream ( & bitD2 ) | BIT_reloadDStream ( & bitD3 ) | BIT_reloadDStream ( & bitD4 ) ;
}
2015-10-18 14:18:32 -07:00
2016-02-19 08:33:43 -08:00
/* check corruption */
if ( op1 > opStart2 ) return ERROR ( corruption_detected ) ;
if ( op2 > opStart3 ) return ERROR ( corruption_detected ) ;
if ( op3 > opStart4 ) return ERROR ( corruption_detected ) ;
/* note : op4 supposed already verified within main loop */
2015-10-18 14:18:32 -07:00
2016-02-19 08:33:43 -08:00
/* finish bitStreams one by one */
HUF_decodeStreamX2 ( op1 , & bitD1 , opStart2 , dt , dtLog ) ;
HUF_decodeStreamX2 ( op2 , & bitD2 , opStart3 , dt , dtLog ) ;
HUF_decodeStreamX2 ( op3 , & bitD3 , opStart4 , dt , dtLog ) ;
HUF_decodeStreamX2 ( op4 , & bitD4 , oend , dt , dtLog ) ;
2015-10-18 14:18:32 -07:00
2016-02-19 08:33:43 -08:00
/* check */
endSignal = BIT_endOfDStream ( & bitD1 ) & BIT_endOfDStream ( & bitD2 ) & BIT_endOfDStream ( & bitD3 ) & BIT_endOfDStream ( & bitD4 ) ;
if ( ! endSignal ) return ERROR ( corruption_detected ) ;
2015-10-18 14:18:32 -07:00
2016-02-19 08:33:43 -08:00
/* decoded size */
return dstSize ;
}
2015-10-18 14:18:32 -07:00
}
size_t HUF_decompress4X2 ( void * dst , size_t dstSize , const void * cSrc , size_t cSrcSize )
{
2016-05-20 05:36:36 -07:00
HUF_CREATE_STATIC_DTABLEX2 ( DTable , HUF_TABLELOG_MAX ) ;
2015-10-18 14:18:32 -07:00
const BYTE * ip = ( const BYTE * ) cSrc ;
2016-06-08 02:11:02 -07:00
size_t const hSize = HUF_readDTableX2 ( DTable , cSrc , cSrcSize ) ;
if ( HUF_isError ( hSize ) ) return hSize ;
if ( hSize > = cSrcSize ) return ERROR ( srcSize_wrong ) ;
ip + = hSize ;
cSrcSize - = hSize ;
2015-10-18 14:18:32 -07:00
return HUF_decompress4X2_usingDTable ( dst , dstSize , ip , cSrcSize , DTable ) ;
}
2016-01-23 10:28:41 -08:00
/* *************************/
2015-10-18 14:18:32 -07:00
/* double-symbols decoding */
2016-01-23 10:28:41 -08:00
/* *************************/
2016-06-08 02:11:02 -07:00
typedef struct { U16 sequence ; BYTE nbBits ; BYTE length ; } HUF_DEltX4 ; /* double-symbols decoding */
typedef struct { BYTE symbol ; BYTE weight ; } sortedSymbol_t ;
2015-10-18 14:18:32 -07:00
static void HUF_fillDTableX4Level2 ( HUF_DEltX4 * DTable , U32 sizeLog , const U32 consumed ,
const U32 * rankValOrigin , const int minWeight ,
const sortedSymbol_t * sortedSymbols , const U32 sortedListSize ,
U32 nbBitsBaseline , U16 baseSeq )
{
HUF_DEltX4 DElt ;
2016-05-20 05:36:36 -07:00
U32 rankVal [ HUF_TABLELOG_ABSOLUTEMAX + 1 ] ;
2015-10-18 14:18:32 -07:00
/* get pre-calculated rankVal */
memcpy ( rankVal , rankValOrigin , sizeof ( rankVal ) ) ;
/* fill skipped values */
2016-01-28 06:39:52 -08:00
if ( minWeight > 1 ) {
2015-10-18 14:18:32 -07:00
U32 i , skipSize = rankVal [ minWeight ] ;
MEM_writeLE16 ( & ( DElt . sequence ) , baseSeq ) ;
DElt . nbBits = ( BYTE ) ( consumed ) ;
DElt . length = 1 ;
for ( i = 0 ; i < skipSize ; i + + )
DTable [ i ] = DElt ;
}
/* fill DTable */
2016-03-19 21:40:39 -07:00
{ U32 s ; for ( s = 0 ; s < sortedListSize ; s + + ) { /* note : sortedSymbols already skipped */
2015-10-18 14:18:32 -07:00
const U32 symbol = sortedSymbols [ s ] . symbol ;
const U32 weight = sortedSymbols [ s ] . weight ;
const U32 nbBits = nbBitsBaseline - weight ;
const U32 length = 1 < < ( sizeLog - nbBits ) ;
const U32 start = rankVal [ weight ] ;
U32 i = start ;
const U32 end = start + length ;
MEM_writeLE16 ( & ( DElt . sequence ) , ( U16 ) ( baseSeq + ( symbol < < 8 ) ) ) ;
DElt . nbBits = ( BYTE ) ( nbBits + consumed ) ;
DElt . length = 2 ;
do { DTable [ i + + ] = DElt ; } while ( i < end ) ; /* since length >= 1 */
rankVal [ weight ] + = length ;
2016-03-19 21:40:39 -07:00
} }
2015-10-18 14:18:32 -07:00
}
2016-05-20 05:36:36 -07:00
typedef U32 rankVal_t [ HUF_TABLELOG_ABSOLUTEMAX ] [ HUF_TABLELOG_ABSOLUTEMAX + 1 ] ;
2015-10-18 14:18:32 -07:00
static void HUF_fillDTableX4 ( HUF_DEltX4 * DTable , const U32 targetLog ,
const sortedSymbol_t * sortedList , const U32 sortedListSize ,
const U32 * rankStart , rankVal_t rankValOrigin , const U32 maxWeight ,
const U32 nbBitsBaseline )
{
2016-05-20 05:36:36 -07:00
U32 rankVal [ HUF_TABLELOG_ABSOLUTEMAX + 1 ] ;
2015-10-18 14:18:32 -07:00
const int scaleLog = nbBitsBaseline - targetLog ; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
const U32 minBits = nbBitsBaseline - maxWeight ;
U32 s ;
memcpy ( rankVal , rankValOrigin , sizeof ( rankVal ) ) ;
/* fill DTable */
2016-01-28 06:39:52 -08:00
for ( s = 0 ; s < sortedListSize ; s + + ) {
2015-10-18 14:18:32 -07:00
const U16 symbol = sortedList [ s ] . symbol ;
const U32 weight = sortedList [ s ] . weight ;
const U32 nbBits = nbBitsBaseline - weight ;
const U32 start = rankVal [ weight ] ;
const U32 length = 1 < < ( targetLog - nbBits ) ;
2016-01-28 06:39:52 -08:00
if ( targetLog - nbBits > = minBits ) { /* enough room for a second symbol */
2015-10-18 14:18:32 -07:00
U32 sortedRank ;
int minWeight = nbBits + scaleLog ;
if ( minWeight < 1 ) minWeight = 1 ;
sortedRank = rankStart [ minWeight ] ;
HUF_fillDTableX4Level2 ( DTable + start , targetLog - nbBits , nbBits ,
rankValOrigin [ nbBits ] , minWeight ,
sortedList + sortedRank , sortedListSize - sortedRank ,
nbBitsBaseline , symbol ) ;
2016-01-28 06:39:52 -08:00
} else {
2015-10-18 14:18:32 -07:00
HUF_DEltX4 DElt ;
MEM_writeLE16 ( & ( DElt . sequence ) , symbol ) ;
2016-03-19 21:40:39 -07:00
DElt . nbBits = ( BYTE ) ( nbBits ) ;
DElt . length = 1 ;
{ U32 u ;
const U32 end = start + length ;
for ( u = start ; u < end ; u + + ) DTable [ u ] = DElt ;
} }
2015-10-18 14:18:32 -07:00
rankVal [ weight ] + = length ;
}
}
2016-06-08 02:11:02 -07:00
size_t HUF_readDTableX4 ( HUF_DTable * DTable , const void * src , size_t srcSize )
2015-10-18 14:18:32 -07:00
{
2016-05-20 05:36:36 -07:00
BYTE weightList [ HUF_SYMBOLVALUE_MAX + 1 ] ;
sortedSymbol_t sortedSymbol [ HUF_SYMBOLVALUE_MAX + 1 ] ;
U32 rankStats [ HUF_TABLELOG_ABSOLUTEMAX + 1 ] = { 0 } ;
U32 rankStart0 [ HUF_TABLELOG_ABSOLUTEMAX + 2 ] = { 0 } ;
2015-10-18 14:18:32 -07:00
U32 * const rankStart = rankStart0 + 1 ;
rankVal_t rankVal ;
U32 tableLog , maxW , sizeOfSort , nbSymbols ;
2016-06-08 02:11:02 -07:00
DTableDesc dtd ;
U32 maxTableLog ;
2016-01-05 16:58:37 -08:00
size_t iSize ;
2016-06-08 02:11:02 -07:00
void * dtPtr = DTable + 1 ; /* force compiler to avoid strict-aliasing */
HUF_DEltX4 * const dt = ( HUF_DEltX4 * ) dtPtr ;
2015-10-18 14:18:32 -07:00
HUF_STATIC_ASSERT ( sizeof ( HUF_DEltX4 ) = = sizeof ( U32 ) ) ; /* if compilation fails here, assertion is false */
2016-06-08 02:11:02 -07:00
memcpy ( & dtd , DTable , sizeof ( dtd ) ) ;
maxTableLog = dtd . maxTableLog - 1 ;
if ( maxTableLog > HUF_TABLELOG_ABSOLUTEMAX ) return ERROR ( tableLog_tooLarge ) ;
2015-10-18 14:18:32 -07:00
//memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */
2016-05-20 05:36:36 -07:00
iSize = HUF_readStats ( weightList , HUF_SYMBOLVALUE_MAX + 1 , rankStats , & nbSymbols , & tableLog , src , srcSize ) ;
2015-10-18 14:18:32 -07:00
if ( HUF_isError ( iSize ) ) return iSize ;
/* check result */
2016-06-08 02:11:02 -07:00
if ( tableLog > maxTableLog ) return ERROR ( tableLog_tooLarge ) ; /* DTable can't fit code depth */
2015-10-18 14:18:32 -07:00
/* find maxWeight */
for ( maxW = tableLog ; rankStats [ maxW ] = = 0 ; maxW - - ) { } /* necessarily finds a solution before 0 */
/* Get start index of each weight */
2016-03-19 21:40:39 -07:00
{ U32 w , nextRankStart = 0 ;
2016-05-06 07:55:27 -07:00
for ( w = 1 ; w < maxW + 1 ; w + + ) {
2015-10-18 14:18:32 -07:00
U32 current = nextRankStart ;
nextRankStart + = rankStats [ w ] ;
rankStart [ w ] = current ;
}
rankStart [ 0 ] = nextRankStart ; /* put all 0w symbols at the end of sorted list*/
sizeOfSort = nextRankStart ;
}
/* sort symbols by weight */
2016-03-19 21:40:39 -07:00
{ U32 s ;
2016-01-28 06:39:52 -08:00
for ( s = 0 ; s < nbSymbols ; s + + ) {
2016-05-06 07:55:27 -07:00
U32 const w = weightList [ s ] ;
U32 const r = rankStart [ w ] + + ;
2015-10-18 14:18:32 -07:00
sortedSymbol [ r ] . symbol = ( BYTE ) s ;
sortedSymbol [ r ] . weight = ( BYTE ) w ;
}
rankStart [ 0 ] = 0 ; /* forget 0w symbols; this is beginning of weight(1) */
}
/* Build rankVal */
2016-05-06 07:55:27 -07:00
{ U32 * const rankVal0 = rankVal [ 0 ] ;
2016-06-08 02:11:02 -07:00
{ int const rescale = ( maxTableLog - tableLog ) - 1 ; /* tableLog <= maxTableLog */
2016-05-06 07:55:27 -07:00
U32 nextRankVal = 0 ;
U32 w ;
for ( w = 1 ; w < maxW + 1 ; w + + ) {
U32 current = nextRankVal ;
nextRankVal + = rankStats [ w ] < < ( w + rescale ) ;
rankVal0 [ w ] = current ;
} }
{ U32 const minBits = tableLog + 1 - maxW ;
U32 consumed ;
2016-06-08 02:11:02 -07:00
for ( consumed = minBits ; consumed < maxTableLog - minBits + 1 ; consumed + + ) {
2016-05-06 07:55:27 -07:00
U32 * const rankValPtr = rankVal [ consumed ] ;
U32 w ;
for ( w = 1 ; w < maxW + 1 ; w + + ) {
rankValPtr [ w ] = rankVal0 [ w ] > > consumed ;
} } } }
2015-10-18 14:18:32 -07:00
2016-06-08 02:11:02 -07:00
HUF_fillDTableX4 ( dt , maxTableLog ,
2015-10-18 14:18:32 -07:00
sortedSymbol , sizeOfSort ,
rankStart0 , rankVal , maxW ,
tableLog + 1 ) ;
2016-06-08 02:11:02 -07:00
dtd . currentTableLog = ( BYTE ) maxTableLog ;
memcpy ( DTable , & dtd , sizeof ( dtd ) ) ;
2015-10-18 14:18:32 -07:00
return iSize ;
}
static U32 HUF_decodeSymbolX4 ( void * op , BIT_DStream_t * DStream , const HUF_DEltX4 * dt , const U32 dtLog )
{
const size_t val = BIT_lookBitsFast ( DStream , dtLog ) ; /* note : dtLog >= 1 */
memcpy ( op , dt + val , 2 ) ;
BIT_skipBits ( DStream , dt [ val ] . nbBits ) ;
return dt [ val ] . length ;
}
static U32 HUF_decodeLastSymbolX4 ( void * op , BIT_DStream_t * DStream , const HUF_DEltX4 * dt , const U32 dtLog )
{
const size_t val = BIT_lookBitsFast ( DStream , dtLog ) ; /* note : dtLog >= 1 */
memcpy ( op , dt + val , 1 ) ;
if ( dt [ val ] . length = = 1 ) BIT_skipBits ( DStream , dt [ val ] . nbBits ) ;
2016-01-28 06:39:52 -08:00
else {
if ( DStream - > bitsConsumed < ( sizeof ( DStream - > bitContainer ) * 8 ) ) {
2015-10-18 14:18:32 -07:00
BIT_skipBits ( DStream , dt [ val ] . nbBits ) ;
if ( DStream - > bitsConsumed > ( sizeof ( DStream - > bitContainer ) * 8 ) )
DStream - > bitsConsumed = ( sizeof ( DStream - > bitContainer ) * 8 ) ; /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
2016-01-28 06:39:52 -08:00
} }
2015-10-18 14:18:32 -07:00
return 1 ;
}
# define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
ptr + = HUF_decodeSymbolX4 ( ptr , DStreamPtr , dt , dtLog )
# define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
2016-05-20 05:36:36 -07:00
if ( MEM_64bits ( ) | | ( HUF_TABLELOG_MAX < = 12 ) ) \
2015-10-18 14:18:32 -07:00
ptr + = HUF_decodeSymbolX4 ( ptr , DStreamPtr , dt , dtLog )
# define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
2015-10-21 02:01:09 -07:00
if ( MEM_64bits ( ) ) \
2015-10-18 14:18:32 -07:00
ptr + = HUF_decodeSymbolX4 ( ptr , DStreamPtr , dt , dtLog )
static inline size_t HUF_decodeStreamX4 ( BYTE * p , BIT_DStream_t * bitDPtr , BYTE * const pEnd , const HUF_DEltX4 * const dt , const U32 dtLog )
{
BYTE * const pStart = p ;
/* up to 8 symbols at a time */
2016-01-28 06:39:52 -08:00
while ( ( BIT_reloadDStream ( bitDPtr ) = = BIT_DStream_unfinished ) & & ( p < pEnd - 7 ) ) {
2015-10-18 14:18:32 -07:00
HUF_DECODE_SYMBOLX4_2 ( p , bitDPtr ) ;
HUF_DECODE_SYMBOLX4_1 ( p , bitDPtr ) ;
HUF_DECODE_SYMBOLX4_2 ( p , bitDPtr ) ;
HUF_DECODE_SYMBOLX4_0 ( p , bitDPtr ) ;
}
2016-06-08 02:11:02 -07:00
/* closer to end : up to 2 symbols at a time */
2015-10-18 14:18:32 -07:00
while ( ( BIT_reloadDStream ( bitDPtr ) = = BIT_DStream_unfinished ) & & ( p < = pEnd - 2 ) )
HUF_DECODE_SYMBOLX4_0 ( p , bitDPtr ) ;
while ( p < = pEnd - 2 )
HUF_DECODE_SYMBOLX4_0 ( p , bitDPtr ) ; /* no need to reload : reached the end of DStream */
if ( p < pEnd )
p + = HUF_decodeLastSymbolX4 ( p , bitDPtr , dt , dtLog ) ;
return p - pStart ;
}
size_t HUF_decompress1X4_usingDTable (
void * dst , size_t dstSize ,
const void * cSrc , size_t cSrcSize ,
2016-06-08 02:11:02 -07:00
const HUF_DTable * DTable )
2015-10-18 14:18:32 -07:00
{
2016-06-08 02:11:02 -07:00
BIT_DStream_t bitD ;
2015-10-18 14:18:32 -07:00
/* Init */
2016-06-08 02:11:02 -07:00
{ size_t const errorCode = BIT_initDStream ( & bitD , cSrc , cSrcSize ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ;
}
2015-10-18 14:18:32 -07:00
2016-03-19 21:40:39 -07:00
/* decode */
2016-06-08 02:11:02 -07:00
{ BYTE * const ostart = ( BYTE * ) dst ;
BYTE * const oend = ostart + dstSize ;
const void * const dtPtr = DTable + 1 ; /* force compiler to not use strict-aliasing */
const HUF_DEltX4 * const dt = ( const HUF_DEltX4 * ) dtPtr ;
DTableDesc dtd ;
memcpy ( & dtd , DTable , sizeof ( dtd ) ) ;
HUF_decodeStreamX4 ( ostart , & bitD , oend , dt , dtd . currentTableLog ) ;
}
2015-10-18 14:18:32 -07:00
/* check */
if ( ! BIT_endOfDStream ( & bitD ) ) return ERROR ( corruption_detected ) ;
/* decoded size */
return dstSize ;
}
size_t HUF_decompress1X4 ( void * dst , size_t dstSize , const void * cSrc , size_t cSrcSize )
{
2016-05-20 05:36:36 -07:00
HUF_CREATE_STATIC_DTABLEX4 ( DTable , HUF_TABLELOG_MAX ) ;
2015-10-18 14:18:32 -07:00
const BYTE * ip = ( const BYTE * ) cSrc ;
2016-03-19 21:40:39 -07:00
size_t const hSize = HUF_readDTableX4 ( DTable , cSrc , cSrcSize ) ;
2015-10-18 14:18:32 -07:00
if ( HUF_isError ( hSize ) ) return hSize ;
if ( hSize > = cSrcSize ) return ERROR ( srcSize_wrong ) ;
ip + = hSize ;
cSrcSize - = hSize ;
return HUF_decompress1X4_usingDTable ( dst , dstSize , ip , cSrcSize , DTable ) ;
}
size_t HUF_decompress4X4_usingDTable (
void * dst , size_t dstSize ,
const void * cSrc , size_t cSrcSize ,
2016-06-08 02:11:02 -07:00
const HUF_DTable * DTable )
2015-10-18 14:18:32 -07:00
{
if ( cSrcSize < 10 ) return ERROR ( corruption_detected ) ; /* strict minimum : jump table + 1 byte per stream */
2016-03-19 21:40:39 -07:00
{ const BYTE * const istart = ( const BYTE * ) cSrc ;
2015-10-18 14:18:32 -07:00
BYTE * const ostart = ( BYTE * ) dst ;
BYTE * const oend = ostart + dstSize ;
2016-06-08 02:11:02 -07:00
const void * const dtPtr = DTable + 1 ;
const HUF_DEltX4 * const dt = ( const HUF_DEltX4 * ) dtPtr ;
2015-10-18 14:18:32 -07:00
/* Init */
BIT_DStream_t bitD1 ;
BIT_DStream_t bitD2 ;
BIT_DStream_t bitD3 ;
BIT_DStream_t bitD4 ;
2016-06-08 02:11:02 -07:00
size_t const length1 = MEM_readLE16 ( istart ) ;
size_t const length2 = MEM_readLE16 ( istart + 2 ) ;
size_t const length3 = MEM_readLE16 ( istart + 4 ) ;
size_t const length4 = cSrcSize - ( length1 + length2 + length3 + 6 ) ;
2015-10-18 14:18:32 -07:00
const BYTE * const istart1 = istart + 6 ; /* jumpTable */
const BYTE * const istart2 = istart1 + length1 ;
const BYTE * const istart3 = istart2 + length2 ;
const BYTE * const istart4 = istart3 + length3 ;
2016-06-08 02:11:02 -07:00
size_t const segmentSize = ( dstSize + 3 ) / 4 ;
2015-10-18 14:18:32 -07:00
BYTE * const opStart2 = ostart + segmentSize ;
BYTE * const opStart3 = opStart2 + segmentSize ;
BYTE * const opStart4 = opStart3 + segmentSize ;
BYTE * op1 = ostart ;
BYTE * op2 = opStart2 ;
BYTE * op3 = opStart3 ;
BYTE * op4 = opStart4 ;
U32 endSignal ;
2016-06-08 02:11:02 -07:00
DTableDesc dtd ;
U32 dtLog ;
memcpy ( & dtd , DTable , sizeof ( dtd ) ) ;
dtLog = dtd . currentTableLog ;
2015-10-18 14:18:32 -07:00
if ( length4 > cSrcSize ) return ERROR ( corruption_detected ) ; /* overflow */
2016-06-08 02:11:02 -07:00
{ size_t const errorCode = BIT_initDStream ( & bitD1 , istart1 , length1 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
{ size_t const errorCode = BIT_initDStream ( & bitD2 , istart2 , length2 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
{ size_t const errorCode = BIT_initDStream ( & bitD3 , istart3 , length3 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
{ size_t const errorCode = BIT_initDStream ( & bitD4 , istart4 , length4 ) ;
if ( HUF_isError ( errorCode ) ) return errorCode ; }
2015-10-18 14:18:32 -07:00
/* 16-32 symbols per loop (4-8 symbols per stream) */
endSignal = BIT_reloadDStream ( & bitD1 ) | BIT_reloadDStream ( & bitD2 ) | BIT_reloadDStream ( & bitD3 ) | BIT_reloadDStream ( & bitD4 ) ;
2016-01-28 06:39:52 -08:00
for ( ; ( endSignal = = BIT_DStream_unfinished ) & & ( op4 < ( oend - 7 ) ) ; ) {
2015-10-18 14:18:32 -07:00
HUF_DECODE_SYMBOLX4_2 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX4_2 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX4_2 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX4_2 ( op4 , & bitD4 ) ;
HUF_DECODE_SYMBOLX4_1 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX4_1 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX4_1 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX4_1 ( op4 , & bitD4 ) ;
HUF_DECODE_SYMBOLX4_2 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX4_2 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX4_2 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX4_2 ( op4 , & bitD4 ) ;
HUF_DECODE_SYMBOLX4_0 ( op1 , & bitD1 ) ;
HUF_DECODE_SYMBOLX4_0 ( op2 , & bitD2 ) ;
HUF_DECODE_SYMBOLX4_0 ( op3 , & bitD3 ) ;
HUF_DECODE_SYMBOLX4_0 ( op4 , & bitD4 ) ;
endSignal = BIT_reloadDStream ( & bitD1 ) | BIT_reloadDStream ( & bitD2 ) | BIT_reloadDStream ( & bitD3 ) | BIT_reloadDStream ( & bitD4 ) ;
}
/* check corruption */
if ( op1 > opStart2 ) return ERROR ( corruption_detected ) ;
if ( op2 > opStart3 ) return ERROR ( corruption_detected ) ;
if ( op3 > opStart4 ) return ERROR ( corruption_detected ) ;
/* note : op4 supposed already verified within main loop */
/* finish bitStreams one by one */
HUF_decodeStreamX4 ( op1 , & bitD1 , opStart2 , dt , dtLog ) ;
HUF_decodeStreamX4 ( op2 , & bitD2 , opStart3 , dt , dtLog ) ;
HUF_decodeStreamX4 ( op3 , & bitD3 , opStart4 , dt , dtLog ) ;
HUF_decodeStreamX4 ( op4 , & bitD4 , oend , dt , dtLog ) ;
/* check */
2016-06-08 02:11:02 -07:00
{ U32 const endCheck = BIT_endOfDStream ( & bitD1 ) & BIT_endOfDStream ( & bitD2 ) & BIT_endOfDStream ( & bitD3 ) & BIT_endOfDStream ( & bitD4 ) ;
if ( ! endCheck ) return ERROR ( corruption_detected ) ; }
2015-10-18 14:18:32 -07:00
/* decoded size */
return dstSize ;
}
}
size_t HUF_decompress4X4 ( void * dst , size_t dstSize , const void * cSrc , size_t cSrcSize )
{
2016-05-20 05:36:36 -07:00
HUF_CREATE_STATIC_DTABLEX4 ( DTable , HUF_TABLELOG_MAX ) ;
2015-10-18 14:18:32 -07:00
const BYTE * ip = ( const BYTE * ) cSrc ;
size_t hSize = HUF_readDTableX4 ( DTable , cSrc , cSrcSize ) ;
if ( HUF_isError ( hSize ) ) return hSize ;
if ( hSize > = cSrcSize ) return ERROR ( srcSize_wrong ) ;
ip + = hSize ;
cSrcSize - = hSize ;
return HUF_decompress4X4_usingDTable ( dst , dstSize , ip , cSrcSize , DTable ) ;
}
2016-01-23 10:28:41 -08:00
/* ********************************/
2015-10-18 14:18:32 -07:00
/* Generic decompression selector */
2016-01-23 10:28:41 -08:00
/* ********************************/
2015-10-18 14:18:32 -07:00
typedef struct { U32 tableTime ; U32 decode256Time ; } algo_time_t ;
static const algo_time_t algoTime [ 16 /* Quantization */ ] [ 3 /* single, double, quad */ ] =
{
/* single, double, quad */
{ { 0 , 0 } , { 1 , 1 } , { 2 , 2 } } , /* Q==0 : impossible */
{ { 0 , 0 } , { 1 , 1 } , { 2 , 2 } } , /* Q==1 : impossible */
{ { 38 , 130 } , { 1313 , 74 } , { 2151 , 38 } } , /* Q == 2 : 12-18% */
{ { 448 , 128 } , { 1353 , 74 } , { 2238 , 41 } } , /* Q == 3 : 18-25% */
{ { 556 , 128 } , { 1353 , 74 } , { 2238 , 47 } } , /* Q == 4 : 25-32% */
{ { 714 , 128 } , { 1418 , 74 } , { 2436 , 53 } } , /* Q == 5 : 32-38% */
{ { 883 , 128 } , { 1437 , 74 } , { 2464 , 61 } } , /* Q == 6 : 38-44% */
{ { 897 , 128 } , { 1515 , 75 } , { 2622 , 68 } } , /* Q == 7 : 44-50% */
{ { 926 , 128 } , { 1613 , 75 } , { 2730 , 75 } } , /* Q == 8 : 50-56% */
{ { 947 , 128 } , { 1729 , 77 } , { 3359 , 77 } } , /* Q == 9 : 56-62% */
{ { 1107 , 128 } , { 2083 , 81 } , { 4006 , 84 } } , /* Q ==10 : 62-69% */
{ { 1177 , 128 } , { 2379 , 87 } , { 4785 , 88 } } , /* Q ==11 : 69-75% */
{ { 1242 , 128 } , { 2415 , 93 } , { 5155 , 84 } } , /* Q ==12 : 75-81% */
{ { 1349 , 128 } , { 2644 , 106 } , { 5260 , 106 } } , /* Q ==13 : 81-87% */
{ { 1455 , 128 } , { 2422 , 124 } , { 4174 , 124 } } , /* Q ==14 : 87-93% */
{ { 722 , 128 } , { 1891 , 145 } , { 1936 , 146 } } , /* Q ==15 : 93-99% */
} ;
2016-06-08 02:11:02 -07:00
/** HUF_selectDecoder() :
* Tells which decoder is likely to decode faster ,
* based on a set of pre - determined metrics .
* @ return : 0 = = HUF_decompress4X2 , 1 = = HUF_decompress4X4 .
* Assumption : 0 < cSrcSize < dstSize < = 128 KB */
U32 HUF_selectDecoder ( size_t dstSize , size_t cSrcSize )
{
/* decoder timing evaluation */
U32 const Q = ( U32 ) ( cSrcSize * 16 / dstSize ) ; /* Q < 16 since dstSize > cSrcSize */
U32 const D256 = ( U32 ) ( dstSize > > 8 ) ;
U32 const DTime0 = algoTime [ Q ] [ 0 ] . tableTime + ( algoTime [ Q ] [ 0 ] . decode256Time * D256 ) ;
U32 DTime1 = algoTime [ Q ] [ 1 ] . tableTime + ( algoTime [ Q ] [ 1 ] . decode256Time * D256 ) ;
DTime1 + = DTime1 > > 3 ; /* advantage to algorithm using less memory, for cache eviction */
return DTime1 < DTime0 ;
}
2015-10-18 14:18:32 -07:00
typedef size_t ( * decompressionAlgo ) ( void * dst , size_t dstSize , const void * cSrc , size_t cSrcSize ) ;
size_t HUF_decompress ( void * dst , size_t dstSize , const void * cSrc , size_t cSrcSize )
{
2016-06-08 02:11:02 -07:00
static const decompressionAlgo decompress [ 2 ] = { HUF_decompress4X2 , HUF_decompress4X4 } ;
2015-10-18 14:18:32 -07:00
/* validation checks */
if ( dstSize = = 0 ) return ERROR ( dstSize_tooSmall ) ;
if ( cSrcSize > dstSize ) return ERROR ( corruption_detected ) ; /* invalid */
if ( cSrcSize = = dstSize ) { memcpy ( dst , cSrc , dstSize ) ; return dstSize ; } /* not compressed */
2015-10-21 01:07:25 -07:00
if ( cSrcSize = = 1 ) { memset ( dst , * ( const BYTE * ) cSrc , dstSize ) ; return dstSize ; } /* RLE */
2015-10-18 14:18:32 -07:00
2016-06-08 02:11:02 -07:00
{ U32 const algoNb = HUF_selectDecoder ( dstSize , cSrcSize ) ;
2016-05-05 03:41:36 -07:00
return decompress [ algoNb ] ( dst , dstSize , cSrc , cSrcSize ) ;
}
2015-10-18 14:18:32 -07:00
//return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); /* multi-streams single-symbol decoding */
//return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize); /* multi-streams double-symbols decoding */
}