Path: blob/main/sys/contrib/zstd/lib/legacy/zstd_v06.c
48378 views
/*1* Copyright (c) Yann Collet, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under both the BSD-style license (found in the5* LICENSE file in the root directory of this source tree) and the GPLv2 (found6* in the COPYING file in the root directory of this source tree).7* You may select, at your option, one of the above-listed licenses.8*/91011/*- Dependencies -*/12#include "zstd_v06.h"13#include <stddef.h> /* size_t, ptrdiff_t */14#include <string.h> /* memcpy */15#include <stdlib.h> /* malloc, free, qsort */16#include "../common/error_private.h"17181920/* ******************************************************************21mem.h22low-level memory access routines23Copyright (C) 2013-2015, Yann Collet.2425BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)2627Redistribution and use in source and binary forms, with or without28modification, are permitted provided that the following conditions are29met:3031* Redistributions of source code must retain the above copyright32notice, this list of conditions and the following disclaimer.33* Redistributions in binary form must reproduce the above34copyright notice, this list of conditions and the following disclaimer35in the documentation and/or other materials provided with the36distribution.3738THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS39"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT40LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR41A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT42OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,43SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT44LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,45DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY46THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT47(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE48OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.4950You can contact the author at :51- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy52- Public forum : https://groups.google.com/forum/#!forum/lz4c53****************************************************************** */54#ifndef MEM_H_MODULE55#define MEM_H_MODULE5657#if defined (__cplusplus)58extern "C" {59#endif606162/*-****************************************63* Compiler specifics64******************************************/65#if defined(_MSC_VER) /* Visual Studio */66# include <stdlib.h> /* _byteswap_ulong */67# include <intrin.h> /* _byteswap_* */68#endif69#if defined(__GNUC__)70# define MEM_STATIC static __attribute__((unused))71#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)72# define MEM_STATIC static inline73#elif defined(_MSC_VER)74# define MEM_STATIC static __inline75#else76# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */77#endif787980/*-**************************************************************81* Basic Types82*****************************************************************/83#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )84# if defined(_AIX)85# include <inttypes.h>86# else87# include <stdint.h> /* intptr_t */88# endif89typedef uint8_t BYTE;90typedef uint16_t U16;91typedef int16_t S16;92typedef uint32_t U32;93typedef int32_t S32;94typedef uint64_t U64;95typedef int64_t S64;96#else97typedef unsigned char BYTE;98typedef unsigned short U16;99typedef signed short S16;100typedef unsigned int U32;101typedef signed int S32;102typedef unsigned long long U64;103typedef signed long long S64;104#endif105106107/*-**************************************************************108* Memory I/O109*****************************************************************/110/* MEM_FORCE_MEMORY_ACCESS :111* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.112* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.113* The below switch allow to select different access method for improved performance.114* Method 0 (default) : use `memcpy()`. Safe and portable.115* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).116* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.117* Method 2 : direct access. This method is portable but violate C standard.118* It can generate buggy code on targets depending on alignment.119* In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)120* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.121* Prefer these methods in priority order (0 > 1 > 2)122*/123#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */124# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)125# define MEM_FORCE_MEMORY_ACCESS 1126# endif127#endif128129MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }130MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }131132MEM_STATIC unsigned MEM_isLittleEndian(void)133{134const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */135return one.c[0];136}137138#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)139140/* violates C standard, by lying on structure alignment.141Only use if no other choice to achieve best performance on target platform */142MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }143MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }144MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }145146MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }147148#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)149150/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */151/* currently only defined for gcc and icc */152typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;153154MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }155MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }156MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }157158MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }159160#else161162/* default method, safe and standard.163can sometimes prove slower */164165MEM_STATIC U16 MEM_read16(const void* memPtr)166{167U16 val; memcpy(&val, memPtr, sizeof(val)); return val;168}169170MEM_STATIC U32 MEM_read32(const void* memPtr)171{172U32 val; memcpy(&val, memPtr, sizeof(val)); return val;173}174175MEM_STATIC U64 MEM_read64(const void* memPtr)176{177U64 val; memcpy(&val, memPtr, sizeof(val)); return val;178}179180MEM_STATIC void MEM_write16(void* memPtr, U16 value)181{182memcpy(memPtr, &value, sizeof(value));183}184185186#endif /* MEM_FORCE_MEMORY_ACCESS */187188MEM_STATIC U32 MEM_swap32(U32 in)189{190#if defined(_MSC_VER) /* Visual Studio */191return _byteswap_ulong(in);192#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)193return __builtin_bswap32(in);194#else195return ((in << 24) & 0xff000000 ) |196((in << 8) & 0x00ff0000 ) |197((in >> 8) & 0x0000ff00 ) |198((in >> 24) & 0x000000ff );199#endif200}201202MEM_STATIC U64 MEM_swap64(U64 in)203{204#if defined(_MSC_VER) /* Visual Studio */205return _byteswap_uint64(in);206#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)207return __builtin_bswap64(in);208#else209return ((in << 56) & 0xff00000000000000ULL) |210((in << 40) & 0x00ff000000000000ULL) |211((in << 24) & 0x0000ff0000000000ULL) |212((in << 8) & 0x000000ff00000000ULL) |213((in >> 8) & 0x00000000ff000000ULL) |214((in >> 24) & 0x0000000000ff0000ULL) |215((in >> 40) & 0x000000000000ff00ULL) |216((in >> 56) & 0x00000000000000ffULL);217#endif218}219220221/*=== Little endian r/w ===*/222223MEM_STATIC U16 MEM_readLE16(const void* memPtr)224{225if (MEM_isLittleEndian())226return MEM_read16(memPtr);227else {228const BYTE* p = (const BYTE*)memPtr;229return (U16)(p[0] + (p[1]<<8));230}231}232233MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)234{235if (MEM_isLittleEndian()) {236MEM_write16(memPtr, val);237} else {238BYTE* p = (BYTE*)memPtr;239p[0] = (BYTE)val;240p[1] = (BYTE)(val>>8);241}242}243244MEM_STATIC U32 MEM_readLE32(const void* memPtr)245{246if (MEM_isLittleEndian())247return MEM_read32(memPtr);248else249return MEM_swap32(MEM_read32(memPtr));250}251252253MEM_STATIC U64 MEM_readLE64(const void* memPtr)254{255if (MEM_isLittleEndian())256return MEM_read64(memPtr);257else258return MEM_swap64(MEM_read64(memPtr));259}260261262MEM_STATIC size_t MEM_readLEST(const void* memPtr)263{264if (MEM_32bits())265return (size_t)MEM_readLE32(memPtr);266else267return (size_t)MEM_readLE64(memPtr);268}269270271272#if defined (__cplusplus)273}274#endif275276#endif /* MEM_H_MODULE */277278/*279zstd - standard compression library280Header File for static linking only281Copyright (C) 2014-2016, Yann Collet.282283BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)284285Redistribution and use in source and binary forms, with or without286modification, are permitted provided that the following conditions are287met:288* Redistributions of source code must retain the above copyright289notice, this list of conditions and the following disclaimer.290* Redistributions in binary form must reproduce the above291copyright notice, this list of conditions and the following disclaimer292in the documentation and/or other materials provided with the293distribution.294THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS295"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT296LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR297A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT298OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,299SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT300LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,301DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY302THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT303(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE304OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.305306You can contact the author at :307- zstd homepage : http://www.zstd.net308*/309#ifndef ZSTDv06_STATIC_H310#define ZSTDv06_STATIC_H311312/* The prototypes defined within this file are considered experimental.313* They should not be used in the context DLL as they may change in the future.314* Prefer static linking if you need them, to control breaking version changes issues.315*/316317#if defined (__cplusplus)318extern "C" {319#endif320321322323/*- Advanced Decompression functions -*/324325/*! ZSTDv06_decompress_usingPreparedDCtx() :326* Same as ZSTDv06_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.327* It avoids reloading the dictionary each time.328* `preparedDCtx` must have been properly initialized using ZSTDv06_decompressBegin_usingDict().329* Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */330ZSTDLIBv06_API size_t ZSTDv06_decompress_usingPreparedDCtx(331ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx,332void* dst, size_t dstCapacity,333const void* src, size_t srcSize);334335336337#define ZSTDv06_FRAMEHEADERSIZE_MAX 13 /* for static allocation */338static const size_t ZSTDv06_frameHeaderSize_min = 5;339static const size_t ZSTDv06_frameHeaderSize_max = ZSTDv06_FRAMEHEADERSIZE_MAX;340341ZSTDLIBv06_API size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx);342343/*344Streaming decompression, direct mode (bufferless)345346A ZSTDv06_DCtx object is required to track streaming operations.347Use ZSTDv06_createDCtx() / ZSTDv06_freeDCtx() to manage it.348A ZSTDv06_DCtx object can be re-used multiple times.349350First optional operation is to retrieve frame parameters, using ZSTDv06_getFrameParams(), which doesn't consume the input.351It can provide the minimum size of rolling buffer required to properly decompress data,352and optionally the final size of uncompressed content.353(Note : content size is an optional info that may not be present. 0 means : content size unknown)354Frame parameters are extracted from the beginning of compressed frame.355The amount of data to read is variable, from ZSTDv06_frameHeaderSize_min to ZSTDv06_frameHeaderSize_max (so if `srcSize` >= ZSTDv06_frameHeaderSize_max, it will always work)356If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.357Result : 0 when successful, it means the ZSTDv06_frameParams structure has been filled.358>0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.359errorCode, which can be tested using ZSTDv06_isError()360361Start decompression, with ZSTDv06_decompressBegin() or ZSTDv06_decompressBegin_usingDict().362Alternatively, you can copy a prepared context, using ZSTDv06_copyDCtx().363364Then use ZSTDv06_nextSrcSizeToDecompress() and ZSTDv06_decompressContinue() alternatively.365ZSTDv06_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv06_decompressContinue().366ZSTDv06_decompressContinue() requires this exact amount of bytes, or it will fail.367ZSTDv06_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).368They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.369370@result of ZSTDv06_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity)371It can be zero, which is not an error; it just means ZSTDv06_decompressContinue() has decoded some header.372373A frame is fully decoded when ZSTDv06_nextSrcSizeToDecompress() returns zero.374Context can then be reset to start a new decompression.375*/376377378/* **************************************379* Block functions380****************************************/381/*! Block functions produce and decode raw zstd blocks, without frame metadata.382User will have to take in charge required information to regenerate data, such as compressed and content sizes.383384A few rules to respect :385- Uncompressed block size must be <= ZSTDv06_BLOCKSIZE_MAX (128 KB)386- Compressing or decompressing requires a context structure387+ Use ZSTDv06_createCCtx() and ZSTDv06_createDCtx()388- It is necessary to init context before starting389+ compression : ZSTDv06_compressBegin()390+ decompression : ZSTDv06_decompressBegin()391+ variants _usingDict() are also allowed392+ copyCCtx() and copyDCtx() work too393- When a block is considered not compressible enough, ZSTDv06_compressBlock() result will be zero.394In which case, nothing is produced into `dst`.395+ User must test for such outcome and deal directly with uncompressed data396+ ZSTDv06_decompressBlock() doesn't accept uncompressed data as input !!397*/398399#define ZSTDv06_BLOCKSIZE_MAX (128 * 1024) /* define, for static allocation */400ZSTDLIBv06_API size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);401402403404#if defined (__cplusplus)405}406#endif407408#endif /* ZSTDv06_STATIC_H */409/*410zstd_internal - common functions to include411Header File for include412Copyright (C) 2014-2016, Yann Collet.413414BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)415416Redistribution and use in source and binary forms, with or without417modification, are permitted provided that the following conditions are418met:419* Redistributions of source code must retain the above copyright420notice, this list of conditions and the following disclaimer.421* Redistributions in binary form must reproduce the above422copyright notice, this list of conditions and the following disclaimer423in the documentation and/or other materials provided with the424distribution.425THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS426"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT427LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR428A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT429OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,430SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT431LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,432DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY433THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT434(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE435OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.436437You can contact the author at :438- zstd homepage : https://www.zstd.net439*/440#ifndef ZSTDv06_CCOMMON_H_MODULE441#define ZSTDv06_CCOMMON_H_MODULE442443444/*-*************************************445* Common macros446***************************************/447#define MIN(a,b) ((a)<(b) ? (a) : (b))448#define MAX(a,b) ((a)>(b) ? (a) : (b))449450451/*-*************************************452* Common constants453***************************************/454#define ZSTDv06_DICT_MAGIC 0xEC30A436455456#define ZSTDv06_REP_NUM 3457#define ZSTDv06_REP_INIT ZSTDv06_REP_NUM458#define ZSTDv06_REP_MOVE (ZSTDv06_REP_NUM-1)459460#define KB *(1 <<10)461#define MB *(1 <<20)462#define GB *(1U<<30)463464#define BIT7 128465#define BIT6 64466#define BIT5 32467#define BIT4 16468#define BIT1 2469#define BIT0 1470471#define ZSTDv06_WINDOWLOG_ABSOLUTEMIN 12472static const size_t ZSTDv06_fcs_fieldSize[4] = { 0, 1, 2, 8 };473474#define ZSTDv06_BLOCKHEADERSIZE 3 /* because C standard does not allow a static const value to be defined using another static const value .... :( */475static const size_t ZSTDv06_blockHeaderSize = ZSTDv06_BLOCKHEADERSIZE;476typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;477478#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */479#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */480481#define HufLog 12482483#define IS_HUF 0484#define IS_PCH 1485#define IS_RAW 2486#define IS_RLE 3487488#define LONGNBSEQ 0x7F00489490#define MINMATCH 3491#define EQUAL_READ32 4492#define REPCODE_STARTVALUE 1493494#define Litbits 8495#define MaxLit ((1<<Litbits) - 1)496#define MaxML 52497#define MaxLL 35498#define MaxOff 28499#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */500#define MLFSELog 9501#define LLFSELog 9502#define OffFSELog 8503504#define FSEv06_ENCODING_RAW 0505#define FSEv06_ENCODING_RLE 1506#define FSEv06_ENCODING_STATIC 2507#define FSEv06_ENCODING_DYNAMIC 3508509#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)510511static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,5121, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,51313,14,15,16 };514static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,5152, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,516-1,-1,-1,-1 };517static const U32 LL_defaultNormLog = 6;518519static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,5200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,5211, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,52212,13,14,15,16 };523static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,5241, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,5251, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,526-1,-1,-1,-1,-1 };527static const U32 ML_defaultNormLog = 6;528529static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,5301, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };531static const U32 OF_defaultNormLog = 5;532533534/*-*******************************************535* Shared functions to include for inlining536*********************************************/537static void ZSTDv06_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }538#define COPY8(d,s) { ZSTDv06_copy8(d,s); d+=8; s+=8; }539540/*! ZSTDv06_wildcopy() :541* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */542#define WILDCOPY_OVERLENGTH 8543MEM_STATIC void ZSTDv06_wildcopy(void* dst, const void* src, ptrdiff_t length)544{545const BYTE* ip = (const BYTE*)src;546BYTE* op = (BYTE*)dst;547BYTE* const oend = op + length;548do549COPY8(op, ip)550while (op < oend);551}552553554555/*-*******************************************556* Private interfaces557*********************************************/558typedef struct {559U32 off;560U32 len;561} ZSTDv06_match_t;562563typedef struct {564U32 price;565U32 off;566U32 mlen;567U32 litlen;568U32 rep[ZSTDv06_REP_INIT];569} ZSTDv06_optimal_t;570571typedef struct { U32 unused; } ZSTDv06_stats_t;572573typedef struct {574void* buffer;575U32* offsetStart;576U32* offset;577BYTE* offCodeStart;578BYTE* litStart;579BYTE* lit;580U16* litLengthStart;581U16* litLength;582BYTE* llCodeStart;583U16* matchLengthStart;584U16* matchLength;585BYTE* mlCodeStart;586U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */587U32 longLengthPos;588/* opt */589ZSTDv06_optimal_t* priceTable;590ZSTDv06_match_t* matchTable;591U32* matchLengthFreq;592U32* litLengthFreq;593U32* litFreq;594U32* offCodeFreq;595U32 matchLengthSum;596U32 matchSum;597U32 litLengthSum;598U32 litSum;599U32 offCodeSum;600U32 log2matchLengthSum;601U32 log2matchSum;602U32 log2litLengthSum;603U32 log2litSum;604U32 log2offCodeSum;605U32 factor;606U32 cachedPrice;607U32 cachedLitLength;608const BYTE* cachedLiterals;609ZSTDv06_stats_t stats;610} seqStore_t;611612void ZSTDv06_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq);613614615#endif /* ZSTDv06_CCOMMON_H_MODULE */616/* ******************************************************************617FSE : Finite State Entropy codec618Public Prototypes declaration619Copyright (C) 2013-2016, Yann Collet.620621BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)622623Redistribution and use in source and binary forms, with or without624modification, are permitted provided that the following conditions are625met:626627* Redistributions of source code must retain the above copyright628notice, this list of conditions and the following disclaimer.629* Redistributions in binary form must reproduce the above630copyright notice, this list of conditions and the following disclaimer631in the documentation and/or other materials provided with the632distribution.633634THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS635"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT636LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR637A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT638OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,639SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT640LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,641DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY642THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT643(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE644OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.645646You can contact the author at :647- Source repository : https://github.com/Cyan4973/FiniteStateEntropy648****************************************************************** */649#ifndef FSEv06_H650#define FSEv06_H651652#if defined (__cplusplus)653extern "C" {654#endif655656657658/*-****************************************659* FSE simple functions660******************************************/661/*! FSEv06_decompress():662Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',663into already allocated destination buffer 'dst', of size 'dstCapacity'.664@return : size of regenerated data (<= maxDstSize),665or an error code, which can be tested using FSEv06_isError() .666667** Important ** : FSEv06_decompress() does not decompress non-compressible nor RLE data !!!668Why ? : making this distinction requires a header.669Header management is intentionally delegated to the user layer, which can better manage special cases.670*/671size_t FSEv06_decompress(void* dst, size_t dstCapacity,672const void* cSrc, size_t cSrcSize);673674675/*-*****************************************676* Tool functions677******************************************/678size_t FSEv06_compressBound(size_t size); /* maximum compressed size */679680/* Error Management */681unsigned FSEv06_isError(size_t code); /* tells if a return value is an error code */682const char* FSEv06_getErrorName(size_t code); /* provides error code string (useful for debugging) */683684685686/*-*****************************************687* FSE detailed API688******************************************/689/*!690691FSEv06_decompress() does the following:6921. read normalized counters with readNCount()6932. build decoding table 'DTable' from normalized counters6943. decode the data stream using decoding table 'DTable'695696The following API allows targeting specific sub-functions for advanced tasks.697For example, it's possible to compress several blocks using the same 'CTable',698or to save and provide normalized distribution using external method.699*/700701702/* *** DECOMPRESSION *** */703704/*! FSEv06_readNCount():705Read compactly saved 'normalizedCounter' from 'rBuffer'.706@return : size read from 'rBuffer',707or an errorCode, which can be tested using FSEv06_isError().708maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */709size_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);710711/*! Constructor and Destructor of FSEv06_DTable.712Note that its size depends on 'tableLog' */713typedef unsigned FSEv06_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */714FSEv06_DTable* FSEv06_createDTable(unsigned tableLog);715void FSEv06_freeDTable(FSEv06_DTable* dt);716717/*! FSEv06_buildDTable():718Builds 'dt', which must be already allocated, using FSEv06_createDTable().719return : 0, or an errorCode, which can be tested using FSEv06_isError() */720size_t FSEv06_buildDTable (FSEv06_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);721722/*! FSEv06_decompress_usingDTable():723Decompress compressed source `cSrc` of size `cSrcSize` using `dt`724into `dst` which must be already allocated.725@return : size of regenerated data (necessarily <= `dstCapacity`),726or an errorCode, which can be tested using FSEv06_isError() */727size_t FSEv06_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv06_DTable* dt);728729/*!730Tutorial :731----------732(Note : these functions only decompress FSE-compressed blocks.733If block is uncompressed, use memcpy() instead734If block is a single repeated byte, use memset() instead )735736The first step is to obtain the normalized frequencies of symbols.737This can be performed by FSEv06_readNCount() if it was saved using FSEv06_writeNCount().738'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.739In practice, that means it's necessary to know 'maxSymbolValue' beforehand,740or size the table to handle worst case situations (typically 256).741FSEv06_readNCount() will provide 'tableLog' and 'maxSymbolValue'.742The result of FSEv06_readNCount() is the number of bytes read from 'rBuffer'.743Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.744If there is an error, the function will return an error code, which can be tested using FSEv06_isError().745746The next step is to build the decompression tables 'FSEv06_DTable' from 'normalizedCounter'.747This is performed by the function FSEv06_buildDTable().748The space required by 'FSEv06_DTable' must be already allocated using FSEv06_createDTable().749If there is an error, the function will return an error code, which can be tested using FSEv06_isError().750751`FSEv06_DTable` can then be used to decompress `cSrc`, with FSEv06_decompress_usingDTable().752`cSrcSize` must be strictly correct, otherwise decompression will fail.753FSEv06_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).754If there is an error, the function will return an error code, which can be tested using FSEv06_isError(). (ex: dst buffer too small)755*/756757758#if defined (__cplusplus)759}760#endif761762#endif /* FSEv06_H */763/* ******************************************************************764bitstream765Part of FSE library766header file (to include)767Copyright (C) 2013-2016, Yann Collet.768769BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)770771Redistribution and use in source and binary forms, with or without772modification, are permitted provided that the following conditions are773met:774775* Redistributions of source code must retain the above copyright776notice, this list of conditions and the following disclaimer.777* Redistributions in binary form must reproduce the above778copyright notice, this list of conditions and the following disclaimer779in the documentation and/or other materials provided with the780distribution.781782THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS783"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT784LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR785A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT786OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,787SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT788LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,789DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY790THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT791(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE792OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.793794You can contact the author at :795- Source repository : https://github.com/Cyan4973/FiniteStateEntropy796****************************************************************** */797#ifndef BITSTREAM_H_MODULE798#define BITSTREAM_H_MODULE799800#if defined (__cplusplus)801extern "C" {802#endif803804805/*806* This API consists of small unitary functions, which must be inlined for best performance.807* Since link-time-optimization is not available for all compilers,808* these functions are defined into a .h to be included.809*/810811812/*=========================================813* Target specific814=========================================*/815#if defined(__BMI__) && defined(__GNUC__)816# include <immintrin.h> /* support for bextr (experimental) */817#endif818819820821/*-********************************************822* bitStream decoding API (read backward)823**********************************************/824typedef struct825{826size_t bitContainer;827unsigned bitsConsumed;828const char* ptr;829const char* start;830} BITv06_DStream_t;831832typedef enum { BITv06_DStream_unfinished = 0,833BITv06_DStream_endOfBuffer = 1,834BITv06_DStream_completed = 2,835BITv06_DStream_overflow = 3 } BITv06_DStream_status; /* result of BITv06_reloadDStream() */836/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */837838MEM_STATIC size_t BITv06_initDStream(BITv06_DStream_t* bitD, const void* srcBuffer, size_t srcSize);839MEM_STATIC size_t BITv06_readBits(BITv06_DStream_t* bitD, unsigned nbBits);840MEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD);841MEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* bitD);842843844845/*-****************************************846* unsafe API847******************************************/848MEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, unsigned nbBits);849/* faster, but works only if nbBits >= 1 */850851852853/*-**************************************************************854* Internal functions855****************************************************************/856MEM_STATIC unsigned BITv06_highbit32 ( U32 val)857{858# if defined(_MSC_VER) /* Visual */859unsigned long r;860return _BitScanReverse(&r, val) ? (unsigned)r : 0;861# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */862return __builtin_clz (val) ^ 31;863# else /* Software version */864static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };865U32 v = val;866unsigned r;867v |= v >> 1;868v |= v >> 2;869v |= v >> 4;870v |= v >> 8;871v |= v >> 16;872r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];873return r;874# endif875}876877878879/*-********************************************************880* bitStream decoding881**********************************************************/882/*! BITv06_initDStream() :883* Initialize a BITv06_DStream_t.884* `bitD` : a pointer to an already allocated BITv06_DStream_t structure.885* `srcSize` must be the *exact* size of the bitStream, in bytes.886* @return : size of stream (== srcSize) or an errorCode if a problem is detected887*/888MEM_STATIC size_t BITv06_initDStream(BITv06_DStream_t* bitD, const void* srcBuffer, size_t srcSize)889{890if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }891892if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */893bitD->start = (const char*)srcBuffer;894bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);895bitD->bitContainer = MEM_readLEST(bitD->ptr);896{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];897if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */898bitD->bitsConsumed = 8 - BITv06_highbit32(lastByte); }899} else {900bitD->start = (const char*)srcBuffer;901bitD->ptr = bitD->start;902bitD->bitContainer = *(const BYTE*)(bitD->start);903switch(srcSize)904{905case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */906case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */907case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */908case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */909case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */910case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8; /* fall-through */911default: break;912}913{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];914if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */915bitD->bitsConsumed = 8 - BITv06_highbit32(lastByte); }916bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;917}918919return srcSize;920}921922923MEM_STATIC size_t BITv06_lookBits(const BITv06_DStream_t* bitD, U32 nbBits)924{925U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;926return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);927}928929/*! BITv06_lookBitsFast() :930* unsafe version; only works only if nbBits >= 1 */931MEM_STATIC size_t BITv06_lookBitsFast(const BITv06_DStream_t* bitD, U32 nbBits)932{933U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;934return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);935}936937MEM_STATIC void BITv06_skipBits(BITv06_DStream_t* bitD, U32 nbBits)938{939bitD->bitsConsumed += nbBits;940}941942MEM_STATIC size_t BITv06_readBits(BITv06_DStream_t* bitD, U32 nbBits)943{944size_t const value = BITv06_lookBits(bitD, nbBits);945BITv06_skipBits(bitD, nbBits);946return value;947}948949/*! BITv06_readBitsFast() :950* unsafe version; only works only if nbBits >= 1 */951MEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, U32 nbBits)952{953size_t const value = BITv06_lookBitsFast(bitD, nbBits);954BITv06_skipBits(bitD, nbBits);955return value;956}957958MEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD)959{960if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */961return BITv06_DStream_overflow;962963if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {964bitD->ptr -= bitD->bitsConsumed >> 3;965bitD->bitsConsumed &= 7;966bitD->bitContainer = MEM_readLEST(bitD->ptr);967return BITv06_DStream_unfinished;968}969if (bitD->ptr == bitD->start) {970if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv06_DStream_endOfBuffer;971return BITv06_DStream_completed;972}973{ U32 nbBytes = bitD->bitsConsumed >> 3;974BITv06_DStream_status result = BITv06_DStream_unfinished;975if (bitD->ptr - nbBytes < bitD->start) {976nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */977result = BITv06_DStream_endOfBuffer;978}979bitD->ptr -= nbBytes;980bitD->bitsConsumed -= nbBytes*8;981bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */982return result;983}984}985986/*! BITv06_endOfDStream() :987* @return Tells if DStream has exactly reached its end (all bits consumed).988*/989MEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* DStream)990{991return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));992}993994#if defined (__cplusplus)995}996#endif997998#endif /* BITSTREAM_H_MODULE */999/* ******************************************************************1000FSE : Finite State Entropy coder1001header file for static linking (only)1002Copyright (C) 2013-2015, Yann Collet10031004BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)10051006Redistribution and use in source and binary forms, with or without1007modification, are permitted provided that the following conditions are1008met:10091010* Redistributions of source code must retain the above copyright1011notice, this list of conditions and the following disclaimer.1012* Redistributions in binary form must reproduce the above1013copyright notice, this list of conditions and the following disclaimer1014in the documentation and/or other materials provided with the1015distribution.10161017THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1018"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1019LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1020A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1021OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1022SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1023LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1024DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1025THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1026(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1027OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.10281029You can contact the author at :1030- Source repository : https://github.com/Cyan4973/FiniteStateEntropy1031- Public forum : https://groups.google.com/forum/#!forum/lz4c1032****************************************************************** */1033#ifndef FSEv06_STATIC_H1034#define FSEv06_STATIC_H10351036#if defined (__cplusplus)1037extern "C" {1038#endif103910401041/* *****************************************1042* Static allocation1043*******************************************/1044/* FSE buffer bounds */1045#define FSEv06_NCOUNTBOUND 5121046#define FSEv06_BLOCKBOUND(size) (size + (size>>7))1047#define FSEv06_COMPRESSBOUND(size) (FSEv06_NCOUNTBOUND + FSEv06_BLOCKBOUND(size)) /* Macro version, useful for static allocation */10481049/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */1050#define FSEv06_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))105110521053/* *****************************************1054* FSE advanced API1055*******************************************/1056size_t FSEv06_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);1057/* same as FSEv06_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr */10581059size_t FSEv06_buildDTable_raw (FSEv06_DTable* dt, unsigned nbBits);1060/* build a fake FSEv06_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */10611062size_t FSEv06_buildDTable_rle (FSEv06_DTable* dt, unsigned char symbolValue);1063/* build a fake FSEv06_DTable, designed to always generate the same symbolValue */106410651066/* *****************************************1067* FSE symbol decompression API1068*******************************************/1069typedef struct1070{1071size_t state;1072const void* table; /* precise table may vary, depending on U16 */1073} FSEv06_DState_t;107410751076static void FSEv06_initDState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD, const FSEv06_DTable* dt);10771078static unsigned char FSEv06_decodeSymbol(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD);107910801081/* *****************************************1082* FSE unsafe API1083*******************************************/1084static unsigned char FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD);1085/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */108610871088/* *****************************************1089* Implementation of inlined functions1090*******************************************/109110921093/* ====== Decompression ====== */10941095typedef struct {1096U16 tableLog;1097U16 fastMode;1098} FSEv06_DTableHeader; /* sizeof U32 */10991100typedef struct1101{1102unsigned short newState;1103unsigned char symbol;1104unsigned char nbBits;1105} FSEv06_decode_t; /* size == U32 */11061107MEM_STATIC void FSEv06_initDState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD, const FSEv06_DTable* dt)1108{1109const void* ptr = dt;1110const FSEv06_DTableHeader* const DTableH = (const FSEv06_DTableHeader*)ptr;1111DStatePtr->state = BITv06_readBits(bitD, DTableH->tableLog);1112BITv06_reloadDStream(bitD);1113DStatePtr->table = dt + 1;1114}11151116MEM_STATIC BYTE FSEv06_peekSymbol(const FSEv06_DState_t* DStatePtr)1117{1118FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];1119return DInfo.symbol;1120}11211122MEM_STATIC void FSEv06_updateState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)1123{1124FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];1125U32 const nbBits = DInfo.nbBits;1126size_t const lowBits = BITv06_readBits(bitD, nbBits);1127DStatePtr->state = DInfo.newState + lowBits;1128}11291130MEM_STATIC BYTE FSEv06_decodeSymbol(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)1131{1132FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];1133U32 const nbBits = DInfo.nbBits;1134BYTE const symbol = DInfo.symbol;1135size_t const lowBits = BITv06_readBits(bitD, nbBits);11361137DStatePtr->state = DInfo.newState + lowBits;1138return symbol;1139}11401141/*! FSEv06_decodeSymbolFast() :1142unsafe, only works if no symbol has a probability > 50% */1143MEM_STATIC BYTE FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)1144{1145FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];1146U32 const nbBits = DInfo.nbBits;1147BYTE const symbol = DInfo.symbol;1148size_t const lowBits = BITv06_readBitsFast(bitD, nbBits);11491150DStatePtr->state = DInfo.newState + lowBits;1151return symbol;1152}1153115411551156#ifndef FSEv06_COMMONDEFS_ONLY11571158/* **************************************************************1159* Tuning parameters1160****************************************************************/1161/*!MEMORY_USAGE :1162* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)1163* Increasing memory usage improves compression ratio1164* Reduced memory usage can improve speed, due to cache effect1165* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */1166#define FSEv06_MAX_MEMORY_USAGE 141167#define FSEv06_DEFAULT_MEMORY_USAGE 1311681169/*!FSEv06_MAX_SYMBOL_VALUE :1170* Maximum symbol value authorized.1171* Required for proper stack allocation */1172#define FSEv06_MAX_SYMBOL_VALUE 255117311741175/* **************************************************************1176* template functions type & suffix1177****************************************************************/1178#define FSEv06_FUNCTION_TYPE BYTE1179#define FSEv06_FUNCTION_EXTENSION1180#define FSEv06_DECODE_TYPE FSEv06_decode_t118111821183#endif /* !FSEv06_COMMONDEFS_ONLY */118411851186/* ***************************************************************1187* Constants1188*****************************************************************/1189#define FSEv06_MAX_TABLELOG (FSEv06_MAX_MEMORY_USAGE-2)1190#define FSEv06_MAX_TABLESIZE (1U<<FSEv06_MAX_TABLELOG)1191#define FSEv06_MAXTABLESIZE_MASK (FSEv06_MAX_TABLESIZE-1)1192#define FSEv06_DEFAULT_TABLELOG (FSEv06_DEFAULT_MEMORY_USAGE-2)1193#define FSEv06_MIN_TABLELOG 511941195#define FSEv06_TABLELOG_ABSOLUTE_MAX 151196#if FSEv06_MAX_TABLELOG > FSEv06_TABLELOG_ABSOLUTE_MAX1197#error "FSEv06_MAX_TABLELOG > FSEv06_TABLELOG_ABSOLUTE_MAX is not supported"1198#endif11991200#define FSEv06_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)120112021203#if defined (__cplusplus)1204}1205#endif12061207#endif /* FSEv06_STATIC_H */1208/*1209Common functions of New Generation Entropy library1210Copyright (C) 2016, Yann Collet.12111212BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)12131214Redistribution and use in source and binary forms, with or without1215modification, are permitted provided that the following conditions are1216met:12171218* Redistributions of source code must retain the above copyright1219notice, this list of conditions and the following disclaimer.1220* Redistributions in binary form must reproduce the above1221copyright notice, this list of conditions and the following disclaimer1222in the documentation and/or other materials provided with the1223distribution.12241225THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1226"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1227LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1228A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1229OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1230SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1231LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1232DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1233THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1234(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1235OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.12361237You can contact the author at :1238- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy1239- Public forum : https://groups.google.com/forum/#!forum/lz4c1240*************************************************************************** */124112421243/*-****************************************1244* FSE Error Management1245******************************************/1246unsigned FSEv06_isError(size_t code) { return ERR_isError(code); }12471248const char* FSEv06_getErrorName(size_t code) { return ERR_getErrorName(code); }124912501251/* **************************************************************1252* HUF Error Management1253****************************************************************/1254static unsigned HUFv06_isError(size_t code) { return ERR_isError(code); }125512561257/*-**************************************************************1258* FSE NCount encoding-decoding1259****************************************************************/1260static short FSEv06_abs(short a) { return a<0 ? -a : a; }12611262size_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,1263const void* headerBuffer, size_t hbSize)1264{1265const BYTE* const istart = (const BYTE*) headerBuffer;1266const BYTE* const iend = istart + hbSize;1267const BYTE* ip = istart;1268int nbBits;1269int remaining;1270int threshold;1271U32 bitStream;1272int bitCount;1273unsigned charnum = 0;1274int previous0 = 0;12751276if (hbSize < 4) return ERROR(srcSize_wrong);1277bitStream = MEM_readLE32(ip);1278nbBits = (bitStream & 0xF) + FSEv06_MIN_TABLELOG; /* extract tableLog */1279if (nbBits > FSEv06_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);1280bitStream >>= 4;1281bitCount = 4;1282*tableLogPtr = nbBits;1283remaining = (1<<nbBits)+1;1284threshold = 1<<nbBits;1285nbBits++;12861287while ((remaining>1) && (charnum<=*maxSVPtr)) {1288if (previous0) {1289unsigned n0 = charnum;1290while ((bitStream & 0xFFFF) == 0xFFFF) {1291n0+=24;1292if (ip < iend-5) {1293ip+=2;1294bitStream = MEM_readLE32(ip) >> bitCount;1295} else {1296bitStream >>= 16;1297bitCount+=16;1298} }1299while ((bitStream & 3) == 3) {1300n0+=3;1301bitStream>>=2;1302bitCount+=2;1303}1304n0 += bitStream & 3;1305bitCount += 2;1306if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);1307while (charnum < n0) normalizedCounter[charnum++] = 0;1308if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {1309ip += bitCount>>3;1310bitCount &= 7;1311bitStream = MEM_readLE32(ip) >> bitCount;1312}1313else1314bitStream >>= 2;1315}1316{ short const max = (short)((2*threshold-1)-remaining);1317short count;13181319if ((bitStream & (threshold-1)) < (U32)max) {1320count = (short)(bitStream & (threshold-1));1321bitCount += nbBits-1;1322} else {1323count = (short)(bitStream & (2*threshold-1));1324if (count >= threshold) count -= max;1325bitCount += nbBits;1326}13271328count--; /* extra accuracy */1329remaining -= FSEv06_abs(count);1330normalizedCounter[charnum++] = count;1331previous0 = !count;1332while (remaining < threshold) {1333nbBits--;1334threshold >>= 1;1335}13361337if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {1338ip += bitCount>>3;1339bitCount &= 7;1340} else {1341bitCount -= (int)(8 * (iend - 4 - ip));1342ip = iend - 4;1343}1344bitStream = MEM_readLE32(ip) >> (bitCount & 31);1345} } /* while ((remaining>1) && (charnum<=*maxSVPtr)) */1346if (remaining != 1) return ERROR(GENERIC);1347*maxSVPtr = charnum-1;13481349ip += (bitCount+7)>>3;1350if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);1351return ip-istart;1352}1353/* ******************************************************************1354FSE : Finite State Entropy decoder1355Copyright (C) 2013-2015, Yann Collet.13561357BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)13581359Redistribution and use in source and binary forms, with or without1360modification, are permitted provided that the following conditions are1361met:13621363* Redistributions of source code must retain the above copyright1364notice, this list of conditions and the following disclaimer.1365* Redistributions in binary form must reproduce the above1366copyright notice, this list of conditions and the following disclaimer1367in the documentation and/or other materials provided with the1368distribution.13691370THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1371"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1372LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1373A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1374OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1375SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1376LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1377DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1378THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1379(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1380OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.13811382You can contact the author at :1383- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy1384- Public forum : https://groups.google.com/forum/#!forum/lz4c1385****************************************************************** */138613871388/* **************************************************************1389* Compiler specifics1390****************************************************************/1391#ifdef _MSC_VER /* Visual Studio */1392# define FORCE_INLINE static __forceinline1393# include <intrin.h> /* For Visual 2005 */1394# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */1395# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */1396#else1397# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */1398# ifdef __GNUC__1399# define FORCE_INLINE static inline __attribute__((always_inline))1400# else1401# define FORCE_INLINE static inline1402# endif1403# else1404# define FORCE_INLINE static1405# endif /* __STDC_VERSION__ */1406#endif140714081409/* **************************************************************1410* Error Management1411****************************************************************/1412#define FSEv06_isError ERR_isError1413#define FSEv06_STATIC_ASSERT(c) { enum { FSEv06_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */141414151416/* **************************************************************1417* Complex types1418****************************************************************/1419typedef U32 DTable_max_t[FSEv06_DTABLE_SIZE_U32(FSEv06_MAX_TABLELOG)];142014211422/* **************************************************************1423* Templates1424****************************************************************/1425/*1426designed to be included1427for type-specific functions (template emulation in C)1428Objective is to write these functions only once, for improved maintenance1429*/14301431/* safety checks */1432#ifndef FSEv06_FUNCTION_EXTENSION1433# error "FSEv06_FUNCTION_EXTENSION must be defined"1434#endif1435#ifndef FSEv06_FUNCTION_TYPE1436# error "FSEv06_FUNCTION_TYPE must be defined"1437#endif14381439/* Function names */1440#define FSEv06_CAT(X,Y) X##Y1441#define FSEv06_FUNCTION_NAME(X,Y) FSEv06_CAT(X,Y)1442#define FSEv06_TYPE_NAME(X,Y) FSEv06_CAT(X,Y)144314441445/* Function templates */1446FSEv06_DTable* FSEv06_createDTable (unsigned tableLog)1447{1448if (tableLog > FSEv06_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv06_TABLELOG_ABSOLUTE_MAX;1449return (FSEv06_DTable*)malloc( FSEv06_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );1450}14511452void FSEv06_freeDTable (FSEv06_DTable* dt)1453{1454free(dt);1455}14561457size_t FSEv06_buildDTable(FSEv06_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)1458{1459void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */1460FSEv06_DECODE_TYPE* const tableDecode = (FSEv06_DECODE_TYPE*) (tdPtr);1461U16 symbolNext[FSEv06_MAX_SYMBOL_VALUE+1];14621463U32 const maxSV1 = maxSymbolValue + 1;1464U32 const tableSize = 1 << tableLog;1465U32 highThreshold = tableSize-1;14661467/* Sanity Checks */1468if (maxSymbolValue > FSEv06_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);1469if (tableLog > FSEv06_MAX_TABLELOG) return ERROR(tableLog_tooLarge);14701471/* Init, lay down lowprob symbols */1472{ FSEv06_DTableHeader DTableH;1473DTableH.tableLog = (U16)tableLog;1474DTableH.fastMode = 1;1475{ S16 const largeLimit= (S16)(1 << (tableLog-1));1476U32 s;1477for (s=0; s<maxSV1; s++) {1478if (normalizedCounter[s]==-1) {1479tableDecode[highThreshold--].symbol = (FSEv06_FUNCTION_TYPE)s;1480symbolNext[s] = 1;1481} else {1482if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;1483symbolNext[s] = normalizedCounter[s];1484} } }1485memcpy(dt, &DTableH, sizeof(DTableH));1486}14871488/* Spread symbols */1489{ U32 const tableMask = tableSize-1;1490U32 const step = FSEv06_TABLESTEP(tableSize);1491U32 s, position = 0;1492for (s=0; s<maxSV1; s++) {1493int i;1494for (i=0; i<normalizedCounter[s]; i++) {1495tableDecode[position].symbol = (FSEv06_FUNCTION_TYPE)s;1496position = (position + step) & tableMask;1497while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */1498} }14991500if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */1501}15021503/* Build Decoding table */1504{ U32 u;1505for (u=0; u<tableSize; u++) {1506FSEv06_FUNCTION_TYPE const symbol = (FSEv06_FUNCTION_TYPE)(tableDecode[u].symbol);1507U16 nextState = symbolNext[symbol]++;1508tableDecode[u].nbBits = (BYTE) (tableLog - BITv06_highbit32 ((U32)nextState) );1509tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);1510} }15111512return 0;1513}1514151515161517#ifndef FSEv06_COMMONDEFS_ONLY15181519/*-*******************************************************1520* Decompression (Byte symbols)1521*********************************************************/1522size_t FSEv06_buildDTable_rle (FSEv06_DTable* dt, BYTE symbolValue)1523{1524void* ptr = dt;1525FSEv06_DTableHeader* const DTableH = (FSEv06_DTableHeader*)ptr;1526void* dPtr = dt + 1;1527FSEv06_decode_t* const cell = (FSEv06_decode_t*)dPtr;15281529DTableH->tableLog = 0;1530DTableH->fastMode = 0;15311532cell->newState = 0;1533cell->symbol = symbolValue;1534cell->nbBits = 0;15351536return 0;1537}153815391540size_t FSEv06_buildDTable_raw (FSEv06_DTable* dt, unsigned nbBits)1541{1542void* ptr = dt;1543FSEv06_DTableHeader* const DTableH = (FSEv06_DTableHeader*)ptr;1544void* dPtr = dt + 1;1545FSEv06_decode_t* const dinfo = (FSEv06_decode_t*)dPtr;1546const unsigned tableSize = 1 << nbBits;1547const unsigned tableMask = tableSize - 1;1548const unsigned maxSV1 = tableMask+1;1549unsigned s;15501551/* Sanity checks */1552if (nbBits < 1) return ERROR(GENERIC); /* min size */15531554/* Build Decoding Table */1555DTableH->tableLog = (U16)nbBits;1556DTableH->fastMode = 1;1557for (s=0; s<maxSV1; s++) {1558dinfo[s].newState = 0;1559dinfo[s].symbol = (BYTE)s;1560dinfo[s].nbBits = (BYTE)nbBits;1561}15621563return 0;1564}15651566FORCE_INLINE size_t FSEv06_decompress_usingDTable_generic(1567void* dst, size_t maxDstSize,1568const void* cSrc, size_t cSrcSize,1569const FSEv06_DTable* dt, const unsigned fast)1570{1571BYTE* const ostart = (BYTE*) dst;1572BYTE* op = ostart;1573BYTE* const omax = op + maxDstSize;1574BYTE* const olimit = omax-3;15751576BITv06_DStream_t bitD;1577FSEv06_DState_t state1;1578FSEv06_DState_t state2;15791580/* Init */1581{ size_t const errorCode = BITv06_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */1582if (FSEv06_isError(errorCode)) return errorCode; }15831584FSEv06_initDState(&state1, &bitD, dt);1585FSEv06_initDState(&state2, &bitD, dt);15861587#define FSEv06_GETSYMBOL(statePtr) fast ? FSEv06_decodeSymbolFast(statePtr, &bitD) : FSEv06_decodeSymbol(statePtr, &bitD)15881589/* 4 symbols per loop */1590for ( ; (BITv06_reloadDStream(&bitD)==BITv06_DStream_unfinished) && (op<olimit) ; op+=4) {1591op[0] = FSEv06_GETSYMBOL(&state1);15921593if (FSEv06_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1594BITv06_reloadDStream(&bitD);15951596op[1] = FSEv06_GETSYMBOL(&state2);15971598if (FSEv06_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1599{ if (BITv06_reloadDStream(&bitD) > BITv06_DStream_unfinished) { op+=2; break; } }16001601op[2] = FSEv06_GETSYMBOL(&state1);16021603if (FSEv06_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1604BITv06_reloadDStream(&bitD);16051606op[3] = FSEv06_GETSYMBOL(&state2);1607}16081609/* tail */1610/* note : BITv06_reloadDStream(&bitD) >= FSEv06_DStream_partiallyFilled; Ends at exactly BITv06_DStream_completed */1611while (1) {1612if (op>(omax-2)) return ERROR(dstSize_tooSmall);16131614*op++ = FSEv06_GETSYMBOL(&state1);16151616if (BITv06_reloadDStream(&bitD)==BITv06_DStream_overflow) {1617*op++ = FSEv06_GETSYMBOL(&state2);1618break;1619}16201621if (op>(omax-2)) return ERROR(dstSize_tooSmall);16221623*op++ = FSEv06_GETSYMBOL(&state2);16241625if (BITv06_reloadDStream(&bitD)==BITv06_DStream_overflow) {1626*op++ = FSEv06_GETSYMBOL(&state1);1627break;1628} }16291630return op-ostart;1631}163216331634size_t FSEv06_decompress_usingDTable(void* dst, size_t originalSize,1635const void* cSrc, size_t cSrcSize,1636const FSEv06_DTable* dt)1637{1638const void* ptr = dt;1639const FSEv06_DTableHeader* DTableH = (const FSEv06_DTableHeader*)ptr;1640const U32 fastMode = DTableH->fastMode;16411642/* select fast mode (static) */1643if (fastMode) return FSEv06_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);1644return FSEv06_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);1645}164616471648size_t FSEv06_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)1649{1650const BYTE* const istart = (const BYTE*)cSrc;1651const BYTE* ip = istart;1652short counting[FSEv06_MAX_SYMBOL_VALUE+1];1653DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */1654unsigned tableLog;1655unsigned maxSymbolValue = FSEv06_MAX_SYMBOL_VALUE;16561657if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */16581659/* normal FSE decoding mode */1660{ size_t const NCountLength = FSEv06_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);1661if (FSEv06_isError(NCountLength)) return NCountLength;1662if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */1663ip += NCountLength;1664cSrcSize -= NCountLength;1665}16661667{ size_t const errorCode = FSEv06_buildDTable (dt, counting, maxSymbolValue, tableLog);1668if (FSEv06_isError(errorCode)) return errorCode; }16691670return FSEv06_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); /* always return, even if it is an error code */1671}1672167316741675#endif /* FSEv06_COMMONDEFS_ONLY */1676/* ******************************************************************1677Huffman coder, part of New Generation Entropy library1678header file1679Copyright (C) 2013-2016, Yann Collet.16801681BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)16821683Redistribution and use in source and binary forms, with or without1684modification, are permitted provided that the following conditions are1685met:16861687* Redistributions of source code must retain the above copyright1688notice, this list of conditions and the following disclaimer.1689* Redistributions in binary form must reproduce the above1690copyright notice, this list of conditions and the following disclaimer1691in the documentation and/or other materials provided with the1692distribution.16931694THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1695"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1696LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1697A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1698OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1699SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1700LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1701DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1702THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1703(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1704OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.17051706You can contact the author at :1707- Source repository : https://github.com/Cyan4973/FiniteStateEntropy1708****************************************************************** */1709#ifndef HUFv06_H1710#define HUFv06_H17111712#if defined (__cplusplus)1713extern "C" {1714#endif171517161717/* ****************************************1718* HUF simple functions1719******************************************/1720size_t HUFv06_decompress(void* dst, size_t dstSize,1721const void* cSrc, size_t cSrcSize);1722/*1723HUFv06_decompress() :1724Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',1725into already allocated destination buffer 'dst', of size 'dstSize'.1726`dstSize` : must be the **exact** size of original (uncompressed) data.1727Note : in contrast with FSE, HUFv06_decompress can regenerate1728RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,1729because it knows size to regenerate.1730@return : size of regenerated data (== dstSize)1731or an error code, which can be tested using HUFv06_isError()1732*/173317341735/* ****************************************1736* Tool functions1737******************************************/1738size_t HUFv06_compressBound(size_t size); /**< maximum compressed size */173917401741#if defined (__cplusplus)1742}1743#endif17441745#endif /* HUFv06_H */1746/* ******************************************************************1747Huffman codec, part of New Generation Entropy library1748header file, for static linking only1749Copyright (C) 2013-2016, Yann Collet17501751BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)17521753Redistribution and use in source and binary forms, with or without1754modification, are permitted provided that the following conditions are1755met:17561757* Redistributions of source code must retain the above copyright1758notice, this list of conditions and the following disclaimer.1759* Redistributions in binary form must reproduce the above1760copyright notice, this list of conditions and the following disclaimer1761in the documentation and/or other materials provided with the1762distribution.17631764THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1765"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1766LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1767A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1768OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1769SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1770LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1771DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1772THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1773(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1774OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.17751776You can contact the author at :1777- Source repository : https://github.com/Cyan4973/FiniteStateEntropy1778****************************************************************** */1779#ifndef HUFv06_STATIC_H1780#define HUFv06_STATIC_H17811782#if defined (__cplusplus)1783extern "C" {1784#endif178517861787/* ****************************************1788* Static allocation1789******************************************/1790/* HUF buffer bounds */1791#define HUFv06_CTABLEBOUND 1291792#define HUFv06_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true if incompressible pre-filtered with fast heuristic */1793#define HUFv06_COMPRESSBOUND(size) (HUFv06_CTABLEBOUND + HUFv06_BLOCKBOUND(size)) /* Macro version, useful for static allocation */17941795/* static allocation of HUF's DTable */1796#define HUFv06_DTABLE_SIZE(maxTableLog) (1 + (1<<maxTableLog))1797#define HUFv06_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \1798unsigned short DTable[HUFv06_DTABLE_SIZE(maxTableLog)] = { maxTableLog }1799#define HUFv06_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \1800unsigned int DTable[HUFv06_DTABLE_SIZE(maxTableLog)] = { maxTableLog }1801#define HUFv06_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \1802unsigned int DTable[HUFv06_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }180318041805/* ****************************************1806* Advanced decompression functions1807******************************************/1808size_t HUFv06_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */1809size_t HUFv06_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */1810181118121813/*!1814HUFv06_decompress() does the following:18151. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics18162. build Huffman table from save, using HUFv06_readDTableXn()18173. decode 1 or 4 segments in parallel using HUFv06_decompressSXn_usingDTable1818*/1819size_t HUFv06_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);1820size_t HUFv06_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);18211822size_t HUFv06_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);1823size_t HUFv06_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);182418251826/* single stream variants */1827size_t HUFv06_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */1828size_t HUFv06_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */18291830size_t HUFv06_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);1831size_t HUFv06_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);1832183318341835/* **************************************************************1836* Constants1837****************************************************************/1838#define HUFv06_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUFv06_MAX_TABLELOG. Beyond that value, code does not work */1839#define HUFv06_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUFv06_ABSOLUTEMAX_TABLELOG */1840#define HUFv06_DEFAULT_TABLELOG HUFv06_MAX_TABLELOG /* tableLog by default, when not specified */1841#define HUFv06_MAX_SYMBOL_VALUE 2551842#if (HUFv06_MAX_TABLELOG > HUFv06_ABSOLUTEMAX_TABLELOG)1843# error "HUFv06_MAX_TABLELOG is too large !"1844#endif1845184618471848/*! HUFv06_readStats() :1849Read compact Huffman tree, saved by HUFv06_writeCTable().1850`huffWeight` is destination buffer.1851@return : size read from `src`1852*/1853MEM_STATIC size_t HUFv06_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,1854U32* nbSymbolsPtr, U32* tableLogPtr,1855const void* src, size_t srcSize)1856{1857U32 weightTotal;1858const BYTE* ip = (const BYTE*) src;1859size_t iSize;1860size_t oSize;18611862if (!srcSize) return ERROR(srcSize_wrong);1863iSize = ip[0];1864/* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */18651866if (iSize >= 128) { /* special header */1867if (iSize >= (242)) { /* RLE */1868static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };1869oSize = l[iSize-242];1870memset(huffWeight, 1, hwSize);1871iSize = 0;1872}1873else { /* Incompressible */1874oSize = iSize - 127;1875iSize = ((oSize+1)/2);1876if (iSize+1 > srcSize) return ERROR(srcSize_wrong);1877if (oSize >= hwSize) return ERROR(corruption_detected);1878ip += 1;1879{ U32 n;1880for (n=0; n<oSize; n+=2) {1881huffWeight[n] = ip[n/2] >> 4;1882huffWeight[n+1] = ip[n/2] & 15;1883} } } }1884else { /* header compressed with FSE (normal case) */1885if (iSize+1 > srcSize) return ERROR(srcSize_wrong);1886oSize = FSEv06_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */1887if (FSEv06_isError(oSize)) return oSize;1888}18891890/* collect weight stats */1891memset(rankStats, 0, (HUFv06_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));1892weightTotal = 0;1893{ U32 n; for (n=0; n<oSize; n++) {1894if (huffWeight[n] >= HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);1895rankStats[huffWeight[n]]++;1896weightTotal += (1 << huffWeight[n]) >> 1;1897} }1898if (weightTotal == 0) return ERROR(corruption_detected);18991900/* get last non-null symbol weight (implied, total must be 2^n) */1901{ U32 const tableLog = BITv06_highbit32(weightTotal) + 1;1902if (tableLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);1903*tableLogPtr = tableLog;1904/* determine last weight */1905{ U32 const total = 1 << tableLog;1906U32 const rest = total - weightTotal;1907U32 const verif = 1 << BITv06_highbit32(rest);1908U32 const lastWeight = BITv06_highbit32(rest) + 1;1909if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */1910huffWeight[oSize] = (BYTE)lastWeight;1911rankStats[lastWeight]++;1912} }19131914/* check tree construction validity */1915if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */19161917/* results */1918*nbSymbolsPtr = (U32)(oSize+1);1919return iSize+1;1920}1921192219231924#if defined (__cplusplus)1925}1926#endif19271928#endif /* HUFv06_STATIC_H */1929/* ******************************************************************1930Huffman decoder, part of New Generation Entropy library1931Copyright (C) 2013-2016, Yann Collet.19321933BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)19341935Redistribution and use in source and binary forms, with or without1936modification, are permitted provided that the following conditions are1937met:19381939* Redistributions of source code must retain the above copyright1940notice, this list of conditions and the following disclaimer.1941* Redistributions in binary form must reproduce the above1942copyright notice, this list of conditions and the following disclaimer1943in the documentation and/or other materials provided with the1944distribution.19451946THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1947"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1948LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1949A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1950OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1951SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1952LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1953DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1954THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1955(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1956OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.19571958You can contact the author at :1959- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy1960- Public forum : https://groups.google.com/forum/#!forum/lz4c1961****************************************************************** */19621963/* **************************************************************1964* Compiler specifics1965****************************************************************/1966#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)1967/* inline is defined */1968#elif defined(_MSC_VER)1969# define inline __inline1970#else1971# define inline /* disable inline */1972#endif197319741975#ifdef _MSC_VER /* Visual Studio */1976# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */1977#endif1978197919801981/* **************************************************************1982* Error Management1983****************************************************************/1984#define HUFv06_STATIC_ASSERT(c) { enum { HUFv06_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */1985198619871988/* *******************************************************1989* HUF : Huffman block decompression1990*********************************************************/1991typedef struct { BYTE byte; BYTE nbBits; } HUFv06_DEltX2; /* single-symbol decoding */19921993typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv06_DEltX4; /* double-symbols decoding */19941995typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;1996199719981999/*-***************************/2000/* single-symbol decoding */2001/*-***************************/20022003size_t HUFv06_readDTableX2 (U16* DTable, const void* src, size_t srcSize)2004{2005BYTE huffWeight[HUFv06_MAX_SYMBOL_VALUE + 1];2006U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */2007U32 tableLog = 0;2008size_t iSize;2009U32 nbSymbols = 0;2010U32 n;2011U32 nextRankStart;2012void* const dtPtr = DTable + 1;2013HUFv06_DEltX2* const dt = (HUFv06_DEltX2*)dtPtr;20142015HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */2016/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */20172018iSize = HUFv06_readStats(huffWeight, HUFv06_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);2019if (HUFv06_isError(iSize)) return iSize;20202021/* check result */2022if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge); /* DTable is too small */2023DTable[0] = (U16)tableLog; /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */20242025/* Prepare ranks */2026nextRankStart = 0;2027for (n=1; n<tableLog+1; n++) {2028U32 current = nextRankStart;2029nextRankStart += (rankVal[n] << (n-1));2030rankVal[n] = current;2031}20322033/* fill DTable */2034for (n=0; n<nbSymbols; n++) {2035const U32 w = huffWeight[n];2036const U32 length = (1 << w) >> 1;2037U32 i;2038HUFv06_DEltX2 D;2039D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);2040for (i = rankVal[w]; i < rankVal[w] + length; i++)2041dt[i] = D;2042rankVal[w] += length;2043}20442045return iSize;2046}204720482049static BYTE HUFv06_decodeSymbolX2(BITv06_DStream_t* Dstream, const HUFv06_DEltX2* dt, const U32 dtLog)2050{2051const size_t val = BITv06_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */2052const BYTE c = dt[val].byte;2053BITv06_skipBits(Dstream, dt[val].nbBits);2054return c;2055}20562057#define HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \2058*ptr++ = HUFv06_decodeSymbolX2(DStreamPtr, dt, dtLog)20592060#define HUFv06_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \2061if (MEM_64bits() || (HUFv06_MAX_TABLELOG<=12)) \2062HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr)20632064#define HUFv06_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \2065if (MEM_64bits()) \2066HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr)20672068static inline size_t HUFv06_decodeStreamX2(BYTE* p, BITv06_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv06_DEltX2* const dt, const U32 dtLog)2069{2070BYTE* const pStart = p;20712072/* up to 4 symbols at a time */2073while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p <= pEnd-4)) {2074HUFv06_DECODE_SYMBOLX2_2(p, bitDPtr);2075HUFv06_DECODE_SYMBOLX2_1(p, bitDPtr);2076HUFv06_DECODE_SYMBOLX2_2(p, bitDPtr);2077HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);2078}20792080/* closer to the end */2081while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p < pEnd))2082HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);20832084/* no more data to retrieve from bitstream, hence no need to reload */2085while (p < pEnd)2086HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);20872088return pEnd-pStart;2089}20902091size_t HUFv06_decompress1X2_usingDTable(2092void* dst, size_t dstSize,2093const void* cSrc, size_t cSrcSize,2094const U16* DTable)2095{2096BYTE* op = (BYTE*)dst;2097BYTE* const oend = op + dstSize;2098const U32 dtLog = DTable[0];2099const void* dtPtr = DTable;2100const HUFv06_DEltX2* const dt = ((const HUFv06_DEltX2*)dtPtr)+1;2101BITv06_DStream_t bitD;21022103{ size_t const errorCode = BITv06_initDStream(&bitD, cSrc, cSrcSize);2104if (HUFv06_isError(errorCode)) return errorCode; }21052106HUFv06_decodeStreamX2(op, &bitD, oend, dt, dtLog);21072108/* check */2109if (!BITv06_endOfDStream(&bitD)) return ERROR(corruption_detected);21102111return dstSize;2112}21132114size_t HUFv06_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2115{2116HUFv06_CREATE_STATIC_DTABLEX2(DTable, HUFv06_MAX_TABLELOG);2117const BYTE* ip = (const BYTE*) cSrc;21182119size_t const errorCode = HUFv06_readDTableX2 (DTable, cSrc, cSrcSize);2120if (HUFv06_isError(errorCode)) return errorCode;2121if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);2122ip += errorCode;2123cSrcSize -= errorCode;21242125return HUFv06_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2126}212721282129size_t HUFv06_decompress4X2_usingDTable(2130void* dst, size_t dstSize,2131const void* cSrc, size_t cSrcSize,2132const U16* DTable)2133{2134/* Check */2135if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */21362137{ const BYTE* const istart = (const BYTE*) cSrc;2138BYTE* const ostart = (BYTE*) dst;2139BYTE* const oend = ostart + dstSize;2140const void* const dtPtr = DTable;2141const HUFv06_DEltX2* const dt = ((const HUFv06_DEltX2*)dtPtr) +1;2142const U32 dtLog = DTable[0];2143size_t errorCode;21442145/* Init */2146BITv06_DStream_t bitD1;2147BITv06_DStream_t bitD2;2148BITv06_DStream_t bitD3;2149BITv06_DStream_t bitD4;2150const size_t length1 = MEM_readLE16(istart);2151const size_t length2 = MEM_readLE16(istart+2);2152const size_t length3 = MEM_readLE16(istart+4);2153size_t length4;2154const BYTE* const istart1 = istart + 6; /* jumpTable */2155const BYTE* const istart2 = istart1 + length1;2156const BYTE* const istart3 = istart2 + length2;2157const BYTE* const istart4 = istart3 + length3;2158const size_t segmentSize = (dstSize+3) / 4;2159BYTE* const opStart2 = ostart + segmentSize;2160BYTE* const opStart3 = opStart2 + segmentSize;2161BYTE* const opStart4 = opStart3 + segmentSize;2162BYTE* op1 = ostart;2163BYTE* op2 = opStart2;2164BYTE* op3 = opStart3;2165BYTE* op4 = opStart4;2166U32 endSignal;21672168length4 = cSrcSize - (length1 + length2 + length3 + 6);2169if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */2170errorCode = BITv06_initDStream(&bitD1, istart1, length1);2171if (HUFv06_isError(errorCode)) return errorCode;2172errorCode = BITv06_initDStream(&bitD2, istart2, length2);2173if (HUFv06_isError(errorCode)) return errorCode;2174errorCode = BITv06_initDStream(&bitD3, istart3, length3);2175if (HUFv06_isError(errorCode)) return errorCode;2176errorCode = BITv06_initDStream(&bitD4, istart4, length4);2177if (HUFv06_isError(errorCode)) return errorCode;21782179/* 16-32 symbols per loop (4-8 symbols per stream) */2180endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);2181for ( ; (endSignal==BITv06_DStream_unfinished) && (op4<(oend-7)) ; ) {2182HUFv06_DECODE_SYMBOLX2_2(op1, &bitD1);2183HUFv06_DECODE_SYMBOLX2_2(op2, &bitD2);2184HUFv06_DECODE_SYMBOLX2_2(op3, &bitD3);2185HUFv06_DECODE_SYMBOLX2_2(op4, &bitD4);2186HUFv06_DECODE_SYMBOLX2_1(op1, &bitD1);2187HUFv06_DECODE_SYMBOLX2_1(op2, &bitD2);2188HUFv06_DECODE_SYMBOLX2_1(op3, &bitD3);2189HUFv06_DECODE_SYMBOLX2_1(op4, &bitD4);2190HUFv06_DECODE_SYMBOLX2_2(op1, &bitD1);2191HUFv06_DECODE_SYMBOLX2_2(op2, &bitD2);2192HUFv06_DECODE_SYMBOLX2_2(op3, &bitD3);2193HUFv06_DECODE_SYMBOLX2_2(op4, &bitD4);2194HUFv06_DECODE_SYMBOLX2_0(op1, &bitD1);2195HUFv06_DECODE_SYMBOLX2_0(op2, &bitD2);2196HUFv06_DECODE_SYMBOLX2_0(op3, &bitD3);2197HUFv06_DECODE_SYMBOLX2_0(op4, &bitD4);2198endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);2199}22002201/* check corruption */2202if (op1 > opStart2) return ERROR(corruption_detected);2203if (op2 > opStart3) return ERROR(corruption_detected);2204if (op3 > opStart4) return ERROR(corruption_detected);2205/* note : op4 supposed already verified within main loop */22062207/* finish bitStreams one by one */2208HUFv06_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);2209HUFv06_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);2210HUFv06_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);2211HUFv06_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);22122213/* check */2214endSignal = BITv06_endOfDStream(&bitD1) & BITv06_endOfDStream(&bitD2) & BITv06_endOfDStream(&bitD3) & BITv06_endOfDStream(&bitD4);2215if (!endSignal) return ERROR(corruption_detected);22162217/* decoded size */2218return dstSize;2219}2220}222122222223size_t HUFv06_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2224{2225HUFv06_CREATE_STATIC_DTABLEX2(DTable, HUFv06_MAX_TABLELOG);2226const BYTE* ip = (const BYTE*) cSrc;22272228size_t const errorCode = HUFv06_readDTableX2 (DTable, cSrc, cSrcSize);2229if (HUFv06_isError(errorCode)) return errorCode;2230if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);2231ip += errorCode;2232cSrcSize -= errorCode;22332234return HUFv06_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2235}223622372238/* *************************/2239/* double-symbols decoding */2240/* *************************/22412242static void HUFv06_fillDTableX4Level2(HUFv06_DEltX4* DTable, U32 sizeLog, const U32 consumed,2243const U32* rankValOrigin, const int minWeight,2244const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,2245U32 nbBitsBaseline, U16 baseSeq)2246{2247HUFv06_DEltX4 DElt;2248U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];22492250/* get pre-calculated rankVal */2251memcpy(rankVal, rankValOrigin, sizeof(rankVal));22522253/* fill skipped values */2254if (minWeight>1) {2255U32 i, skipSize = rankVal[minWeight];2256MEM_writeLE16(&(DElt.sequence), baseSeq);2257DElt.nbBits = (BYTE)(consumed);2258DElt.length = 1;2259for (i = 0; i < skipSize; i++)2260DTable[i] = DElt;2261}22622263/* fill DTable */2264{ U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */2265const U32 symbol = sortedSymbols[s].symbol;2266const U32 weight = sortedSymbols[s].weight;2267const U32 nbBits = nbBitsBaseline - weight;2268const U32 length = 1 << (sizeLog-nbBits);2269const U32 start = rankVal[weight];2270U32 i = start;2271const U32 end = start + length;22722273MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));2274DElt.nbBits = (BYTE)(nbBits + consumed);2275DElt.length = 2;2276do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */22772278rankVal[weight] += length;2279}}2280}22812282typedef U32 rankVal_t[HUFv06_ABSOLUTEMAX_TABLELOG][HUFv06_ABSOLUTEMAX_TABLELOG + 1];22832284static void HUFv06_fillDTableX4(HUFv06_DEltX4* DTable, const U32 targetLog,2285const sortedSymbol_t* sortedList, const U32 sortedListSize,2286const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,2287const U32 nbBitsBaseline)2288{2289U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];2290const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */2291const U32 minBits = nbBitsBaseline - maxWeight;2292U32 s;22932294memcpy(rankVal, rankValOrigin, sizeof(rankVal));22952296/* fill DTable */2297for (s=0; s<sortedListSize; s++) {2298const U16 symbol = sortedList[s].symbol;2299const U32 weight = sortedList[s].weight;2300const U32 nbBits = nbBitsBaseline - weight;2301const U32 start = rankVal[weight];2302const U32 length = 1 << (targetLog-nbBits);23032304if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */2305U32 sortedRank;2306int minWeight = nbBits + scaleLog;2307if (minWeight < 1) minWeight = 1;2308sortedRank = rankStart[minWeight];2309HUFv06_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,2310rankValOrigin[nbBits], minWeight,2311sortedList+sortedRank, sortedListSize-sortedRank,2312nbBitsBaseline, symbol);2313} else {2314HUFv06_DEltX4 DElt;2315MEM_writeLE16(&(DElt.sequence), symbol);2316DElt.nbBits = (BYTE)(nbBits);2317DElt.length = 1;2318{ U32 u;2319const U32 end = start + length;2320for (u = start; u < end; u++) DTable[u] = DElt;2321} }2322rankVal[weight] += length;2323}2324}23252326size_t HUFv06_readDTableX4 (U32* DTable, const void* src, size_t srcSize)2327{2328BYTE weightList[HUFv06_MAX_SYMBOL_VALUE + 1];2329sortedSymbol_t sortedSymbol[HUFv06_MAX_SYMBOL_VALUE + 1];2330U32 rankStats[HUFv06_ABSOLUTEMAX_TABLELOG + 1] = { 0 };2331U32 rankStart0[HUFv06_ABSOLUTEMAX_TABLELOG + 2] = { 0 };2332U32* const rankStart = rankStart0+1;2333rankVal_t rankVal;2334U32 tableLog, maxW, sizeOfSort, nbSymbols;2335const U32 memLog = DTable[0];2336size_t iSize;2337void* dtPtr = DTable;2338HUFv06_DEltX4* const dt = ((HUFv06_DEltX4*)dtPtr) + 1;23392340HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX4) == sizeof(U32)); /* if compilation fails here, assertion is false */2341if (memLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);2342/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */23432344iSize = HUFv06_readStats(weightList, HUFv06_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);2345if (HUFv06_isError(iSize)) return iSize;23462347/* check result */2348if (tableLog > memLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */23492350/* find maxWeight */2351for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */23522353/* Get start index of each weight */2354{ U32 w, nextRankStart = 0;2355for (w=1; w<maxW+1; w++) {2356U32 current = nextRankStart;2357nextRankStart += rankStats[w];2358rankStart[w] = current;2359}2360rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/2361sizeOfSort = nextRankStart;2362}23632364/* sort symbols by weight */2365{ U32 s;2366for (s=0; s<nbSymbols; s++) {2367U32 const w = weightList[s];2368U32 const r = rankStart[w]++;2369sortedSymbol[r].symbol = (BYTE)s;2370sortedSymbol[r].weight = (BYTE)w;2371}2372rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */2373}23742375/* Build rankVal */2376{ U32* const rankVal0 = rankVal[0];2377{ int const rescale = (memLog-tableLog) - 1; /* tableLog <= memLog */2378U32 nextRankVal = 0;2379U32 w;2380for (w=1; w<maxW+1; w++) {2381U32 current = nextRankVal;2382nextRankVal += rankStats[w] << (w+rescale);2383rankVal0[w] = current;2384} }2385{ U32 const minBits = tableLog+1 - maxW;2386U32 consumed;2387for (consumed = minBits; consumed < memLog - minBits + 1; consumed++) {2388U32* const rankValPtr = rankVal[consumed];2389U32 w;2390for (w = 1; w < maxW+1; w++) {2391rankValPtr[w] = rankVal0[w] >> consumed;2392} } } }23932394HUFv06_fillDTableX4(dt, memLog,2395sortedSymbol, sizeOfSort,2396rankStart0, rankVal, maxW,2397tableLog+1);23982399return iSize;2400}240124022403static U32 HUFv06_decodeSymbolX4(void* op, BITv06_DStream_t* DStream, const HUFv06_DEltX4* dt, const U32 dtLog)2404{2405const size_t val = BITv06_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */2406memcpy(op, dt+val, 2);2407BITv06_skipBits(DStream, dt[val].nbBits);2408return dt[val].length;2409}24102411static U32 HUFv06_decodeLastSymbolX4(void* op, BITv06_DStream_t* DStream, const HUFv06_DEltX4* dt, const U32 dtLog)2412{2413const size_t val = BITv06_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */2414memcpy(op, dt+val, 1);2415if (dt[val].length==1) BITv06_skipBits(DStream, dt[val].nbBits);2416else {2417if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {2418BITv06_skipBits(DStream, dt[val].nbBits);2419if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))2420DStream->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 */2421} }2422return 1;2423}242424252426#define HUFv06_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \2427ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)24282429#define HUFv06_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \2430if (MEM_64bits() || (HUFv06_MAX_TABLELOG<=12)) \2431ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)24322433#define HUFv06_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \2434if (MEM_64bits()) \2435ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)24362437static inline size_t HUFv06_decodeStreamX4(BYTE* p, BITv06_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv06_DEltX4* const dt, const U32 dtLog)2438{2439BYTE* const pStart = p;24402441/* up to 8 symbols at a time */2442while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p < pEnd-7)) {2443HUFv06_DECODE_SYMBOLX4_2(p, bitDPtr);2444HUFv06_DECODE_SYMBOLX4_1(p, bitDPtr);2445HUFv06_DECODE_SYMBOLX4_2(p, bitDPtr);2446HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);2447}24482449/* closer to the end */2450while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p <= pEnd-2))2451HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);24522453while (p <= pEnd-2)2454HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */24552456if (p < pEnd)2457p += HUFv06_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);24582459return p-pStart;2460}246124622463size_t HUFv06_decompress1X4_usingDTable(2464void* dst, size_t dstSize,2465const void* cSrc, size_t cSrcSize,2466const U32* DTable)2467{2468const BYTE* const istart = (const BYTE*) cSrc;2469BYTE* const ostart = (BYTE*) dst;2470BYTE* const oend = ostart + dstSize;24712472const U32 dtLog = DTable[0];2473const void* const dtPtr = DTable;2474const HUFv06_DEltX4* const dt = ((const HUFv06_DEltX4*)dtPtr) +1;24752476/* Init */2477BITv06_DStream_t bitD;2478{ size_t const errorCode = BITv06_initDStream(&bitD, istart, cSrcSize);2479if (HUFv06_isError(errorCode)) return errorCode; }24802481/* decode */2482HUFv06_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);24832484/* check */2485if (!BITv06_endOfDStream(&bitD)) return ERROR(corruption_detected);24862487/* decoded size */2488return dstSize;2489}24902491size_t HUFv06_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2492{2493HUFv06_CREATE_STATIC_DTABLEX4(DTable, HUFv06_MAX_TABLELOG);2494const BYTE* ip = (const BYTE*) cSrc;24952496size_t const hSize = HUFv06_readDTableX4 (DTable, cSrc, cSrcSize);2497if (HUFv06_isError(hSize)) return hSize;2498if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2499ip += hSize;2500cSrcSize -= hSize;25012502return HUFv06_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2503}25042505size_t HUFv06_decompress4X4_usingDTable(2506void* dst, size_t dstSize,2507const void* cSrc, size_t cSrcSize,2508const U32* DTable)2509{2510if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */25112512{ const BYTE* const istart = (const BYTE*) cSrc;2513BYTE* const ostart = (BYTE*) dst;2514BYTE* const oend = ostart + dstSize;2515const void* const dtPtr = DTable;2516const HUFv06_DEltX4* const dt = ((const HUFv06_DEltX4*)dtPtr) +1;2517const U32 dtLog = DTable[0];2518size_t errorCode;25192520/* Init */2521BITv06_DStream_t bitD1;2522BITv06_DStream_t bitD2;2523BITv06_DStream_t bitD3;2524BITv06_DStream_t bitD4;2525const size_t length1 = MEM_readLE16(istart);2526const size_t length2 = MEM_readLE16(istart+2);2527const size_t length3 = MEM_readLE16(istart+4);2528size_t length4;2529const BYTE* const istart1 = istart + 6; /* jumpTable */2530const BYTE* const istart2 = istart1 + length1;2531const BYTE* const istart3 = istart2 + length2;2532const BYTE* const istart4 = istart3 + length3;2533const size_t segmentSize = (dstSize+3) / 4;2534BYTE* const opStart2 = ostart + segmentSize;2535BYTE* const opStart3 = opStart2 + segmentSize;2536BYTE* const opStart4 = opStart3 + segmentSize;2537BYTE* op1 = ostart;2538BYTE* op2 = opStart2;2539BYTE* op3 = opStart3;2540BYTE* op4 = opStart4;2541U32 endSignal;25422543length4 = cSrcSize - (length1 + length2 + length3 + 6);2544if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */2545errorCode = BITv06_initDStream(&bitD1, istart1, length1);2546if (HUFv06_isError(errorCode)) return errorCode;2547errorCode = BITv06_initDStream(&bitD2, istart2, length2);2548if (HUFv06_isError(errorCode)) return errorCode;2549errorCode = BITv06_initDStream(&bitD3, istart3, length3);2550if (HUFv06_isError(errorCode)) return errorCode;2551errorCode = BITv06_initDStream(&bitD4, istart4, length4);2552if (HUFv06_isError(errorCode)) return errorCode;25532554/* 16-32 symbols per loop (4-8 symbols per stream) */2555endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);2556for ( ; (endSignal==BITv06_DStream_unfinished) && (op4<(oend-7)) ; ) {2557HUFv06_DECODE_SYMBOLX4_2(op1, &bitD1);2558HUFv06_DECODE_SYMBOLX4_2(op2, &bitD2);2559HUFv06_DECODE_SYMBOLX4_2(op3, &bitD3);2560HUFv06_DECODE_SYMBOLX4_2(op4, &bitD4);2561HUFv06_DECODE_SYMBOLX4_1(op1, &bitD1);2562HUFv06_DECODE_SYMBOLX4_1(op2, &bitD2);2563HUFv06_DECODE_SYMBOLX4_1(op3, &bitD3);2564HUFv06_DECODE_SYMBOLX4_1(op4, &bitD4);2565HUFv06_DECODE_SYMBOLX4_2(op1, &bitD1);2566HUFv06_DECODE_SYMBOLX4_2(op2, &bitD2);2567HUFv06_DECODE_SYMBOLX4_2(op3, &bitD3);2568HUFv06_DECODE_SYMBOLX4_2(op4, &bitD4);2569HUFv06_DECODE_SYMBOLX4_0(op1, &bitD1);2570HUFv06_DECODE_SYMBOLX4_0(op2, &bitD2);2571HUFv06_DECODE_SYMBOLX4_0(op3, &bitD3);2572HUFv06_DECODE_SYMBOLX4_0(op4, &bitD4);25732574endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);2575}25762577/* check corruption */2578if (op1 > opStart2) return ERROR(corruption_detected);2579if (op2 > opStart3) return ERROR(corruption_detected);2580if (op3 > opStart4) return ERROR(corruption_detected);2581/* note : op4 supposed already verified within main loop */25822583/* finish bitStreams one by one */2584HUFv06_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);2585HUFv06_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);2586HUFv06_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);2587HUFv06_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);25882589/* check */2590endSignal = BITv06_endOfDStream(&bitD1) & BITv06_endOfDStream(&bitD2) & BITv06_endOfDStream(&bitD3) & BITv06_endOfDStream(&bitD4);2591if (!endSignal) return ERROR(corruption_detected);25922593/* decoded size */2594return dstSize;2595}2596}259725982599size_t HUFv06_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2600{2601HUFv06_CREATE_STATIC_DTABLEX4(DTable, HUFv06_MAX_TABLELOG);2602const BYTE* ip = (const BYTE*) cSrc;26032604size_t hSize = HUFv06_readDTableX4 (DTable, cSrc, cSrcSize);2605if (HUFv06_isError(hSize)) return hSize;2606if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2607ip += hSize;2608cSrcSize -= hSize;26092610return HUFv06_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2611}26122613261426152616/* ********************************/2617/* Generic decompression selector */2618/* ********************************/26192620typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;2621static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =2622{2623/* single, double, quad */2624{{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */2625{{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */2626{{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */2627{{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */2628{{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */2629{{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */2630{{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */2631{{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */2632{{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */2633{{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */2634{{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */2635{{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */2636{{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */2637{{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */2638{{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */2639{{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */2640};26412642typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);26432644size_t HUFv06_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2645{2646static const decompressionAlgo decompress[3] = { HUFv06_decompress4X2, HUFv06_decompress4X4, NULL };2647U32 Dtime[3]; /* decompression time estimation */26482649/* validation checks */2650if (dstSize == 0) return ERROR(dstSize_tooSmall);2651if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */2652if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */2653if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */26542655/* decoder timing evaluation */2656{ U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */2657U32 const D256 = (U32)(dstSize >> 8);2658U32 n; for (n=0; n<3; n++)2659Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);2660}26612662Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */26632664{ U32 algoNb = 0;2665if (Dtime[1] < Dtime[0]) algoNb = 1;2666/* if (Dtime[2] < Dtime[algoNb]) algoNb = 2; */ /* current speed of HUFv06_decompress4X6 is not good */2667return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);2668}26692670/* return HUFv06_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */2671/* return HUFv06_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */2672/* return HUFv06_decompress4X6(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams quad-symbols decoding */2673}2674/*2675Common functions of Zstd compression library2676Copyright (C) 2015-2016, Yann Collet.26772678BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)26792680Redistribution and use in source and binary forms, with or without2681modification, are permitted provided that the following conditions are2682met:2683* Redistributions of source code must retain the above copyright2684notice, this list of conditions and the following disclaimer.2685* Redistributions in binary form must reproduce the above2686copyright notice, this list of conditions and the following disclaimer2687in the documentation and/or other materials provided with the2688distribution.2689THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS2690"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT2691LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR2692A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT2693OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,2694SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT2695LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,2696DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY2697THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2698(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE2699OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27002701You can contact the author at :2702- zstd homepage : http://www.zstd.net/2703*/270427052706/*-****************************************2707* Version2708******************************************/27092710/*-****************************************2711* ZSTD Error Management2712******************************************/2713/*! ZSTDv06_isError() :2714* tells if a return value is an error code */2715unsigned ZSTDv06_isError(size_t code) { return ERR_isError(code); }27162717/*! ZSTDv06_getErrorName() :2718* provides error code string from function result (useful for debugging) */2719const char* ZSTDv06_getErrorName(size_t code) { return ERR_getErrorName(code); }272027212722/* **************************************************************2723* ZBUFF Error Management2724****************************************************************/2725unsigned ZBUFFv06_isError(size_t errorCode) { return ERR_isError(errorCode); }27262727const char* ZBUFFv06_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }2728/*2729zstd - standard compression library2730Copyright (C) 2014-2016, Yann Collet.27312732BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)27332734Redistribution and use in source and binary forms, with or without2735modification, are permitted provided that the following conditions are2736met:2737* Redistributions of source code must retain the above copyright2738notice, this list of conditions and the following disclaimer.2739* Redistributions in binary form must reproduce the above2740copyright notice, this list of conditions and the following disclaimer2741in the documentation and/or other materials provided with the2742distribution.2743THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS2744"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT2745LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR2746A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT2747OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,2748SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT2749LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,2750DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY2751THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2752(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE2753OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27542755You can contact the author at :2756- zstd homepage : http://www.zstd.net2757*/27582759/* ***************************************************************2760* Tuning parameters2761*****************************************************************/2762/*!2763* HEAPMODE :2764* Select how default decompression function ZSTDv06_decompress() will allocate memory,2765* in memory stack (0), or in memory heap (1, requires malloc())2766*/2767#ifndef ZSTDv06_HEAPMODE2768# define ZSTDv06_HEAPMODE 12769#endif2770277127722773/*-*******************************************************2774* Compiler specifics2775*********************************************************/2776#ifdef _MSC_VER /* Visual Studio */2777# include <intrin.h> /* For Visual 2005 */2778# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */2779# pragma warning(disable : 4324) /* disable: C4324: padded structure */2780#endif278127822783/*-*************************************2784* Macros2785***************************************/2786#define ZSTDv06_isError ERR_isError /* for inlining */2787#define FSEv06_isError ERR_isError2788#define HUFv06_isError ERR_isError278927902791/*_*******************************************************2792* Memory operations2793**********************************************************/2794static void ZSTDv06_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }279527962797/*-*************************************************************2798* Context management2799***************************************************************/2800typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,2801ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTDv06_dStage;28022803struct ZSTDv06_DCtx_s2804{2805FSEv06_DTable LLTable[FSEv06_DTABLE_SIZE_U32(LLFSELog)];2806FSEv06_DTable OffTable[FSEv06_DTABLE_SIZE_U32(OffFSELog)];2807FSEv06_DTable MLTable[FSEv06_DTABLE_SIZE_U32(MLFSELog)];2808unsigned hufTableX4[HUFv06_DTABLE_SIZE(HufLog)];2809const void* previousDstEnd;2810const void* base;2811const void* vBase;2812const void* dictEnd;2813size_t expected;2814size_t headerSize;2815ZSTDv06_frameParams fParams;2816blockType_t bType; /* used in ZSTDv06_decompressContinue(), to transfer blockType between header decoding and block decoding stages */2817ZSTDv06_dStage stage;2818U32 flagRepeatTable;2819const BYTE* litPtr;2820size_t litSize;2821BYTE litBuffer[ZSTDv06_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];2822BYTE headerBuffer[ZSTDv06_FRAMEHEADERSIZE_MAX];2823}; /* typedef'd to ZSTDv06_DCtx within "zstd_static.h" */28242825size_t ZSTDv06_sizeofDCtx (void); /* Hidden declaration */2826size_t ZSTDv06_sizeofDCtx (void) { return sizeof(ZSTDv06_DCtx); }28272828size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx)2829{2830dctx->expected = ZSTDv06_frameHeaderSize_min;2831dctx->stage = ZSTDds_getFrameHeaderSize;2832dctx->previousDstEnd = NULL;2833dctx->base = NULL;2834dctx->vBase = NULL;2835dctx->dictEnd = NULL;2836dctx->hufTableX4[0] = HufLog;2837dctx->flagRepeatTable = 0;2838return 0;2839}28402841ZSTDv06_DCtx* ZSTDv06_createDCtx(void)2842{2843ZSTDv06_DCtx* dctx = (ZSTDv06_DCtx*)malloc(sizeof(ZSTDv06_DCtx));2844if (dctx==NULL) return NULL;2845ZSTDv06_decompressBegin(dctx);2846return dctx;2847}28482849size_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx)2850{2851free(dctx);2852return 0; /* reserved as a potential error code in the future */2853}28542855void ZSTDv06_copyDCtx(ZSTDv06_DCtx* dstDCtx, const ZSTDv06_DCtx* srcDCtx)2856{2857memcpy(dstDCtx, srcDCtx,2858sizeof(ZSTDv06_DCtx) - (ZSTDv06_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH + ZSTDv06_frameHeaderSize_max)); /* no need to copy workspace */2859}286028612862/*-*************************************************************2863* Decompression section2864***************************************************************/28652866/* Frame format description2867Frame Header - [ Block Header - Block ] - Frame End28681) Frame Header2869- 4 bytes - Magic Number : ZSTDv06_MAGICNUMBER (defined within zstd_static.h)2870- 1 byte - Frame Descriptor28712) Block Header2872- 3 bytes, starting with a 2-bits descriptor2873Uncompressed, Compressed, Frame End, unused28743) Block2875See Block Format Description28764) Frame End2877- 3 bytes, compatible with Block Header2878*/287928802881/* Frame descriptor288228831 byte, using :2884bit 0-3 : windowLog - ZSTDv06_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h)2885bit 4 : minmatch 4(0) or 3(1)2886bit 5 : reserved (must be zero)2887bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes28882889Optional : content size (0, 1, 2 or 8 bytes)28900 : unknown28911 : 0-255 bytes28922 : 256 - 65535+25628938 : up to 16 exa2894*/289528962897/* Compressed Block, format description28982899Block = Literal Section - Sequences Section2900Prerequisite : size of (compressed) block, maximum size of regenerated data290129021) Literal Section290329041.1) Header : 1-5 bytes2905flags: 2 bits290600 compressed by Huff0290701 unused290810 is Raw (uncompressed)290911 is Rle2910Note : using 01 => Huff0 with precomputed table ?2911Note : delta map ? => compressed ?291229131.1.1) Huff0-compressed literal block : 3-5 bytes2914srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream2915srcSize < 1 KB => 3 bytes (2-2-10-10)2916srcSize < 16KB => 4 bytes (2-2-14-14)2917else => 5 bytes (2-2-18-18)2918big endian convention291929201.1.2) Raw (uncompressed) literal block header : 1-3 bytes2921size : 5 bits: (IS_RAW<<6) + (0<<4) + size292212 bits: (IS_RAW<<6) + (2<<4) + (size>>8)2923size&255292420 bits: (IS_RAW<<6) + (3<<4) + (size>>16)2925size>>8&2552926size&255292729281.1.3) Rle (repeated single byte) literal block header : 1-3 bytes2929size : 5 bits: (IS_RLE<<6) + (0<<4) + size293012 bits: (IS_RLE<<6) + (2<<4) + (size>>8)2931size&255293220 bits: (IS_RLE<<6) + (3<<4) + (size>>16)2933size>>8&2552934size&255293529361.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes2937srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream2938srcSize < 1 KB => 3 bytes (2-2-10-10)2939srcSize < 16KB => 4 bytes (2-2-14-14)2940else => 5 bytes (2-2-18-18)2941big endian convention294229431- CTable available (stored into workspace ?)29442- Small input (fast heuristic ? Full comparison ? depend on clevel ?)2945294629471.2) Literal block content294829491.2.1) Huff0 block, using sizes from header2950See Huff0 format295129521.2.2) Huff0 block, using prepared table295329541.2.3) Raw content295529561.2.4) single byte2957295829592) Sequences section2960TO DO2961*/29622963/** ZSTDv06_frameHeaderSize() :2964* srcSize must be >= ZSTDv06_frameHeaderSize_min.2965* @return : size of the Frame Header */2966static size_t ZSTDv06_frameHeaderSize(const void* src, size_t srcSize)2967{2968if (srcSize < ZSTDv06_frameHeaderSize_min) return ERROR(srcSize_wrong);2969{ U32 const fcsId = (((const BYTE*)src)[4]) >> 6;2970return ZSTDv06_frameHeaderSize_min + ZSTDv06_fcs_fieldSize[fcsId]; }2971}297229732974/** ZSTDv06_getFrameParams() :2975* decode Frame Header, or provide expected `srcSize`.2976* @return : 0, `fparamsPtr` is correctly filled,2977* >0, `srcSize` is too small, result is expected `srcSize`,2978* or an error code, which can be tested using ZSTDv06_isError() */2979size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize)2980{2981const BYTE* ip = (const BYTE*)src;29822983if (srcSize < ZSTDv06_frameHeaderSize_min) return ZSTDv06_frameHeaderSize_min;2984if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown);29852986/* ensure there is enough `srcSize` to fully read/decode frame header */2987{ size_t const fhsize = ZSTDv06_frameHeaderSize(src, srcSize);2988if (srcSize < fhsize) return fhsize; }29892990memset(fparamsPtr, 0, sizeof(*fparamsPtr));2991{ BYTE const frameDesc = ip[4];2992fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTDv06_WINDOWLOG_ABSOLUTEMIN;2993if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported); /* reserved 1 bit */2994switch(frameDesc >> 6) /* fcsId */2995{2996default: /* impossible */2997case 0 : fparamsPtr->frameContentSize = 0; break;2998case 1 : fparamsPtr->frameContentSize = ip[5]; break;2999case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5)+256; break;3000case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break;3001} }3002return 0;3003}300430053006/** ZSTDv06_decodeFrameHeader() :3007* `srcSize` must be the size provided by ZSTDv06_frameHeaderSize().3008* @return : 0 if success, or an error code, which can be tested using ZSTDv06_isError() */3009static size_t ZSTDv06_decodeFrameHeader(ZSTDv06_DCtx* zc, const void* src, size_t srcSize)3010{3011size_t const result = ZSTDv06_getFrameParams(&(zc->fParams), src, srcSize);3012if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupported);3013return result;3014}301530163017typedef struct3018{3019blockType_t blockType;3020U32 origSize;3021} blockProperties_t;30223023/*! ZSTDv06_getcBlockSize() :3024* Provides the size of compressed block from block header `src` */3025static size_t ZSTDv06_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)3026{3027const BYTE* const in = (const BYTE*)src;3028U32 cSize;30293030if (srcSize < ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);30313032bpPtr->blockType = (blockType_t)((*in) >> 6);3033cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);3034bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;30353036if (bpPtr->blockType == bt_end) return 0;3037if (bpPtr->blockType == bt_rle) return 1;3038return cSize;3039}304030413042static size_t ZSTDv06_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)3043{3044if (dst==NULL) return ERROR(dstSize_tooSmall);3045if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);3046memcpy(dst, src, srcSize);3047return srcSize;3048}304930503051/*! ZSTDv06_decodeLiteralsBlock() :3052@return : nb of bytes read from src (< srcSize ) */3053static size_t ZSTDv06_decodeLiteralsBlock(ZSTDv06_DCtx* dctx,3054const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */3055{3056const BYTE* const istart = (const BYTE*) src;30573058/* any compressed block with literals segment must be at least this size */3059if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);30603061switch(istart[0]>> 6)3062{3063case IS_HUF:3064{ size_t litSize, litCSize, singleStream=0;3065U32 lhSize = ((istart[0]) >> 4) & 3;3066if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */3067switch(lhSize)3068{3069case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */3070/* 2 - 2 - 10 - 10 */3071lhSize=3;3072singleStream = istart[0] & 16;3073litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);3074litCSize = ((istart[1] & 3) << 8) + istart[2];3075break;3076case 2:3077/* 2 - 2 - 14 - 14 */3078lhSize=4;3079litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);3080litCSize = ((istart[2] & 63) << 8) + istart[3];3081break;3082case 3:3083/* 2 - 2 - 18 - 18 */3084lhSize=5;3085litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);3086litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];3087break;3088}3089if (litSize > ZSTDv06_BLOCKSIZE_MAX) return ERROR(corruption_detected);3090if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);30913092if (HUFv06_isError(singleStream ?3093HUFv06_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :3094HUFv06_decompress (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))3095return ERROR(corruption_detected);30963097dctx->litPtr = dctx->litBuffer;3098dctx->litSize = litSize;3099memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);3100return litCSize + lhSize;3101}3102case IS_PCH:3103{ size_t litSize, litCSize;3104U32 lhSize = ((istart[0]) >> 4) & 3;3105if (lhSize != 1) /* only case supported for now : small litSize, single stream */3106return ERROR(corruption_detected);3107if (!dctx->flagRepeatTable)3108return ERROR(dictionary_corrupted);31093110/* 2 - 2 - 10 - 10 */3111lhSize=3;3112litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);3113litCSize = ((istart[1] & 3) << 8) + istart[2];3114if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);31153116{ size_t const errorCode = HUFv06_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);3117if (HUFv06_isError(errorCode)) return ERROR(corruption_detected);3118}3119dctx->litPtr = dctx->litBuffer;3120dctx->litSize = litSize;3121memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);3122return litCSize + lhSize;3123}3124case IS_RAW:3125{ size_t litSize;3126U32 lhSize = ((istart[0]) >> 4) & 3;3127switch(lhSize)3128{3129case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */3130lhSize=1;3131litSize = istart[0] & 31;3132break;3133case 2:3134litSize = ((istart[0] & 15) << 8) + istart[1];3135break;3136case 3:3137litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];3138break;3139}31403141if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */3142if (litSize+lhSize > srcSize) return ERROR(corruption_detected);3143memcpy(dctx->litBuffer, istart+lhSize, litSize);3144dctx->litPtr = dctx->litBuffer;3145dctx->litSize = litSize;3146memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);3147return lhSize+litSize;3148}3149/* direct reference into compressed stream */3150dctx->litPtr = istart+lhSize;3151dctx->litSize = litSize;3152return lhSize+litSize;3153}3154case IS_RLE:3155{ size_t litSize;3156U32 lhSize = ((istart[0]) >> 4) & 3;3157switch(lhSize)3158{3159case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */3160lhSize = 1;3161litSize = istart[0] & 31;3162break;3163case 2:3164litSize = ((istart[0] & 15) << 8) + istart[1];3165break;3166case 3:3167litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];3168if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */3169break;3170}3171if (litSize > ZSTDv06_BLOCKSIZE_MAX) return ERROR(corruption_detected);3172memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);3173dctx->litPtr = dctx->litBuffer;3174dctx->litSize = litSize;3175return lhSize+1;3176}3177default:3178return ERROR(corruption_detected); /* impossible */3179}3180}318131823183/*! ZSTDv06_buildSeqTable() :3184@return : nb bytes read from src,3185or an error code if it fails, testable with ZSTDv06_isError()3186*/3187static size_t ZSTDv06_buildSeqTable(FSEv06_DTable* DTable, U32 type, U32 max, U32 maxLog,3188const void* src, size_t srcSize,3189const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)3190{3191switch(type)3192{3193case FSEv06_ENCODING_RLE :3194if (!srcSize) return ERROR(srcSize_wrong);3195if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);3196FSEv06_buildDTable_rle(DTable, *(const BYTE*)src); /* if *src > max, data is corrupted */3197return 1;3198case FSEv06_ENCODING_RAW :3199FSEv06_buildDTable(DTable, defaultNorm, max, defaultLog);3200return 0;3201case FSEv06_ENCODING_STATIC:3202if (!flagRepeatTable) return ERROR(corruption_detected);3203return 0;3204default : /* impossible */3205case FSEv06_ENCODING_DYNAMIC :3206{ U32 tableLog;3207S16 norm[MaxSeq+1];3208size_t const headerSize = FSEv06_readNCount(norm, &max, &tableLog, src, srcSize);3209if (FSEv06_isError(headerSize)) return ERROR(corruption_detected);3210if (tableLog > maxLog) return ERROR(corruption_detected);3211FSEv06_buildDTable(DTable, norm, max, tableLog);3212return headerSize;3213} }3214}321532163217static size_t ZSTDv06_decodeSeqHeaders(int* nbSeqPtr,3218FSEv06_DTable* DTableLL, FSEv06_DTable* DTableML, FSEv06_DTable* DTableOffb, U32 flagRepeatTable,3219const void* src, size_t srcSize)3220{3221const BYTE* const istart = (const BYTE*)src;3222const BYTE* const iend = istart + srcSize;3223const BYTE* ip = istart;32243225/* check */3226if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);32273228/* SeqHead */3229{ int nbSeq = *ip++;3230if (!nbSeq) { *nbSeqPtr=0; return 1; }3231if (nbSeq > 0x7F) {3232if (nbSeq == 0xFF) {3233if (ip+2 > iend) return ERROR(srcSize_wrong);3234nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;3235} else {3236if (ip >= iend) return ERROR(srcSize_wrong);3237nbSeq = ((nbSeq-0x80)<<8) + *ip++;3238}3239}3240*nbSeqPtr = nbSeq;3241}32423243/* FSE table descriptors */3244if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are "raw", hence no header, but at least xxLog bits per type */3245{ U32 const LLtype = *ip >> 6;3246U32 const Offtype = (*ip >> 4) & 3;3247U32 const MLtype = (*ip >> 2) & 3;3248ip++;32493250/* Build DTables */3251{ size_t const bhSize = ZSTDv06_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);3252if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);3253ip += bhSize;3254}3255{ size_t const bhSize = ZSTDv06_buildSeqTable(DTableOffb, Offtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);3256if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);3257ip += bhSize;3258}3259{ size_t const bhSize = ZSTDv06_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);3260if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);3261ip += bhSize;3262} }32633264return ip-istart;3265}326632673268typedef struct {3269size_t litLength;3270size_t matchLength;3271size_t offset;3272} seq_t;32733274typedef struct {3275BITv06_DStream_t DStream;3276FSEv06_DState_t stateLL;3277FSEv06_DState_t stateOffb;3278FSEv06_DState_t stateML;3279size_t prevOffset[ZSTDv06_REP_INIT];3280} seqState_t;3281328232833284static void ZSTDv06_decodeSequence(seq_t* seq, seqState_t* seqState)3285{3286/* Literal length */3287U32 const llCode = FSEv06_peekSymbol(&(seqState->stateLL));3288U32 const mlCode = FSEv06_peekSymbol(&(seqState->stateML));3289U32 const ofCode = FSEv06_peekSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */32903291U32 const llBits = LL_bits[llCode];3292U32 const mlBits = ML_bits[mlCode];3293U32 const ofBits = ofCode;3294U32 const totalBits = llBits+mlBits+ofBits;32953296static const U32 LL_base[MaxLL+1] = {32970, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,329816, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,32990x2000, 0x4000, 0x8000, 0x10000 };33003301static const U32 ML_base[MaxML+1] = {33020, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,330316, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,330432, 34, 36, 38, 40, 44, 48, 56, 64, 80, 96, 0x80, 0x100, 0x200, 0x400, 0x800,33050x1000, 0x2000, 0x4000, 0x8000, 0x10000 };33063307static const U32 OF_base[MaxOff+1] = {33080, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F,33090xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF,33100xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,33110xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, /*fake*/ 1, 1 };33123313/* sequence */3314{ size_t offset;3315if (!ofCode)3316offset = 0;3317else {3318offset = OF_base[ofCode] + BITv06_readBits(&(seqState->DStream), ofBits); /* <= 26 bits */3319if (MEM_32bits()) BITv06_reloadDStream(&(seqState->DStream));3320}33213322if (offset < ZSTDv06_REP_NUM) {3323if (llCode == 0 && offset <= 1) offset = 1-offset;33243325if (offset != 0) {3326size_t temp = seqState->prevOffset[offset];3327if (offset != 1) {3328seqState->prevOffset[2] = seqState->prevOffset[1];3329}3330seqState->prevOffset[1] = seqState->prevOffset[0];3331seqState->prevOffset[0] = offset = temp;33323333} else {3334offset = seqState->prevOffset[0];3335}3336} else {3337offset -= ZSTDv06_REP_MOVE;3338seqState->prevOffset[2] = seqState->prevOffset[1];3339seqState->prevOffset[1] = seqState->prevOffset[0];3340seqState->prevOffset[0] = offset;3341}3342seq->offset = offset;3343}33443345seq->matchLength = ML_base[mlCode] + MINMATCH + ((mlCode>31) ? BITv06_readBits(&(seqState->DStream), mlBits) : 0); /* <= 16 bits */3346if (MEM_32bits() && (mlBits+llBits>24)) BITv06_reloadDStream(&(seqState->DStream));33473348seq->litLength = LL_base[llCode] + ((llCode>15) ? BITv06_readBits(&(seqState->DStream), llBits) : 0); /* <= 16 bits */3349if (MEM_32bits() ||3350(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv06_reloadDStream(&(seqState->DStream));33513352/* ANS state update */3353FSEv06_updateState(&(seqState->stateLL), &(seqState->DStream)); /* <= 9 bits */3354FSEv06_updateState(&(seqState->stateML), &(seqState->DStream)); /* <= 9 bits */3355if (MEM_32bits()) BITv06_reloadDStream(&(seqState->DStream)); /* <= 18 bits */3356FSEv06_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <= 8 bits */3357}335833593360static size_t ZSTDv06_execSequence(BYTE* op,3361BYTE* const oend, seq_t sequence,3362const BYTE** litPtr, const BYTE* const litLimit,3363const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)3364{3365BYTE* const oLitEnd = op + sequence.litLength;3366size_t const sequenceLength = sequence.litLength + sequence.matchLength;3367BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */3368BYTE* const oend_8 = oend-8;3369const BYTE* const iLitEnd = *litPtr + sequence.litLength;3370const BYTE* match = oLitEnd - sequence.offset;33713372/* check */3373if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */3374if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */3375if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */33763377/* copy Literals */3378ZSTDv06_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */3379op = oLitEnd;3380*litPtr = iLitEnd; /* update for next sequence */33813382/* copy Match */3383if (sequence.offset > (size_t)(oLitEnd - base)) {3384/* offset beyond prefix */3385if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);3386match = dictEnd - (base-match);3387if (match + sequence.matchLength <= dictEnd) {3388memmove(oLitEnd, match, sequence.matchLength);3389return sequenceLength;3390}3391/* span extDict & currentPrefixSegment */3392{ size_t const length1 = dictEnd - match;3393memmove(oLitEnd, match, length1);3394op = oLitEnd + length1;3395sequence.matchLength -= length1;3396match = base;3397if (op > oend_8 || sequence.matchLength < MINMATCH) {3398while (op < oMatchEnd) *op++ = *match++;3399return sequenceLength;3400}3401} }3402/* Requirement: op <= oend_8 */34033404/* match within prefix */3405if (sequence.offset < 8) {3406/* close range match, overlap */3407static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */3408static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */3409int const sub2 = dec64table[sequence.offset];3410op[0] = match[0];3411op[1] = match[1];3412op[2] = match[2];3413op[3] = match[3];3414match += dec32table[sequence.offset];3415ZSTDv06_copy4(op+4, match);3416match -= sub2;3417} else {3418ZSTDv06_copy8(op, match);3419}3420op += 8; match += 8;34213422if (oMatchEnd > oend-(16-MINMATCH)) {3423if (op < oend_8) {3424ZSTDv06_wildcopy(op, match, oend_8 - op);3425match += oend_8 - op;3426op = oend_8;3427}3428while (op < oMatchEnd) *op++ = *match++;3429} else {3430ZSTDv06_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */3431}3432return sequenceLength;3433}343434353436static size_t ZSTDv06_decompressSequences(3437ZSTDv06_DCtx* dctx,3438void* dst, size_t maxDstSize,3439const void* seqStart, size_t seqSize)3440{3441const BYTE* ip = (const BYTE*)seqStart;3442const BYTE* const iend = ip + seqSize;3443BYTE* const ostart = (BYTE*)dst;3444BYTE* const oend = ostart + maxDstSize;3445BYTE* op = ostart;3446const BYTE* litPtr = dctx->litPtr;3447const BYTE* const litEnd = litPtr + dctx->litSize;3448FSEv06_DTable* DTableLL = dctx->LLTable;3449FSEv06_DTable* DTableML = dctx->MLTable;3450FSEv06_DTable* DTableOffb = dctx->OffTable;3451const BYTE* const base = (const BYTE*) (dctx->base);3452const BYTE* const vBase = (const BYTE*) (dctx->vBase);3453const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);3454int nbSeq;34553456/* Build Decoding Tables */3457{ size_t const seqHSize = ZSTDv06_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->flagRepeatTable, ip, seqSize);3458if (ZSTDv06_isError(seqHSize)) return seqHSize;3459ip += seqHSize;3460dctx->flagRepeatTable = 0;3461}34623463/* Regen sequences */3464if (nbSeq) {3465seq_t sequence;3466seqState_t seqState;34673468memset(&sequence, 0, sizeof(sequence));3469sequence.offset = REPCODE_STARTVALUE;3470{ U32 i; for (i=0; i<ZSTDv06_REP_INIT; i++) seqState.prevOffset[i] = REPCODE_STARTVALUE; }3471{ size_t const errorCode = BITv06_initDStream(&(seqState.DStream), ip, iend-ip);3472if (ERR_isError(errorCode)) return ERROR(corruption_detected); }3473FSEv06_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);3474FSEv06_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);3475FSEv06_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);34763477for ( ; (BITv06_reloadDStream(&(seqState.DStream)) <= BITv06_DStream_completed) && nbSeq ; ) {3478nbSeq--;3479ZSTDv06_decodeSequence(&sequence, &seqState);34803481#if 0 /* debug */3482static BYTE* start = NULL;3483if (start==NULL) start = op;3484size_t pos = (size_t)(op-start);3485if ((pos >= 5810037) && (pos < 5810400))3486printf("Dpos %6u :%5u literals & match %3u bytes at distance %6u \n",3487pos, (U32)sequence.litLength, (U32)sequence.matchLength, (U32)sequence.offset);3488#endif34893490{ size_t const oneSeqSize = ZSTDv06_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);3491if (ZSTDv06_isError(oneSeqSize)) return oneSeqSize;3492op += oneSeqSize;3493} }34943495/* check if reached exact end */3496if (nbSeq) return ERROR(corruption_detected);3497}34983499/* last literal segment */3500{ size_t const lastLLSize = litEnd - litPtr;3501if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */3502if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);3503if (lastLLSize > 0) {3504memcpy(op, litPtr, lastLLSize);3505op += lastLLSize;3506}3507}35083509return op-ostart;3510}351135123513static void ZSTDv06_checkContinuity(ZSTDv06_DCtx* dctx, const void* dst)3514{3515if (dst != dctx->previousDstEnd) { /* not contiguous */3516dctx->dictEnd = dctx->previousDstEnd;3517dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));3518dctx->base = dst;3519dctx->previousDstEnd = dst;3520}3521}352235233524static size_t ZSTDv06_decompressBlock_internal(ZSTDv06_DCtx* dctx,3525void* dst, size_t dstCapacity,3526const void* src, size_t srcSize)3527{ /* blockType == blockCompressed */3528const BYTE* ip = (const BYTE*)src;35293530if (srcSize >= ZSTDv06_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);35313532/* Decode literals sub-block */3533{ size_t const litCSize = ZSTDv06_decodeLiteralsBlock(dctx, src, srcSize);3534if (ZSTDv06_isError(litCSize)) return litCSize;3535ip += litCSize;3536srcSize -= litCSize;3537}3538return ZSTDv06_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);3539}354035413542size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx,3543void* dst, size_t dstCapacity,3544const void* src, size_t srcSize)3545{3546ZSTDv06_checkContinuity(dctx, dst);3547return ZSTDv06_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);3548}354935503551/*! ZSTDv06_decompressFrame() :3552* `dctx` must be properly initialized */3553static size_t ZSTDv06_decompressFrame(ZSTDv06_DCtx* dctx,3554void* dst, size_t dstCapacity,3555const void* src, size_t srcSize)3556{3557const BYTE* ip = (const BYTE*)src;3558const BYTE* const iend = ip + srcSize;3559BYTE* const ostart = (BYTE*)dst;3560BYTE* op = ostart;3561BYTE* const oend = ostart + dstCapacity;3562size_t remainingSize = srcSize;3563blockProperties_t blockProperties = { bt_compressed, 0 };35643565/* check */3566if (srcSize < ZSTDv06_frameHeaderSize_min+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);35673568/* Frame Header */3569{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);3570if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize;3571if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);3572if (ZSTDv06_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);3573ip += frameHeaderSize; remainingSize -= frameHeaderSize;3574}35753576/* Loop on each block */3577while (1) {3578size_t decodedSize=0;3579size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, iend-ip, &blockProperties);3580if (ZSTDv06_isError(cBlockSize)) return cBlockSize;35813582ip += ZSTDv06_blockHeaderSize;3583remainingSize -= ZSTDv06_blockHeaderSize;3584if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);35853586switch(blockProperties.blockType)3587{3588case bt_compressed:3589decodedSize = ZSTDv06_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);3590break;3591case bt_raw :3592decodedSize = ZSTDv06_copyRawBlock(op, oend-op, ip, cBlockSize);3593break;3594case bt_rle :3595return ERROR(GENERIC); /* not yet supported */3596break;3597case bt_end :3598/* end of frame */3599if (remainingSize) return ERROR(srcSize_wrong);3600break;3601default:3602return ERROR(GENERIC); /* impossible */3603}3604if (cBlockSize == 0) break; /* bt_end */36053606if (ZSTDv06_isError(decodedSize)) return decodedSize;3607op += decodedSize;3608ip += cBlockSize;3609remainingSize -= cBlockSize;3610}36113612return op-ostart;3613}361436153616size_t ZSTDv06_decompress_usingPreparedDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* refDCtx,3617void* dst, size_t dstCapacity,3618const void* src, size_t srcSize)3619{3620ZSTDv06_copyDCtx(dctx, refDCtx);3621ZSTDv06_checkContinuity(dctx, dst);3622return ZSTDv06_decompressFrame(dctx, dst, dstCapacity, src, srcSize);3623}362436253626size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,3627void* dst, size_t dstCapacity,3628const void* src, size_t srcSize,3629const void* dict, size_t dictSize)3630{3631ZSTDv06_decompressBegin_usingDict(dctx, dict, dictSize);3632ZSTDv06_checkContinuity(dctx, dst);3633return ZSTDv06_decompressFrame(dctx, dst, dstCapacity, src, srcSize);3634}363536363637size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)3638{3639return ZSTDv06_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);3640}364136423643size_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)3644{3645#if defined(ZSTDv06_HEAPMODE) && (ZSTDv06_HEAPMODE==1)3646size_t regenSize;3647ZSTDv06_DCtx* dctx = ZSTDv06_createDCtx();3648if (dctx==NULL) return ERROR(memory_allocation);3649regenSize = ZSTDv06_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);3650ZSTDv06_freeDCtx(dctx);3651return regenSize;3652#else /* stack mode */3653ZSTDv06_DCtx dctx;3654return ZSTDv06_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);3655#endif3656}36573658/* ZSTD_errorFrameSizeInfoLegacy() :3659assumes `cSize` and `dBound` are _not_ NULL */3660static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)3661{3662*cSize = ret;3663*dBound = ZSTD_CONTENTSIZE_ERROR;3664}36653666void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)3667{3668const BYTE* ip = (const BYTE*)src;3669size_t remainingSize = srcSize;3670size_t nbBlocks = 0;3671blockProperties_t blockProperties = { bt_compressed, 0 };36723673/* Frame Header */3674{ size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, srcSize);3675if (ZSTDv06_isError(frameHeaderSize)) {3676ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);3677return;3678}3679if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) {3680ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));3681return;3682}3683if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) {3684ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3685return;3686}3687ip += frameHeaderSize; remainingSize -= frameHeaderSize;3688}36893690/* Loop on each block */3691while (1) {3692size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);3693if (ZSTDv06_isError(cBlockSize)) {3694ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);3695return;3696}36973698ip += ZSTDv06_blockHeaderSize;3699remainingSize -= ZSTDv06_blockHeaderSize;3700if (cBlockSize > remainingSize) {3701ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3702return;3703}37043705if (cBlockSize == 0) break; /* bt_end */37063707ip += cBlockSize;3708remainingSize -= cBlockSize;3709nbBlocks++;3710}37113712*cSize = ip - (const BYTE*)src;3713*dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX;3714}37153716/*_******************************3717* Streaming Decompression API3718********************************/3719size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx)3720{3721return dctx->expected;3722}37233724size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)3725{3726/* Sanity check */3727if (srcSize != dctx->expected) return ERROR(srcSize_wrong);3728if (dstCapacity) ZSTDv06_checkContinuity(dctx, dst);37293730/* Decompress : frame header; part 1 */3731switch (dctx->stage)3732{3733case ZSTDds_getFrameHeaderSize :3734if (srcSize != ZSTDv06_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */3735dctx->headerSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);3736if (ZSTDv06_isError(dctx->headerSize)) return dctx->headerSize;3737memcpy(dctx->headerBuffer, src, ZSTDv06_frameHeaderSize_min);3738if (dctx->headerSize > ZSTDv06_frameHeaderSize_min) {3739dctx->expected = dctx->headerSize - ZSTDv06_frameHeaderSize_min;3740dctx->stage = ZSTDds_decodeFrameHeader;3741return 0;3742}3743dctx->expected = 0; /* not necessary to copy more */3744/* fall-through */3745case ZSTDds_decodeFrameHeader:3746{ size_t result;3747memcpy(dctx->headerBuffer + ZSTDv06_frameHeaderSize_min, src, dctx->expected);3748result = ZSTDv06_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);3749if (ZSTDv06_isError(result)) return result;3750dctx->expected = ZSTDv06_blockHeaderSize;3751dctx->stage = ZSTDds_decodeBlockHeader;3752return 0;3753}3754case ZSTDds_decodeBlockHeader:3755{ blockProperties_t bp;3756size_t const cBlockSize = ZSTDv06_getcBlockSize(src, ZSTDv06_blockHeaderSize, &bp);3757if (ZSTDv06_isError(cBlockSize)) return cBlockSize;3758if (bp.blockType == bt_end) {3759dctx->expected = 0;3760dctx->stage = ZSTDds_getFrameHeaderSize;3761} else {3762dctx->expected = cBlockSize;3763dctx->bType = bp.blockType;3764dctx->stage = ZSTDds_decompressBlock;3765}3766return 0;3767}3768case ZSTDds_decompressBlock:3769{ size_t rSize;3770switch(dctx->bType)3771{3772case bt_compressed:3773rSize = ZSTDv06_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);3774break;3775case bt_raw :3776rSize = ZSTDv06_copyRawBlock(dst, dstCapacity, src, srcSize);3777break;3778case bt_rle :3779return ERROR(GENERIC); /* not yet handled */3780break;3781case bt_end : /* should never happen (filtered at phase 1) */3782rSize = 0;3783break;3784default:3785return ERROR(GENERIC); /* impossible */3786}3787dctx->stage = ZSTDds_decodeBlockHeader;3788dctx->expected = ZSTDv06_blockHeaderSize;3789dctx->previousDstEnd = (char*)dst + rSize;3790return rSize;3791}3792default:3793return ERROR(GENERIC); /* impossible */3794}3795}379637973798static void ZSTDv06_refDictContent(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)3799{3800dctx->dictEnd = dctx->previousDstEnd;3801dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));3802dctx->base = dict;3803dctx->previousDstEnd = (const char*)dict + dictSize;3804}38053806static size_t ZSTDv06_loadEntropy(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)3807{3808size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize;38093810hSize = HUFv06_readDTableX4(dctx->hufTableX4, dict, dictSize);3811if (HUFv06_isError(hSize)) return ERROR(dictionary_corrupted);3812dict = (const char*)dict + hSize;3813dictSize -= hSize;38143815{ short offcodeNCount[MaxOff+1];3816U32 offcodeMaxValue=MaxOff, offcodeLog;3817offcodeHeaderSize = FSEv06_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);3818if (FSEv06_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);3819if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);3820{ size_t const errorCode = FSEv06_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);3821if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }3822dict = (const char*)dict + offcodeHeaderSize;3823dictSize -= offcodeHeaderSize;3824}38253826{ short matchlengthNCount[MaxML+1];3827unsigned matchlengthMaxValue = MaxML, matchlengthLog;3828matchlengthHeaderSize = FSEv06_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);3829if (FSEv06_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);3830if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);3831{ size_t const errorCode = FSEv06_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);3832if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }3833dict = (const char*)dict + matchlengthHeaderSize;3834dictSize -= matchlengthHeaderSize;3835}38363837{ short litlengthNCount[MaxLL+1];3838unsigned litlengthMaxValue = MaxLL, litlengthLog;3839litlengthHeaderSize = FSEv06_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);3840if (FSEv06_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);3841if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);3842{ size_t const errorCode = FSEv06_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);3843if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }3844}38453846dctx->flagRepeatTable = 1;3847return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;3848}38493850static size_t ZSTDv06_decompress_insertDictionary(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)3851{3852size_t eSize;3853U32 const magic = MEM_readLE32(dict);3854if (magic != ZSTDv06_DICT_MAGIC) {3855/* pure content mode */3856ZSTDv06_refDictContent(dctx, dict, dictSize);3857return 0;3858}3859/* load entropy tables */3860dict = (const char*)dict + 4;3861dictSize -= 4;3862eSize = ZSTDv06_loadEntropy(dctx, dict, dictSize);3863if (ZSTDv06_isError(eSize)) return ERROR(dictionary_corrupted);38643865/* reference dictionary content */3866dict = (const char*)dict + eSize;3867dictSize -= eSize;3868ZSTDv06_refDictContent(dctx, dict, dictSize);38693870return 0;3871}387238733874size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)3875{3876{ size_t const errorCode = ZSTDv06_decompressBegin(dctx);3877if (ZSTDv06_isError(errorCode)) return errorCode; }38783879if (dict && dictSize) {3880size_t const errorCode = ZSTDv06_decompress_insertDictionary(dctx, dict, dictSize);3881if (ZSTDv06_isError(errorCode)) return ERROR(dictionary_corrupted);3882}38833884return 0;3885}38863887/*3888Buffered version of Zstd compression library3889Copyright (C) 2015-2016, Yann Collet.38903891BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)38923893Redistribution and use in source and binary forms, with or without3894modification, are permitted provided that the following conditions are3895met:3896* Redistributions of source code must retain the above copyright3897notice, this list of conditions and the following disclaimer.3898* Redistributions in binary form must reproduce the above3899copyright notice, this list of conditions and the following disclaimer3900in the documentation and/or other materials provided with the3901distribution.3902THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS3903"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT3904LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR3905A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT3906OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,3907SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT3908LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,3909DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY3910THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT3911(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE3912OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.39133914You can contact the author at :3915- zstd homepage : http://www.zstd.net/3916*/391739183919/*-***************************************************************************3920* Streaming decompression howto3921*3922* A ZBUFFv06_DCtx object is required to track streaming operations.3923* Use ZBUFFv06_createDCtx() and ZBUFFv06_freeDCtx() to create/release resources.3924* Use ZBUFFv06_decompressInit() to start a new decompression operation,3925* or ZBUFFv06_decompressInitDictionary() if decompression requires a dictionary.3926* Note that ZBUFFv06_DCtx objects can be re-init multiple times.3927*3928* Use ZBUFFv06_decompressContinue() repetitively to consume your input.3929* *srcSizePtr and *dstCapacityPtr can be any size.3930* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.3931* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.3932* The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.3933* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),3934* or 0 when a frame is completely decoded,3935* or an error code, which can be tested using ZBUFFv06_isError().3936*3937* Hint : recommended buffer sizes (not compulsory) : ZBUFFv06_recommendedDInSize() and ZBUFFv06_recommendedDOutSize()3938* output : ZBUFFv06_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.3939* input : ZBUFFv06_recommendedDInSize == 128KB + 3;3940* just follow indications from ZBUFFv06_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .3941* *******************************************************************************/39423943typedef enum { ZBUFFds_init, ZBUFFds_loadHeader,3944ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv06_dStage;39453946/* *** Resource management *** */3947struct ZBUFFv06_DCtx_s {3948ZSTDv06_DCtx* zd;3949ZSTDv06_frameParams fParams;3950ZBUFFv06_dStage stage;3951char* inBuff;3952size_t inBuffSize;3953size_t inPos;3954char* outBuff;3955size_t outBuffSize;3956size_t outStart;3957size_t outEnd;3958size_t blockSize;3959BYTE headerBuffer[ZSTDv06_FRAMEHEADERSIZE_MAX];3960size_t lhSize;3961}; /* typedef'd to ZBUFFv06_DCtx within "zstd_buffered.h" */396239633964ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void)3965{3966ZBUFFv06_DCtx* zbd = (ZBUFFv06_DCtx*)malloc(sizeof(ZBUFFv06_DCtx));3967if (zbd==NULL) return NULL;3968memset(zbd, 0, sizeof(*zbd));3969zbd->zd = ZSTDv06_createDCtx();3970zbd->stage = ZBUFFds_init;3971return zbd;3972}39733974size_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* zbd)3975{3976if (zbd==NULL) return 0; /* support free on null */3977ZSTDv06_freeDCtx(zbd->zd);3978free(zbd->inBuff);3979free(zbd->outBuff);3980free(zbd);3981return 0;3982}398339843985/* *** Initialization *** */39863987size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* zbd, const void* dict, size_t dictSize)3988{3989zbd->stage = ZBUFFds_loadHeader;3990zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;3991return ZSTDv06_decompressBegin_usingDict(zbd->zd, dict, dictSize);3992}39933994size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* zbd)3995{3996return ZBUFFv06_decompressInitDictionary(zbd, NULL, 0);3997}3998399940004001MEM_STATIC size_t ZBUFFv06_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)4002{4003size_t length = MIN(dstCapacity, srcSize);4004if (length > 0) {4005memcpy(dst, src, length);4006}4007return length;4008}400940104011/* *** Decompression *** */40124013size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* zbd,4014void* dst, size_t* dstCapacityPtr,4015const void* src, size_t* srcSizePtr)4016{4017const char* const istart = (const char*)src;4018const char* const iend = istart + *srcSizePtr;4019const char* ip = istart;4020char* const ostart = (char*)dst;4021char* const oend = ostart + *dstCapacityPtr;4022char* op = ostart;4023U32 notDone = 1;40244025while (notDone) {4026switch(zbd->stage)4027{4028case ZBUFFds_init :4029return ERROR(init_missing);40304031case ZBUFFds_loadHeader :4032{ size_t const hSize = ZSTDv06_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);4033if (hSize != 0) {4034size_t const toLoad = hSize - zbd->lhSize; /* if hSize!=0, hSize > zbd->lhSize */4035if (ZSTDv06_isError(hSize)) return hSize;4036if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */4037memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);4038zbd->lhSize += iend-ip;4039*dstCapacityPtr = 0;4040return (hSize - zbd->lhSize) + ZSTDv06_blockHeaderSize; /* remaining header bytes + next block header */4041}4042memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;4043break;4044} }40454046/* Consume header */4047{ size_t const h1Size = ZSTDv06_nextSrcSizeToDecompress(zbd->zd); /* == ZSTDv06_frameHeaderSize_min */4048size_t const h1Result = ZSTDv06_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);4049if (ZSTDv06_isError(h1Result)) return h1Result;4050if (h1Size < zbd->lhSize) { /* long header */4051size_t const h2Size = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);4052size_t const h2Result = ZSTDv06_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);4053if (ZSTDv06_isError(h2Result)) return h2Result;4054} }40554056/* Frame header instruct buffer sizes */4057{ size_t const blockSize = MIN(1 << zbd->fParams.windowLog, ZSTDv06_BLOCKSIZE_MAX);4058zbd->blockSize = blockSize;4059if (zbd->inBuffSize < blockSize) {4060free(zbd->inBuff);4061zbd->inBuffSize = blockSize;4062zbd->inBuff = (char*)malloc(blockSize);4063if (zbd->inBuff == NULL) return ERROR(memory_allocation);4064}4065{ size_t const neededOutSize = ((size_t)1 << zbd->fParams.windowLog) + blockSize + WILDCOPY_OVERLENGTH * 2;4066if (zbd->outBuffSize < neededOutSize) {4067free(zbd->outBuff);4068zbd->outBuffSize = neededOutSize;4069zbd->outBuff = (char*)malloc(neededOutSize);4070if (zbd->outBuff == NULL) return ERROR(memory_allocation);4071} } }4072zbd->stage = ZBUFFds_read;4073/* fall-through */4074case ZBUFFds_read:4075{ size_t const neededInSize = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);4076if (neededInSize==0) { /* end of frame */4077zbd->stage = ZBUFFds_init;4078notDone = 0;4079break;4080}4081if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */4082size_t const decodedSize = ZSTDv06_decompressContinue(zbd->zd,4083zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,4084ip, neededInSize);4085if (ZSTDv06_isError(decodedSize)) return decodedSize;4086ip += neededInSize;4087if (!decodedSize) break; /* this was just a header */4088zbd->outEnd = zbd->outStart + decodedSize;4089zbd->stage = ZBUFFds_flush;4090break;4091}4092if (ip==iend) { notDone = 0; break; } /* no more input */4093zbd->stage = ZBUFFds_load;4094}4095/* fall-through */4096case ZBUFFds_load:4097{ size_t const neededInSize = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);4098size_t const toLoad = neededInSize - zbd->inPos; /* should always be <= remaining space within inBuff */4099size_t loadedSize;4100if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected); /* should never happen */4101loadedSize = ZBUFFv06_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);4102ip += loadedSize;4103zbd->inPos += loadedSize;4104if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */41054106/* decode loaded input */4107{ size_t const decodedSize = ZSTDv06_decompressContinue(zbd->zd,4108zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,4109zbd->inBuff, neededInSize);4110if (ZSTDv06_isError(decodedSize)) return decodedSize;4111zbd->inPos = 0; /* input is consumed */4112if (!decodedSize) { zbd->stage = ZBUFFds_read; break; } /* this was just a header */4113zbd->outEnd = zbd->outStart + decodedSize;4114zbd->stage = ZBUFFds_flush;4115/* break; */ /* ZBUFFds_flush follows */4116}4117}4118/* fall-through */4119case ZBUFFds_flush:4120{ size_t const toFlushSize = zbd->outEnd - zbd->outStart;4121size_t const flushedSize = ZBUFFv06_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);4122op += flushedSize;4123zbd->outStart += flushedSize;4124if (flushedSize == toFlushSize) {4125zbd->stage = ZBUFFds_read;4126if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)4127zbd->outStart = zbd->outEnd = 0;4128break;4129}4130/* cannot flush everything */4131notDone = 0;4132break;4133}4134default: return ERROR(GENERIC); /* impossible */4135} }41364137/* result */4138*srcSizePtr = ip-istart;4139*dstCapacityPtr = op-ostart;4140{ size_t nextSrcSizeHint = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);4141if (nextSrcSizeHint > ZSTDv06_blockHeaderSize) nextSrcSizeHint+= ZSTDv06_blockHeaderSize; /* get following block header too */4142nextSrcSizeHint -= zbd->inPos; /* already loaded*/4143return nextSrcSizeHint;4144}4145}4146414741484149/* *************************************4150* Tool functions4151***************************************/4152size_t ZBUFFv06_recommendedDInSize(void) { return ZSTDv06_BLOCKSIZE_MAX + ZSTDv06_blockHeaderSize /* block header size*/ ; }4153size_t ZBUFFv06_recommendedDOutSize(void) { return ZSTDv06_BLOCKSIZE_MAX; }415441554156