Path: blob/main/sys/contrib/zstd/lib/legacy/zstd_v05.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_v05.h"13#include "../common/error_private.h"141516/* ******************************************************************17mem.h18low-level memory access routines19Copyright (C) 2013-2015, Yann Collet.2021BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)2223Redistribution and use in source and binary forms, with or without24modification, are permitted provided that the following conditions are25met:2627* Redistributions of source code must retain the above copyright28notice, this list of conditions and the following disclaimer.29* Redistributions in binary form must reproduce the above30copyright notice, this list of conditions and the following disclaimer31in the documentation and/or other materials provided with the32distribution.3334THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS35"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT36LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR37A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT38OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,39SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT40LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,41DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY42THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT43(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE44OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.4546You can contact the author at :47- FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy48- Public forum : https://groups.google.com/forum/#!forum/lz4c49****************************************************************** */50#ifndef MEM_H_MODULE51#define MEM_H_MODULE5253#if defined (__cplusplus)54extern "C" {55#endif5657/*-****************************************58* Dependencies59******************************************/60#include <stddef.h> /* size_t, ptrdiff_t */61#include <string.h> /* memcpy */626364/*-****************************************65* Compiler specifics66******************************************/67#if defined(__GNUC__)68# define MEM_STATIC static __attribute__((unused))69#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)70# define MEM_STATIC static inline71#elif defined(_MSC_VER)72# define MEM_STATIC static __inline73#else74# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */75#endif767778/*-**************************************************************79* Basic Types80*****************************************************************/81#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)82# if defined(_AIX)83# include <inttypes.h>84# else85# include <stdint.h> /* intptr_t */86# endif87typedef uint8_t BYTE;88typedef uint16_t U16;89typedef int16_t S16;90typedef uint32_t U32;91typedef int32_t S32;92typedef uint64_t U64;93typedef int64_t S64;94#else95typedef unsigned char BYTE;96typedef unsigned short U16;97typedef signed short S16;98typedef unsigned int U32;99typedef signed int S32;100typedef unsigned long long U64;101typedef signed long long S64;102#endif103104105/*-**************************************************************106* Memory I/O107*****************************************************************/108/* MEM_FORCE_MEMORY_ACCESS :109* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.110* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.111* The below switch allow to select different access method for improved performance.112* Method 0 (default) : use `memcpy()`. Safe and portable.113* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).114* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.115* Method 2 : direct access. This method is portable but violate C standard.116* It can generate buggy code on targets depending on alignment.117* In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)118* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.119* Prefer these methods in priority order (0 > 1 > 2)120*/121#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */122# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)123# define MEM_FORCE_MEMORY_ACCESS 1124# endif125#endif126127MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }128MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }129130MEM_STATIC unsigned MEM_isLittleEndian(void)131{132const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */133return one.c[0];134}135136#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)137138/* violates C standard, by lying on structure alignment.139Only use if no other choice to achieve best performance on target platform */140MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }141MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }142MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }143144MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }145MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }146MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)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; }159MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }160MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }161162#else163164/* default method, safe and standard.165can sometimes prove slower */166167MEM_STATIC U16 MEM_read16(const void* memPtr)168{169U16 val; memcpy(&val, memPtr, sizeof(val)); return val;170}171172MEM_STATIC U32 MEM_read32(const void* memPtr)173{174U32 val; memcpy(&val, memPtr, sizeof(val)); return val;175}176177MEM_STATIC U64 MEM_read64(const void* memPtr)178{179U64 val; memcpy(&val, memPtr, sizeof(val)); return val;180}181182MEM_STATIC void MEM_write16(void* memPtr, U16 value)183{184memcpy(memPtr, &value, sizeof(value));185}186187MEM_STATIC void MEM_write32(void* memPtr, U32 value)188{189memcpy(memPtr, &value, sizeof(value));190}191192MEM_STATIC void MEM_write64(void* memPtr, U64 value)193{194memcpy(memPtr, &value, sizeof(value));195}196197#endif /* MEM_FORCE_MEMORY_ACCESS */198199200MEM_STATIC U16 MEM_readLE16(const void* memPtr)201{202if (MEM_isLittleEndian())203return MEM_read16(memPtr);204else {205const BYTE* p = (const BYTE*)memPtr;206return (U16)(p[0] + (p[1]<<8));207}208}209210MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)211{212if (MEM_isLittleEndian()) {213MEM_write16(memPtr, val);214} else {215BYTE* p = (BYTE*)memPtr;216p[0] = (BYTE)val;217p[1] = (BYTE)(val>>8);218}219}220221MEM_STATIC U32 MEM_readLE32(const void* memPtr)222{223if (MEM_isLittleEndian())224return MEM_read32(memPtr);225else {226const BYTE* p = (const BYTE*)memPtr;227return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));228}229}230231232MEM_STATIC U64 MEM_readLE64(const void* memPtr)233{234if (MEM_isLittleEndian())235return MEM_read64(memPtr);236else {237const BYTE* p = (const BYTE*)memPtr;238return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)239+ ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));240}241}242243244MEM_STATIC size_t MEM_readLEST(const void* memPtr)245{246if (MEM_32bits())247return (size_t)MEM_readLE32(memPtr);248else249return (size_t)MEM_readLE64(memPtr);250}251252253#if defined (__cplusplus)254}255#endif256257#endif /* MEM_H_MODULE */258259/*260zstd - standard compression library261Header File for static linking only262Copyright (C) 2014-2016, Yann Collet.263264BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)265266Redistribution and use in source and binary forms, with or without267modification, are permitted provided that the following conditions are268met:269* Redistributions of source code must retain the above copyright270notice, this list of conditions and the following disclaimer.271* Redistributions in binary form must reproduce the above272copyright notice, this list of conditions and the following disclaimer273in the documentation and/or other materials provided with the274distribution.275THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS276"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT277LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR278A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT279OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,280SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT281LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,282DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY283THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT284(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE285OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.286287You can contact the author at :288- zstd homepage : http://www.zstd.net289*/290#ifndef ZSTD_STATIC_H291#define ZSTD_STATIC_H292293/* The prototypes defined within this file are considered experimental.294* They should not be used in the context DLL as they may change in the future.295* Prefer static linking if you need them, to control breaking version changes issues.296*/297298#if defined (__cplusplus)299extern "C" {300#endif301302303304/*-*************************************305* Types306***************************************/307#define ZSTDv05_WINDOWLOG_ABSOLUTEMIN 11308309310/*-*************************************311* Advanced functions312***************************************/313/*- Advanced Decompression functions -*/314315/*! ZSTDv05_decompress_usingPreparedDCtx() :316* Same as ZSTDv05_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.317* It avoids reloading the dictionary each time.318* `preparedDCtx` must have been properly initialized using ZSTDv05_decompressBegin_usingDict().319* Requires 2 contexts : 1 for reference, which will not be modified, and 1 to run the decompression operation */320size_t ZSTDv05_decompress_usingPreparedDCtx(321ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* preparedDCtx,322void* dst, size_t dstCapacity,323const void* src, size_t srcSize);324325326/* **************************************327* Streaming functions (direct mode)328****************************************/329size_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx);330331/*332Streaming decompression, direct mode (bufferless)333334A ZSTDv05_DCtx object is required to track streaming operations.335Use ZSTDv05_createDCtx() / ZSTDv05_freeDCtx() to manage it.336A ZSTDv05_DCtx object can be re-used multiple times.337338First typical operation is to retrieve frame parameters, using ZSTDv05_getFrameParams().339This operation is independent, and just needs enough input data to properly decode the frame header.340Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.341Result : 0 when successful, it means the ZSTDv05_parameters structure has been filled.342>0 : means there is not enough data into src. Provides the expected size to successfully decode header.343errorCode, which can be tested using ZSTDv05_isError()344345Start decompression, with ZSTDv05_decompressBegin() or ZSTDv05_decompressBegin_usingDict()346Alternatively, you can copy a prepared context, using ZSTDv05_copyDCtx()347348Then use ZSTDv05_nextSrcSizeToDecompress() and ZSTDv05_decompressContinue() alternatively.349ZSTDv05_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv05_decompressContinue().350ZSTDv05_decompressContinue() requires this exact amount of bytes, or it will fail.351ZSTDv05_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).352They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.353354@result of ZSTDv05_decompressContinue() is the number of bytes regenerated within 'dst'.355It can be zero, which is not an error; it just means ZSTDv05_decompressContinue() has decoded some header.356357A frame is fully decoded when ZSTDv05_nextSrcSizeToDecompress() returns zero.358Context can then be reset to start a new decompression.359*/360361362/* **************************************363* Block functions364****************************************/365/*! Block functions produce and decode raw zstd blocks, without frame metadata.366User will have to take in charge required information to regenerate data, such as block sizes.367368A few rules to respect :369- Uncompressed block size must be <= 128 KB370- Compressing or decompressing requires a context structure371+ Use ZSTDv05_createCCtx() and ZSTDv05_createDCtx()372- It is necessary to init context before starting373+ compression : ZSTDv05_compressBegin()374+ decompression : ZSTDv05_decompressBegin()375+ variants _usingDict() are also allowed376+ copyCCtx() and copyDCtx() work too377- When a block is considered not compressible enough, ZSTDv05_compressBlock() result will be zero.378In which case, nothing is produced into `dst`.379+ User must test for such outcome and deal directly with uncompressed data380+ ZSTDv05_decompressBlock() doesn't accept uncompressed data as input !!381*/382383size_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);384385386387388#if defined (__cplusplus)389}390#endif391392#endif /* ZSTDv05_STATIC_H */393394395/*396zstd_internal - common functions to include397Header File for include398Copyright (C) 2014-2016, Yann Collet.399400BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)401402Redistribution and use in source and binary forms, with or without403modification, are permitted provided that the following conditions are404met:405* Redistributions of source code must retain the above copyright406notice, this list of conditions and the following disclaimer.407* Redistributions in binary form must reproduce the above408copyright notice, this list of conditions and the following disclaimer409in the documentation and/or other materials provided with the410distribution.411THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS412"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT413LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR414A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT415OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,416SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT417LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,418DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY419THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT420(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE421OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.422423You can contact the author at :424- zstd source repository : https://github.com/Cyan4973/zstd425*/426#ifndef ZSTD_CCOMMON_H_MODULE427#define ZSTD_CCOMMON_H_MODULE428429430431/*-*************************************432* Common macros433***************************************/434#define MIN(a,b) ((a)<(b) ? (a) : (b))435#define MAX(a,b) ((a)>(b) ? (a) : (b))436437438/*-*************************************439* Common constants440***************************************/441#define ZSTDv05_DICT_MAGIC 0xEC30A435442443#define KB *(1 <<10)444#define MB *(1 <<20)445#define GB *(1U<<30)446447#define BLOCKSIZE (128 KB) /* define, for static allocation */448449static const size_t ZSTDv05_blockHeaderSize = 3;450static const size_t ZSTDv05_frameHeaderSize_min = 5;451#define ZSTDv05_frameHeaderSize_max 5 /* define, for static allocation */452453#define BITv057 128454#define BITv056 64455#define BITv055 32456#define BITv054 16457#define BITv051 2458#define BITv050 1459460#define IS_HUFv05 0461#define IS_PCH 1462#define IS_RAW 2463#define IS_RLE 3464465#define MINMATCH 4466#define REPCODE_STARTVALUE 1467468#define Litbits 8469#define MLbits 7470#define LLbits 6471#define Offbits 5472#define MaxLit ((1<<Litbits) - 1)473#define MaxML ((1<<MLbits) - 1)474#define MaxLL ((1<<LLbits) - 1)475#define MaxOff ((1<<Offbits)- 1)476#define MLFSEv05Log 10477#define LLFSEv05Log 10478#define OffFSEv05Log 9479#define MaxSeq MAX(MaxLL, MaxML)480481#define FSEv05_ENCODING_RAW 0482#define FSEv05_ENCODING_RLE 1483#define FSEv05_ENCODING_STATIC 2484#define FSEv05_ENCODING_DYNAMIC 3485486487#define HufLog 12488489#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */490#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */491492#define WILDCOPY_OVERLENGTH 8493494#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)495496typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;497498499/*-*******************************************500* Shared functions to include for inlining501*********************************************/502static void ZSTDv05_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }503504#define COPY8(d,s) { ZSTDv05_copy8(d,s); d+=8; s+=8; }505506/*! ZSTDv05_wildcopy() :507* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */508MEM_STATIC void ZSTDv05_wildcopy(void* dst, const void* src, ptrdiff_t length)509{510const BYTE* ip = (const BYTE*)src;511BYTE* op = (BYTE*)dst;512BYTE* const oend = op + length;513do514COPY8(op, ip)515while (op < oend);516}517518519/*-*******************************************520* Private interfaces521*********************************************/522typedef struct {523void* buffer;524U32* offsetStart;525U32* offset;526BYTE* offCodeStart;527BYTE* offCode;528BYTE* litStart;529BYTE* lit;530BYTE* litLengthStart;531BYTE* litLength;532BYTE* matchLengthStart;533BYTE* matchLength;534BYTE* dumpsStart;535BYTE* dumps;536/* opt */537U32* matchLengthFreq;538U32* litLengthFreq;539U32* litFreq;540U32* offCodeFreq;541U32 matchLengthSum;542U32 litLengthSum;543U32 litSum;544U32 offCodeSum;545} seqStore_t;546547548549#endif /* ZSTDv05_CCOMMON_H_MODULE */550/* ******************************************************************551FSEv05 : Finite State Entropy coder552header file553Copyright (C) 2013-2015, Yann Collet.554555BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)556557Redistribution and use in source and binary forms, with or without558modification, are permitted provided that the following conditions are559met:560561* Redistributions of source code must retain the above copyright562notice, this list of conditions and the following disclaimer.563* Redistributions in binary form must reproduce the above564copyright notice, this list of conditions and the following disclaimer565in the documentation and/or other materials provided with the566distribution.567568THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS569"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT570LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR571A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT572OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,573SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT574LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,575DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY576THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT577(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE578OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.579580You can contact the author at :581- Source repository : https://github.com/Cyan4973/FiniteStateEntropy582- Public forum : https://groups.google.com/forum/#!forum/lz4c583****************************************************************** */584#ifndef FSEv05_H585#define FSEv05_H586587#if defined (__cplusplus)588extern "C" {589#endif590591592/* *****************************************593* Includes594******************************************/595#include <stddef.h> /* size_t, ptrdiff_t */596597598/*-****************************************599* FSEv05 simple functions600******************************************/601size_t FSEv05_decompress(void* dst, size_t maxDstSize,602const void* cSrc, size_t cSrcSize);603/*!604FSEv05_decompress():605Decompress FSEv05 data from buffer 'cSrc', of size 'cSrcSize',606into already allocated destination buffer 'dst', of size 'maxDstSize'.607return : size of regenerated data (<= maxDstSize)608or an error code, which can be tested using FSEv05_isError()609610** Important ** : FSEv05_decompress() doesn't decompress non-compressible nor RLE data !!!611Why ? : making this distinction requires a header.612Header management is intentionally delegated to the user layer, which can better manage special cases.613*/614615616/* *****************************************617* Tool functions618******************************************/619/* Error Management */620unsigned FSEv05_isError(size_t code); /* tells if a return value is an error code */621const char* FSEv05_getErrorName(size_t code); /* provides error code string (useful for debugging) */622623624625626/* *****************************************627* FSEv05 detailed API628******************************************/629/* *** DECOMPRESSION *** */630631/*!632FSEv05_readNCount():633Read compactly saved 'normalizedCounter' from 'rBuffer'.634return : size read from 'rBuffer'635or an errorCode, which can be tested using FSEv05_isError()636maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */637size_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);638639/*!640Constructor and Destructor of type FSEv05_DTable641Note that its size depends on 'tableLog' */642typedef unsigned FSEv05_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */643FSEv05_DTable* FSEv05_createDTable(unsigned tableLog);644void FSEv05_freeDTable(FSEv05_DTable* dt);645646/*!647FSEv05_buildDTable():648Builds 'dt', which must be already allocated, using FSEv05_createDTable()649@return : 0,650or an errorCode, which can be tested using FSEv05_isError() */651size_t FSEv05_buildDTable (FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);652653/*!654FSEv05_decompress_usingDTable():655Decompress compressed source @cSrc of size @cSrcSize using `dt`656into `dst` which must be already allocated.657@return : size of regenerated data (necessarily <= @dstCapacity)658or an errorCode, which can be tested using FSEv05_isError() */659size_t FSEv05_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv05_DTable* dt);660661662663#if defined (__cplusplus)664}665#endif666667#endif /* FSEv05_H */668/* ******************************************************************669bitstream670Part of FSEv05 library671header file (to include)672Copyright (C) 2013-2016, Yann Collet.673674BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)675676Redistribution and use in source and binary forms, with or without677modification, are permitted provided that the following conditions are678met:679680* Redistributions of source code must retain the above copyright681notice, this list of conditions and the following disclaimer.682* Redistributions in binary form must reproduce the above683copyright notice, this list of conditions and the following disclaimer684in the documentation and/or other materials provided with the685distribution.686687THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS688"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT689LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR690A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT691OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,692SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT693LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,694DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY695THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT696(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE697OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.698699You can contact the author at :700- Source repository : https://github.com/Cyan4973/FiniteStateEntropy701****************************************************************** */702#ifndef BITv05STREAM_H_MODULE703#define BITv05STREAM_H_MODULE704705#if defined (__cplusplus)706extern "C" {707#endif708709710/*711* This API consists of small unitary functions, which highly benefit from being inlined.712* Since link-time-optimization is not available for all compilers,713* these functions are defined into a .h to be included.714*/715716717718/*-********************************************719* bitStream decoding API (read backward)720**********************************************/721typedef struct722{723size_t bitContainer;724unsigned bitsConsumed;725const char* ptr;726const char* start;727} BITv05_DStream_t;728729typedef enum { BITv05_DStream_unfinished = 0,730BITv05_DStream_endOfBuffer = 1,731BITv05_DStream_completed = 2,732BITv05_DStream_overflow = 3 } BITv05_DStream_status; /* result of BITv05_reloadDStream() */733/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */734735MEM_STATIC size_t BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize);736MEM_STATIC size_t BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits);737MEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD);738MEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* bitD);739740741/*-****************************************742* unsafe API743******************************************/744MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits);745/* faster, but works only if nbBits >= 1 */746747748749/*-**************************************************************750* Helper functions751****************************************************************/752MEM_STATIC unsigned BITv05_highbit32 (U32 val)753{754# if defined(_MSC_VER) /* Visual */755unsigned long r;756return _BitScanReverse(&r, val) ? (unsigned)r : 0;757# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */758return __builtin_clz (val) ^ 31;759# else /* Software version */760static 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 };761U32 v = val;762unsigned r;763v |= v >> 1;764v |= v >> 2;765v |= v >> 4;766v |= v >> 8;767v |= v >> 16;768r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];769return r;770# endif771}772773774775/*-********************************************************776* bitStream decoding777**********************************************************/778/*!BITv05_initDStream779* Initialize a BITv05_DStream_t.780* @bitD : a pointer to an already allocated BITv05_DStream_t structure781* @srcBuffer must point at the beginning of a bitStream782* @srcSize must be the exact size of the bitStream783* @result : size of stream (== srcSize) or an errorCode if a problem is detected784*/785MEM_STATIC size_t BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize)786{787if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }788789if (srcSize >= sizeof(size_t)) { /* normal case */790U32 contain32;791bitD->start = (const char*)srcBuffer;792bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t);793bitD->bitContainer = MEM_readLEST(bitD->ptr);794contain32 = ((const BYTE*)srcBuffer)[srcSize-1];795if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */796bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);797} else {798U32 contain32;799bitD->start = (const char*)srcBuffer;800bitD->ptr = bitD->start;801bitD->bitContainer = *(const BYTE*)(bitD->start);802switch(srcSize)803{804case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */805case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */806case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */807case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */808case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */809case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8; /* fall-through */810default: break;811}812contain32 = ((const BYTE*)srcBuffer)[srcSize-1];813if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */814bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);815bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;816}817818return srcSize;819}820821MEM_STATIC size_t BITv05_lookBits(BITv05_DStream_t* bitD, U32 nbBits)822{823const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;824return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);825}826827/*! BITv05_lookBitsFast :828* unsafe version; only works only if nbBits >= 1 */829MEM_STATIC size_t BITv05_lookBitsFast(BITv05_DStream_t* bitD, U32 nbBits)830{831const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;832return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);833}834835MEM_STATIC void BITv05_skipBits(BITv05_DStream_t* bitD, U32 nbBits)836{837bitD->bitsConsumed += nbBits;838}839840MEM_STATIC size_t BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits)841{842size_t value = BITv05_lookBits(bitD, nbBits);843BITv05_skipBits(bitD, nbBits);844return value;845}846847/*!BITv05_readBitsFast :848* unsafe version; only works only if nbBits >= 1 */849MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits)850{851size_t value = BITv05_lookBitsFast(bitD, nbBits);852BITv05_skipBits(bitD, nbBits);853return value;854}855856MEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD)857{858if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */859return BITv05_DStream_overflow;860861if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {862bitD->ptr -= bitD->bitsConsumed >> 3;863bitD->bitsConsumed &= 7;864bitD->bitContainer = MEM_readLEST(bitD->ptr);865return BITv05_DStream_unfinished;866}867if (bitD->ptr == bitD->start) {868if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv05_DStream_endOfBuffer;869return BITv05_DStream_completed;870}871{872U32 nbBytes = bitD->bitsConsumed >> 3;873BITv05_DStream_status result = BITv05_DStream_unfinished;874if (bitD->ptr - nbBytes < bitD->start) {875nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */876result = BITv05_DStream_endOfBuffer;877}878bitD->ptr -= nbBytes;879bitD->bitsConsumed -= nbBytes*8;880bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */881return result;882}883}884885/*! BITv05_endOfDStream886* @return Tells if DStream has reached its exact end887*/888MEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* DStream)889{890return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));891}892893#if defined (__cplusplus)894}895#endif896897#endif /* BITv05STREAM_H_MODULE */898/* ******************************************************************899FSEv05 : Finite State Entropy coder900header file for static linking (only)901Copyright (C) 2013-2015, Yann Collet902903BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)904905Redistribution and use in source and binary forms, with or without906modification, are permitted provided that the following conditions are907met:908909* Redistributions of source code must retain the above copyright910notice, this list of conditions and the following disclaimer.911* Redistributions in binary form must reproduce the above912copyright notice, this list of conditions and the following disclaimer913in the documentation and/or other materials provided with the914distribution.915916THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS917"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT918LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR919A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT920OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,921SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT922LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,923DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY924THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT925(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE926OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.927928You can contact the author at :929- Source repository : https://github.com/Cyan4973/FiniteStateEntropy930- Public forum : https://groups.google.com/forum/#!forum/lz4c931****************************************************************** */932#ifndef FSEv05_STATIC_H933#define FSEv05_STATIC_H934935#if defined (__cplusplus)936extern "C" {937#endif938939940941/* *****************************************942* Static allocation943*******************************************/944/* It is possible to statically allocate FSEv05 CTable/DTable as a table of unsigned using below macros */945#define FSEv05_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))946947948/* *****************************************949* FSEv05 advanced API950*******************************************/951size_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits);952/* build a fake FSEv05_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */953954size_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, unsigned char symbolValue);955/* build a fake FSEv05_DTable, designed to always generate the same symbolValue */956957958959/* *****************************************960* FSEv05 symbol decompression API961*******************************************/962typedef struct963{964size_t state;965const void* table; /* precise table may vary, depending on U16 */966} FSEv05_DState_t;967968969static void FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt);970971static unsigned char FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);972973static unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr);974975976977/* *****************************************978* FSEv05 unsafe API979*******************************************/980static unsigned char FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);981/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */982983984/* *****************************************985* Implementation of inlined functions986*******************************************/987/* decompression */988989typedef struct {990U16 tableLog;991U16 fastMode;992} FSEv05_DTableHeader; /* sizeof U32 */993994typedef struct995{996unsigned short newState;997unsigned char symbol;998unsigned char nbBits;999} FSEv05_decode_t; /* size == U32 */10001001MEM_STATIC void FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt)1002{1003const void* ptr = dt;1004const FSEv05_DTableHeader* const DTableH = (const FSEv05_DTableHeader*)ptr;1005DStatePtr->state = BITv05_readBits(bitD, DTableH->tableLog);1006BITv05_reloadDStream(bitD);1007DStatePtr->table = dt + 1;1008}10091010MEM_STATIC BYTE FSEv05_peakSymbol(FSEv05_DState_t* DStatePtr)1011{1012const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];1013return DInfo.symbol;1014}10151016MEM_STATIC BYTE FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)1017{1018const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];1019const U32 nbBits = DInfo.nbBits;1020BYTE symbol = DInfo.symbol;1021size_t lowBits = BITv05_readBits(bitD, nbBits);10221023DStatePtr->state = DInfo.newState + lowBits;1024return symbol;1025}10261027MEM_STATIC BYTE FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)1028{1029const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];1030const U32 nbBits = DInfo.nbBits;1031BYTE symbol = DInfo.symbol;1032size_t lowBits = BITv05_readBitsFast(bitD, nbBits);10331034DStatePtr->state = DInfo.newState + lowBits;1035return symbol;1036}10371038MEM_STATIC unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr)1039{1040return DStatePtr->state == 0;1041}104210431044#if defined (__cplusplus)1045}1046#endif10471048#endif /* FSEv05_STATIC_H */1049/* ******************************************************************1050FSEv05 : Finite State Entropy coder1051Copyright (C) 2013-2015, Yann Collet.10521053BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)10541055Redistribution and use in source and binary forms, with or without1056modification, are permitted provided that the following conditions are1057met:10581059* Redistributions of source code must retain the above copyright1060notice, this list of conditions and the following disclaimer.1061* Redistributions in binary form must reproduce the above1062copyright notice, this list of conditions and the following disclaimer1063in the documentation and/or other materials provided with the1064distribution.10651066THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1067"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1068LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1069A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1070OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1071SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1072LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1073DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1074THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1075(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1076OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.10771078You can contact the author at :1079- FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy1080- Public forum : https://groups.google.com/forum/#!forum/lz4c1081****************************************************************** */10821083#ifndef FSEv05_COMMONDEFS_ONLY10841085/* **************************************************************1086* Tuning parameters1087****************************************************************/1088/*!MEMORY_USAGE :1089* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)1090* Increasing memory usage improves compression ratio1091* Reduced memory usage can improve speed, due to cache effect1092* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */1093#define FSEv05_MAX_MEMORY_USAGE 141094#define FSEv05_DEFAULT_MEMORY_USAGE 1310951096/*!FSEv05_MAX_SYMBOL_VALUE :1097* Maximum symbol value authorized.1098* Required for proper stack allocation */1099#define FSEv05_MAX_SYMBOL_VALUE 255110011011102/* **************************************************************1103* template functions type & suffix1104****************************************************************/1105#define FSEv05_FUNCTION_TYPE BYTE1106#define FSEv05_FUNCTION_EXTENSION1107#define FSEv05_DECODE_TYPE FSEv05_decode_t110811091110#endif /* !FSEv05_COMMONDEFS_ONLY */11111112/* **************************************************************1113* Compiler specifics1114****************************************************************/1115#ifdef _MSC_VER /* Visual Studio */1116# define FORCE_INLINE static __forceinline1117# include <intrin.h> /* For Visual 2005 */1118# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */1119# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */1120#else1121# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */1122# ifdef __GNUC__1123# define FORCE_INLINE static inline __attribute__((always_inline))1124# else1125# define FORCE_INLINE static inline1126# endif1127# else1128# define FORCE_INLINE static1129# endif /* __STDC_VERSION__ */1130#endif113111321133/* **************************************************************1134* Includes1135****************************************************************/1136#include <stdlib.h> /* malloc, free, qsort */1137#include <string.h> /* memcpy, memset */1138#include <stdio.h> /* printf (debug) */1139114011411142/* ***************************************************************1143* Constants1144*****************************************************************/1145#define FSEv05_MAX_TABLELOG (FSEv05_MAX_MEMORY_USAGE-2)1146#define FSEv05_MAX_TABLESIZE (1U<<FSEv05_MAX_TABLELOG)1147#define FSEv05_MAXTABLESIZE_MASK (FSEv05_MAX_TABLESIZE-1)1148#define FSEv05_DEFAULT_TABLELOG (FSEv05_DEFAULT_MEMORY_USAGE-2)1149#define FSEv05_MIN_TABLELOG 511501151#define FSEv05_TABLELOG_ABSOLUTE_MAX 151152#if FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX1153#error "FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX is not supported"1154#endif115511561157/* **************************************************************1158* Error Management1159****************************************************************/1160#define FSEv05_STATIC_ASSERT(c) { enum { FSEv05_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */116111621163/* **************************************************************1164* Complex types1165****************************************************************/1166typedef unsigned DTable_max_t[FSEv05_DTABLE_SIZE_U32(FSEv05_MAX_TABLELOG)];116711681169/* **************************************************************1170* Templates1171****************************************************************/1172/*1173designed to be included1174for type-specific functions (template emulation in C)1175Objective is to write these functions only once, for improved maintenance1176*/11771178/* safety checks */1179#ifndef FSEv05_FUNCTION_EXTENSION1180# error "FSEv05_FUNCTION_EXTENSION must be defined"1181#endif1182#ifndef FSEv05_FUNCTION_TYPE1183# error "FSEv05_FUNCTION_TYPE must be defined"1184#endif11851186/* Function names */1187#define FSEv05_CAT(X,Y) X##Y1188#define FSEv05_FUNCTION_NAME(X,Y) FSEv05_CAT(X,Y)1189#define FSEv05_TYPE_NAME(X,Y) FSEv05_CAT(X,Y)119011911192/* Function templates */1193static U32 FSEv05_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }1194119511961197FSEv05_DTable* FSEv05_createDTable (unsigned tableLog)1198{1199if (tableLog > FSEv05_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv05_TABLELOG_ABSOLUTE_MAX;1200return (FSEv05_DTable*)malloc( FSEv05_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );1201}12021203void FSEv05_freeDTable (FSEv05_DTable* dt)1204{1205free(dt);1206}12071208size_t FSEv05_buildDTable(FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)1209{1210FSEv05_DTableHeader DTableH;1211void* const tdPtr = dt+1; /* because dt is unsigned, 32-bits aligned on 32-bits */1212FSEv05_DECODE_TYPE* const tableDecode = (FSEv05_DECODE_TYPE*) (tdPtr);1213const U32 tableSize = 1 << tableLog;1214const U32 tableMask = tableSize-1;1215const U32 step = FSEv05_tableStep(tableSize);1216U16 symbolNext[FSEv05_MAX_SYMBOL_VALUE+1];1217U32 position = 0;1218U32 highThreshold = tableSize-1;1219const S16 largeLimit= (S16)(1 << (tableLog-1));1220U32 noLarge = 1;1221U32 s;12221223/* Sanity Checks */1224if (maxSymbolValue > FSEv05_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);1225if (tableLog > FSEv05_MAX_TABLELOG) return ERROR(tableLog_tooLarge);12261227/* Init, lay down lowprob symbols */1228memset(tableDecode, 0, sizeof(FSEv05_FUNCTION_TYPE) * (maxSymbolValue+1) ); /* useless init, but keep static analyzer happy, and we don't need to performance optimize legacy decoders */1229DTableH.tableLog = (U16)tableLog;1230for (s=0; s<=maxSymbolValue; s++) {1231if (normalizedCounter[s]==-1) {1232tableDecode[highThreshold--].symbol = (FSEv05_FUNCTION_TYPE)s;1233symbolNext[s] = 1;1234} else {1235if (normalizedCounter[s] >= largeLimit) noLarge=0;1236symbolNext[s] = normalizedCounter[s];1237} }12381239/* Spread symbols */1240for (s=0; s<=maxSymbolValue; s++) {1241int i;1242for (i=0; i<normalizedCounter[s]; i++) {1243tableDecode[position].symbol = (FSEv05_FUNCTION_TYPE)s;1244position = (position + step) & tableMask;1245while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */1246} }12471248if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */12491250/* Build Decoding table */1251{1252U32 i;1253for (i=0; i<tableSize; i++) {1254FSEv05_FUNCTION_TYPE symbol = (FSEv05_FUNCTION_TYPE)(tableDecode[i].symbol);1255U16 nextState = symbolNext[symbol]++;1256tableDecode[i].nbBits = (BYTE) (tableLog - BITv05_highbit32 ((U32)nextState) );1257tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);1258} }12591260DTableH.fastMode = (U16)noLarge;1261memcpy(dt, &DTableH, sizeof(DTableH));1262return 0;1263}126412651266#ifndef FSEv05_COMMONDEFS_ONLY1267/*-****************************************1268* FSEv05 helper functions1269******************************************/1270unsigned FSEv05_isError(size_t code) { return ERR_isError(code); }12711272const char* FSEv05_getErrorName(size_t code) { return ERR_getErrorName(code); }127312741275/*-**************************************************************1276* FSEv05 NCount encoding-decoding1277****************************************************************/1278static short FSEv05_abs(short a) { return a<0 ? -a : a; }127912801281size_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,1282const void* headerBuffer, size_t hbSize)1283{1284const BYTE* const istart = (const BYTE*) headerBuffer;1285const BYTE* const iend = istart + hbSize;1286const BYTE* ip = istart;1287int nbBits;1288int remaining;1289int threshold;1290U32 bitStream;1291int bitCount;1292unsigned charnum = 0;1293int previous0 = 0;12941295if (hbSize < 4) return ERROR(srcSize_wrong);1296bitStream = MEM_readLE32(ip);1297nbBits = (bitStream & 0xF) + FSEv05_MIN_TABLELOG; /* extract tableLog */1298if (nbBits > FSEv05_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);1299bitStream >>= 4;1300bitCount = 4;1301*tableLogPtr = nbBits;1302remaining = (1<<nbBits)+1;1303threshold = 1<<nbBits;1304nbBits++;13051306while ((remaining>1) && (charnum<=*maxSVPtr)) {1307if (previous0) {1308unsigned n0 = charnum;1309while ((bitStream & 0xFFFF) == 0xFFFF) {1310n0+=24;1311if (ip < iend-5) {1312ip+=2;1313bitStream = MEM_readLE32(ip) >> bitCount;1314} else {1315bitStream >>= 16;1316bitCount+=16;1317} }1318while ((bitStream & 3) == 3) {1319n0+=3;1320bitStream>>=2;1321bitCount+=2;1322}1323n0 += bitStream & 3;1324bitCount += 2;1325if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);1326while (charnum < n0) normalizedCounter[charnum++] = 0;1327if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {1328ip += bitCount>>3;1329bitCount &= 7;1330bitStream = MEM_readLE32(ip) >> bitCount;1331}1332else1333bitStream >>= 2;1334}1335{1336const short max = (short)((2*threshold-1)-remaining);1337short count;13381339if ((bitStream & (threshold-1)) < (U32)max) {1340count = (short)(bitStream & (threshold-1));1341bitCount += nbBits-1;1342} else {1343count = (short)(bitStream & (2*threshold-1));1344if (count >= threshold) count -= max;1345bitCount += nbBits;1346}13471348count--; /* extra accuracy */1349remaining -= FSEv05_abs(count);1350normalizedCounter[charnum++] = count;1351previous0 = !count;1352while (remaining < threshold) {1353nbBits--;1354threshold >>= 1;1355}13561357if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {1358ip += bitCount>>3;1359bitCount &= 7;1360} else {1361bitCount -= (int)(8 * (iend - 4 - ip));1362ip = iend - 4;1363}1364bitStream = MEM_readLE32(ip) >> (bitCount & 31);1365} }1366if (remaining != 1) return ERROR(GENERIC);1367*maxSVPtr = charnum-1;13681369ip += (bitCount+7)>>3;1370if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);1371return ip-istart;1372}1373137413751376/*-*******************************************************1377* Decompression (Byte symbols)1378*********************************************************/1379size_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, BYTE symbolValue)1380{1381void* ptr = dt;1382FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;1383void* dPtr = dt + 1;1384FSEv05_decode_t* const cell = (FSEv05_decode_t*)dPtr;13851386DTableH->tableLog = 0;1387DTableH->fastMode = 0;13881389cell->newState = 0;1390cell->symbol = symbolValue;1391cell->nbBits = 0;13921393return 0;1394}139513961397size_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits)1398{1399void* ptr = dt;1400FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;1401void* dPtr = dt + 1;1402FSEv05_decode_t* const dinfo = (FSEv05_decode_t*)dPtr;1403const unsigned tableSize = 1 << nbBits;1404const unsigned tableMask = tableSize - 1;1405const unsigned maxSymbolValue = tableMask;1406unsigned s;14071408/* Sanity checks */1409if (nbBits < 1) return ERROR(GENERIC); /* min size */14101411/* Build Decoding Table */1412DTableH->tableLog = (U16)nbBits;1413DTableH->fastMode = 1;1414for (s=0; s<=maxSymbolValue; s++) {1415dinfo[s].newState = 0;1416dinfo[s].symbol = (BYTE)s;1417dinfo[s].nbBits = (BYTE)nbBits;1418}14191420return 0;1421}14221423FORCE_INLINE size_t FSEv05_decompress_usingDTable_generic(1424void* dst, size_t maxDstSize,1425const void* cSrc, size_t cSrcSize,1426const FSEv05_DTable* dt, const unsigned fast)1427{1428BYTE* const ostart = (BYTE*) dst;1429BYTE* op = ostart;1430BYTE* const omax = op + maxDstSize;1431BYTE* const olimit = omax-3;14321433BITv05_DStream_t bitD;1434FSEv05_DState_t state1;1435FSEv05_DState_t state2;1436size_t errorCode;14371438/* Init */1439errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */1440if (FSEv05_isError(errorCode)) return errorCode;14411442FSEv05_initDState(&state1, &bitD, dt);1443FSEv05_initDState(&state2, &bitD, dt);14441445#define FSEv05_GETSYMBOL(statePtr) fast ? FSEv05_decodeSymbolFast(statePtr, &bitD) : FSEv05_decodeSymbol(statePtr, &bitD)14461447/* 4 symbols per loop */1448for ( ; (BITv05_reloadDStream(&bitD)==BITv05_DStream_unfinished) && (op<olimit) ; op+=4) {1449op[0] = FSEv05_GETSYMBOL(&state1);14501451if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1452BITv05_reloadDStream(&bitD);14531454op[1] = FSEv05_GETSYMBOL(&state2);14551456if (FSEv05_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1457{ if (BITv05_reloadDStream(&bitD) > BITv05_DStream_unfinished) { op+=2; break; } }14581459op[2] = FSEv05_GETSYMBOL(&state1);14601461if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1462BITv05_reloadDStream(&bitD);14631464op[3] = FSEv05_GETSYMBOL(&state2);1465}14661467/* tail */1468/* note : BITv05_reloadDStream(&bitD) >= FSEv05_DStream_partiallyFilled; Ends at exactly BITv05_DStream_completed */1469while (1) {1470if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state1))) )1471break;14721473*op++ = FSEv05_GETSYMBOL(&state1);14741475if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state2))) )1476break;14771478*op++ = FSEv05_GETSYMBOL(&state2);1479}14801481/* end ? */1482if (BITv05_endOfDStream(&bitD) && FSEv05_endOfDState(&state1) && FSEv05_endOfDState(&state2))1483return op-ostart;14841485if (op==omax) return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */14861487return ERROR(corruption_detected);1488}148914901491size_t FSEv05_decompress_usingDTable(void* dst, size_t originalSize,1492const void* cSrc, size_t cSrcSize,1493const FSEv05_DTable* dt)1494{1495const void* ptr = dt;1496const FSEv05_DTableHeader* DTableH = (const FSEv05_DTableHeader*)ptr;1497const U32 fastMode = DTableH->fastMode;14981499/* select fast mode (static) */1500if (fastMode) return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);1501return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);1502}150315041505size_t FSEv05_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)1506{1507const BYTE* const istart = (const BYTE*)cSrc;1508const BYTE* ip = istart;1509short counting[FSEv05_MAX_SYMBOL_VALUE+1];1510DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */1511unsigned tableLog;1512unsigned maxSymbolValue = FSEv05_MAX_SYMBOL_VALUE;1513size_t errorCode;15141515if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */15161517/* normal FSEv05 decoding mode */1518errorCode = FSEv05_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);1519if (FSEv05_isError(errorCode)) return errorCode;1520if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */1521ip += errorCode;1522cSrcSize -= errorCode;15231524errorCode = FSEv05_buildDTable (dt, counting, maxSymbolValue, tableLog);1525if (FSEv05_isError(errorCode)) return errorCode;15261527/* always return, even if it is an error code */1528return FSEv05_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);1529}1530153115321533#endif /* FSEv05_COMMONDEFS_ONLY */1534/* ******************************************************************1535Huff0 : Huffman coder, part of New Generation Entropy library1536header file1537Copyright (C) 2013-2016, Yann Collet.15381539BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)15401541Redistribution and use in source and binary forms, with or without1542modification, are permitted provided that the following conditions are1543met:15441545* Redistributions of source code must retain the above copyright1546notice, this list of conditions and the following disclaimer.1547* Redistributions in binary form must reproduce the above1548copyright notice, this list of conditions and the following disclaimer1549in the documentation and/or other materials provided with the1550distribution.15511552THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1553"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1554LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1555A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1556OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1557SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1558LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1559DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1560THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1561(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1562OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.15631564You can contact the author at :1565- Source repository : https://github.com/Cyan4973/FiniteStateEntropy1566****************************************************************** */1567#ifndef HUFF0_H1568#define HUFF0_H15691570#if defined (__cplusplus)1571extern "C" {1572#endif1573157415751576/* ****************************************1577* Huff0 simple functions1578******************************************/1579size_t HUFv05_decompress(void* dst, size_t dstSize,1580const void* cSrc, size_t cSrcSize);1581/*!1582HUFv05_decompress():1583Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',1584into already allocated destination buffer 'dst', of size 'dstSize'.1585@dstSize : must be the **exact** size of original (uncompressed) data.1586Note : in contrast with FSEv05, HUFv05_decompress can regenerate1587RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,1588because it knows size to regenerate.1589@return : size of regenerated data (== dstSize)1590or an error code, which can be tested using HUFv05_isError()1591*/159215931594/* ****************************************1595* Tool functions1596******************************************/1597/* Error Management */1598unsigned HUFv05_isError(size_t code); /* tells if a return value is an error code */1599const char* HUFv05_getErrorName(size_t code); /* provides error code string (useful for debugging) */160016011602#if defined (__cplusplus)1603}1604#endif16051606#endif /* HUF0_H */1607/* ******************************************************************1608Huff0 : Huffman codec, part of New Generation Entropy library1609header file, for static linking only1610Copyright (C) 2013-2016, Yann Collet16111612BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)16131614Redistribution and use in source and binary forms, with or without1615modification, are permitted provided that the following conditions are1616met:16171618* Redistributions of source code must retain the above copyright1619notice, this list of conditions and the following disclaimer.1620* Redistributions in binary form must reproduce the above1621copyright notice, this list of conditions and the following disclaimer1622in the documentation and/or other materials provided with the1623distribution.16241625THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1626"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1627LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1628A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1629OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1630SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1631LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1632DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1633THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1634(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1635OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.16361637You can contact the author at :1638- Source repository : https://github.com/Cyan4973/FiniteStateEntropy1639****************************************************************** */1640#ifndef HUF0_STATIC_H1641#define HUF0_STATIC_H16421643#if defined (__cplusplus)1644extern "C" {1645#endif1646164716481649/* ****************************************1650* Static allocation1651******************************************/1652/* static allocation of Huff0's DTable */1653#define HUFv05_DTABLE_SIZE(maxTableLog) (1 + (1<<maxTableLog))1654#define HUFv05_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \1655unsigned short DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }1656#define HUFv05_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \1657unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }1658#define HUFv05_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \1659unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }166016611662/* ****************************************1663* Advanced decompression functions1664******************************************/1665size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */1666size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */166716681669/* ****************************************1670* Huff0 detailed API1671******************************************/1672/*!1673HUFv05_decompress() does the following:16741. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics16752. build Huffman table from save, using HUFv05_readDTableXn()16763. decode 1 or 4 segments in parallel using HUFv05_decompressSXn_usingDTable1677*/1678size_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);1679size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);16801681size_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);1682size_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);168316841685/* single stream variants */16861687size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */1688size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */16891690size_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);1691size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);1692169316941695#if defined (__cplusplus)1696}1697#endif16981699#endif /* HUF0_STATIC_H */1700/* ******************************************************************1701Huff0 : Huffman coder, part of New Generation Entropy library1702Copyright (C) 2013-2015, Yann Collet.17031704BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)17051706Redistribution and use in source and binary forms, with or without1707modification, are permitted provided that the following conditions are1708met:17091710* Redistributions of source code must retain the above copyright1711notice, this list of conditions and the following disclaimer.1712* Redistributions in binary form must reproduce the above1713copyright notice, this list of conditions and the following disclaimer1714in the documentation and/or other materials provided with the1715distribution.17161717THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1718"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1719LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1720A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1721OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1722SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1723LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1724DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1725THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1726(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1727OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.17281729You can contact the author at :1730- FSEv05+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy1731- Public forum : https://groups.google.com/forum/#!forum/lz4c1732****************************************************************** */17331734/* **************************************************************1735* Compiler specifics1736****************************************************************/1737#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)1738/* inline is defined */1739#elif defined(_MSC_VER)1740# define inline __inline1741#else1742# define inline /* disable inline */1743#endif174417451746#ifdef _MSC_VER /* Visual Studio */1747# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */1748#endif174917501751/* **************************************************************1752* Includes1753****************************************************************/1754#include <stdlib.h> /* malloc, free, qsort */1755#include <string.h> /* memcpy, memset */1756#include <stdio.h> /* printf (debug) */175717581759/* **************************************************************1760* Constants1761****************************************************************/1762#define HUFv05_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUFv05_MAX_TABLELOG. Beyond that value, code does not work */1763#define HUFv05_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUFv05_ABSOLUTEMAX_TABLELOG */1764#define HUFv05_DEFAULT_TABLELOG HUFv05_MAX_TABLELOG /* tableLog by default, when not specified */1765#define HUFv05_MAX_SYMBOL_VALUE 2551766#if (HUFv05_MAX_TABLELOG > HUFv05_ABSOLUTEMAX_TABLELOG)1767# error "HUFv05_MAX_TABLELOG is too large !"1768#endif176917701771/* **************************************************************1772* Error Management1773****************************************************************/1774unsigned HUFv05_isError(size_t code) { return ERR_isError(code); }1775const char* HUFv05_getErrorName(size_t code) { return ERR_getErrorName(code); }1776#define HUFv05_STATIC_ASSERT(c) { enum { HUFv05_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */177717781779/* *******************************************************1780* Huff0 : Huffman block decompression1781*********************************************************/1782typedef struct { BYTE byte; BYTE nbBits; } HUFv05_DEltX2; /* single-symbol decoding */17831784typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv05_DEltX4; /* double-symbols decoding */17851786typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;17871788/*! HUFv05_readStats1789Read compact Huffman tree, saved by HUFv05_writeCTable1790@huffWeight : destination buffer1791@return : size read from `src`1792*/1793static size_t HUFv05_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,1794U32* nbSymbolsPtr, U32* tableLogPtr,1795const void* src, size_t srcSize)1796{1797U32 weightTotal;1798U32 tableLog;1799const BYTE* ip = (const BYTE*) src;1800size_t iSize;1801size_t oSize;1802U32 n;18031804if (!srcSize) return ERROR(srcSize_wrong);1805iSize = ip[0];1806/* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */18071808if (iSize >= 128) { /* special header */1809if (iSize >= (242)) { /* RLE */1810static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };1811oSize = l[iSize-242];1812memset(huffWeight, 1, hwSize);1813iSize = 0;1814}1815else { /* Incompressible */1816oSize = iSize - 127;1817iSize = ((oSize+1)/2);1818if (iSize+1 > srcSize) return ERROR(srcSize_wrong);1819if (oSize >= hwSize) return ERROR(corruption_detected);1820ip += 1;1821for (n=0; n<oSize; n+=2) {1822huffWeight[n] = ip[n/2] >> 4;1823huffWeight[n+1] = ip[n/2] & 15;1824} } }1825else { /* header compressed with FSEv05 (normal case) */1826if (iSize+1 > srcSize) return ERROR(srcSize_wrong);1827oSize = FSEv05_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */1828if (FSEv05_isError(oSize)) return oSize;1829}18301831/* collect weight stats */1832memset(rankStats, 0, (HUFv05_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));1833weightTotal = 0;1834for (n=0; n<oSize; n++) {1835if (huffWeight[n] >= HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);1836rankStats[huffWeight[n]]++;1837weightTotal += (1 << huffWeight[n]) >> 1;1838}1839if (weightTotal == 0) return ERROR(corruption_detected);18401841/* get last non-null symbol weight (implied, total must be 2^n) */1842tableLog = BITv05_highbit32(weightTotal) + 1;1843if (tableLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);1844{ /* determine last weight */1845U32 total = 1 << tableLog;1846U32 rest = total - weightTotal;1847U32 verif = 1 << BITv05_highbit32(rest);1848U32 lastWeight = BITv05_highbit32(rest) + 1;1849if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */1850huffWeight[oSize] = (BYTE)lastWeight;1851rankStats[lastWeight]++;1852}18531854/* check tree construction validity */1855if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */18561857/* results */1858*nbSymbolsPtr = (U32)(oSize+1);1859*tableLogPtr = tableLog;1860return iSize+1;1861}186218631864/*-***************************/1865/* single-symbol decoding */1866/*-***************************/18671868size_t HUFv05_readDTableX2 (U16* DTable, const void* src, size_t srcSize)1869{1870BYTE huffWeight[HUFv05_MAX_SYMBOL_VALUE + 1];1871U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */1872U32 tableLog = 0;1873size_t iSize;1874U32 nbSymbols = 0;1875U32 n;1876U32 nextRankStart;1877void* const dtPtr = DTable + 1;1878HUFv05_DEltX2* const dt = (HUFv05_DEltX2*)dtPtr;18791880HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */1881/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */18821883iSize = HUFv05_readStats(huffWeight, HUFv05_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);1884if (HUFv05_isError(iSize)) return iSize;18851886/* check result */1887if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge); /* DTable is too small */1888DTable[0] = (U16)tableLog; /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */18891890/* Prepare ranks */1891nextRankStart = 0;1892for (n=1; n<=tableLog; n++) {1893U32 current = nextRankStart;1894nextRankStart += (rankVal[n] << (n-1));1895rankVal[n] = current;1896}18971898/* fill DTable */1899for (n=0; n<nbSymbols; n++) {1900const U32 w = huffWeight[n];1901const U32 length = (1 << w) >> 1;1902U32 i;1903HUFv05_DEltX2 D;1904D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);1905for (i = rankVal[w]; i < rankVal[w] + length; i++)1906dt[i] = D;1907rankVal[w] += length;1908}19091910return iSize;1911}19121913static BYTE HUFv05_decodeSymbolX2(BITv05_DStream_t* Dstream, const HUFv05_DEltX2* dt, const U32 dtLog)1914{1915const size_t val = BITv05_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */1916const BYTE c = dt[val].byte;1917BITv05_skipBits(Dstream, dt[val].nbBits);1918return c;1919}19201921#define HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \1922*ptr++ = HUFv05_decodeSymbolX2(DStreamPtr, dt, dtLog)19231924#define HUFv05_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \1925if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \1926HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)19271928#define HUFv05_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \1929if (MEM_64bits()) \1930HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)19311932static inline size_t HUFv05_decodeStreamX2(BYTE* p, BITv05_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv05_DEltX2* const dt, const U32 dtLog)1933{1934BYTE* const pStart = p;19351936/* up to 4 symbols at a time */1937while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-4)) {1938HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);1939HUFv05_DECODE_SYMBOLX2_1(p, bitDPtr);1940HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);1941HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);1942}19431944/* closer to the end */1945while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd))1946HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);19471948/* no more data to retrieve from bitstream, hence no need to reload */1949while (p < pEnd)1950HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);19511952return pEnd-pStart;1953}19541955size_t HUFv05_decompress1X2_usingDTable(1956void* dst, size_t dstSize,1957const void* cSrc, size_t cSrcSize,1958const U16* DTable)1959{1960BYTE* op = (BYTE*)dst;1961BYTE* const oend = op + dstSize;1962const U32 dtLog = DTable[0];1963const void* dtPtr = DTable;1964const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr)+1;1965BITv05_DStream_t bitD;19661967if (dstSize <= cSrcSize) return ERROR(dstSize_tooSmall);1968{ size_t const errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);1969if (HUFv05_isError(errorCode)) return errorCode; }19701971HUFv05_decodeStreamX2(op, &bitD, oend, dt, dtLog);19721973/* check */1974if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);19751976return dstSize;1977}19781979size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)1980{1981HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);1982const BYTE* ip = (const BYTE*) cSrc;1983size_t errorCode;19841985errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);1986if (HUFv05_isError(errorCode)) return errorCode;1987if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);1988ip += errorCode;1989cSrcSize -= errorCode;19901991return HUFv05_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);1992}199319941995size_t HUFv05_decompress4X2_usingDTable(1996void* dst, size_t dstSize,1997const void* cSrc, size_t cSrcSize,1998const U16* DTable)1999{2000/* Check */2001if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */2002{2003const BYTE* const istart = (const BYTE*) cSrc;2004BYTE* const ostart = (BYTE*) dst;2005BYTE* const oend = ostart + dstSize;2006const void* const dtPtr = DTable;2007const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1;2008const U32 dtLog = DTable[0];2009size_t errorCode;20102011/* Init */2012BITv05_DStream_t bitD1;2013BITv05_DStream_t bitD2;2014BITv05_DStream_t bitD3;2015BITv05_DStream_t bitD4;2016const size_t length1 = MEM_readLE16(istart);2017const size_t length2 = MEM_readLE16(istart+2);2018const size_t length3 = MEM_readLE16(istart+4);2019size_t length4;2020const BYTE* const istart1 = istart + 6; /* jumpTable */2021const BYTE* const istart2 = istart1 + length1;2022const BYTE* const istart3 = istart2 + length2;2023const BYTE* const istart4 = istart3 + length3;2024const size_t segmentSize = (dstSize+3) / 4;2025BYTE* const opStart2 = ostart + segmentSize;2026BYTE* const opStart3 = opStart2 + segmentSize;2027BYTE* const opStart4 = opStart3 + segmentSize;2028BYTE* op1 = ostart;2029BYTE* op2 = opStart2;2030BYTE* op3 = opStart3;2031BYTE* op4 = opStart4;2032U32 endSignal;20332034length4 = cSrcSize - (length1 + length2 + length3 + 6);2035if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */2036errorCode = BITv05_initDStream(&bitD1, istart1, length1);2037if (HUFv05_isError(errorCode)) return errorCode;2038errorCode = BITv05_initDStream(&bitD2, istart2, length2);2039if (HUFv05_isError(errorCode)) return errorCode;2040errorCode = BITv05_initDStream(&bitD3, istart3, length3);2041if (HUFv05_isError(errorCode)) return errorCode;2042errorCode = BITv05_initDStream(&bitD4, istart4, length4);2043if (HUFv05_isError(errorCode)) return errorCode;20442045/* 16-32 symbols per loop (4-8 symbols per stream) */2046endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);2047for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {2048HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);2049HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);2050HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);2051HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);2052HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1);2053HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2);2054HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3);2055HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4);2056HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);2057HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);2058HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);2059HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);2060HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1);2061HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2);2062HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3);2063HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4);2064endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);2065}20662067/* check corruption */2068if (op1 > opStart2) return ERROR(corruption_detected);2069if (op2 > opStart3) return ERROR(corruption_detected);2070if (op3 > opStart4) return ERROR(corruption_detected);2071/* note : op4 supposed already verified within main loop */20722073/* finish bitStreams one by one */2074HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);2075HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);2076HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);2077HUFv05_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);20782079/* check */2080endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);2081if (!endSignal) return ERROR(corruption_detected);20822083/* decoded size */2084return dstSize;2085}2086}208720882089size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2090{2091HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);2092const BYTE* ip = (const BYTE*) cSrc;2093size_t errorCode;20942095errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);2096if (HUFv05_isError(errorCode)) return errorCode;2097if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);2098ip += errorCode;2099cSrcSize -= errorCode;21002101return HUFv05_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2102}210321042105/* *************************/2106/* double-symbols decoding */2107/* *************************/21082109static void HUFv05_fillDTableX4Level2(HUFv05_DEltX4* DTable, U32 sizeLog, const U32 consumed,2110const U32* rankValOrigin, const int minWeight,2111const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,2112U32 nbBitsBaseline, U16 baseSeq)2113{2114HUFv05_DEltX4 DElt;2115U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];2116U32 s;21172118/* get pre-calculated rankVal */2119memcpy(rankVal, rankValOrigin, sizeof(rankVal));21202121/* fill skipped values */2122if (minWeight>1) {2123U32 i, skipSize = rankVal[minWeight];2124MEM_writeLE16(&(DElt.sequence), baseSeq);2125DElt.nbBits = (BYTE)(consumed);2126DElt.length = 1;2127for (i = 0; i < skipSize; i++)2128DTable[i] = DElt;2129}21302131/* fill DTable */2132for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */2133const U32 symbol = sortedSymbols[s].symbol;2134const U32 weight = sortedSymbols[s].weight;2135const U32 nbBits = nbBitsBaseline - weight;2136const U32 length = 1 << (sizeLog-nbBits);2137const U32 start = rankVal[weight];2138U32 i = start;2139const U32 end = start + length;21402141MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));2142DElt.nbBits = (BYTE)(nbBits + consumed);2143DElt.length = 2;2144do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */21452146rankVal[weight] += length;2147}2148}21492150typedef U32 rankVal_t[HUFv05_ABSOLUTEMAX_TABLELOG][HUFv05_ABSOLUTEMAX_TABLELOG + 1];21512152static void HUFv05_fillDTableX4(HUFv05_DEltX4* DTable, const U32 targetLog,2153const sortedSymbol_t* sortedList, const U32 sortedListSize,2154const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,2155const U32 nbBitsBaseline)2156{2157U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];2158const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */2159const U32 minBits = nbBitsBaseline - maxWeight;2160U32 s;21612162memcpy(rankVal, rankValOrigin, sizeof(rankVal));21632164/* fill DTable */2165for (s=0; s<sortedListSize; s++) {2166const U16 symbol = sortedList[s].symbol;2167const U32 weight = sortedList[s].weight;2168const U32 nbBits = nbBitsBaseline - weight;2169const U32 start = rankVal[weight];2170const U32 length = 1 << (targetLog-nbBits);21712172if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */2173U32 sortedRank;2174int minWeight = nbBits + scaleLog;2175if (minWeight < 1) minWeight = 1;2176sortedRank = rankStart[minWeight];2177HUFv05_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,2178rankValOrigin[nbBits], minWeight,2179sortedList+sortedRank, sortedListSize-sortedRank,2180nbBitsBaseline, symbol);2181} else {2182U32 i;2183const U32 end = start + length;2184HUFv05_DEltX4 DElt;21852186MEM_writeLE16(&(DElt.sequence), symbol);2187DElt.nbBits = (BYTE)(nbBits);2188DElt.length = 1;2189for (i = start; i < end; i++)2190DTable[i] = DElt;2191}2192rankVal[weight] += length;2193}2194}21952196size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize)2197{2198BYTE weightList[HUFv05_MAX_SYMBOL_VALUE + 1];2199sortedSymbol_t sortedSymbol[HUFv05_MAX_SYMBOL_VALUE + 1];2200U32 rankStats[HUFv05_ABSOLUTEMAX_TABLELOG + 1] = { 0 };2201U32 rankStart0[HUFv05_ABSOLUTEMAX_TABLELOG + 2] = { 0 };2202U32* const rankStart = rankStart0+1;2203rankVal_t rankVal;2204U32 tableLog, maxW, sizeOfSort, nbSymbols;2205const U32 memLog = DTable[0];2206size_t iSize;2207void* dtPtr = DTable;2208HUFv05_DEltX4* const dt = ((HUFv05_DEltX4*)dtPtr) + 1;22092210HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX4) == sizeof(unsigned)); /* if compilation fails here, assertion is false */2211if (memLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);2212/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */22132214iSize = HUFv05_readStats(weightList, HUFv05_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);2215if (HUFv05_isError(iSize)) return iSize;22162217/* check result */2218if (tableLog > memLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */22192220/* find maxWeight */2221for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */22222223/* Get start index of each weight */2224{2225U32 w, nextRankStart = 0;2226for (w=1; w<=maxW; w++) {2227U32 current = nextRankStart;2228nextRankStart += rankStats[w];2229rankStart[w] = current;2230}2231rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/2232sizeOfSort = nextRankStart;2233}22342235/* sort symbols by weight */2236{2237U32 s;2238for (s=0; s<nbSymbols; s++) {2239U32 w = weightList[s];2240U32 r = rankStart[w]++;2241sortedSymbol[r].symbol = (BYTE)s;2242sortedSymbol[r].weight = (BYTE)w;2243}2244rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */2245}22462247/* Build rankVal */2248{2249const U32 minBits = tableLog+1 - maxW;2250U32 nextRankVal = 0;2251U32 w, consumed;2252const int rescale = (memLog-tableLog) - 1; /* tableLog <= memLog */2253U32* rankVal0 = rankVal[0];2254for (w=1; w<=maxW; w++) {2255U32 current = nextRankVal;2256nextRankVal += rankStats[w] << (w+rescale);2257rankVal0[w] = current;2258}2259for (consumed = minBits; consumed <= memLog - minBits; consumed++) {2260U32* rankValPtr = rankVal[consumed];2261for (w = 1; w <= maxW; w++) {2262rankValPtr[w] = rankVal0[w] >> consumed;2263} } }22642265HUFv05_fillDTableX4(dt, memLog,2266sortedSymbol, sizeOfSort,2267rankStart0, rankVal, maxW,2268tableLog+1);22692270return iSize;2271}227222732274static U32 HUFv05_decodeSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)2275{2276const size_t val = BITv05_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */2277memcpy(op, dt+val, 2);2278BITv05_skipBits(DStream, dt[val].nbBits);2279return dt[val].length;2280}22812282static U32 HUFv05_decodeLastSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)2283{2284const size_t val = BITv05_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */2285memcpy(op, dt+val, 1);2286if (dt[val].length==1) BITv05_skipBits(DStream, dt[val].nbBits);2287else {2288if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {2289BITv05_skipBits(DStream, dt[val].nbBits);2290if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))2291DStream->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 */2292} }2293return 1;2294}229522962297#define HUFv05_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \2298ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)22992300#define HUFv05_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \2301if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \2302ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)23032304#define HUFv05_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \2305if (MEM_64bits()) \2306ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)23072308static inline size_t HUFv05_decodeStreamX4(BYTE* p, BITv05_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv05_DEltX4* const dt, const U32 dtLog)2309{2310BYTE* const pStart = p;23112312/* up to 8 symbols at a time */2313while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd-7)) {2314HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);2315HUFv05_DECODE_SYMBOLX4_1(p, bitDPtr);2316HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);2317HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);2318}23192320/* closer to the end */2321while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-2))2322HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);23232324while (p <= pEnd-2)2325HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */23262327if (p < pEnd)2328p += HUFv05_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);23292330return p-pStart;2331}233223332334size_t HUFv05_decompress1X4_usingDTable(2335void* dst, size_t dstSize,2336const void* cSrc, size_t cSrcSize,2337const unsigned* DTable)2338{2339const BYTE* const istart = (const BYTE*) cSrc;2340BYTE* const ostart = (BYTE*) dst;2341BYTE* const oend = ostart + dstSize;23422343const U32 dtLog = DTable[0];2344const void* const dtPtr = DTable;2345const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;2346size_t errorCode;23472348/* Init */2349BITv05_DStream_t bitD;2350errorCode = BITv05_initDStream(&bitD, istart, cSrcSize);2351if (HUFv05_isError(errorCode)) return errorCode;23522353/* finish bitStreams one by one */2354HUFv05_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);23552356/* check */2357if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);23582359/* decoded size */2360return dstSize;2361}23622363size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2364{2365HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);2366const BYTE* ip = (const BYTE*) cSrc;23672368size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);2369if (HUFv05_isError(hSize)) return hSize;2370if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2371ip += hSize;2372cSrcSize -= hSize;23732374return HUFv05_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2375}23762377size_t HUFv05_decompress4X4_usingDTable(2378void* dst, size_t dstSize,2379const void* cSrc, size_t cSrcSize,2380const unsigned* DTable)2381{2382if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */23832384{2385const BYTE* const istart = (const BYTE*) cSrc;2386BYTE* const ostart = (BYTE*) dst;2387BYTE* const oend = ostart + dstSize;2388const void* const dtPtr = DTable;2389const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;2390const U32 dtLog = DTable[0];2391size_t errorCode;23922393/* Init */2394BITv05_DStream_t bitD1;2395BITv05_DStream_t bitD2;2396BITv05_DStream_t bitD3;2397BITv05_DStream_t bitD4;2398const size_t length1 = MEM_readLE16(istart);2399const size_t length2 = MEM_readLE16(istart+2);2400const size_t length3 = MEM_readLE16(istart+4);2401size_t length4;2402const BYTE* const istart1 = istart + 6; /* jumpTable */2403const BYTE* const istart2 = istart1 + length1;2404const BYTE* const istart3 = istart2 + length2;2405const BYTE* const istart4 = istart3 + length3;2406const size_t segmentSize = (dstSize+3) / 4;2407BYTE* const opStart2 = ostart + segmentSize;2408BYTE* const opStart3 = opStart2 + segmentSize;2409BYTE* const opStart4 = opStart3 + segmentSize;2410BYTE* op1 = ostart;2411BYTE* op2 = opStart2;2412BYTE* op3 = opStart3;2413BYTE* op4 = opStart4;2414U32 endSignal;24152416length4 = cSrcSize - (length1 + length2 + length3 + 6);2417if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */2418errorCode = BITv05_initDStream(&bitD1, istart1, length1);2419if (HUFv05_isError(errorCode)) return errorCode;2420errorCode = BITv05_initDStream(&bitD2, istart2, length2);2421if (HUFv05_isError(errorCode)) return errorCode;2422errorCode = BITv05_initDStream(&bitD3, istart3, length3);2423if (HUFv05_isError(errorCode)) return errorCode;2424errorCode = BITv05_initDStream(&bitD4, istart4, length4);2425if (HUFv05_isError(errorCode)) return errorCode;24262427/* 16-32 symbols per loop (4-8 symbols per stream) */2428endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);2429for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {2430HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);2431HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);2432HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);2433HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);2434HUFv05_DECODE_SYMBOLX4_1(op1, &bitD1);2435HUFv05_DECODE_SYMBOLX4_1(op2, &bitD2);2436HUFv05_DECODE_SYMBOLX4_1(op3, &bitD3);2437HUFv05_DECODE_SYMBOLX4_1(op4, &bitD4);2438HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);2439HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);2440HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);2441HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);2442HUFv05_DECODE_SYMBOLX4_0(op1, &bitD1);2443HUFv05_DECODE_SYMBOLX4_0(op2, &bitD2);2444HUFv05_DECODE_SYMBOLX4_0(op3, &bitD3);2445HUFv05_DECODE_SYMBOLX4_0(op4, &bitD4);24462447endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);2448}24492450/* check corruption */2451if (op1 > opStart2) return ERROR(corruption_detected);2452if (op2 > opStart3) return ERROR(corruption_detected);2453if (op3 > opStart4) return ERROR(corruption_detected);2454/* note : op4 supposed already verified within main loop */24552456/* finish bitStreams one by one */2457HUFv05_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);2458HUFv05_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);2459HUFv05_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);2460HUFv05_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);24612462/* check */2463endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);2464if (!endSignal) return ERROR(corruption_detected);24652466/* decoded size */2467return dstSize;2468}2469}247024712472size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2473{2474HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);2475const BYTE* ip = (const BYTE*) cSrc;24762477size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);2478if (HUFv05_isError(hSize)) return hSize;2479if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2480ip += hSize;2481cSrcSize -= hSize;24822483return HUFv05_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);2484}248524862487/* ********************************/2488/* Generic decompression selector */2489/* ********************************/24902491typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;2492static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =2493{2494/* single, double, quad */2495{{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */2496{{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */2497{{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */2498{{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */2499{{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */2500{{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */2501{{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */2502{{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */2503{{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */2504{{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */2505{{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */2506{{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */2507{{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */2508{{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */2509{{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */2510{{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */2511};25122513typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);25142515size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2516{2517static const decompressionAlgo decompress[3] = { HUFv05_decompress4X2, HUFv05_decompress4X4, NULL };2518/* estimate decompression time */2519U32 Q;2520const U32 D256 = (U32)(dstSize >> 8);2521U32 Dtime[3];2522U32 algoNb = 0;2523int n;25242525/* validation checks */2526if (dstSize == 0) return ERROR(dstSize_tooSmall);2527if (cSrcSize >= dstSize) return ERROR(corruption_detected); /* invalid, or not compressed, but not compressed already dealt with */2528if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */25292530/* decoder timing evaluation */2531Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */2532for (n=0; n<3; n++)2533Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);25342535Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */25362537if (Dtime[1] < Dtime[0]) algoNb = 1;25382539return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);25402541/* return HUFv05_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */2542/* return HUFv05_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */2543/* return HUFv05_decompress4X6(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams quad-symbols decoding */2544}2545/*2546zstd - standard compression library2547Copyright (C) 2014-2016, Yann Collet.25482549BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)25502551Redistribution and use in source and binary forms, with or without2552modification, are permitted provided that the following conditions are2553met:2554* Redistributions of source code must retain the above copyright2555notice, this list of conditions and the following disclaimer.2556* Redistributions in binary form must reproduce the above2557copyright notice, this list of conditions and the following disclaimer2558in the documentation and/or other materials provided with the2559distribution.2560THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS2561"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT2562LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR2563A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT2564OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,2565SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT2566LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,2567DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY2568THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2569(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE2570OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.25712572You can contact the author at :2573- zstd source repository : https://github.com/Cyan4973/zstd2574*/25752576/* ***************************************************************2577* Tuning parameters2578*****************************************************************/2579/*!2580* HEAPMODE :2581* Select how default decompression function ZSTDv05_decompress() will allocate memory,2582* in memory stack (0), or in memory heap (1, requires malloc())2583*/2584#ifndef ZSTDv05_HEAPMODE2585# define ZSTDv05_HEAPMODE 12586#endif258725882589/*-*******************************************************2590* Dependencies2591*********************************************************/2592#include <stdlib.h> /* calloc */2593#include <string.h> /* memcpy, memmove */2594#include <stdio.h> /* debug only : printf */259525962597/*-*******************************************************2598* Compiler specifics2599*********************************************************/2600#ifdef _MSC_VER /* Visual Studio */2601# include <intrin.h> /* For Visual 2005 */2602# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */2603# pragma warning(disable : 4324) /* disable: C4324: padded structure */2604#endif260526062607/*-*************************************2608* Local types2609***************************************/2610typedef struct2611{2612blockType_t blockType;2613U32 origSize;2614} blockProperties_t;261526162617/* *******************************************************2618* Memory operations2619**********************************************************/2620static void ZSTDv05_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }262126222623/* *************************************2624* Error Management2625***************************************/2626/*! ZSTDv05_isError() :2627* tells if a return value is an error code */2628unsigned ZSTDv05_isError(size_t code) { return ERR_isError(code); }262926302631/*! ZSTDv05_getErrorName() :2632* provides error code string (useful for debugging) */2633const char* ZSTDv05_getErrorName(size_t code) { return ERR_getErrorName(code); }263426352636/* *************************************************************2637* Context management2638***************************************************************/2639typedef enum { ZSTDv05ds_getFrameHeaderSize, ZSTDv05ds_decodeFrameHeader,2640ZSTDv05ds_decodeBlockHeader, ZSTDv05ds_decompressBlock } ZSTDv05_dStage;26412642struct ZSTDv05_DCtx_s2643{2644FSEv05_DTable LLTable[FSEv05_DTABLE_SIZE_U32(LLFSEv05Log)];2645FSEv05_DTable OffTable[FSEv05_DTABLE_SIZE_U32(OffFSEv05Log)];2646FSEv05_DTable MLTable[FSEv05_DTABLE_SIZE_U32(MLFSEv05Log)];2647unsigned hufTableX4[HUFv05_DTABLE_SIZE(HufLog)];2648const void* previousDstEnd;2649const void* base;2650const void* vBase;2651const void* dictEnd;2652size_t expected;2653size_t headerSize;2654ZSTDv05_parameters params;2655blockType_t bType; /* used in ZSTDv05_decompressContinue(), to transfer blockType between header decoding and block decoding stages */2656ZSTDv05_dStage stage;2657U32 flagStaticTables;2658const BYTE* litPtr;2659size_t litSize;2660BYTE litBuffer[BLOCKSIZE + WILDCOPY_OVERLENGTH];2661BYTE headerBuffer[ZSTDv05_frameHeaderSize_max];2662}; /* typedef'd to ZSTDv05_DCtx within "zstd_static.h" */26632664size_t ZSTDv05_sizeofDCtx (void); /* Hidden declaration */2665size_t ZSTDv05_sizeofDCtx (void) { return sizeof(ZSTDv05_DCtx); }26662667size_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx)2668{2669dctx->expected = ZSTDv05_frameHeaderSize_min;2670dctx->stage = ZSTDv05ds_getFrameHeaderSize;2671dctx->previousDstEnd = NULL;2672dctx->base = NULL;2673dctx->vBase = NULL;2674dctx->dictEnd = NULL;2675dctx->hufTableX4[0] = HufLog;2676dctx->flagStaticTables = 0;2677return 0;2678}26792680ZSTDv05_DCtx* ZSTDv05_createDCtx(void)2681{2682ZSTDv05_DCtx* dctx = (ZSTDv05_DCtx*)malloc(sizeof(ZSTDv05_DCtx));2683if (dctx==NULL) return NULL;2684ZSTDv05_decompressBegin(dctx);2685return dctx;2686}26872688size_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx)2689{2690free(dctx);2691return 0; /* reserved as a potential error code in the future */2692}26932694void ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx)2695{2696memcpy(dstDCtx, srcDCtx,2697sizeof(ZSTDv05_DCtx) - (BLOCKSIZE+WILDCOPY_OVERLENGTH + ZSTDv05_frameHeaderSize_max)); /* no need to copy workspace */2698}269927002701/* *************************************************************2702* Decompression section2703***************************************************************/27042705/* Frame format description2706Frame Header - [ Block Header - Block ] - Frame End27071) Frame Header2708- 4 bytes - Magic Number : ZSTDv05_MAGICNUMBER (defined within zstd_internal.h)2709- 1 byte - Window Descriptor27102) Block Header2711- 3 bytes, starting with a 2-bits descriptor2712Uncompressed, Compressed, Frame End, unused27133) Block2714See Block Format Description27154) Frame End2716- 3 bytes, compatible with Block Header2717*/27182719/* Block format description27202721Block = Literal Section - Sequences Section2722Prerequisite : size of (compressed) block, maximum size of regenerated data272327241) Literal Section272527261.1) Header : 1-5 bytes2727flags: 2 bits272800 compressed by Huff0272901 unused273010 is Raw (uncompressed)273111 is Rle2732Note : using 01 => Huff0 with precomputed table ?2733Note : delta map ? => compressed ?273427351.1.1) Huff0-compressed literal block : 3-5 bytes2736srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream2737srcSize < 1 KB => 3 bytes (2-2-10-10)2738srcSize < 16KB => 4 bytes (2-2-14-14)2739else => 5 bytes (2-2-18-18)2740big endian convention274127421.1.2) Raw (uncompressed) literal block header : 1-3 bytes2743size : 5 bits: (IS_RAW<<6) + (0<<4) + size274412 bits: (IS_RAW<<6) + (2<<4) + (size>>8)2745size&255274620 bits: (IS_RAW<<6) + (3<<4) + (size>>16)2747size>>8&2552748size&255274927501.1.3) Rle (repeated single byte) literal block header : 1-3 bytes2751size : 5 bits: (IS_RLE<<6) + (0<<4) + size275212 bits: (IS_RLE<<6) + (2<<4) + (size>>8)2753size&255275420 bits: (IS_RLE<<6) + (3<<4) + (size>>16)2755size>>8&2552756size&255275727581.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes2759srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream2760srcSize < 1 KB => 3 bytes (2-2-10-10)2761srcSize < 16KB => 4 bytes (2-2-14-14)2762else => 5 bytes (2-2-18-18)2763big endian convention276427651- CTable available (stored into workspace ?)27662- Small input (fast heuristic ? Full comparison ? depend on clevel ?)2767276827691.2) Literal block content277027711.2.1) Huff0 block, using sizes from header2772See Huff0 format277327741.2.2) Huff0 block, using prepared table277527761.2.3) Raw content277727781.2.4) single byte2779278027812) Sequences section2782TO DO2783*/278427852786/** ZSTDv05_decodeFrameHeader_Part1() :2787* decode the 1st part of the Frame Header, which tells Frame Header size.2788* srcSize must be == ZSTDv05_frameHeaderSize_min.2789* @return : the full size of the Frame Header */2790static size_t ZSTDv05_decodeFrameHeader_Part1(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)2791{2792U32 magicNumber;2793if (srcSize != ZSTDv05_frameHeaderSize_min)2794return ERROR(srcSize_wrong);2795magicNumber = MEM_readLE32(src);2796if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);2797zc->headerSize = ZSTDv05_frameHeaderSize_min;2798return zc->headerSize;2799}280028012802size_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize)2803{2804U32 magicNumber;2805if (srcSize < ZSTDv05_frameHeaderSize_min) return ZSTDv05_frameHeaderSize_max;2806magicNumber = MEM_readLE32(src);2807if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);2808memset(params, 0, sizeof(*params));2809params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTDv05_WINDOWLOG_ABSOLUTEMIN;2810if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported); /* reserved bits */2811return 0;2812}28132814/** ZSTDv05_decodeFrameHeader_Part2() :2815* decode the full Frame Header.2816* srcSize must be the size provided by ZSTDv05_decodeFrameHeader_Part1().2817* @return : 0, or an error code, which can be tested using ZSTDv05_isError() */2818static size_t ZSTDv05_decodeFrameHeader_Part2(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)2819{2820size_t result;2821if (srcSize != zc->headerSize)2822return ERROR(srcSize_wrong);2823result = ZSTDv05_getFrameParams(&(zc->params), src, srcSize);2824if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported);2825return result;2826}282728282829static size_t ZSTDv05_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)2830{2831const BYTE* const in = (const BYTE*)src;2832BYTE headerFlags;2833U32 cSize;28342835if (srcSize < 3)2836return ERROR(srcSize_wrong);28372838headerFlags = *in;2839cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);28402841bpPtr->blockType = (blockType_t)(headerFlags >> 6);2842bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;28432844if (bpPtr->blockType == bt_end) return 0;2845if (bpPtr->blockType == bt_rle) return 1;2846return cSize;2847}284828492850static size_t ZSTDv05_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)2851{2852if (dst==NULL) return ERROR(dstSize_tooSmall);2853if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);2854memcpy(dst, src, srcSize);2855return srcSize;2856}285728582859/*! ZSTDv05_decodeLiteralsBlock() :2860@return : nb of bytes read from src (< srcSize ) */2861static size_t ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx* dctx,2862const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */2863{2864const BYTE* const istart = (const BYTE*) src;28652866/* any compressed block with literals segment must be at least this size */2867if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);28682869switch(istart[0]>> 6)2870{2871case IS_HUFv05:2872{2873size_t litSize, litCSize, singleStream=0;2874U32 lhSize = ((istart[0]) >> 4) & 3;2875if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */2876switch(lhSize)2877{2878case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */2879/* 2 - 2 - 10 - 10 */2880lhSize=3;2881singleStream = istart[0] & 16;2882litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);2883litCSize = ((istart[1] & 3) << 8) + istart[2];2884break;2885case 2:2886/* 2 - 2 - 14 - 14 */2887lhSize=4;2888litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);2889litCSize = ((istart[2] & 63) << 8) + istart[3];2890break;2891case 3:2892/* 2 - 2 - 18 - 18 */2893lhSize=5;2894litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);2895litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];2896break;2897}2898if (litSize > BLOCKSIZE) return ERROR(corruption_detected);2899if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);29002901if (HUFv05_isError(singleStream ?2902HUFv05_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :2903HUFv05_decompress (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))2904return ERROR(corruption_detected);29052906dctx->litPtr = dctx->litBuffer;2907dctx->litSize = litSize;2908memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);2909return litCSize + lhSize;2910}2911case IS_PCH:2912{2913size_t errorCode;2914size_t litSize, litCSize;2915U32 lhSize = ((istart[0]) >> 4) & 3;2916if (lhSize != 1) /* only case supported for now : small litSize, single stream */2917return ERROR(corruption_detected);2918if (!dctx->flagStaticTables)2919return ERROR(dictionary_corrupted);29202921/* 2 - 2 - 10 - 10 */2922lhSize=3;2923litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);2924litCSize = ((istart[1] & 3) << 8) + istart[2];2925if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);29262927errorCode = HUFv05_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);2928if (HUFv05_isError(errorCode)) return ERROR(corruption_detected);29292930dctx->litPtr = dctx->litBuffer;2931dctx->litSize = litSize;2932memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);2933return litCSize + lhSize;2934}2935case IS_RAW:2936{2937size_t litSize;2938U32 lhSize = ((istart[0]) >> 4) & 3;2939switch(lhSize)2940{2941case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */2942lhSize=1;2943litSize = istart[0] & 31;2944break;2945case 2:2946litSize = ((istart[0] & 15) << 8) + istart[1];2947break;2948case 3:2949litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];2950break;2951}29522953if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */2954if (litSize+lhSize > srcSize) return ERROR(corruption_detected);2955memcpy(dctx->litBuffer, istart+lhSize, litSize);2956dctx->litPtr = dctx->litBuffer;2957dctx->litSize = litSize;2958memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);2959return lhSize+litSize;2960}2961/* direct reference into compressed stream */2962dctx->litPtr = istart+lhSize;2963dctx->litSize = litSize;2964return lhSize+litSize;2965}2966case IS_RLE:2967{2968size_t litSize;2969U32 lhSize = ((istart[0]) >> 4) & 3;2970switch(lhSize)2971{2972case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */2973lhSize = 1;2974litSize = istart[0] & 31;2975break;2976case 2:2977litSize = ((istart[0] & 15) << 8) + istart[1];2978break;2979case 3:2980litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];2981if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */2982break;2983}2984if (litSize > BLOCKSIZE) return ERROR(corruption_detected);2985memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);2986dctx->litPtr = dctx->litBuffer;2987dctx->litSize = litSize;2988return lhSize+1;2989}2990default:2991return ERROR(corruption_detected); /* impossible */2992}2993}299429952996static size_t ZSTDv05_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,2997FSEv05_DTable* DTableLL, FSEv05_DTable* DTableML, FSEv05_DTable* DTableOffb,2998const void* src, size_t srcSize, U32 flagStaticTable)2999{3000const BYTE* const istart = (const BYTE*)src;3001const BYTE* ip = istart;3002const BYTE* const iend = istart + srcSize;3003U32 LLtype, Offtype, MLtype;3004unsigned LLlog, Offlog, MLlog;3005size_t dumpsLength;30063007/* check */3008if (srcSize < MIN_SEQUENCES_SIZE)3009return ERROR(srcSize_wrong);30103011/* SeqHead */3012*nbSeq = *ip++;3013if (*nbSeq==0) return 1;3014if (*nbSeq >= 128) {3015if (ip >= iend) return ERROR(srcSize_wrong);3016*nbSeq = ((nbSeq[0]-128)<<8) + *ip++;3017}30183019if (ip >= iend) return ERROR(srcSize_wrong);3020LLtype = *ip >> 6;3021Offtype = (*ip >> 4) & 3;3022MLtype = (*ip >> 2) & 3;3023if (*ip & 2) {3024if (ip+3 > iend) return ERROR(srcSize_wrong);3025dumpsLength = ip[2];3026dumpsLength += ip[1] << 8;3027ip += 3;3028} else {3029if (ip+2 > iend) return ERROR(srcSize_wrong);3030dumpsLength = ip[1];3031dumpsLength += (ip[0] & 1) << 8;3032ip += 2;3033}3034*dumpsPtr = ip;3035ip += dumpsLength;3036*dumpsLengthPtr = dumpsLength;30373038/* check */3039if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */30403041/* sequences */3042{3043S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */3044size_t headerSize;30453046/* Build DTables */3047switch(LLtype)3048{3049case FSEv05_ENCODING_RLE :3050LLlog = 0;3051FSEv05_buildDTable_rle(DTableLL, *ip++);3052break;3053case FSEv05_ENCODING_RAW :3054LLlog = LLbits;3055FSEv05_buildDTable_raw(DTableLL, LLbits);3056break;3057case FSEv05_ENCODING_STATIC:3058if (!flagStaticTable) return ERROR(corruption_detected);3059break;3060case FSEv05_ENCODING_DYNAMIC :3061default : /* impossible */3062{ unsigned max = MaxLL;3063headerSize = FSEv05_readNCount(norm, &max, &LLlog, ip, iend-ip);3064if (FSEv05_isError(headerSize)) return ERROR(GENERIC);3065if (LLlog > LLFSEv05Log) return ERROR(corruption_detected);3066ip += headerSize;3067FSEv05_buildDTable(DTableLL, norm, max, LLlog);3068} }30693070switch(Offtype)3071{3072case FSEv05_ENCODING_RLE :3073Offlog = 0;3074if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */3075FSEv05_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */3076break;3077case FSEv05_ENCODING_RAW :3078Offlog = Offbits;3079FSEv05_buildDTable_raw(DTableOffb, Offbits);3080break;3081case FSEv05_ENCODING_STATIC:3082if (!flagStaticTable) return ERROR(corruption_detected);3083break;3084case FSEv05_ENCODING_DYNAMIC :3085default : /* impossible */3086{ unsigned max = MaxOff;3087headerSize = FSEv05_readNCount(norm, &max, &Offlog, ip, iend-ip);3088if (FSEv05_isError(headerSize)) return ERROR(GENERIC);3089if (Offlog > OffFSEv05Log) return ERROR(corruption_detected);3090ip += headerSize;3091FSEv05_buildDTable(DTableOffb, norm, max, Offlog);3092} }30933094switch(MLtype)3095{3096case FSEv05_ENCODING_RLE :3097MLlog = 0;3098if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */3099FSEv05_buildDTable_rle(DTableML, *ip++);3100break;3101case FSEv05_ENCODING_RAW :3102MLlog = MLbits;3103FSEv05_buildDTable_raw(DTableML, MLbits);3104break;3105case FSEv05_ENCODING_STATIC:3106if (!flagStaticTable) return ERROR(corruption_detected);3107break;3108case FSEv05_ENCODING_DYNAMIC :3109default : /* impossible */3110{ unsigned max = MaxML;3111headerSize = FSEv05_readNCount(norm, &max, &MLlog, ip, iend-ip);3112if (FSEv05_isError(headerSize)) return ERROR(GENERIC);3113if (MLlog > MLFSEv05Log) return ERROR(corruption_detected);3114ip += headerSize;3115FSEv05_buildDTable(DTableML, norm, max, MLlog);3116} } }31173118return ip-istart;3119}312031213122typedef struct {3123size_t litLength;3124size_t matchLength;3125size_t offset;3126} seq_t;31273128typedef struct {3129BITv05_DStream_t DStream;3130FSEv05_DState_t stateLL;3131FSEv05_DState_t stateOffb;3132FSEv05_DState_t stateML;3133size_t prevOffset;3134const BYTE* dumps;3135const BYTE* dumpsEnd;3136} seqState_t;3137313831393140static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)3141{3142size_t litLength;3143size_t prevOffset;3144size_t offset;3145size_t matchLength;3146const BYTE* dumps = seqState->dumps;3147const BYTE* const de = seqState->dumpsEnd;31483149/* Literal length */3150litLength = FSEv05_peakSymbol(&(seqState->stateLL));3151prevOffset = litLength ? seq->offset : seqState->prevOffset;3152if (litLength == MaxLL) {3153const U32 add = *dumps++;3154if (add < 255) litLength += add;3155else if (dumps + 2 <= de) {3156litLength = MEM_readLE16(dumps);3157dumps += 2;3158if ((litLength & 1) && dumps < de) {3159litLength += *dumps << 16;3160dumps += 1;3161}3162litLength>>=1;3163}3164if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */3165}31663167/* Offset */3168{3169static const U32 offsetPrefix[MaxOff+1] = {31701 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,3171512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,3172524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };3173U32 offsetCode = FSEv05_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */3174U32 nbBits = offsetCode - 1;3175if (offsetCode==0) nbBits = 0; /* cmove */3176offset = offsetPrefix[offsetCode] + BITv05_readBits(&(seqState->DStream), nbBits);3177if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));3178if (offsetCode==0) offset = prevOffset; /* repcode, cmove */3179if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */3180FSEv05_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */3181}31823183/* Literal length update */3184FSEv05_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */3185if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));31863187/* MatchLength */3188matchLength = FSEv05_decodeSymbol(&(seqState->stateML), &(seqState->DStream));3189if (matchLength == MaxML) {3190const U32 add = dumps<de ? *dumps++ : 0;3191if (add < 255) matchLength += add;3192else if (dumps + 2 <= de) {3193matchLength = MEM_readLE16(dumps);3194dumps += 2;3195if ((matchLength & 1) && dumps < de) {3196matchLength += *dumps << 16;3197dumps += 1;3198}3199matchLength >>= 1;3200}3201if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */3202}3203matchLength += MINMATCH;32043205/* save result */3206seq->litLength = litLength;3207seq->offset = offset;3208seq->matchLength = matchLength;3209seqState->dumps = dumps;32103211#if 0 /* debug */3212{3213static U64 totalDecoded = 0;3214printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",3215(U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);3216totalDecoded += litLength + matchLength;3217}3218#endif3219}322032213222static size_t ZSTDv05_execSequence(BYTE* op,3223BYTE* const oend, seq_t sequence,3224const BYTE** litPtr, const BYTE* const litLimit,3225const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)3226{3227static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */3228static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */3229BYTE* const oLitEnd = op + sequence.litLength;3230const size_t sequenceLength = sequence.litLength + sequence.matchLength;3231BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */3232BYTE* const oend_8 = oend-8;3233const BYTE* const litEnd = *litPtr + sequence.litLength;3234const BYTE* match = oLitEnd - sequence.offset;32353236/* check */3237if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */3238if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */3239if (litEnd > litLimit) return ERROR(corruption_detected); /* risk read beyond lit buffer */32403241/* copy Literals */3242ZSTDv05_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */3243op = oLitEnd;3244*litPtr = litEnd; /* update for next sequence */32453246/* copy Match */3247if (sequence.offset > (size_t)(oLitEnd - base)) {3248/* offset beyond prefix */3249if (sequence.offset > (size_t)(oLitEnd - vBase))3250return ERROR(corruption_detected);3251match = dictEnd - (base-match);3252if (match + sequence.matchLength <= dictEnd) {3253memmove(oLitEnd, match, sequence.matchLength);3254return sequenceLength;3255}3256/* span extDict & currentPrefixSegment */3257{3258size_t length1 = dictEnd - match;3259memmove(oLitEnd, match, length1);3260op = oLitEnd + length1;3261sequence.matchLength -= length1;3262match = base;3263if (op > oend_8 || sequence.matchLength < MINMATCH) {3264while (op < oMatchEnd) *op++ = *match++;3265return sequenceLength;3266}3267} }3268/* Requirement: op <= oend_8 */32693270/* match within prefix */3271if (sequence.offset < 8) {3272/* close range match, overlap */3273const int sub2 = dec64table[sequence.offset];3274op[0] = match[0];3275op[1] = match[1];3276op[2] = match[2];3277op[3] = match[3];3278match += dec32table[sequence.offset];3279ZSTDv05_copy4(op+4, match);3280match -= sub2;3281} else {3282ZSTDv05_copy8(op, match);3283}3284op += 8; match += 8;32853286if (oMatchEnd > oend-(16-MINMATCH)) {3287if (op < oend_8) {3288ZSTDv05_wildcopy(op, match, oend_8 - op);3289match += oend_8 - op;3290op = oend_8;3291}3292while (op < oMatchEnd)3293*op++ = *match++;3294} else {3295ZSTDv05_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */3296}3297return sequenceLength;3298}329933003301static size_t ZSTDv05_decompressSequences(3302ZSTDv05_DCtx* dctx,3303void* dst, size_t maxDstSize,3304const void* seqStart, size_t seqSize)3305{3306const BYTE* ip = (const BYTE*)seqStart;3307const BYTE* const iend = ip + seqSize;3308BYTE* const ostart = (BYTE*)dst;3309BYTE* op = ostart;3310BYTE* const oend = ostart + maxDstSize;3311size_t errorCode, dumpsLength=0;3312const BYTE* litPtr = dctx->litPtr;3313const BYTE* const litEnd = litPtr + dctx->litSize;3314int nbSeq=0;3315const BYTE* dumps = NULL;3316unsigned* DTableLL = dctx->LLTable;3317unsigned* DTableML = dctx->MLTable;3318unsigned* DTableOffb = dctx->OffTable;3319const BYTE* const base = (const BYTE*) (dctx->base);3320const BYTE* const vBase = (const BYTE*) (dctx->vBase);3321const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);33223323/* Build Decoding Tables */3324errorCode = ZSTDv05_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,3325DTableLL, DTableML, DTableOffb,3326ip, seqSize, dctx->flagStaticTables);3327if (ZSTDv05_isError(errorCode)) return errorCode;3328ip += errorCode;33293330/* Regen sequences */3331if (nbSeq) {3332seq_t sequence;3333seqState_t seqState;33343335memset(&sequence, 0, sizeof(sequence));3336sequence.offset = REPCODE_STARTVALUE;3337seqState.dumps = dumps;3338seqState.dumpsEnd = dumps + dumpsLength;3339seqState.prevOffset = REPCODE_STARTVALUE;3340errorCode = BITv05_initDStream(&(seqState.DStream), ip, iend-ip);3341if (ERR_isError(errorCode)) return ERROR(corruption_detected);3342FSEv05_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);3343FSEv05_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);3344FSEv05_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);33453346for ( ; (BITv05_reloadDStream(&(seqState.DStream)) <= BITv05_DStream_completed) && nbSeq ; ) {3347size_t oneSeqSize;3348nbSeq--;3349ZSTDv05_decodeSequence(&sequence, &seqState);3350oneSeqSize = ZSTDv05_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);3351if (ZSTDv05_isError(oneSeqSize)) return oneSeqSize;3352op += oneSeqSize;3353}33543355/* check if reached exact end */3356if (nbSeq) return ERROR(corruption_detected);3357}33583359/* last literal segment */3360{3361size_t lastLLSize = litEnd - litPtr;3362if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */3363if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);3364if (lastLLSize > 0) {3365memcpy(op, litPtr, lastLLSize);3366op += lastLLSize;3367}3368}33693370return op-ostart;3371}337233733374static void ZSTDv05_checkContinuity(ZSTDv05_DCtx* dctx, const void* dst)3375{3376if (dst != dctx->previousDstEnd) { /* not contiguous */3377dctx->dictEnd = dctx->previousDstEnd;3378dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));3379dctx->base = dst;3380dctx->previousDstEnd = dst;3381}3382}338333843385static size_t ZSTDv05_decompressBlock_internal(ZSTDv05_DCtx* dctx,3386void* dst, size_t dstCapacity,3387const void* src, size_t srcSize)3388{ /* blockType == blockCompressed */3389const BYTE* ip = (const BYTE*)src;3390size_t litCSize;33913392if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);33933394/* Decode literals sub-block */3395litCSize = ZSTDv05_decodeLiteralsBlock(dctx, src, srcSize);3396if (ZSTDv05_isError(litCSize)) return litCSize;3397ip += litCSize;3398srcSize -= litCSize;33993400return ZSTDv05_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);3401}340234033404size_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx,3405void* dst, size_t dstCapacity,3406const void* src, size_t srcSize)3407{3408ZSTDv05_checkContinuity(dctx, dst);3409return ZSTDv05_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);3410}341134123413/*! ZSTDv05_decompress_continueDCtx3414* dctx must have been properly initialized */3415static size_t ZSTDv05_decompress_continueDCtx(ZSTDv05_DCtx* dctx,3416void* dst, size_t maxDstSize,3417const void* src, size_t srcSize)3418{3419const BYTE* ip = (const BYTE*)src;3420const BYTE* iend = ip + srcSize;3421BYTE* const ostart = (BYTE*)dst;3422BYTE* op = ostart;3423BYTE* const oend = ostart + maxDstSize;3424size_t remainingSize = srcSize;3425blockProperties_t blockProperties;3426memset(&blockProperties, 0, sizeof(blockProperties));34273428/* Frame Header */3429{ size_t frameHeaderSize;3430if (srcSize < ZSTDv05_frameHeaderSize_min+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);3431frameHeaderSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);3432if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;3433if (srcSize < frameHeaderSize+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);3434ip += frameHeaderSize; remainingSize -= frameHeaderSize;3435frameHeaderSize = ZSTDv05_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);3436if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;3437}34383439/* Loop on each block */3440while (1)3441{3442size_t decodedSize=0;3443size_t cBlockSize = ZSTDv05_getcBlockSize(ip, iend-ip, &blockProperties);3444if (ZSTDv05_isError(cBlockSize)) return cBlockSize;34453446ip += ZSTDv05_blockHeaderSize;3447remainingSize -= ZSTDv05_blockHeaderSize;3448if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);34493450switch(blockProperties.blockType)3451{3452case bt_compressed:3453decodedSize = ZSTDv05_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);3454break;3455case bt_raw :3456decodedSize = ZSTDv05_copyRawBlock(op, oend-op, ip, cBlockSize);3457break;3458case bt_rle :3459return ERROR(GENERIC); /* not yet supported */3460break;3461case bt_end :3462/* end of frame */3463if (remainingSize) return ERROR(srcSize_wrong);3464break;3465default:3466return ERROR(GENERIC); /* impossible */3467}3468if (cBlockSize == 0) break; /* bt_end */34693470if (ZSTDv05_isError(decodedSize)) return decodedSize;3471op += decodedSize;3472ip += cBlockSize;3473remainingSize -= cBlockSize;3474}34753476return op-ostart;3477}347834793480size_t ZSTDv05_decompress_usingPreparedDCtx(ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* refDCtx,3481void* dst, size_t maxDstSize,3482const void* src, size_t srcSize)3483{3484ZSTDv05_copyDCtx(dctx, refDCtx);3485ZSTDv05_checkContinuity(dctx, dst);3486return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);3487}348834893490size_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,3491void* dst, size_t maxDstSize,3492const void* src, size_t srcSize,3493const void* dict, size_t dictSize)3494{3495ZSTDv05_decompressBegin_usingDict(dctx, dict, dictSize);3496ZSTDv05_checkContinuity(dctx, dst);3497return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);3498}349935003501size_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)3502{3503return ZSTDv05_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);3504}35053506size_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)3507{3508#if defined(ZSTDv05_HEAPMODE) && (ZSTDv05_HEAPMODE==1)3509size_t regenSize;3510ZSTDv05_DCtx* dctx = ZSTDv05_createDCtx();3511if (dctx==NULL) return ERROR(memory_allocation);3512regenSize = ZSTDv05_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);3513ZSTDv05_freeDCtx(dctx);3514return regenSize;3515#else3516ZSTDv05_DCtx dctx;3517return ZSTDv05_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);3518#endif3519}35203521/* ZSTD_errorFrameSizeInfoLegacy() :3522assumes `cSize` and `dBound` are _not_ NULL */3523static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)3524{3525*cSize = ret;3526*dBound = ZSTD_CONTENTSIZE_ERROR;3527}35283529void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)3530{3531const BYTE* ip = (const BYTE*)src;3532size_t remainingSize = srcSize;3533size_t nbBlocks = 0;3534blockProperties_t blockProperties;35353536/* Frame Header */3537if (srcSize < ZSTDv05_frameHeaderSize_min) {3538ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3539return;3540}3541if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {3542ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));3543return;3544}3545ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;35463547/* Loop on each block */3548while (1)3549{3550size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);3551if (ZSTDv05_isError(cBlockSize)) {3552ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);3553return;3554}35553556ip += ZSTDv05_blockHeaderSize;3557remainingSize -= ZSTDv05_blockHeaderSize;3558if (cBlockSize > remainingSize) {3559ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3560return;3561}35623563if (cBlockSize == 0) break; /* bt_end */35643565ip += cBlockSize;3566remainingSize -= cBlockSize;3567nbBlocks++;3568}35693570*cSize = ip - (const BYTE*)src;3571*dBound = nbBlocks * BLOCKSIZE;3572}35733574/* ******************************3575* Streaming Decompression API3576********************************/3577size_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx)3578{3579return dctx->expected;3580}35813582size_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)3583{3584/* Sanity check */3585if (srcSize != dctx->expected) return ERROR(srcSize_wrong);3586ZSTDv05_checkContinuity(dctx, dst);35873588/* Decompress : frame header; part 1 */3589switch (dctx->stage)3590{3591case ZSTDv05ds_getFrameHeaderSize :3592/* get frame header size */3593if (srcSize != ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */3594dctx->headerSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);3595if (ZSTDv05_isError(dctx->headerSize)) return dctx->headerSize;3596memcpy(dctx->headerBuffer, src, ZSTDv05_frameHeaderSize_min);3597if (dctx->headerSize > ZSTDv05_frameHeaderSize_min) return ERROR(GENERIC); /* should never happen */3598dctx->expected = 0; /* not necessary to copy more */3599/* fallthrough */3600case ZSTDv05ds_decodeFrameHeader:3601/* get frame header */3602{ size_t const result = ZSTDv05_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);3603if (ZSTDv05_isError(result)) return result;3604dctx->expected = ZSTDv05_blockHeaderSize;3605dctx->stage = ZSTDv05ds_decodeBlockHeader;3606return 0;3607}3608case ZSTDv05ds_decodeBlockHeader:3609{3610/* Decode block header */3611blockProperties_t bp;3612size_t blockSize = ZSTDv05_getcBlockSize(src, ZSTDv05_blockHeaderSize, &bp);3613if (ZSTDv05_isError(blockSize)) return blockSize;3614if (bp.blockType == bt_end) {3615dctx->expected = 0;3616dctx->stage = ZSTDv05ds_getFrameHeaderSize;3617}3618else {3619dctx->expected = blockSize;3620dctx->bType = bp.blockType;3621dctx->stage = ZSTDv05ds_decompressBlock;3622}3623return 0;3624}3625case ZSTDv05ds_decompressBlock:3626{3627/* Decompress : block content */3628size_t rSize;3629switch(dctx->bType)3630{3631case bt_compressed:3632rSize = ZSTDv05_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);3633break;3634case bt_raw :3635rSize = ZSTDv05_copyRawBlock(dst, maxDstSize, src, srcSize);3636break;3637case bt_rle :3638return ERROR(GENERIC); /* not yet handled */3639break;3640case bt_end : /* should never happen (filtered at phase 1) */3641rSize = 0;3642break;3643default:3644return ERROR(GENERIC); /* impossible */3645}3646dctx->stage = ZSTDv05ds_decodeBlockHeader;3647dctx->expected = ZSTDv05_blockHeaderSize;3648dctx->previousDstEnd = (char*)dst + rSize;3649return rSize;3650}3651default:3652return ERROR(GENERIC); /* impossible */3653}3654}365536563657static void ZSTDv05_refDictContent(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)3658{3659dctx->dictEnd = dctx->previousDstEnd;3660dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));3661dctx->base = dict;3662dctx->previousDstEnd = (const char*)dict + dictSize;3663}36643665static size_t ZSTDv05_loadEntropy(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)3666{3667size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;3668short offcodeNCount[MaxOff+1];3669unsigned offcodeMaxValue=MaxOff, offcodeLog;3670short matchlengthNCount[MaxML+1];3671unsigned matchlengthMaxValue = MaxML, matchlengthLog;3672short litlengthNCount[MaxLL+1];3673unsigned litlengthMaxValue = MaxLL, litlengthLog;36743675hSize = HUFv05_readDTableX4(dctx->hufTableX4, dict, dictSize);3676if (HUFv05_isError(hSize)) return ERROR(dictionary_corrupted);3677dict = (const char*)dict + hSize;3678dictSize -= hSize;36793680offcodeHeaderSize = FSEv05_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);3681if (FSEv05_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);3682if (offcodeLog > OffFSEv05Log) return ERROR(dictionary_corrupted);3683errorCode = FSEv05_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);3684if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);3685dict = (const char*)dict + offcodeHeaderSize;3686dictSize -= offcodeHeaderSize;36873688matchlengthHeaderSize = FSEv05_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);3689if (FSEv05_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);3690if (matchlengthLog > MLFSEv05Log) return ERROR(dictionary_corrupted);3691errorCode = FSEv05_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);3692if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);3693dict = (const char*)dict + matchlengthHeaderSize;3694dictSize -= matchlengthHeaderSize;36953696litlengthHeaderSize = FSEv05_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);3697if (litlengthLog > LLFSEv05Log) return ERROR(dictionary_corrupted);3698if (FSEv05_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);3699errorCode = FSEv05_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);3700if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);37013702dctx->flagStaticTables = 1;3703return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;3704}37053706static size_t ZSTDv05_decompress_insertDictionary(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)3707{3708size_t eSize;3709U32 magic = MEM_readLE32(dict);3710if (magic != ZSTDv05_DICT_MAGIC) {3711/* pure content mode */3712ZSTDv05_refDictContent(dctx, dict, dictSize);3713return 0;3714}3715/* load entropy tables */3716dict = (const char*)dict + 4;3717dictSize -= 4;3718eSize = ZSTDv05_loadEntropy(dctx, dict, dictSize);3719if (ZSTDv05_isError(eSize)) return ERROR(dictionary_corrupted);37203721/* reference dictionary content */3722dict = (const char*)dict + eSize;3723dictSize -= eSize;3724ZSTDv05_refDictContent(dctx, dict, dictSize);37253726return 0;3727}372837293730size_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)3731{3732size_t errorCode;3733errorCode = ZSTDv05_decompressBegin(dctx);3734if (ZSTDv05_isError(errorCode)) return errorCode;37353736if (dict && dictSize) {3737errorCode = ZSTDv05_decompress_insertDictionary(dctx, dict, dictSize);3738if (ZSTDv05_isError(errorCode)) return ERROR(dictionary_corrupted);3739}37403741return 0;3742}37433744/*3745Buffered version of Zstd compression library3746Copyright (C) 2015-2016, Yann Collet.37473748BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)37493750Redistribution and use in source and binary forms, with or without3751modification, are permitted provided that the following conditions are3752met:3753* Redistributions of source code must retain the above copyright3754notice, this list of conditions and the following disclaimer.3755* Redistributions in binary form must reproduce the above3756copyright notice, this list of conditions and the following disclaimer3757in the documentation and/or other materials provided with the3758distribution.3759THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS3760"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT3761LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR3762A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT3763OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,3764SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT3765LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,3766DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY3767THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT3768(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE3769OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.37703771You can contact the author at :3772- zstd source repository : https://github.com/Cyan4973/zstd3773- ztsd public forum : https://groups.google.com/forum/#!forum/lz4c3774*/37753776/* The objects defined into this file should be considered experimental.3777* They are not labelled stable, as their prototype may change in the future.3778* You can use them for tests, provide feedback, or if you can endure risk of future changes.3779*/3780378137823783/* *************************************3784* Constants3785***************************************/3786static size_t ZBUFFv05_blockHeaderSize = 3;3787378837893790/* *** Compression *** */37913792static size_t ZBUFFv05_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize)3793{3794size_t length = MIN(maxDstSize, srcSize);3795if (length > 0) {3796memcpy(dst, src, length);3797}3798return length;3799}38003801380238033804/** ************************************************3805* Streaming decompression3806*3807* A ZBUFFv05_DCtx object is required to track streaming operation.3808* Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources.3809* Use ZBUFFv05_decompressInit() to start a new decompression operation.3810* ZBUFFv05_DCtx objects can be reused multiple times.3811*3812* Use ZBUFFv05_decompressContinue() repetitively to consume your input.3813* *srcSizePtr and *maxDstSizePtr can be any size.3814* The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.3815* Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.3816* The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst .3817* return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)3818* or 0 when a frame is completely decoded3819* or an error code, which can be tested using ZBUFFv05_isError().3820*3821* Hint : recommended buffer sizes (not compulsory)3822* output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.3823* input : just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .3824* **************************************************/38253826typedef enum { ZBUFFv05ds_init, ZBUFFv05ds_readHeader, ZBUFFv05ds_loadHeader, ZBUFFv05ds_decodeHeader,3827ZBUFFv05ds_read, ZBUFFv05ds_load, ZBUFFv05ds_flush } ZBUFFv05_dStage;38283829/* *** Resource management *** */38303831#define ZSTDv05_frameHeaderSize_max 5 /* too magical, should come from reference */3832struct ZBUFFv05_DCtx_s {3833ZSTDv05_DCtx* zc;3834ZSTDv05_parameters params;3835char* inBuff;3836size_t inBuffSize;3837size_t inPos;3838char* outBuff;3839size_t outBuffSize;3840size_t outStart;3841size_t outEnd;3842size_t hPos;3843ZBUFFv05_dStage stage;3844unsigned char headerBuffer[ZSTDv05_frameHeaderSize_max];3845}; /* typedef'd to ZBUFFv05_DCtx within "zstd_buffered.h" */384638473848ZBUFFv05_DCtx* ZBUFFv05_createDCtx(void)3849{3850ZBUFFv05_DCtx* zbc = (ZBUFFv05_DCtx*)malloc(sizeof(ZBUFFv05_DCtx));3851if (zbc==NULL) return NULL;3852memset(zbc, 0, sizeof(*zbc));3853zbc->zc = ZSTDv05_createDCtx();3854zbc->stage = ZBUFFv05ds_init;3855return zbc;3856}38573858size_t ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* zbc)3859{3860if (zbc==NULL) return 0; /* support free on null */3861ZSTDv05_freeDCtx(zbc->zc);3862free(zbc->inBuff);3863free(zbc->outBuff);3864free(zbc);3865return 0;3866}386738683869/* *** Initialization *** */38703871size_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* zbc, const void* dict, size_t dictSize)3872{3873zbc->stage = ZBUFFv05ds_readHeader;3874zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = 0;3875return ZSTDv05_decompressBegin_usingDict(zbc->zc, dict, dictSize);3876}38773878size_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* zbc)3879{3880return ZBUFFv05_decompressInitDictionary(zbc, NULL, 0);3881}388238833884/* *** Decompression *** */38853886size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)3887{3888const char* const istart = (const char*)src;3889const char* ip = istart;3890const char* const iend = istart + *srcSizePtr;3891char* const ostart = (char*)dst;3892char* op = ostart;3893char* const oend = ostart + *maxDstSizePtr;3894U32 notDone = 1;38953896while (notDone) {3897switch(zbc->stage)3898{3899case ZBUFFv05ds_init :3900return ERROR(init_missing);39013902case ZBUFFv05ds_readHeader :3903/* read header from src */3904{3905size_t headerSize = ZSTDv05_getFrameParams(&(zbc->params), src, *srcSizePtr);3906if (ZSTDv05_isError(headerSize)) return headerSize;3907if (headerSize) {3908/* not enough input to decode header : tell how many bytes would be necessary */3909memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr);3910zbc->hPos += *srcSizePtr;3911*maxDstSizePtr = 0;3912zbc->stage = ZBUFFv05ds_loadHeader;3913return headerSize - zbc->hPos;3914}3915zbc->stage = ZBUFFv05ds_decodeHeader;3916break;3917}3918/* fall-through */3919case ZBUFFv05ds_loadHeader:3920/* complete header from src */3921{3922size_t headerSize = ZBUFFv05_limitCopy(3923zbc->headerBuffer + zbc->hPos, ZSTDv05_frameHeaderSize_max - zbc->hPos,3924src, *srcSizePtr);3925zbc->hPos += headerSize;3926ip += headerSize;3927headerSize = ZSTDv05_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos);3928if (ZSTDv05_isError(headerSize)) return headerSize;3929if (headerSize) {3930/* not enough input to decode header : tell how many bytes would be necessary */3931*maxDstSizePtr = 0;3932return headerSize - zbc->hPos;3933}3934/* zbc->stage = ZBUFFv05ds_decodeHeader; break; */ /* useless : stage follows */3935}3936/* fall-through */3937case ZBUFFv05ds_decodeHeader:3938/* apply header to create / resize buffers */3939{3940size_t neededOutSize = (size_t)1 << zbc->params.windowLog;3941size_t neededInSize = BLOCKSIZE; /* a block is never > BLOCKSIZE */3942if (zbc->inBuffSize < neededInSize) {3943free(zbc->inBuff);3944zbc->inBuffSize = neededInSize;3945zbc->inBuff = (char*)malloc(neededInSize);3946if (zbc->inBuff == NULL) return ERROR(memory_allocation);3947}3948if (zbc->outBuffSize < neededOutSize) {3949free(zbc->outBuff);3950zbc->outBuffSize = neededOutSize;3951zbc->outBuff = (char*)malloc(neededOutSize);3952if (zbc->outBuff == NULL) return ERROR(memory_allocation);3953} }3954if (zbc->hPos) {3955/* some data already loaded into headerBuffer : transfer into inBuff */3956memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos);3957zbc->inPos = zbc->hPos;3958zbc->hPos = 0;3959zbc->stage = ZBUFFv05ds_load;3960break;3961}3962zbc->stage = ZBUFFv05ds_read;3963/* fall-through */3964case ZBUFFv05ds_read:3965{3966size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);3967if (neededInSize==0) { /* end of frame */3968zbc->stage = ZBUFFv05ds_init;3969notDone = 0;3970break;3971}3972if ((size_t)(iend-ip) >= neededInSize) {3973/* directly decode from src */3974size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,3975zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,3976ip, neededInSize);3977if (ZSTDv05_isError(decodedSize)) return decodedSize;3978ip += neededInSize;3979if (!decodedSize) break; /* this was just a header */3980zbc->outEnd = zbc->outStart + decodedSize;3981zbc->stage = ZBUFFv05ds_flush;3982break;3983}3984if (ip==iend) { notDone = 0; break; } /* no more input */3985zbc->stage = ZBUFFv05ds_load;3986}3987/* fall-through */3988case ZBUFFv05ds_load:3989{3990size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);3991size_t toLoad = neededInSize - zbc->inPos; /* should always be <= remaining space within inBuff */3992size_t loadedSize;3993if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected); /* should never happen */3994loadedSize = ZBUFFv05_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip);3995ip += loadedSize;3996zbc->inPos += loadedSize;3997if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */3998{3999size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,4000zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,4001zbc->inBuff, neededInSize);4002if (ZSTDv05_isError(decodedSize)) return decodedSize;4003zbc->inPos = 0; /* input is consumed */4004if (!decodedSize) { zbc->stage = ZBUFFv05ds_read; break; } /* this was just a header */4005zbc->outEnd = zbc->outStart + decodedSize;4006zbc->stage = ZBUFFv05ds_flush;4007/* break; */ /* ZBUFFv05ds_flush follows */4008}4009}4010/* fall-through */4011case ZBUFFv05ds_flush:4012{4013size_t toFlushSize = zbc->outEnd - zbc->outStart;4014size_t flushedSize = ZBUFFv05_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);4015op += flushedSize;4016zbc->outStart += flushedSize;4017if (flushedSize == toFlushSize) {4018zbc->stage = ZBUFFv05ds_read;4019if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)4020zbc->outStart = zbc->outEnd = 0;4021break;4022}4023/* cannot flush everything */4024notDone = 0;4025break;4026}4027default: return ERROR(GENERIC); /* impossible */4028} }40294030*srcSizePtr = ip-istart;4031*maxDstSizePtr = op-ostart;40324033{ size_t nextSrcSizeHint = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);4034if (nextSrcSizeHint > ZBUFFv05_blockHeaderSize) nextSrcSizeHint+= ZBUFFv05_blockHeaderSize; /* get next block header too */4035nextSrcSizeHint -= zbc->inPos; /* already loaded*/4036return nextSrcSizeHint;4037}4038}4039404040414042/* *************************************4043* Tool functions4044***************************************/4045unsigned ZBUFFv05_isError(size_t errorCode) { return ERR_isError(errorCode); }4046const char* ZBUFFv05_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }40474048size_t ZBUFFv05_recommendedDInSize(void) { return BLOCKSIZE + ZBUFFv05_blockHeaderSize /* block header size*/ ; }4049size_t ZBUFFv05_recommendedDOutSize(void) { return BLOCKSIZE; }405040514052