Path: blob/main/sys/contrib/zstd/lib/legacy/zstd_v07.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 <stddef.h> /* size_t, ptrdiff_t */13#include <string.h> /* memcpy */14#include <stdlib.h> /* malloc, free, qsort */1516#ifndef XXH_STATIC_LINKING_ONLY17# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */18#endif19#include "../common/xxhash.h" /* XXH64_* */20#include "zstd_v07.h"2122#define FSEv07_STATIC_LINKING_ONLY /* FSEv07_MIN_TABLELOG */23#define HUFv07_STATIC_LINKING_ONLY /* HUFv07_TABLELOG_ABSOLUTEMAX */24#define ZSTDv07_STATIC_LINKING_ONLY2526#include "../common/error_private.h"272829#ifdef ZSTDv07_STATIC_LINKING_ONLY3031/* ====================================================================================32* The definitions in this section are considered experimental.33* They should never be used with a dynamic library, as they may change in the future.34* They are provided for advanced usages.35* Use them only in association with static linking.36* ==================================================================================== */3738/*--- Constants ---*/39#define ZSTDv07_MAGIC_SKIPPABLE_START 0x184D2A50U4041#define ZSTDv07_WINDOWLOG_MAX_32 2542#define ZSTDv07_WINDOWLOG_MAX_64 2743#define ZSTDv07_WINDOWLOG_MAX ((U32)(MEM_32bits() ? ZSTDv07_WINDOWLOG_MAX_32 : ZSTDv07_WINDOWLOG_MAX_64))44#define ZSTDv07_WINDOWLOG_MIN 1845#define ZSTDv07_CHAINLOG_MAX (ZSTDv07_WINDOWLOG_MAX+1)46#define ZSTDv07_CHAINLOG_MIN 447#define ZSTDv07_HASHLOG_MAX ZSTDv07_WINDOWLOG_MAX48#define ZSTDv07_HASHLOG_MIN 1249#define ZSTDv07_HASHLOG3_MAX 1750#define ZSTDv07_SEARCHLOG_MAX (ZSTDv07_WINDOWLOG_MAX-1)51#define ZSTDv07_SEARCHLOG_MIN 152#define ZSTDv07_SEARCHLENGTH_MAX 753#define ZSTDv07_SEARCHLENGTH_MIN 354#define ZSTDv07_TARGETLENGTH_MIN 455#define ZSTDv07_TARGETLENGTH_MAX 9995657#define ZSTDv07_FRAMEHEADERSIZE_MAX 18 /* for static allocation */58static const size_t ZSTDv07_frameHeaderSize_min = 5;59static const size_t ZSTDv07_frameHeaderSize_max = ZSTDv07_FRAMEHEADERSIZE_MAX;60static const size_t ZSTDv07_skippableHeaderSize = 8; /* magic number + skippable frame length */616263/* custom memory allocation functions */64typedef void* (*ZSTDv07_allocFunction) (void* opaque, size_t size);65typedef void (*ZSTDv07_freeFunction) (void* opaque, void* address);66typedef struct { ZSTDv07_allocFunction customAlloc; ZSTDv07_freeFunction customFree; void* opaque; } ZSTDv07_customMem;676869/*--- Advanced Decompression functions ---*/7071/*! ZSTDv07_estimateDCtxSize() :72* Gives the potential amount of memory allocated to create a ZSTDv07_DCtx */73ZSTDLIBv07_API size_t ZSTDv07_estimateDCtxSize(void);7475/*! ZSTDv07_createDCtx_advanced() :76* Create a ZSTD decompression context using external alloc and free functions */77ZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);7879/*! ZSTDv07_sizeofDCtx() :80* Gives the amount of memory used by a given ZSTDv07_DCtx */81ZSTDLIBv07_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);828384/* ******************************************************************85* Buffer-less streaming functions (synchronous mode)86********************************************************************/8788ZSTDLIBv07_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);89ZSTDLIBv07_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);90ZSTDLIBv07_API void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);9192ZSTDLIBv07_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);93ZSTDLIBv07_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);9495/*96Buffer-less streaming decompression (synchronous mode)9798A ZSTDv07_DCtx object is required to track streaming operations.99Use ZSTDv07_createDCtx() / ZSTDv07_freeDCtx() to manage it.100A ZSTDv07_DCtx object can be re-used multiple times.101102First optional operation is to retrieve frame parameters, using ZSTDv07_getFrameParams(), which doesn't consume the input.103It can provide the minimum size of rolling buffer required to properly decompress data (`windowSize`),104and optionally the final size of uncompressed content.105(Note : content size is an optional info that may not be present. 0 means : content size unknown)106Frame parameters are extracted from the beginning of compressed frame.107The amount of data to read is variable, from ZSTDv07_frameHeaderSize_min to ZSTDv07_frameHeaderSize_max (so if `srcSize` >= ZSTDv07_frameHeaderSize_max, it will always work)108If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.109Result : 0 when successful, it means the ZSTDv07_frameParams structure has been filled.110>0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.111errorCode, which can be tested using ZSTDv07_isError()112113Start decompression, with ZSTDv07_decompressBegin() or ZSTDv07_decompressBegin_usingDict().114Alternatively, you can copy a prepared context, using ZSTDv07_copyDCtx().115116Then use ZSTDv07_nextSrcSizeToDecompress() and ZSTDv07_decompressContinue() alternatively.117ZSTDv07_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv07_decompressContinue().118ZSTDv07_decompressContinue() requires this exact amount of bytes, or it will fail.119120@result of ZSTDv07_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).121It can be zero, which is not an error; it just means ZSTDv07_decompressContinue() has decoded some header.122123ZSTDv07_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.124They should preferably be located contiguously, prior to current block.125Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.126ZSTDv07_decompressContinue() is very sensitive to contiguity,127if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,128or that previous contiguous segment is large enough to properly handle maximum back-reference.129130A frame is fully decoded when ZSTDv07_nextSrcSizeToDecompress() returns zero.131Context can then be reset to start a new decompression.132133134== Special case : skippable frames ==135136Skippable frames allow the integration of user-defined data into a flow of concatenated frames.137Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frame is following:138a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F139b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits140c) Frame Content - any content (User Data) of length equal to Frame Size141For skippable frames ZSTDv07_decompressContinue() always returns 0.142For skippable frames ZSTDv07_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.143It also returns Frame Size as fparamsPtr->frameContentSize.144*/145146147/* **************************************148* Block functions149****************************************/150/*! Block functions produce and decode raw zstd blocks, without frame metadata.151Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).152User will have to take in charge required information to regenerate data, such as compressed and content sizes.153154A few rules to respect :155- Compressing and decompressing require a context structure156+ Use ZSTDv07_createCCtx() and ZSTDv07_createDCtx()157- It is necessary to init context before starting158+ compression : ZSTDv07_compressBegin()159+ decompression : ZSTDv07_decompressBegin()160+ variants _usingDict() are also allowed161+ copyCCtx() and copyDCtx() work too162- Block size is limited, it must be <= ZSTDv07_getBlockSizeMax()163+ If you need to compress more, cut data into multiple blocks164+ Consider using the regular ZSTDv07_compress() instead, as frame metadata costs become negligible when source size is large.165- When a block is considered not compressible enough, ZSTDv07_compressBlock() result will be zero.166In which case, nothing is produced into `dst`.167+ User must test for such outcome and deal directly with uncompressed data168+ ZSTDv07_decompressBlock() doesn't accept uncompressed data as input !!!169+ In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.170Use ZSTDv07_insertBlock() in such a case.171*/172173#define ZSTDv07_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */174ZSTDLIBv07_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);175ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */176177178#endif /* ZSTDv07_STATIC_LINKING_ONLY */179180181/* ******************************************************************182mem.h183low-level memory access routines184Copyright (C) 2013-2015, Yann Collet.185186BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)187188Redistribution and use in source and binary forms, with or without189modification, are permitted provided that the following conditions are190met:191192* Redistributions of source code must retain the above copyright193notice, this list of conditions and the following disclaimer.194* Redistributions in binary form must reproduce the above195copyright notice, this list of conditions and the following disclaimer196in the documentation and/or other materials provided with the197distribution.198199THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS200"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT201LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR202A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT203OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,204SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT205LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,206DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY207THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT208(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE209OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.210211You can contact the author at :212- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy213- Public forum : https://groups.google.com/forum/#!forum/lz4c214****************************************************************** */215#ifndef MEM_H_MODULE216#define MEM_H_MODULE217218#if defined (__cplusplus)219extern "C" {220#endif221222/*-****************************************223* Compiler specifics224******************************************/225#if defined(_MSC_VER) /* Visual Studio */226# include <stdlib.h> /* _byteswap_ulong */227# include <intrin.h> /* _byteswap_* */228#endif229#if defined(__GNUC__)230# define MEM_STATIC static __attribute__((unused))231#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)232# define MEM_STATIC static inline233#elif defined(_MSC_VER)234# define MEM_STATIC static __inline235#else236# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */237#endif238239240/*-**************************************************************241* Basic Types242*****************************************************************/243#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )244# if defined(_AIX)245# include <inttypes.h>246# else247# include <stdint.h> /* intptr_t */248# endif249typedef uint8_t BYTE;250typedef uint16_t U16;251typedef int16_t S16;252typedef uint32_t U32;253typedef int32_t S32;254typedef uint64_t U64;255typedef int64_t S64;256#else257typedef unsigned char BYTE;258typedef unsigned short U16;259typedef signed short S16;260typedef unsigned int U32;261typedef signed int S32;262typedef unsigned long long U64;263typedef signed long long S64;264#endif265266267/*-**************************************************************268* Memory I/O269*****************************************************************/270/* MEM_FORCE_MEMORY_ACCESS :271* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.272* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.273* The below switch allow to select different access method for improved performance.274* Method 0 (default) : use `memcpy()`. Safe and portable.275* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).276* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.277* Method 2 : direct access. This method is portable but violate C standard.278* It can generate buggy code on targets depending on alignment.279* In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)280* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.281* Prefer these methods in priority order (0 > 1 > 2)282*/283#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */284# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)285# define MEM_FORCE_MEMORY_ACCESS 1286# endif287#endif288289MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }290MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }291292MEM_STATIC unsigned MEM_isLittleEndian(void)293{294const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */295return one.c[0];296}297298#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)299300/* violates C standard, by lying on structure alignment.301Only use if no other choice to achieve best performance on target platform */302MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }303MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }304MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }305306MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }307308#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)309310/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */311/* currently only defined for gcc and icc */312typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;313314MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }315MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }316MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }317318MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }319320#else321322/* default method, safe and standard.323can sometimes prove slower */324325MEM_STATIC U16 MEM_read16(const void* memPtr)326{327U16 val; memcpy(&val, memPtr, sizeof(val)); return val;328}329330MEM_STATIC U32 MEM_read32(const void* memPtr)331{332U32 val; memcpy(&val, memPtr, sizeof(val)); return val;333}334335MEM_STATIC U64 MEM_read64(const void* memPtr)336{337U64 val; memcpy(&val, memPtr, sizeof(val)); return val;338}339340MEM_STATIC void MEM_write16(void* memPtr, U16 value)341{342memcpy(memPtr, &value, sizeof(value));343}344345#endif /* MEM_FORCE_MEMORY_ACCESS */346347MEM_STATIC U32 MEM_swap32(U32 in)348{349#if defined(_MSC_VER) /* Visual Studio */350return _byteswap_ulong(in);351#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)352return __builtin_bswap32(in);353#else354return ((in << 24) & 0xff000000 ) |355((in << 8) & 0x00ff0000 ) |356((in >> 8) & 0x0000ff00 ) |357((in >> 24) & 0x000000ff );358#endif359}360361MEM_STATIC U64 MEM_swap64(U64 in)362{363#if defined(_MSC_VER) /* Visual Studio */364return _byteswap_uint64(in);365#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)366return __builtin_bswap64(in);367#else368return ((in << 56) & 0xff00000000000000ULL) |369((in << 40) & 0x00ff000000000000ULL) |370((in << 24) & 0x0000ff0000000000ULL) |371((in << 8) & 0x000000ff00000000ULL) |372((in >> 8) & 0x00000000ff000000ULL) |373((in >> 24) & 0x0000000000ff0000ULL) |374((in >> 40) & 0x000000000000ff00ULL) |375((in >> 56) & 0x00000000000000ffULL);376#endif377}378379380/*=== Little endian r/w ===*/381382MEM_STATIC U16 MEM_readLE16(const void* memPtr)383{384if (MEM_isLittleEndian())385return MEM_read16(memPtr);386else {387const BYTE* p = (const BYTE*)memPtr;388return (U16)(p[0] + (p[1]<<8));389}390}391392MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)393{394if (MEM_isLittleEndian()) {395MEM_write16(memPtr, val);396} else {397BYTE* p = (BYTE*)memPtr;398p[0] = (BYTE)val;399p[1] = (BYTE)(val>>8);400}401}402403MEM_STATIC U32 MEM_readLE32(const void* memPtr)404{405if (MEM_isLittleEndian())406return MEM_read32(memPtr);407else408return MEM_swap32(MEM_read32(memPtr));409}410411412MEM_STATIC U64 MEM_readLE64(const void* memPtr)413{414if (MEM_isLittleEndian())415return MEM_read64(memPtr);416else417return MEM_swap64(MEM_read64(memPtr));418}419420MEM_STATIC size_t MEM_readLEST(const void* memPtr)421{422if (MEM_32bits())423return (size_t)MEM_readLE32(memPtr);424else425return (size_t)MEM_readLE64(memPtr);426}427428429430#if defined (__cplusplus)431}432#endif433434#endif /* MEM_H_MODULE */435/* ******************************************************************436bitstream437Part of FSE library438header file (to include)439Copyright (C) 2013-2016, Yann Collet.440441BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)442443Redistribution and use in source and binary forms, with or without444modification, are permitted provided that the following conditions are445met:446447* Redistributions of source code must retain the above copyright448notice, this list of conditions and the following disclaimer.449* Redistributions in binary form must reproduce the above450copyright notice, this list of conditions and the following disclaimer451in the documentation and/or other materials provided with the452distribution.453454THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS455"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT456LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR457A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT458OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,459SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT460LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,461DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY462THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT463(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE464OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.465466You can contact the author at :467- Source repository : https://github.com/Cyan4973/FiniteStateEntropy468****************************************************************** */469#ifndef BITSTREAM_H_MODULE470#define BITSTREAM_H_MODULE471472#if defined (__cplusplus)473extern "C" {474#endif475476477/*478* This API consists of small unitary functions, which must be inlined for best performance.479* Since link-time-optimization is not available for all compilers,480* these functions are defined into a .h to be included.481*/482483484/*=========================================485* Target specific486=========================================*/487#if defined(__BMI__) && defined(__GNUC__)488# include <immintrin.h> /* support for bextr (experimental) */489#endif490491/*-********************************************492* bitStream decoding API (read backward)493**********************************************/494typedef struct495{496size_t bitContainer;497unsigned bitsConsumed;498const char* ptr;499const char* start;500} BITv07_DStream_t;501502typedef enum { BITv07_DStream_unfinished = 0,503BITv07_DStream_endOfBuffer = 1,504BITv07_DStream_completed = 2,505BITv07_DStream_overflow = 3 } BITv07_DStream_status; /* result of BITv07_reloadDStream() */506/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */507508MEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize);509MEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, unsigned nbBits);510MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD);511MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* bitD);512513514515/*-****************************************516* unsafe API517******************************************/518MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, unsigned nbBits);519/* faster, but works only if nbBits >= 1 */520521522523/*-**************************************************************524* Internal functions525****************************************************************/526MEM_STATIC unsigned BITv07_highbit32 (U32 val)527{528# if defined(_MSC_VER) /* Visual */529unsigned long r;530return _BitScanReverse(&r, val) ? (unsigned)r : 0;531# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */532return __builtin_clz (val) ^ 31;533# else /* Software version */534static 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 };535U32 v = val;536v |= v >> 1;537v |= v >> 2;538v |= v >> 4;539v |= v >> 8;540v |= v >> 16;541return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];542# endif543}544545546547/*-********************************************************548* bitStream decoding549**********************************************************/550/*! BITv07_initDStream() :551* Initialize a BITv07_DStream_t.552* `bitD` : a pointer to an already allocated BITv07_DStream_t structure.553* `srcSize` must be the *exact* size of the bitStream, in bytes.554* @return : size of stream (== srcSize) or an errorCode if a problem is detected555*/556MEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize)557{558if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }559560if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */561bitD->start = (const char*)srcBuffer;562bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);563bitD->bitContainer = MEM_readLEST(bitD->ptr);564{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];565bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;566if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }567} else {568bitD->start = (const char*)srcBuffer;569bitD->ptr = bitD->start;570bitD->bitContainer = *(const BYTE*)(bitD->start);571switch(srcSize)572{573case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */574case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */575case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */576case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */577case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */578case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8; /* fall-through */579default: break;580}581{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];582bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;583if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }584bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;585}586587return srcSize;588}589590591MEM_STATIC size_t BITv07_lookBits(const BITv07_DStream_t* bitD, U32 nbBits)592{593U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;594return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);595}596597/*! BITv07_lookBitsFast() :598* unsafe version; only works only if nbBits >= 1 */599MEM_STATIC size_t BITv07_lookBitsFast(const BITv07_DStream_t* bitD, U32 nbBits)600{601U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;602return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);603}604605MEM_STATIC void BITv07_skipBits(BITv07_DStream_t* bitD, U32 nbBits)606{607bitD->bitsConsumed += nbBits;608}609610MEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, U32 nbBits)611{612size_t const value = BITv07_lookBits(bitD, nbBits);613BITv07_skipBits(bitD, nbBits);614return value;615}616617/*! BITv07_readBitsFast() :618* unsafe version; only works only if nbBits >= 1 */619MEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, U32 nbBits)620{621size_t const value = BITv07_lookBitsFast(bitD, nbBits);622BITv07_skipBits(bitD, nbBits);623return value;624}625626MEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD)627{628if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */629return BITv07_DStream_overflow;630631if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {632bitD->ptr -= bitD->bitsConsumed >> 3;633bitD->bitsConsumed &= 7;634bitD->bitContainer = MEM_readLEST(bitD->ptr);635return BITv07_DStream_unfinished;636}637if (bitD->ptr == bitD->start) {638if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv07_DStream_endOfBuffer;639return BITv07_DStream_completed;640}641{ U32 nbBytes = bitD->bitsConsumed >> 3;642BITv07_DStream_status result = BITv07_DStream_unfinished;643if (bitD->ptr - nbBytes < bitD->start) {644nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */645result = BITv07_DStream_endOfBuffer;646}647bitD->ptr -= nbBytes;648bitD->bitsConsumed -= nbBytes*8;649bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */650return result;651}652}653654/*! BITv07_endOfDStream() :655* @return Tells if DStream has exactly reached its end (all bits consumed).656*/657MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* DStream)658{659return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));660}661662#if defined (__cplusplus)663}664#endif665666#endif /* BITSTREAM_H_MODULE */667/* ******************************************************************668FSE : Finite State Entropy codec669Public Prototypes declaration670Copyright (C) 2013-2016, Yann Collet.671672BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)673674Redistribution and use in source and binary forms, with or without675modification, are permitted provided that the following conditions are676met:677678* Redistributions of source code must retain the above copyright679notice, this list of conditions and the following disclaimer.680* Redistributions in binary form must reproduce the above681copyright notice, this list of conditions and the following disclaimer682in the documentation and/or other materials provided with the683distribution.684685THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS686"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT687LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR688A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT689OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,690SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT691LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,692DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY693THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT694(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE695OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.696697You can contact the author at :698- Source repository : https://github.com/Cyan4973/FiniteStateEntropy699****************************************************************** */700#ifndef FSEv07_H701#define FSEv07_H702703#if defined (__cplusplus)704extern "C" {705#endif706707708709/*-****************************************710* FSE simple functions711******************************************/712713/*! FSEv07_decompress():714Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',715into already allocated destination buffer 'dst', of size 'dstCapacity'.716@return : size of regenerated data (<= maxDstSize),717or an error code, which can be tested using FSEv07_isError() .718719** Important ** : FSEv07_decompress() does not decompress non-compressible nor RLE data !!!720Why ? : making this distinction requires a header.721Header management is intentionally delegated to the user layer, which can better manage special cases.722*/723size_t FSEv07_decompress(void* dst, size_t dstCapacity,724const void* cSrc, size_t cSrcSize);725726727/* Error Management */728unsigned FSEv07_isError(size_t code); /* tells if a return value is an error code */729const char* FSEv07_getErrorName(size_t code); /* provides error code string (useful for debugging) */730731732/*-*****************************************733* FSE detailed API734******************************************/735/*!736FSEv07_decompress() does the following:7371. read normalized counters with readNCount()7382. build decoding table 'DTable' from normalized counters7393. decode the data stream using decoding table 'DTable'740741The following API allows targeting specific sub-functions for advanced tasks.742For example, it's possible to compress several blocks using the same 'CTable',743or to save and provide normalized distribution using external method.744*/745746747/* *** DECOMPRESSION *** */748749/*! FSEv07_readNCount():750Read compactly saved 'normalizedCounter' from 'rBuffer'.751@return : size read from 'rBuffer',752or an errorCode, which can be tested using FSEv07_isError().753maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */754size_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);755756/*! Constructor and Destructor of FSEv07_DTable.757Note that its size depends on 'tableLog' */758typedef unsigned FSEv07_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */759FSEv07_DTable* FSEv07_createDTable(unsigned tableLog);760void FSEv07_freeDTable(FSEv07_DTable* dt);761762/*! FSEv07_buildDTable():763Builds 'dt', which must be already allocated, using FSEv07_createDTable().764return : 0, or an errorCode, which can be tested using FSEv07_isError() */765size_t FSEv07_buildDTable (FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);766767/*! FSEv07_decompress_usingDTable():768Decompress compressed source `cSrc` of size `cSrcSize` using `dt`769into `dst` which must be already allocated.770@return : size of regenerated data (necessarily <= `dstCapacity`),771or an errorCode, which can be tested using FSEv07_isError() */772size_t FSEv07_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv07_DTable* dt);773774/*!775Tutorial :776----------777(Note : these functions only decompress FSE-compressed blocks.778If block is uncompressed, use memcpy() instead779If block is a single repeated byte, use memset() instead )780781The first step is to obtain the normalized frequencies of symbols.782This can be performed by FSEv07_readNCount() if it was saved using FSEv07_writeNCount().783'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.784In practice, that means it's necessary to know 'maxSymbolValue' beforehand,785or size the table to handle worst case situations (typically 256).786FSEv07_readNCount() will provide 'tableLog' and 'maxSymbolValue'.787The result of FSEv07_readNCount() is the number of bytes read from 'rBuffer'.788Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.789If there is an error, the function will return an error code, which can be tested using FSEv07_isError().790791The next step is to build the decompression tables 'FSEv07_DTable' from 'normalizedCounter'.792This is performed by the function FSEv07_buildDTable().793The space required by 'FSEv07_DTable' must be already allocated using FSEv07_createDTable().794If there is an error, the function will return an error code, which can be tested using FSEv07_isError().795796`FSEv07_DTable` can then be used to decompress `cSrc`, with FSEv07_decompress_usingDTable().797`cSrcSize` must be strictly correct, otherwise decompression will fail.798FSEv07_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).799If there is an error, the function will return an error code, which can be tested using FSEv07_isError(). (ex: dst buffer too small)800*/801802803#ifdef FSEv07_STATIC_LINKING_ONLY804805806/* *****************************************807* Static allocation808*******************************************/809/* FSE buffer bounds */810#define FSEv07_NCOUNTBOUND 512811#define FSEv07_BLOCKBOUND(size) (size + (size>>7))812813/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */814#define FSEv07_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))815816817/* *****************************************818* FSE advanced API819*******************************************/820size_t FSEv07_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);821/**< same as FSEv07_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr */822823unsigned FSEv07_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);824/**< same as FSEv07_optimalTableLog(), which used `minus==2` */825826size_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits);827/**< build a fake FSEv07_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */828829size_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, unsigned char symbolValue);830/**< build a fake FSEv07_DTable, designed to always generate the same symbolValue */831832833834/* *****************************************835* FSE symbol decompression API836*******************************************/837typedef struct838{839size_t state;840const void* table; /* precise table may vary, depending on U16 */841} FSEv07_DState_t;842843844static void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt);845846static unsigned char FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);847848849850/* *****************************************851* FSE unsafe API852*******************************************/853static unsigned char FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);854/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */855856857/* ====== Decompression ====== */858859typedef struct {860U16 tableLog;861U16 fastMode;862} FSEv07_DTableHeader; /* sizeof U32 */863864typedef struct865{866unsigned short newState;867unsigned char symbol;868unsigned char nbBits;869} FSEv07_decode_t; /* size == U32 */870871MEM_STATIC void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt)872{873const void* ptr = dt;874const FSEv07_DTableHeader* const DTableH = (const FSEv07_DTableHeader*)ptr;875DStatePtr->state = BITv07_readBits(bitD, DTableH->tableLog);876BITv07_reloadDStream(bitD);877DStatePtr->table = dt + 1;878}879880MEM_STATIC BYTE FSEv07_peekSymbol(const FSEv07_DState_t* DStatePtr)881{882FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];883return DInfo.symbol;884}885886MEM_STATIC void FSEv07_updateState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)887{888FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];889U32 const nbBits = DInfo.nbBits;890size_t const lowBits = BITv07_readBits(bitD, nbBits);891DStatePtr->state = DInfo.newState + lowBits;892}893894MEM_STATIC BYTE FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)895{896FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];897U32 const nbBits = DInfo.nbBits;898BYTE const symbol = DInfo.symbol;899size_t const lowBits = BITv07_readBits(bitD, nbBits);900901DStatePtr->state = DInfo.newState + lowBits;902return symbol;903}904905/*! FSEv07_decodeSymbolFast() :906unsafe, only works if no symbol has a probability > 50% */907MEM_STATIC BYTE FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)908{909FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];910U32 const nbBits = DInfo.nbBits;911BYTE const symbol = DInfo.symbol;912size_t const lowBits = BITv07_readBitsFast(bitD, nbBits);913914DStatePtr->state = DInfo.newState + lowBits;915return symbol;916}917918919920#ifndef FSEv07_COMMONDEFS_ONLY921922/* **************************************************************923* Tuning parameters924****************************************************************/925/*!MEMORY_USAGE :926* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)927* Increasing memory usage improves compression ratio928* Reduced memory usage can improve speed, due to cache effect929* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */930#define FSEv07_MAX_MEMORY_USAGE 14931#define FSEv07_DEFAULT_MEMORY_USAGE 13932933/*!FSEv07_MAX_SYMBOL_VALUE :934* Maximum symbol value authorized.935* Required for proper stack allocation */936#define FSEv07_MAX_SYMBOL_VALUE 255937938939/* **************************************************************940* template functions type & suffix941****************************************************************/942#define FSEv07_FUNCTION_TYPE BYTE943#define FSEv07_FUNCTION_EXTENSION944#define FSEv07_DECODE_TYPE FSEv07_decode_t945946947#endif /* !FSEv07_COMMONDEFS_ONLY */948949950/* ***************************************************************951* Constants952*****************************************************************/953#define FSEv07_MAX_TABLELOG (FSEv07_MAX_MEMORY_USAGE-2)954#define FSEv07_MAX_TABLESIZE (1U<<FSEv07_MAX_TABLELOG)955#define FSEv07_MAXTABLESIZE_MASK (FSEv07_MAX_TABLESIZE-1)956#define FSEv07_DEFAULT_TABLELOG (FSEv07_DEFAULT_MEMORY_USAGE-2)957#define FSEv07_MIN_TABLELOG 5958959#define FSEv07_TABLELOG_ABSOLUTE_MAX 15960#if FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX961# error "FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX is not supported"962#endif963964#define FSEv07_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)965966967#endif /* FSEv07_STATIC_LINKING_ONLY */968969970#if defined (__cplusplus)971}972#endif973974#endif /* FSEv07_H */975/* ******************************************************************976Huffman coder, part of New Generation Entropy library977header file978Copyright (C) 2013-2016, Yann Collet.979980BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)981982Redistribution and use in source and binary forms, with or without983modification, are permitted provided that the following conditions are984met:985986* Redistributions of source code must retain the above copyright987notice, this list of conditions and the following disclaimer.988* Redistributions in binary form must reproduce the above989copyright notice, this list of conditions and the following disclaimer990in the documentation and/or other materials provided with the991distribution.992993THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS994"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT995LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR996A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT997OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,998SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT999LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1000DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1001THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1002(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1003OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.10041005You can contact the author at :1006- Source repository : https://github.com/Cyan4973/FiniteStateEntropy1007****************************************************************** */1008#ifndef HUFv07_H_2987342341009#define HUFv07_H_29873423410101011#if defined (__cplusplus)1012extern "C" {1013#endif1014101510161017/* *** simple functions *** */1018/**1019HUFv07_decompress() :1020Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',1021into already allocated buffer 'dst', of minimum size 'dstSize'.1022`dstSize` : **must** be the ***exact*** size of original (uncompressed) data.1023Note : in contrast with FSE, HUFv07_decompress can regenerate1024RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,1025because it knows size to regenerate.1026@return : size of regenerated data (== dstSize),1027or an error code, which can be tested using HUFv07_isError()1028*/1029size_t HUFv07_decompress(void* dst, size_t dstSize,1030const void* cSrc, size_t cSrcSize);103110321033/* ****************************************1034* Tool functions1035******************************************/1036#define HUFv07_BLOCKSIZE_MAX (128 * 1024)10371038/* Error Management */1039unsigned HUFv07_isError(size_t code); /**< tells if a return value is an error code */1040const char* HUFv07_getErrorName(size_t code); /**< provides error code string (useful for debugging) */104110421043/* *** Advanced function *** */104410451046#ifdef HUFv07_STATIC_LINKING_ONLY104710481049/* *** Constants *** */1050#define HUFv07_TABLELOG_ABSOLUTEMAX 16 /* absolute limit of HUFv07_MAX_TABLELOG. Beyond that value, code does not work */1051#define HUFv07_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUFv07_ABSOLUTEMAX_TABLELOG */1052#define HUFv07_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */1053#define HUFv07_SYMBOLVALUE_MAX 2551054#if (HUFv07_TABLELOG_MAX > HUFv07_TABLELOG_ABSOLUTEMAX)1055# error "HUFv07_TABLELOG_MAX is too large !"1056#endif105710581059/* ****************************************1060* Static allocation1061******************************************/1062/* HUF buffer bounds */1063#define HUFv07_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true if incompressible pre-filtered with fast heuristic */10641065/* static allocation of HUF's DTable */1066typedef U32 HUFv07_DTable;1067#define HUFv07_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog)))1068#define HUFv07_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \1069HUFv07_DTable DTable[HUFv07_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1)*0x1000001) }1070#define HUFv07_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \1071HUFv07_DTable DTable[HUFv07_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog)*0x1000001) }107210731074/* ****************************************1075* Advanced decompression functions1076******************************************/1077size_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */1078size_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */10791080size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */1081size_t HUFv07_decompress4X_hufOnly(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */1082size_t HUFv07_decompress4X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */1083size_t HUFv07_decompress4X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */10841085size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);1086size_t HUFv07_decompress1X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */1087size_t HUFv07_decompress1X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */108810891090/* ****************************************1091* HUF detailed API1092******************************************/1093/*!1094The following API allows targeting specific sub-functions for advanced tasks.1095For example, it's possible to compress several blocks using the same 'CTable',1096or to save and regenerate 'CTable' using external methods.1097*/1098/* FSEv07_count() : find it within "fse.h" */10991100/*! HUFv07_readStats() :1101Read compact Huffman tree, saved by HUFv07_writeCTable().1102`huffWeight` is destination buffer.1103@return : size read from `src` , or an error Code .1104Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() . */1105size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,1106U32* nbSymbolsPtr, U32* tableLogPtr,1107const void* src, size_t srcSize);110811091110/*1111HUFv07_decompress() does the following:11121. select the decompression algorithm (X2, X4) based on pre-computed heuristics11132. build Huffman table from save, using HUFv07_readDTableXn()11143. decode 1 or 4 segments in parallel using HUFv07_decompressSXn_usingDTable1115*/11161117/** HUFv07_selectDecoder() :1118* Tells which decoder is likely to decode faster,1119* based on a set of pre-determined metrics.1120* @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .1121* Assumption : 0 < cSrcSize < dstSize <= 128 KB */1122U32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize);11231124size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize);1125size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize);11261127size_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);1128size_t HUFv07_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);1129size_t HUFv07_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);113011311132/* single stream variants */1133size_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */1134size_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */11351136size_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);1137size_t HUFv07_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);1138size_t HUFv07_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);113911401141#endif /* HUFv07_STATIC_LINKING_ONLY */114211431144#if defined (__cplusplus)1145}1146#endif11471148#endif /* HUFv07_H_298734234 */1149/*1150Common functions of New Generation Entropy library1151Copyright (C) 2016, Yann Collet.11521153BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)11541155Redistribution and use in source and binary forms, with or without1156modification, are permitted provided that the following conditions are1157met:11581159* Redistributions of source code must retain the above copyright1160notice, this list of conditions and the following disclaimer.1161* Redistributions in binary form must reproduce the above1162copyright notice, this list of conditions and the following disclaimer1163in the documentation and/or other materials provided with the1164distribution.11651166THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1167"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1168LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1169A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1170OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1171SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1172LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1173DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1174THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1175(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1176OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.11771178You can contact the author at :1179- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy1180- Public forum : https://groups.google.com/forum/#!forum/lz4c1181*************************************************************************** */1182118311841185/*-****************************************1186* FSE Error Management1187******************************************/1188unsigned FSEv07_isError(size_t code) { return ERR_isError(code); }11891190const char* FSEv07_getErrorName(size_t code) { return ERR_getErrorName(code); }119111921193/* **************************************************************1194* HUF Error Management1195****************************************************************/1196unsigned HUFv07_isError(size_t code) { return ERR_isError(code); }11971198const char* HUFv07_getErrorName(size_t code) { return ERR_getErrorName(code); }119912001201/*-**************************************************************1202* FSE NCount encoding-decoding1203****************************************************************/1204static short FSEv07_abs(short a) { return (short)(a<0 ? -a : a); }12051206size_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,1207const void* headerBuffer, size_t hbSize)1208{1209const BYTE* const istart = (const BYTE*) headerBuffer;1210const BYTE* const iend = istart + hbSize;1211const BYTE* ip = istart;1212int nbBits;1213int remaining;1214int threshold;1215U32 bitStream;1216int bitCount;1217unsigned charnum = 0;1218int previous0 = 0;12191220if (hbSize < 4) return ERROR(srcSize_wrong);1221bitStream = MEM_readLE32(ip);1222nbBits = (bitStream & 0xF) + FSEv07_MIN_TABLELOG; /* extract tableLog */1223if (nbBits > FSEv07_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);1224bitStream >>= 4;1225bitCount = 4;1226*tableLogPtr = nbBits;1227remaining = (1<<nbBits)+1;1228threshold = 1<<nbBits;1229nbBits++;12301231while ((remaining>1) && (charnum<=*maxSVPtr)) {1232if (previous0) {1233unsigned n0 = charnum;1234while ((bitStream & 0xFFFF) == 0xFFFF) {1235n0+=24;1236if (ip < iend-5) {1237ip+=2;1238bitStream = MEM_readLE32(ip) >> bitCount;1239} else {1240bitStream >>= 16;1241bitCount+=16;1242} }1243while ((bitStream & 3) == 3) {1244n0+=3;1245bitStream>>=2;1246bitCount+=2;1247}1248n0 += bitStream & 3;1249bitCount += 2;1250if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);1251while (charnum < n0) normalizedCounter[charnum++] = 0;1252if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {1253ip += bitCount>>3;1254bitCount &= 7;1255bitStream = MEM_readLE32(ip) >> bitCount;1256}1257else1258bitStream >>= 2;1259}1260{ short const max = (short)((2*threshold-1)-remaining);1261short count;12621263if ((bitStream & (threshold-1)) < (U32)max) {1264count = (short)(bitStream & (threshold-1));1265bitCount += nbBits-1;1266} else {1267count = (short)(bitStream & (2*threshold-1));1268if (count >= threshold) count -= max;1269bitCount += nbBits;1270}12711272count--; /* extra accuracy */1273remaining -= FSEv07_abs(count);1274normalizedCounter[charnum++] = count;1275previous0 = !count;1276while (remaining < threshold) {1277nbBits--;1278threshold >>= 1;1279}12801281if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {1282ip += bitCount>>3;1283bitCount &= 7;1284} else {1285bitCount -= (int)(8 * (iend - 4 - ip));1286ip = iend - 4;1287}1288bitStream = MEM_readLE32(ip) >> (bitCount & 31);1289} } /* while ((remaining>1) && (charnum<=*maxSVPtr)) */1290if (remaining != 1) return ERROR(GENERIC);1291*maxSVPtr = charnum-1;12921293ip += (bitCount+7)>>3;1294if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);1295return ip-istart;1296}129712981299/*! HUFv07_readStats() :1300Read compact Huffman tree, saved by HUFv07_writeCTable().1301`huffWeight` is destination buffer.1302@return : size read from `src` , or an error Code .1303Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() .1304*/1305size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,1306U32* nbSymbolsPtr, U32* tableLogPtr,1307const void* src, size_t srcSize)1308{1309U32 weightTotal;1310const BYTE* ip = (const BYTE*) src;1311size_t iSize;1312size_t oSize;13131314if (!srcSize) return ERROR(srcSize_wrong);1315iSize = ip[0];1316/* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */13171318if (iSize >= 128) { /* special header */1319if (iSize >= (242)) { /* RLE */1320static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };1321oSize = l[iSize-242];1322memset(huffWeight, 1, hwSize);1323iSize = 0;1324}1325else { /* Incompressible */1326oSize = iSize - 127;1327iSize = ((oSize+1)/2);1328if (iSize+1 > srcSize) return ERROR(srcSize_wrong);1329if (oSize >= hwSize) return ERROR(corruption_detected);1330ip += 1;1331{ U32 n;1332for (n=0; n<oSize; n+=2) {1333huffWeight[n] = ip[n/2] >> 4;1334huffWeight[n+1] = ip[n/2] & 15;1335} } } }1336else { /* header compressed with FSE (normal case) */1337if (iSize+1 > srcSize) return ERROR(srcSize_wrong);1338oSize = FSEv07_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */1339if (FSEv07_isError(oSize)) return oSize;1340}13411342/* collect weight stats */1343memset(rankStats, 0, (HUFv07_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32));1344weightTotal = 0;1345{ U32 n; for (n=0; n<oSize; n++) {1346if (huffWeight[n] >= HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);1347rankStats[huffWeight[n]]++;1348weightTotal += (1 << huffWeight[n]) >> 1;1349} }1350if (weightTotal == 0) return ERROR(corruption_detected);13511352/* get last non-null symbol weight (implied, total must be 2^n) */1353{ U32 const tableLog = BITv07_highbit32(weightTotal) + 1;1354if (tableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);1355*tableLogPtr = tableLog;1356/* determine last weight */1357{ U32 const total = 1 << tableLog;1358U32 const rest = total - weightTotal;1359U32 const verif = 1 << BITv07_highbit32(rest);1360U32 const lastWeight = BITv07_highbit32(rest) + 1;1361if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */1362huffWeight[oSize] = (BYTE)lastWeight;1363rankStats[lastWeight]++;1364} }13651366/* check tree construction validity */1367if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */13681369/* results */1370*nbSymbolsPtr = (U32)(oSize+1);1371return iSize+1;1372}1373/* ******************************************************************1374FSE : Finite State Entropy decoder1375Copyright (C) 2013-2015, Yann Collet.13761377BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)13781379Redistribution and use in source and binary forms, with or without1380modification, are permitted provided that the following conditions are1381met:13821383* Redistributions of source code must retain the above copyright1384notice, this list of conditions and the following disclaimer.1385* Redistributions in binary form must reproduce the above1386copyright notice, this list of conditions and the following disclaimer1387in the documentation and/or other materials provided with the1388distribution.13891390THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1391"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1392LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1393A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1394OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1395SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1396LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1397DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1398THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1399(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1400OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.14011402You can contact the author at :1403- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy1404- Public forum : https://groups.google.com/forum/#!forum/lz4c1405****************************************************************** */140614071408/* **************************************************************1409* Compiler specifics1410****************************************************************/1411#ifdef _MSC_VER /* Visual Studio */1412# define FORCE_INLINE static __forceinline1413# include <intrin.h> /* For Visual 2005 */1414# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */1415# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */1416#else1417# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */1418# ifdef __GNUC__1419# define FORCE_INLINE static inline __attribute__((always_inline))1420# else1421# define FORCE_INLINE static inline1422# endif1423# else1424# define FORCE_INLINE static1425# endif /* __STDC_VERSION__ */1426#endif142714281429/* **************************************************************1430* Error Management1431****************************************************************/1432#define FSEv07_isError ERR_isError1433#define FSEv07_STATIC_ASSERT(c) { enum { FSEv07_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */143414351436/* **************************************************************1437* Complex types1438****************************************************************/1439typedef U32 DTable_max_t[FSEv07_DTABLE_SIZE_U32(FSEv07_MAX_TABLELOG)];144014411442/* **************************************************************1443* Templates1444****************************************************************/1445/*1446designed to be included1447for type-specific functions (template emulation in C)1448Objective is to write these functions only once, for improved maintenance1449*/14501451/* safety checks */1452#ifndef FSEv07_FUNCTION_EXTENSION1453# error "FSEv07_FUNCTION_EXTENSION must be defined"1454#endif1455#ifndef FSEv07_FUNCTION_TYPE1456# error "FSEv07_FUNCTION_TYPE must be defined"1457#endif14581459/* Function names */1460#define FSEv07_CAT(X,Y) X##Y1461#define FSEv07_FUNCTION_NAME(X,Y) FSEv07_CAT(X,Y)1462#define FSEv07_TYPE_NAME(X,Y) FSEv07_CAT(X,Y)146314641465/* Function templates */1466FSEv07_DTable* FSEv07_createDTable (unsigned tableLog)1467{1468if (tableLog > FSEv07_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv07_TABLELOG_ABSOLUTE_MAX;1469return (FSEv07_DTable*)malloc( FSEv07_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );1470}14711472void FSEv07_freeDTable (FSEv07_DTable* dt)1473{1474free(dt);1475}14761477size_t FSEv07_buildDTable(FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)1478{1479void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */1480FSEv07_DECODE_TYPE* const tableDecode = (FSEv07_DECODE_TYPE*) (tdPtr);1481U16 symbolNext[FSEv07_MAX_SYMBOL_VALUE+1];14821483U32 const maxSV1 = maxSymbolValue + 1;1484U32 const tableSize = 1 << tableLog;1485U32 highThreshold = tableSize-1;14861487/* Sanity Checks */1488if (maxSymbolValue > FSEv07_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);1489if (tableLog > FSEv07_MAX_TABLELOG) return ERROR(tableLog_tooLarge);14901491/* Init, lay down lowprob symbols */1492{ FSEv07_DTableHeader DTableH;1493DTableH.tableLog = (U16)tableLog;1494DTableH.fastMode = 1;1495{ S16 const largeLimit= (S16)(1 << (tableLog-1));1496U32 s;1497for (s=0; s<maxSV1; s++) {1498if (normalizedCounter[s]==-1) {1499tableDecode[highThreshold--].symbol = (FSEv07_FUNCTION_TYPE)s;1500symbolNext[s] = 1;1501} else {1502if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;1503symbolNext[s] = normalizedCounter[s];1504} } }1505memcpy(dt, &DTableH, sizeof(DTableH));1506}15071508/* Spread symbols */1509{ U32 const tableMask = tableSize-1;1510U32 const step = FSEv07_TABLESTEP(tableSize);1511U32 s, position = 0;1512for (s=0; s<maxSV1; s++) {1513int i;1514for (i=0; i<normalizedCounter[s]; i++) {1515tableDecode[position].symbol = (FSEv07_FUNCTION_TYPE)s;1516position = (position + step) & tableMask;1517while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */1518} }15191520if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */1521}15221523/* Build Decoding table */1524{ U32 u;1525for (u=0; u<tableSize; u++) {1526FSEv07_FUNCTION_TYPE const symbol = (FSEv07_FUNCTION_TYPE)(tableDecode[u].symbol);1527U16 nextState = symbolNext[symbol]++;1528tableDecode[u].nbBits = (BYTE) (tableLog - BITv07_highbit32 ((U32)nextState) );1529tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);1530} }15311532return 0;1533}1534153515361537#ifndef FSEv07_COMMONDEFS_ONLY15381539/*-*******************************************************1540* Decompression (Byte symbols)1541*********************************************************/1542size_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, BYTE symbolValue)1543{1544void* ptr = dt;1545FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;1546void* dPtr = dt + 1;1547FSEv07_decode_t* const cell = (FSEv07_decode_t*)dPtr;15481549DTableH->tableLog = 0;1550DTableH->fastMode = 0;15511552cell->newState = 0;1553cell->symbol = symbolValue;1554cell->nbBits = 0;15551556return 0;1557}155815591560size_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits)1561{1562void* ptr = dt;1563FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;1564void* dPtr = dt + 1;1565FSEv07_decode_t* const dinfo = (FSEv07_decode_t*)dPtr;1566const unsigned tableSize = 1 << nbBits;1567const unsigned tableMask = tableSize - 1;1568const unsigned maxSV1 = tableMask+1;1569unsigned s;15701571/* Sanity checks */1572if (nbBits < 1) return ERROR(GENERIC); /* min size */15731574/* Build Decoding Table */1575DTableH->tableLog = (U16)nbBits;1576DTableH->fastMode = 1;1577for (s=0; s<maxSV1; s++) {1578dinfo[s].newState = 0;1579dinfo[s].symbol = (BYTE)s;1580dinfo[s].nbBits = (BYTE)nbBits;1581}15821583return 0;1584}15851586FORCE_INLINE size_t FSEv07_decompress_usingDTable_generic(1587void* dst, size_t maxDstSize,1588const void* cSrc, size_t cSrcSize,1589const FSEv07_DTable* dt, const unsigned fast)1590{1591BYTE* const ostart = (BYTE*) dst;1592BYTE* op = ostart;1593BYTE* const omax = op + maxDstSize;1594BYTE* const olimit = omax-3;15951596BITv07_DStream_t bitD;1597FSEv07_DState_t state1;1598FSEv07_DState_t state2;15991600/* Init */1601{ size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */1602if (FSEv07_isError(errorCode)) return errorCode; }16031604FSEv07_initDState(&state1, &bitD, dt);1605FSEv07_initDState(&state2, &bitD, dt);16061607#define FSEv07_GETSYMBOL(statePtr) fast ? FSEv07_decodeSymbolFast(statePtr, &bitD) : FSEv07_decodeSymbol(statePtr, &bitD)16081609/* 4 symbols per loop */1610for ( ; (BITv07_reloadDStream(&bitD)==BITv07_DStream_unfinished) && (op<olimit) ; op+=4) {1611op[0] = FSEv07_GETSYMBOL(&state1);16121613if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1614BITv07_reloadDStream(&bitD);16151616op[1] = FSEv07_GETSYMBOL(&state2);16171618if (FSEv07_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1619{ if (BITv07_reloadDStream(&bitD) > BITv07_DStream_unfinished) { op+=2; break; } }16201621op[2] = FSEv07_GETSYMBOL(&state1);16221623if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */1624BITv07_reloadDStream(&bitD);16251626op[3] = FSEv07_GETSYMBOL(&state2);1627}16281629/* tail */1630/* note : BITv07_reloadDStream(&bitD) >= FSEv07_DStream_partiallyFilled; Ends at exactly BITv07_DStream_completed */1631while (1) {1632if (op>(omax-2)) return ERROR(dstSize_tooSmall);16331634*op++ = FSEv07_GETSYMBOL(&state1);16351636if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {1637*op++ = FSEv07_GETSYMBOL(&state2);1638break;1639}16401641if (op>(omax-2)) return ERROR(dstSize_tooSmall);16421643*op++ = FSEv07_GETSYMBOL(&state2);16441645if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {1646*op++ = FSEv07_GETSYMBOL(&state1);1647break;1648} }16491650return op-ostart;1651}165216531654size_t FSEv07_decompress_usingDTable(void* dst, size_t originalSize,1655const void* cSrc, size_t cSrcSize,1656const FSEv07_DTable* dt)1657{1658const void* ptr = dt;1659const FSEv07_DTableHeader* DTableH = (const FSEv07_DTableHeader*)ptr;1660const U32 fastMode = DTableH->fastMode;16611662/* select fast mode (static) */1663if (fastMode) return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);1664return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);1665}166616671668size_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)1669{1670const BYTE* const istart = (const BYTE*)cSrc;1671const BYTE* ip = istart;1672short counting[FSEv07_MAX_SYMBOL_VALUE+1];1673DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */1674unsigned tableLog;1675unsigned maxSymbolValue = FSEv07_MAX_SYMBOL_VALUE;16761677if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */16781679/* normal FSE decoding mode */1680{ size_t const NCountLength = FSEv07_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);1681if (FSEv07_isError(NCountLength)) return NCountLength;1682if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */1683ip += NCountLength;1684cSrcSize -= NCountLength;1685}16861687{ size_t const errorCode = FSEv07_buildDTable (dt, counting, maxSymbolValue, tableLog);1688if (FSEv07_isError(errorCode)) return errorCode; }16891690return FSEv07_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); /* always return, even if it is an error code */1691}1692169316941695#endif /* FSEv07_COMMONDEFS_ONLY */16961697/* ******************************************************************1698Huffman decoder, part of New Generation Entropy library1699Copyright (C) 2013-2016, Yann Collet.17001701BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)17021703Redistribution and use in source and binary forms, with or without1704modification, are permitted provided that the following conditions are1705met:17061707* Redistributions of source code must retain the above copyright1708notice, this list of conditions and the following disclaimer.1709* Redistributions in binary form must reproduce the above1710copyright notice, this list of conditions and the following disclaimer1711in the documentation and/or other materials provided with the1712distribution.17131714THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS1715"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT1716LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR1717A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT1718OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,1719SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT1720LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,1721DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY1722THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT1723(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE1724OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.17251726You can contact the author at :1727- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy1728- Public forum : https://groups.google.com/forum/#!forum/lz4c1729****************************************************************** */17301731/* **************************************************************1732* Compiler specifics1733****************************************************************/1734#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)1735/* inline is defined */1736#elif defined(_MSC_VER)1737# define inline __inline1738#else1739# define inline /* disable inline */1740#endif174117421743#ifdef _MSC_VER /* Visual Studio */1744# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */1745#endif1746174717481749/* **************************************************************1750* Error Management1751****************************************************************/1752#define HUFv07_STATIC_ASSERT(c) { enum { HUFv07_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */175317541755/*-***************************/1756/* generic DTableDesc */1757/*-***************************/17581759typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;17601761static DTableDesc HUFv07_getDTableDesc(const HUFv07_DTable* table)1762{1763DTableDesc dtd;1764memcpy(&dtd, table, sizeof(dtd));1765return dtd;1766}176717681769/*-***************************/1770/* single-symbol decoding */1771/*-***************************/17721773typedef struct { BYTE byte; BYTE nbBits; } HUFv07_DEltX2; /* single-symbol decoding */17741775size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize)1776{1777BYTE huffWeight[HUFv07_SYMBOLVALUE_MAX + 1];1778U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */1779U32 tableLog = 0;1780U32 nbSymbols = 0;1781size_t iSize;1782void* const dtPtr = DTable + 1;1783HUFv07_DEltX2* const dt = (HUFv07_DEltX2*)dtPtr;17841785HUFv07_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUFv07_DTable));1786/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */17871788iSize = HUFv07_readStats(huffWeight, HUFv07_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);1789if (HUFv07_isError(iSize)) return iSize;17901791/* Table header */1792{ DTableDesc dtd = HUFv07_getDTableDesc(DTable);1793if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, huffman tree cannot fit in */1794dtd.tableType = 0;1795dtd.tableLog = (BYTE)tableLog;1796memcpy(DTable, &dtd, sizeof(dtd));1797}17981799/* Prepare ranks */1800{ U32 n, nextRankStart = 0;1801for (n=1; n<tableLog+1; n++) {1802U32 current = nextRankStart;1803nextRankStart += (rankVal[n] << (n-1));1804rankVal[n] = current;1805} }18061807/* fill DTable */1808{ U32 n;1809for (n=0; n<nbSymbols; n++) {1810U32 const w = huffWeight[n];1811U32 const length = (1 << w) >> 1;1812U32 i;1813HUFv07_DEltX2 D;1814D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);1815for (i = rankVal[w]; i < rankVal[w] + length; i++)1816dt[i] = D;1817rankVal[w] += length;1818} }18191820return iSize;1821}182218231824static BYTE HUFv07_decodeSymbolX2(BITv07_DStream_t* Dstream, const HUFv07_DEltX2* dt, const U32 dtLog)1825{1826size_t const val = BITv07_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */1827BYTE const c = dt[val].byte;1828BITv07_skipBits(Dstream, dt[val].nbBits);1829return c;1830}18311832#define HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \1833*ptr++ = HUFv07_decodeSymbolX2(DStreamPtr, dt, dtLog)18341835#define HUFv07_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \1836if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \1837HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)18381839#define HUFv07_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \1840if (MEM_64bits()) \1841HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)18421843static inline size_t HUFv07_decodeStreamX2(BYTE* p, BITv07_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv07_DEltX2* const dt, const U32 dtLog)1844{1845BYTE* const pStart = p;18461847/* up to 4 symbols at a time */1848while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-4)) {1849HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);1850HUFv07_DECODE_SYMBOLX2_1(p, bitDPtr);1851HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);1852HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);1853}18541855/* closer to the end */1856while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd))1857HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);18581859/* no more data to retrieve from bitstream, hence no need to reload */1860while (p < pEnd)1861HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);18621863return pEnd-pStart;1864}18651866static size_t HUFv07_decompress1X2_usingDTable_internal(1867void* dst, size_t dstSize,1868const void* cSrc, size_t cSrcSize,1869const HUFv07_DTable* DTable)1870{1871BYTE* op = (BYTE*)dst;1872BYTE* const oend = op + dstSize;1873const void* dtPtr = DTable + 1;1874const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;1875BITv07_DStream_t bitD;1876DTableDesc const dtd = HUFv07_getDTableDesc(DTable);1877U32 const dtLog = dtd.tableLog;18781879{ size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);1880if (HUFv07_isError(errorCode)) return errorCode; }18811882HUFv07_decodeStreamX2(op, &bitD, oend, dt, dtLog);18831884/* check */1885if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);18861887return dstSize;1888}18891890size_t HUFv07_decompress1X2_usingDTable(1891void* dst, size_t dstSize,1892const void* cSrc, size_t cSrcSize,1893const HUFv07_DTable* DTable)1894{1895DTableDesc dtd = HUFv07_getDTableDesc(DTable);1896if (dtd.tableType != 0) return ERROR(GENERIC);1897return HUFv07_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);1898}18991900size_t HUFv07_decompress1X2_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)1901{1902const BYTE* ip = (const BYTE*) cSrc;19031904size_t const hSize = HUFv07_readDTableX2 (DCtx, cSrc, cSrcSize);1905if (HUFv07_isError(hSize)) return hSize;1906if (hSize >= cSrcSize) return ERROR(srcSize_wrong);1907ip += hSize; cSrcSize -= hSize;19081909return HUFv07_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);1910}19111912size_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)1913{1914HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);1915return HUFv07_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);1916}191719181919static size_t HUFv07_decompress4X2_usingDTable_internal(1920void* dst, size_t dstSize,1921const void* cSrc, size_t cSrcSize,1922const HUFv07_DTable* DTable)1923{1924/* Check */1925if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */19261927{ const BYTE* const istart = (const BYTE*) cSrc;1928BYTE* const ostart = (BYTE*) dst;1929BYTE* const oend = ostart + dstSize;1930const void* const dtPtr = DTable + 1;1931const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;19321933/* Init */1934BITv07_DStream_t bitD1;1935BITv07_DStream_t bitD2;1936BITv07_DStream_t bitD3;1937BITv07_DStream_t bitD4;1938size_t const length1 = MEM_readLE16(istart);1939size_t const length2 = MEM_readLE16(istart+2);1940size_t const length3 = MEM_readLE16(istart+4);1941size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);1942const BYTE* const istart1 = istart + 6; /* jumpTable */1943const BYTE* const istart2 = istart1 + length1;1944const BYTE* const istart3 = istart2 + length2;1945const BYTE* const istart4 = istart3 + length3;1946const size_t segmentSize = (dstSize+3) / 4;1947BYTE* const opStart2 = ostart + segmentSize;1948BYTE* const opStart3 = opStart2 + segmentSize;1949BYTE* const opStart4 = opStart3 + segmentSize;1950BYTE* op1 = ostart;1951BYTE* op2 = opStart2;1952BYTE* op3 = opStart3;1953BYTE* op4 = opStart4;1954U32 endSignal;1955DTableDesc const dtd = HUFv07_getDTableDesc(DTable);1956U32 const dtLog = dtd.tableLog;19571958if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */1959{ size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);1960if (HUFv07_isError(errorCode)) return errorCode; }1961{ size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);1962if (HUFv07_isError(errorCode)) return errorCode; }1963{ size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);1964if (HUFv07_isError(errorCode)) return errorCode; }1965{ size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);1966if (HUFv07_isError(errorCode)) return errorCode; }19671968/* 16-32 symbols per loop (4-8 symbols per stream) */1969endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);1970for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {1971HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);1972HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);1973HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);1974HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);1975HUFv07_DECODE_SYMBOLX2_1(op1, &bitD1);1976HUFv07_DECODE_SYMBOLX2_1(op2, &bitD2);1977HUFv07_DECODE_SYMBOLX2_1(op3, &bitD3);1978HUFv07_DECODE_SYMBOLX2_1(op4, &bitD4);1979HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);1980HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);1981HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);1982HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);1983HUFv07_DECODE_SYMBOLX2_0(op1, &bitD1);1984HUFv07_DECODE_SYMBOLX2_0(op2, &bitD2);1985HUFv07_DECODE_SYMBOLX2_0(op3, &bitD3);1986HUFv07_DECODE_SYMBOLX2_0(op4, &bitD4);1987endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);1988}19891990/* check corruption */1991if (op1 > opStart2) return ERROR(corruption_detected);1992if (op2 > opStart3) return ERROR(corruption_detected);1993if (op3 > opStart4) return ERROR(corruption_detected);1994/* note : op4 supposed already verified within main loop */19951996/* finish bitStreams one by one */1997HUFv07_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);1998HUFv07_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);1999HUFv07_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);2000HUFv07_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);20012002/* check */2003endSignal = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);2004if (!endSignal) return ERROR(corruption_detected);20052006/* decoded size */2007return dstSize;2008}2009}201020112012size_t HUFv07_decompress4X2_usingDTable(2013void* dst, size_t dstSize,2014const void* cSrc, size_t cSrcSize,2015const HUFv07_DTable* DTable)2016{2017DTableDesc dtd = HUFv07_getDTableDesc(DTable);2018if (dtd.tableType != 0) return ERROR(GENERIC);2019return HUFv07_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);2020}202120222023size_t HUFv07_decompress4X2_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2024{2025const BYTE* ip = (const BYTE*) cSrc;20262027size_t const hSize = HUFv07_readDTableX2 (dctx, cSrc, cSrcSize);2028if (HUFv07_isError(hSize)) return hSize;2029if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2030ip += hSize; cSrcSize -= hSize;20312032return HUFv07_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);2033}20342035size_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2036{2037HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);2038return HUFv07_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);2039}204020412042/* *************************/2043/* double-symbols decoding */2044/* *************************/2045typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv07_DEltX4; /* double-symbols decoding */20462047typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;20482049static void HUFv07_fillDTableX4Level2(HUFv07_DEltX4* DTable, U32 sizeLog, const U32 consumed,2050const U32* rankValOrigin, const int minWeight,2051const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,2052U32 nbBitsBaseline, U16 baseSeq)2053{2054HUFv07_DEltX4 DElt;2055U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];20562057/* get pre-calculated rankVal */2058memcpy(rankVal, rankValOrigin, sizeof(rankVal));20592060/* fill skipped values */2061if (minWeight>1) {2062U32 i, skipSize = rankVal[minWeight];2063MEM_writeLE16(&(DElt.sequence), baseSeq);2064DElt.nbBits = (BYTE)(consumed);2065DElt.length = 1;2066for (i = 0; i < skipSize; i++)2067DTable[i] = DElt;2068}20692070/* fill DTable */2071{ U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */2072const U32 symbol = sortedSymbols[s].symbol;2073const U32 weight = sortedSymbols[s].weight;2074const U32 nbBits = nbBitsBaseline - weight;2075const U32 length = 1 << (sizeLog-nbBits);2076const U32 start = rankVal[weight];2077U32 i = start;2078const U32 end = start + length;20792080MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));2081DElt.nbBits = (BYTE)(nbBits + consumed);2082DElt.length = 2;2083do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */20842085rankVal[weight] += length;2086}}2087}20882089typedef U32 rankVal_t[HUFv07_TABLELOG_ABSOLUTEMAX][HUFv07_TABLELOG_ABSOLUTEMAX + 1];20902091static void HUFv07_fillDTableX4(HUFv07_DEltX4* DTable, const U32 targetLog,2092const sortedSymbol_t* sortedList, const U32 sortedListSize,2093const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,2094const U32 nbBitsBaseline)2095{2096U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];2097const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */2098const U32 minBits = nbBitsBaseline - maxWeight;2099U32 s;21002101memcpy(rankVal, rankValOrigin, sizeof(rankVal));21022103/* fill DTable */2104for (s=0; s<sortedListSize; s++) {2105const U16 symbol = sortedList[s].symbol;2106const U32 weight = sortedList[s].weight;2107const U32 nbBits = nbBitsBaseline - weight;2108const U32 start = rankVal[weight];2109const U32 length = 1 << (targetLog-nbBits);21102111if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */2112U32 sortedRank;2113int minWeight = nbBits + scaleLog;2114if (minWeight < 1) minWeight = 1;2115sortedRank = rankStart[minWeight];2116HUFv07_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,2117rankValOrigin[nbBits], minWeight,2118sortedList+sortedRank, sortedListSize-sortedRank,2119nbBitsBaseline, symbol);2120} else {2121HUFv07_DEltX4 DElt;2122MEM_writeLE16(&(DElt.sequence), symbol);2123DElt.nbBits = (BYTE)(nbBits);2124DElt.length = 1;2125{ U32 u;2126const U32 end = start + length;2127for (u = start; u < end; u++) DTable[u] = DElt;2128} }2129rankVal[weight] += length;2130}2131}21322133size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize)2134{2135BYTE weightList[HUFv07_SYMBOLVALUE_MAX + 1];2136sortedSymbol_t sortedSymbol[HUFv07_SYMBOLVALUE_MAX + 1];2137U32 rankStats[HUFv07_TABLELOG_ABSOLUTEMAX + 1] = { 0 };2138U32 rankStart0[HUFv07_TABLELOG_ABSOLUTEMAX + 2] = { 0 };2139U32* const rankStart = rankStart0+1;2140rankVal_t rankVal;2141U32 tableLog, maxW, sizeOfSort, nbSymbols;2142DTableDesc dtd = HUFv07_getDTableDesc(DTable);2143U32 const maxTableLog = dtd.maxTableLog;2144size_t iSize;2145void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */2146HUFv07_DEltX4* const dt = (HUFv07_DEltX4*)dtPtr;21472148HUFv07_STATIC_ASSERT(sizeof(HUFv07_DEltX4) == sizeof(HUFv07_DTable)); /* if compilation fails here, assertion is false */2149if (maxTableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge);2150/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */21512152iSize = HUFv07_readStats(weightList, HUFv07_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);2153if (HUFv07_isError(iSize)) return iSize;21542155/* check result */2156if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */21572158/* find maxWeight */2159for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */21602161/* Get start index of each weight */2162{ U32 w, nextRankStart = 0;2163for (w=1; w<maxW+1; w++) {2164U32 current = nextRankStart;2165nextRankStart += rankStats[w];2166rankStart[w] = current;2167}2168rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/2169sizeOfSort = nextRankStart;2170}21712172/* sort symbols by weight */2173{ U32 s;2174for (s=0; s<nbSymbols; s++) {2175U32 const w = weightList[s];2176U32 const r = rankStart[w]++;2177sortedSymbol[r].symbol = (BYTE)s;2178sortedSymbol[r].weight = (BYTE)w;2179}2180rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */2181}21822183/* Build rankVal */2184{ U32* const rankVal0 = rankVal[0];2185{ int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */2186U32 nextRankVal = 0;2187U32 w;2188for (w=1; w<maxW+1; w++) {2189U32 current = nextRankVal;2190nextRankVal += rankStats[w] << (w+rescale);2191rankVal0[w] = current;2192} }2193{ U32 const minBits = tableLog+1 - maxW;2194U32 consumed;2195for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {2196U32* const rankValPtr = rankVal[consumed];2197U32 w;2198for (w = 1; w < maxW+1; w++) {2199rankValPtr[w] = rankVal0[w] >> consumed;2200} } } }22012202HUFv07_fillDTableX4(dt, maxTableLog,2203sortedSymbol, sizeOfSort,2204rankStart0, rankVal, maxW,2205tableLog+1);22062207dtd.tableLog = (BYTE)maxTableLog;2208dtd.tableType = 1;2209memcpy(DTable, &dtd, sizeof(dtd));2210return iSize;2211}221222132214static U32 HUFv07_decodeSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)2215{2216const size_t val = BITv07_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */2217memcpy(op, dt+val, 2);2218BITv07_skipBits(DStream, dt[val].nbBits);2219return dt[val].length;2220}22212222static U32 HUFv07_decodeLastSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)2223{2224const size_t val = BITv07_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */2225memcpy(op, dt+val, 1);2226if (dt[val].length==1) BITv07_skipBits(DStream, dt[val].nbBits);2227else {2228if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {2229BITv07_skipBits(DStream, dt[val].nbBits);2230if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))2231DStream->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 */2232} }2233return 1;2234}223522362237#define HUFv07_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \2238ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)22392240#define HUFv07_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \2241if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \2242ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)22432244#define HUFv07_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \2245if (MEM_64bits()) \2246ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)22472248static inline size_t HUFv07_decodeStreamX4(BYTE* p, BITv07_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv07_DEltX4* const dt, const U32 dtLog)2249{2250BYTE* const pStart = p;22512252/* up to 8 symbols at a time */2253while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd-7)) {2254HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);2255HUFv07_DECODE_SYMBOLX4_1(p, bitDPtr);2256HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);2257HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);2258}22592260/* closer to end : up to 2 symbols at a time */2261while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-2))2262HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);22632264while (p <= pEnd-2)2265HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */22662267if (p < pEnd)2268p += HUFv07_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);22692270return p-pStart;2271}227222732274static size_t HUFv07_decompress1X4_usingDTable_internal(2275void* dst, size_t dstSize,2276const void* cSrc, size_t cSrcSize,2277const HUFv07_DTable* DTable)2278{2279BITv07_DStream_t bitD;22802281/* Init */2282{ size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);2283if (HUFv07_isError(errorCode)) return errorCode;2284}22852286/* decode */2287{ BYTE* const ostart = (BYTE*) dst;2288BYTE* const oend = ostart + dstSize;2289const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */2290const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;2291DTableDesc const dtd = HUFv07_getDTableDesc(DTable);2292HUFv07_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);2293}22942295/* check */2296if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);22972298/* decoded size */2299return dstSize;2300}23012302size_t HUFv07_decompress1X4_usingDTable(2303void* dst, size_t dstSize,2304const void* cSrc, size_t cSrcSize,2305const HUFv07_DTable* DTable)2306{2307DTableDesc dtd = HUFv07_getDTableDesc(DTable);2308if (dtd.tableType != 1) return ERROR(GENERIC);2309return HUFv07_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);2310}23112312size_t HUFv07_decompress1X4_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2313{2314const BYTE* ip = (const BYTE*) cSrc;23152316size_t const hSize = HUFv07_readDTableX4 (DCtx, cSrc, cSrcSize);2317if (HUFv07_isError(hSize)) return hSize;2318if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2319ip += hSize; cSrcSize -= hSize;23202321return HUFv07_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);2322}23232324size_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2325{2326HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);2327return HUFv07_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);2328}23292330static size_t HUFv07_decompress4X4_usingDTable_internal(2331void* dst, size_t dstSize,2332const void* cSrc, size_t cSrcSize,2333const HUFv07_DTable* DTable)2334{2335if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */23362337{ const BYTE* const istart = (const BYTE*) cSrc;2338BYTE* const ostart = (BYTE*) dst;2339BYTE* const oend = ostart + dstSize;2340const void* const dtPtr = DTable+1;2341const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;23422343/* Init */2344BITv07_DStream_t bitD1;2345BITv07_DStream_t bitD2;2346BITv07_DStream_t bitD3;2347BITv07_DStream_t bitD4;2348size_t const length1 = MEM_readLE16(istart);2349size_t const length2 = MEM_readLE16(istart+2);2350size_t const length3 = MEM_readLE16(istart+4);2351size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);2352const BYTE* const istart1 = istart + 6; /* jumpTable */2353const BYTE* const istart2 = istart1 + length1;2354const BYTE* const istart3 = istart2 + length2;2355const BYTE* const istart4 = istart3 + length3;2356size_t const segmentSize = (dstSize+3) / 4;2357BYTE* const opStart2 = ostart + segmentSize;2358BYTE* const opStart3 = opStart2 + segmentSize;2359BYTE* const opStart4 = opStart3 + segmentSize;2360BYTE* op1 = ostart;2361BYTE* op2 = opStart2;2362BYTE* op3 = opStart3;2363BYTE* op4 = opStart4;2364U32 endSignal;2365DTableDesc const dtd = HUFv07_getDTableDesc(DTable);2366U32 const dtLog = dtd.tableLog;23672368if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */2369{ size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);2370if (HUFv07_isError(errorCode)) return errorCode; }2371{ size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);2372if (HUFv07_isError(errorCode)) return errorCode; }2373{ size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);2374if (HUFv07_isError(errorCode)) return errorCode; }2375{ size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);2376if (HUFv07_isError(errorCode)) return errorCode; }23772378/* 16-32 symbols per loop (4-8 symbols per stream) */2379endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);2380for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {2381HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);2382HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);2383HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);2384HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);2385HUFv07_DECODE_SYMBOLX4_1(op1, &bitD1);2386HUFv07_DECODE_SYMBOLX4_1(op2, &bitD2);2387HUFv07_DECODE_SYMBOLX4_1(op3, &bitD3);2388HUFv07_DECODE_SYMBOLX4_1(op4, &bitD4);2389HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);2390HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);2391HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);2392HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);2393HUFv07_DECODE_SYMBOLX4_0(op1, &bitD1);2394HUFv07_DECODE_SYMBOLX4_0(op2, &bitD2);2395HUFv07_DECODE_SYMBOLX4_0(op3, &bitD3);2396HUFv07_DECODE_SYMBOLX4_0(op4, &bitD4);23972398endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);2399}24002401/* check corruption */2402if (op1 > opStart2) return ERROR(corruption_detected);2403if (op2 > opStart3) return ERROR(corruption_detected);2404if (op3 > opStart4) return ERROR(corruption_detected);2405/* note : op4 supposed already verified within main loop */24062407/* finish bitStreams one by one */2408HUFv07_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);2409HUFv07_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);2410HUFv07_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);2411HUFv07_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);24122413/* check */2414{ U32 const endCheck = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);2415if (!endCheck) return ERROR(corruption_detected); }24162417/* decoded size */2418return dstSize;2419}2420}242124222423size_t HUFv07_decompress4X4_usingDTable(2424void* dst, size_t dstSize,2425const void* cSrc, size_t cSrcSize,2426const HUFv07_DTable* DTable)2427{2428DTableDesc dtd = HUFv07_getDTableDesc(DTable);2429if (dtd.tableType != 1) return ERROR(GENERIC);2430return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);2431}243224332434size_t HUFv07_decompress4X4_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2435{2436const BYTE* ip = (const BYTE*) cSrc;24372438size_t hSize = HUFv07_readDTableX4 (dctx, cSrc, cSrcSize);2439if (HUFv07_isError(hSize)) return hSize;2440if (hSize >= cSrcSize) return ERROR(srcSize_wrong);2441ip += hSize; cSrcSize -= hSize;24422443return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);2444}24452446size_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2447{2448HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);2449return HUFv07_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);2450}245124522453/* ********************************/2454/* Generic decompression selector */2455/* ********************************/24562457size_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize,2458const void* cSrc, size_t cSrcSize,2459const HUFv07_DTable* DTable)2460{2461DTableDesc const dtd = HUFv07_getDTableDesc(DTable);2462return dtd.tableType ? HUFv07_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :2463HUFv07_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);2464}24652466size_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize,2467const void* cSrc, size_t cSrcSize,2468const HUFv07_DTable* DTable)2469{2470DTableDesc const dtd = HUFv07_getDTableDesc(DTable);2471return dtd.tableType ? HUFv07_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :2472HUFv07_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);2473}247424752476typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;2477static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =2478{2479/* single, double, quad */2480{{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */2481{{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */2482{{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */2483{{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */2484{{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */2485{{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */2486{{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */2487{{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */2488{{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */2489{{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */2490{{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */2491{{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */2492{{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */2493{{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */2494{{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */2495{{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */2496};24972498/** HUFv07_selectDecoder() :2499* Tells which decoder is likely to decode faster,2500* based on a set of pre-determined metrics.2501* @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .2502* Assumption : 0 < cSrcSize < dstSize <= 128 KB */2503U32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize)2504{2505/* decoder timing evaluation */2506U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */2507U32 const D256 = (U32)(dstSize >> 8);2508U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);2509U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);2510DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */25112512return DTime1 < DTime0;2513}251425152516typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);25172518size_t HUFv07_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2519{2520static const decompressionAlgo decompress[2] = { HUFv07_decompress4X2, HUFv07_decompress4X4 };25212522/* validation checks */2523if (dstSize == 0) return ERROR(dstSize_tooSmall);2524if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */2525if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */2526if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */25272528{ U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);2529return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);2530}25312532/* return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */2533/* return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */2534}25352536size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2537{2538/* validation checks */2539if (dstSize == 0) return ERROR(dstSize_tooSmall);2540if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */2541if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */2542if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */25432544{ U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);2545return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :2546HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;2547}2548}25492550size_t HUFv07_decompress4X_hufOnly (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2551{2552/* validation checks */2553if (dstSize == 0) return ERROR(dstSize_tooSmall);2554if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected); /* invalid */25552556{ U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);2557return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :2558HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;2559}2560}25612562size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)2563{2564/* validation checks */2565if (dstSize == 0) return ERROR(dstSize_tooSmall);2566if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */2567if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */2568if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */25692570{ U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);2571return algoNb ? HUFv07_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :2572HUFv07_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;2573}2574}2575/*2576Common functions of Zstd compression library2577Copyright (C) 2015-2016, Yann Collet.25782579BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)25802581Redistribution and use in source and binary forms, with or without2582modification, are permitted provided that the following conditions are2583met:2584* Redistributions of source code must retain the above copyright2585notice, this list of conditions and the following disclaimer.2586* Redistributions in binary form must reproduce the above2587copyright notice, this list of conditions and the following disclaimer2588in the documentation and/or other materials provided with the2589distribution.2590THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS2591"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT2592LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR2593A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT2594OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,2595SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT2596LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,2597DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY2598THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2599(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE2600OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.26012602You can contact the author at :2603- zstd homepage : http://www.zstd.net/2604*/2605260626072608/*-****************************************2609* ZSTD Error Management2610******************************************/2611/*! ZSTDv07_isError() :2612* tells if a return value is an error code */2613unsigned ZSTDv07_isError(size_t code) { return ERR_isError(code); }26142615/*! ZSTDv07_getErrorName() :2616* provides error code string from function result (useful for debugging) */2617const char* ZSTDv07_getErrorName(size_t code) { return ERR_getErrorName(code); }2618261926202621/* **************************************************************2622* ZBUFF Error Management2623****************************************************************/2624unsigned ZBUFFv07_isError(size_t errorCode) { return ERR_isError(errorCode); }26252626const char* ZBUFFv07_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }2627262826292630static void* ZSTDv07_defaultAllocFunction(void* opaque, size_t size)2631{2632void* address = malloc(size);2633(void)opaque;2634/* printf("alloc %p, %d opaque=%p \n", address, (int)size, opaque); */2635return address;2636}26372638static void ZSTDv07_defaultFreeFunction(void* opaque, void* address)2639{2640(void)opaque;2641/* if (address) printf("free %p opaque=%p \n", address, opaque); */2642free(address);2643}2644/*2645zstd_internal - common functions to include2646Header File for include2647Copyright (C) 2014-2016, Yann Collet.26482649BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)26502651Redistribution and use in source and binary forms, with or without2652modification, are permitted provided that the following conditions are2653met:2654* Redistributions of source code must retain the above copyright2655notice, this list of conditions and the following disclaimer.2656* Redistributions in binary form must reproduce the above2657copyright notice, this list of conditions and the following disclaimer2658in the documentation and/or other materials provided with the2659distribution.2660THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS2661"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT2662LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR2663A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT2664OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,2665SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT2666LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,2667DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY2668THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2669(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE2670OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.26712672You can contact the author at :2673- zstd homepage : https://www.zstd.net2674*/2675#ifndef ZSTDv07_CCOMMON_H_MODULE2676#define ZSTDv07_CCOMMON_H_MODULE267726782679/*-*************************************2680* Common macros2681***************************************/2682#define MIN(a,b) ((a)<(b) ? (a) : (b))2683#define MAX(a,b) ((a)>(b) ? (a) : (b))268426852686/*-*************************************2687* Common constants2688***************************************/2689#define ZSTDv07_OPT_NUM (1<<12)2690#define ZSTDv07_DICT_MAGIC 0xEC30A437 /* v0.7 */26912692#define ZSTDv07_REP_NUM 32693#define ZSTDv07_REP_INIT ZSTDv07_REP_NUM2694#define ZSTDv07_REP_MOVE (ZSTDv07_REP_NUM-1)2695static const U32 repStartValue[ZSTDv07_REP_NUM] = { 1, 4, 8 };26962697#define KB *(1 <<10)2698#define MB *(1 <<20)2699#define GB *(1U<<30)27002701#define BIT7 1282702#define BIT6 642703#define BIT5 322704#define BIT4 162705#define BIT1 22706#define BIT0 127072708#define ZSTDv07_WINDOWLOG_ABSOLUTEMIN 102709static const size_t ZSTDv07_fcs_fieldSize[4] = { 0, 2, 4, 8 };2710static const size_t ZSTDv07_did_fieldSize[4] = { 0, 1, 2, 4 };27112712#define ZSTDv07_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */2713static const size_t ZSTDv07_blockHeaderSize = ZSTDv07_BLOCKHEADERSIZE;2714typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;27152716#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */2717#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */27182719#define HufLog 122720typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;27212722#define LONGNBSEQ 0x7F0027232724#define MINMATCH 32725#define EQUAL_READ32 427262727#define Litbits 82728#define MaxLit ((1<<Litbits) - 1)2729#define MaxML 522730#define MaxLL 352731#define MaxOff 282732#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */2733#define MLFSELog 92734#define LLFSELog 92735#define OffFSELog 827362737#define FSEv07_ENCODING_RAW 02738#define FSEv07_ENCODING_RLE 12739#define FSEv07_ENCODING_STATIC 22740#define FSEv07_ENCODING_DYNAMIC 327412742#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)27432744static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,27451, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,274613,14,15,16 };2747static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,27482, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,2749-1,-1,-1,-1 };2750static const U32 LL_defaultNormLog = 6;27512752static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,27530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,27541, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,275512,13,14,15,16 };2756static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,27571, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,27581, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,2759-1,-1,-1,-1,-1 };2760static const U32 ML_defaultNormLog = 6;27612762static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,27631, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };2764static const U32 OF_defaultNormLog = 5;276527662767/*-*******************************************2768* Shared functions to include for inlining2769*********************************************/2770static void ZSTDv07_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }2771#define COPY8(d,s) { ZSTDv07_copy8(d,s); d+=8; s+=8; }27722773/*! ZSTDv07_wildcopy() :2774* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */2775#define WILDCOPY_OVERLENGTH 82776MEM_STATIC void ZSTDv07_wildcopy(void* dst, const void* src, ptrdiff_t length)2777{2778const BYTE* ip = (const BYTE*)src;2779BYTE* op = (BYTE*)dst;2780BYTE* const oend = op + length;2781do2782COPY8(op, ip)2783while (op < oend);2784}278527862787/*-*******************************************2788* Private interfaces2789*********************************************/2790typedef struct ZSTDv07_stats_s ZSTDv07_stats_t;27912792typedef struct {2793U32 off;2794U32 len;2795} ZSTDv07_match_t;27962797typedef struct {2798U32 price;2799U32 off;2800U32 mlen;2801U32 litlen;2802U32 rep[ZSTDv07_REP_INIT];2803} ZSTDv07_optimal_t;28042805struct ZSTDv07_stats_s { U32 unused; };28062807typedef struct {2808void* buffer;2809U32* offsetStart;2810U32* offset;2811BYTE* offCodeStart;2812BYTE* litStart;2813BYTE* lit;2814U16* litLengthStart;2815U16* litLength;2816BYTE* llCodeStart;2817U16* matchLengthStart;2818U16* matchLength;2819BYTE* mlCodeStart;2820U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */2821U32 longLengthPos;2822/* opt */2823ZSTDv07_optimal_t* priceTable;2824ZSTDv07_match_t* matchTable;2825U32* matchLengthFreq;2826U32* litLengthFreq;2827U32* litFreq;2828U32* offCodeFreq;2829U32 matchLengthSum;2830U32 matchSum;2831U32 litLengthSum;2832U32 litSum;2833U32 offCodeSum;2834U32 log2matchLengthSum;2835U32 log2matchSum;2836U32 log2litLengthSum;2837U32 log2litSum;2838U32 log2offCodeSum;2839U32 factor;2840U32 cachedPrice;2841U32 cachedLitLength;2842const BYTE* cachedLiterals;2843ZSTDv07_stats_t stats;2844} seqStore_t;28452846void ZSTDv07_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq);28472848/* custom memory allocation functions */2849static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction, ZSTDv07_defaultFreeFunction, NULL };28502851#endif /* ZSTDv07_CCOMMON_H_MODULE */2852/*2853zstd - standard compression library2854Copyright (C) 2014-2016, Yann Collet.28552856BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)28572858Redistribution and use in source and binary forms, with or without2859modification, are permitted provided that the following conditions are2860met:2861* Redistributions of source code must retain the above copyright2862notice, this list of conditions and the following disclaimer.2863* Redistributions in binary form must reproduce the above2864copyright notice, this list of conditions and the following disclaimer2865in the documentation and/or other materials provided with the2866distribution.2867THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS2868"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT2869LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR2870A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT2871OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,2872SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT2873LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,2874DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY2875THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2876(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE2877OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28782879You can contact the author at :2880- zstd homepage : http://www.zstd.net2881*/28822883/* ***************************************************************2884* Tuning parameters2885*****************************************************************/2886/*!2887* HEAPMODE :2888* Select how default decompression function ZSTDv07_decompress() will allocate memory,2889* in memory stack (0), or in memory heap (1, requires malloc())2890*/2891#ifndef ZSTDv07_HEAPMODE2892# define ZSTDv07_HEAPMODE 12893#endif289428952896/*-*******************************************************2897* Compiler specifics2898*********************************************************/2899#ifdef _MSC_VER /* Visual Studio */2900# include <intrin.h> /* For Visual 2005 */2901# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */2902# pragma warning(disable : 4324) /* disable: C4324: padded structure */2903# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */2904#endif290529062907/*-*************************************2908* Macros2909***************************************/2910#define ZSTDv07_isError ERR_isError /* for inlining */2911#define FSEv07_isError ERR_isError2912#define HUFv07_isError ERR_isError291329142915/*_*******************************************************2916* Memory operations2917**********************************************************/2918static void ZSTDv07_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }291929202921/*-*************************************************************2922* Context management2923***************************************************************/2924typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,2925ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,2926ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTDv07_dStage;29272928struct ZSTDv07_DCtx_s2929{2930FSEv07_DTable LLTable[FSEv07_DTABLE_SIZE_U32(LLFSELog)];2931FSEv07_DTable OffTable[FSEv07_DTABLE_SIZE_U32(OffFSELog)];2932FSEv07_DTable MLTable[FSEv07_DTABLE_SIZE_U32(MLFSELog)];2933HUFv07_DTable hufTable[HUFv07_DTABLE_SIZE(HufLog)]; /* can accommodate HUFv07_decompress4X */2934const void* previousDstEnd;2935const void* base;2936const void* vBase;2937const void* dictEnd;2938size_t expected;2939U32 rep[3];2940ZSTDv07_frameParams fParams;2941blockType_t bType; /* used in ZSTDv07_decompressContinue(), to transfer blockType between header decoding and block decoding stages */2942ZSTDv07_dStage stage;2943U32 litEntropy;2944U32 fseEntropy;2945XXH64_state_t xxhState;2946size_t headerSize;2947U32 dictID;2948const BYTE* litPtr;2949ZSTDv07_customMem customMem;2950size_t litSize;2951BYTE litBuffer[ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];2952BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];2953}; /* typedef'd to ZSTDv07_DCtx within "zstd_static.h" */29542955int ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx);29562957size_t ZSTDv07_sizeofDCtx (const ZSTDv07_DCtx* dctx) { return sizeof(*dctx); }29582959size_t ZSTDv07_estimateDCtxSize(void) { return sizeof(ZSTDv07_DCtx); }29602961size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx)2962{2963dctx->expected = ZSTDv07_frameHeaderSize_min;2964dctx->stage = ZSTDds_getFrameHeaderSize;2965dctx->previousDstEnd = NULL;2966dctx->base = NULL;2967dctx->vBase = NULL;2968dctx->dictEnd = NULL;2969dctx->hufTable[0] = (HUFv07_DTable)((HufLog)*0x1000001);2970dctx->litEntropy = dctx->fseEntropy = 0;2971dctx->dictID = 0;2972{ int i; for (i=0; i<ZSTDv07_REP_NUM; i++) dctx->rep[i] = repStartValue[i]; }2973return 0;2974}29752976ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem)2977{2978ZSTDv07_DCtx* dctx;29792980if (!customMem.customAlloc && !customMem.customFree)2981customMem = defaultCustomMem;29822983if (!customMem.customAlloc || !customMem.customFree)2984return NULL;29852986dctx = (ZSTDv07_DCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTDv07_DCtx));2987if (!dctx) return NULL;2988memcpy(&dctx->customMem, &customMem, sizeof(ZSTDv07_customMem));2989ZSTDv07_decompressBegin(dctx);2990return dctx;2991}29922993ZSTDv07_DCtx* ZSTDv07_createDCtx(void)2994{2995return ZSTDv07_createDCtx_advanced(defaultCustomMem);2996}29972998size_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx)2999{3000if (dctx==NULL) return 0; /* support free on NULL */3001dctx->customMem.customFree(dctx->customMem.opaque, dctx);3002return 0; /* reserved as a potential error code in the future */3003}30043005void ZSTDv07_copyDCtx(ZSTDv07_DCtx* dstDCtx, const ZSTDv07_DCtx* srcDCtx)3006{3007memcpy(dstDCtx, srcDCtx,3008sizeof(ZSTDv07_DCtx) - (ZSTDv07_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH + ZSTDv07_frameHeaderSize_max)); /* no need to copy workspace */3009}301030113012/*-*************************************************************3013* Decompression section3014***************************************************************/30153016/* Frame format description3017Frame Header - [ Block Header - Block ] - Frame End30181) Frame Header3019- 4 bytes - Magic Number : ZSTDv07_MAGICNUMBER (defined within zstd.h)3020- 1 byte - Frame Descriptor30212) Block Header3022- 3 bytes, starting with a 2-bits descriptor3023Uncompressed, Compressed, Frame End, unused30243) Block3025See Block Format Description30264) Frame End3027- 3 bytes, compatible with Block Header3028*/302930303031/* Frame Header :303230331 byte - FrameHeaderDescription :3034bit 0-1 : dictID (0, 1, 2 or 4 bytes)3035bit 2 : checksumFlag3036bit 3 : reserved (must be zero)3037bit 4 : reserved (unused, can be any value)3038bit 5 : Single Segment (if 1, WindowLog byte is not present)3039bit 6-7 : FrameContentFieldSize (0, 2, 4, or 8)3040if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1;30413042Optional : WindowLog (0 or 1 byte)3043bit 0-2 : octal Fractional (1/8th)3044bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB)30453046Optional : dictID (0, 1, 2 or 4 bytes)3047Automatic adaptation30480 : no dictID30491 : 1 - 25530502 : 256 - 6553530514 : all other values30523053Optional : content size (0, 1, 2, 4 or 8 bytes)30540 : unknown (fcfs==0 and swl==0)30551 : 0-255 bytes (fcfs==0 and swl==1)30562 : 256 - 65535+256 (fcfs==1)30574 : 0 - 4GB-1 (fcfs==2)30588 : 0 - 16EB-1 (fcfs==3)3059*/306030613062/* Compressed Block, format description30633064Block = Literal Section - Sequences Section3065Prerequisite : size of (compressed) block, maximum size of regenerated data306630671) Literal Section306830691.1) Header : 1-5 bytes3070flags: 2 bits307100 compressed by Huff0307201 unused307310 is Raw (uncompressed)307411 is Rle3075Note : using 01 => Huff0 with precomputed table ?3076Note : delta map ? => compressed ?307730781.1.1) Huff0-compressed literal block : 3-5 bytes3079srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream3080srcSize < 1 KB => 3 bytes (2-2-10-10)3081srcSize < 16KB => 4 bytes (2-2-14-14)3082else => 5 bytes (2-2-18-18)3083big endian convention308430851.1.2) Raw (uncompressed) literal block header : 1-3 bytes3086size : 5 bits: (IS_RAW<<6) + (0<<4) + size308712 bits: (IS_RAW<<6) + (2<<4) + (size>>8)3088size&255308920 bits: (IS_RAW<<6) + (3<<4) + (size>>16)3090size>>8&2553091size&255309230931.1.3) Rle (repeated single byte) literal block header : 1-3 bytes3094size : 5 bits: (IS_RLE<<6) + (0<<4) + size309512 bits: (IS_RLE<<6) + (2<<4) + (size>>8)3096size&255309720 bits: (IS_RLE<<6) + (3<<4) + (size>>16)3098size>>8&2553099size&255310031011.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes3102srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream3103srcSize < 1 KB => 3 bytes (2-2-10-10)3104srcSize < 16KB => 4 bytes (2-2-14-14)3105else => 5 bytes (2-2-18-18)3106big endian convention310731081- CTable available (stored into workspace ?)31092- Small input (fast heuristic ? Full comparison ? depend on clevel ?)3110311131121.2) Literal block content311331141.2.1) Huff0 block, using sizes from header3115See Huff0 format311631171.2.2) Huff0 block, using prepared table311831191.2.3) Raw content312031211.2.4) single byte3122312331242) Sequences section3125TO DO3126*/31273128/** ZSTDv07_frameHeaderSize() :3129* srcSize must be >= ZSTDv07_frameHeaderSize_min.3130* @return : size of the Frame Header */3131static size_t ZSTDv07_frameHeaderSize(const void* src, size_t srcSize)3132{3133if (srcSize < ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);3134{ BYTE const fhd = ((const BYTE*)src)[4];3135U32 const dictID= fhd & 3;3136U32 const directMode = (fhd >> 5) & 1;3137U32 const fcsId = fhd >> 6;3138return ZSTDv07_frameHeaderSize_min + !directMode + ZSTDv07_did_fieldSize[dictID] + ZSTDv07_fcs_fieldSize[fcsId]3139+ (directMode && !ZSTDv07_fcs_fieldSize[fcsId]);3140}3141}314231433144/** ZSTDv07_getFrameParams() :3145* decode Frame Header, or require larger `srcSize`.3146* @return : 0, `fparamsPtr` is correctly filled,3147* >0, `srcSize` is too small, result is expected `srcSize`,3148* or an error code, which can be tested using ZSTDv07_isError() */3149size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize)3150{3151const BYTE* ip = (const BYTE*)src;31523153if (srcSize < ZSTDv07_frameHeaderSize_min) return ZSTDv07_frameHeaderSize_min;3154memset(fparamsPtr, 0, sizeof(*fparamsPtr));3155if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {3156if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {3157if (srcSize < ZSTDv07_skippableHeaderSize) return ZSTDv07_skippableHeaderSize; /* magic number + skippable frame length */3158fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4);3159fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */3160return 0;3161}3162return ERROR(prefix_unknown);3163}31643165/* ensure there is enough `srcSize` to fully read/decode frame header */3166{ size_t const fhsize = ZSTDv07_frameHeaderSize(src, srcSize);3167if (srcSize < fhsize) return fhsize; }31683169{ BYTE const fhdByte = ip[4];3170size_t pos = 5;3171U32 const dictIDSizeCode = fhdByte&3;3172U32 const checksumFlag = (fhdByte>>2)&1;3173U32 const directMode = (fhdByte>>5)&1;3174U32 const fcsID = fhdByte>>6;3175U32 const windowSizeMax = 1U << ZSTDv07_WINDOWLOG_MAX;3176U32 windowSize = 0;3177U32 dictID = 0;3178U64 frameContentSize = 0;3179if ((fhdByte & 0x08) != 0) /* reserved bits, which must be zero */3180return ERROR(frameParameter_unsupported);3181if (!directMode) {3182BYTE const wlByte = ip[pos++];3183U32 const windowLog = (wlByte >> 3) + ZSTDv07_WINDOWLOG_ABSOLUTEMIN;3184if (windowLog > ZSTDv07_WINDOWLOG_MAX)3185return ERROR(frameParameter_unsupported);3186windowSize = (1U << windowLog);3187windowSize += (windowSize >> 3) * (wlByte&7);3188}31893190switch(dictIDSizeCode)3191{3192default: /* impossible */3193case 0 : break;3194case 1 : dictID = ip[pos]; pos++; break;3195case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;3196case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;3197}3198switch(fcsID)3199{3200default: /* impossible */3201case 0 : if (directMode) frameContentSize = ip[pos]; break;3202case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;3203case 2 : frameContentSize = MEM_readLE32(ip+pos); break;3204case 3 : frameContentSize = MEM_readLE64(ip+pos); break;3205}3206if (!windowSize) windowSize = (U32)frameContentSize;3207if (windowSize > windowSizeMax)3208return ERROR(frameParameter_unsupported);3209fparamsPtr->frameContentSize = frameContentSize;3210fparamsPtr->windowSize = windowSize;3211fparamsPtr->dictID = dictID;3212fparamsPtr->checksumFlag = checksumFlag;3213}3214return 0;3215}321632173218/** ZSTDv07_getDecompressedSize() :3219* compatible with legacy mode3220* @return : decompressed size if known, 0 otherwise3221note : 0 can mean any of the following :3222- decompressed size is not provided within frame header3223- frame header unknown / not supported3224- frame header not completely provided (`srcSize` too small) */3225unsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize)3226{3227ZSTDv07_frameParams fparams;3228size_t const frResult = ZSTDv07_getFrameParams(&fparams, src, srcSize);3229if (frResult!=0) return 0;3230return fparams.frameContentSize;3231}323232333234/** ZSTDv07_decodeFrameHeader() :3235* `srcSize` must be the size provided by ZSTDv07_frameHeaderSize().3236* @return : 0 if success, or an error code, which can be tested using ZSTDv07_isError() */3237static size_t ZSTDv07_decodeFrameHeader(ZSTDv07_DCtx* dctx, const void* src, size_t srcSize)3238{3239size_t const result = ZSTDv07_getFrameParams(&(dctx->fParams), src, srcSize);3240if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong);3241if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);3242return result;3243}324432453246typedef struct3247{3248blockType_t blockType;3249U32 origSize;3250} blockProperties_t;32513252/*! ZSTDv07_getcBlockSize() :3253* Provides the size of compressed block from block header `src` */3254static size_t ZSTDv07_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)3255{3256const BYTE* const in = (const BYTE*)src;3257U32 cSize;32583259if (srcSize < ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);32603261bpPtr->blockType = (blockType_t)((*in) >> 6);3262cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);3263bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;32643265if (bpPtr->blockType == bt_end) return 0;3266if (bpPtr->blockType == bt_rle) return 1;3267return cSize;3268}326932703271static size_t ZSTDv07_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)3272{3273if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);3274if (srcSize > 0) {3275memcpy(dst, src, srcSize);3276}3277return srcSize;3278}327932803281/*! ZSTDv07_decodeLiteralsBlock() :3282@return : nb of bytes read from src (< srcSize ) */3283static size_t ZSTDv07_decodeLiteralsBlock(ZSTDv07_DCtx* dctx,3284const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */3285{3286const BYTE* const istart = (const BYTE*) src;32873288if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);32893290switch((litBlockType_t)(istart[0]>> 6))3291{3292case lbt_huffman:3293{ size_t litSize, litCSize, singleStream=0;3294U32 lhSize = (istart[0] >> 4) & 3;3295if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */3296switch(lhSize)3297{3298case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */3299/* 2 - 2 - 10 - 10 */3300lhSize=3;3301singleStream = istart[0] & 16;3302litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);3303litCSize = ((istart[1] & 3) << 8) + istart[2];3304break;3305case 2:3306/* 2 - 2 - 14 - 14 */3307lhSize=4;3308litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);3309litCSize = ((istart[2] & 63) << 8) + istart[3];3310break;3311case 3:3312/* 2 - 2 - 18 - 18 */3313lhSize=5;3314litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);3315litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];3316break;3317}3318if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);3319if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);33203321if (HUFv07_isError(singleStream ?3322HUFv07_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :3323HUFv07_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) ))3324return ERROR(corruption_detected);33253326dctx->litPtr = dctx->litBuffer;3327dctx->litSize = litSize;3328dctx->litEntropy = 1;3329memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);3330return litCSize + lhSize;3331}3332case lbt_repeat:3333{ size_t litSize, litCSize;3334U32 lhSize = ((istart[0]) >> 4) & 3;3335if (lhSize != 1) /* only case supported for now : small litSize, single stream */3336return ERROR(corruption_detected);3337if (dctx->litEntropy==0)3338return ERROR(dictionary_corrupted);33393340/* 2 - 2 - 10 - 10 */3341lhSize=3;3342litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);3343litCSize = ((istart[1] & 3) << 8) + istart[2];3344if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);33453346{ size_t const errorCode = HUFv07_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable);3347if (HUFv07_isError(errorCode)) return ERROR(corruption_detected);3348}3349dctx->litPtr = dctx->litBuffer;3350dctx->litSize = litSize;3351memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);3352return litCSize + lhSize;3353}3354case lbt_raw:3355{ size_t litSize;3356U32 lhSize = ((istart[0]) >> 4) & 3;3357switch(lhSize)3358{3359case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */3360lhSize=1;3361litSize = istart[0] & 31;3362break;3363case 2:3364litSize = ((istart[0] & 15) << 8) + istart[1];3365break;3366case 3:3367litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];3368break;3369}33703371if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */3372if (litSize+lhSize > srcSize) return ERROR(corruption_detected);3373memcpy(dctx->litBuffer, istart+lhSize, litSize);3374dctx->litPtr = dctx->litBuffer;3375dctx->litSize = litSize;3376memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);3377return lhSize+litSize;3378}3379/* direct reference into compressed stream */3380dctx->litPtr = istart+lhSize;3381dctx->litSize = litSize;3382return lhSize+litSize;3383}3384case lbt_rle:3385{ size_t litSize;3386U32 lhSize = ((istart[0]) >> 4) & 3;3387switch(lhSize)3388{3389case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */3390lhSize = 1;3391litSize = istart[0] & 31;3392break;3393case 2:3394litSize = ((istart[0] & 15) << 8) + istart[1];3395break;3396case 3:3397litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];3398if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */3399break;3400}3401if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);3402memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);3403dctx->litPtr = dctx->litBuffer;3404dctx->litSize = litSize;3405return lhSize+1;3406}3407default:3408return ERROR(corruption_detected); /* impossible */3409}3410}341134123413/*! ZSTDv07_buildSeqTable() :3414@return : nb bytes read from src,3415or an error code if it fails, testable with ZSTDv07_isError()3416*/3417static size_t ZSTDv07_buildSeqTable(FSEv07_DTable* DTable, U32 type, U32 max, U32 maxLog,3418const void* src, size_t srcSize,3419const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)3420{3421switch(type)3422{3423case FSEv07_ENCODING_RLE :3424if (!srcSize) return ERROR(srcSize_wrong);3425if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);3426FSEv07_buildDTable_rle(DTable, *(const BYTE*)src); /* if *src > max, data is corrupted */3427return 1;3428case FSEv07_ENCODING_RAW :3429FSEv07_buildDTable(DTable, defaultNorm, max, defaultLog);3430return 0;3431case FSEv07_ENCODING_STATIC:3432if (!flagRepeatTable) return ERROR(corruption_detected);3433return 0;3434default : /* impossible */3435case FSEv07_ENCODING_DYNAMIC :3436{ U32 tableLog;3437S16 norm[MaxSeq+1];3438size_t const headerSize = FSEv07_readNCount(norm, &max, &tableLog, src, srcSize);3439if (FSEv07_isError(headerSize)) return ERROR(corruption_detected);3440if (tableLog > maxLog) return ERROR(corruption_detected);3441FSEv07_buildDTable(DTable, norm, max, tableLog);3442return headerSize;3443} }3444}344534463447static size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,3448FSEv07_DTable* DTableLL, FSEv07_DTable* DTableML, FSEv07_DTable* DTableOffb, U32 flagRepeatTable,3449const void* src, size_t srcSize)3450{3451const BYTE* const istart = (const BYTE*)src;3452const BYTE* const iend = istart + srcSize;3453const BYTE* ip = istart;34543455/* check */3456if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);34573458/* SeqHead */3459{ int nbSeq = *ip++;3460if (!nbSeq) { *nbSeqPtr=0; return 1; }3461if (nbSeq > 0x7F) {3462if (nbSeq == 0xFF) {3463if (ip+2 > iend) return ERROR(srcSize_wrong);3464nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;3465} else {3466if (ip >= iend) return ERROR(srcSize_wrong);3467nbSeq = ((nbSeq-0x80)<<8) + *ip++;3468}3469}3470*nbSeqPtr = nbSeq;3471}34723473/* FSE table descriptors */3474if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are "raw", hence no header, but at least xxLog bits per type */3475{ U32 const LLtype = *ip >> 6;3476U32 const OFtype = (*ip >> 4) & 3;3477U32 const MLtype = (*ip >> 2) & 3;3478ip++;34793480/* Build DTables */3481{ size_t const llhSize = ZSTDv07_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);3482if (ZSTDv07_isError(llhSize)) return ERROR(corruption_detected);3483ip += llhSize;3484}3485{ size_t const ofhSize = ZSTDv07_buildSeqTable(DTableOffb, OFtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);3486if (ZSTDv07_isError(ofhSize)) return ERROR(corruption_detected);3487ip += ofhSize;3488}3489{ size_t const mlhSize = ZSTDv07_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);3490if (ZSTDv07_isError(mlhSize)) return ERROR(corruption_detected);3491ip += mlhSize;3492} }34933494return ip-istart;3495}349634973498typedef struct {3499size_t litLength;3500size_t matchLength;3501size_t offset;3502} seq_t;35033504typedef struct {3505BITv07_DStream_t DStream;3506FSEv07_DState_t stateLL;3507FSEv07_DState_t stateOffb;3508FSEv07_DState_t stateML;3509size_t prevOffset[ZSTDv07_REP_INIT];3510} seqState_t;351135123513static seq_t ZSTDv07_decodeSequence(seqState_t* seqState)3514{3515seq_t seq;35163517U32 const llCode = FSEv07_peekSymbol(&(seqState->stateLL));3518U32 const mlCode = FSEv07_peekSymbol(&(seqState->stateML));3519U32 const ofCode = FSEv07_peekSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */35203521U32 const llBits = LL_bits[llCode];3522U32 const mlBits = ML_bits[mlCode];3523U32 const ofBits = ofCode;3524U32 const totalBits = llBits+mlBits+ofBits;35253526static const U32 LL_base[MaxLL+1] = {35270, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,352816, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,35290x2000, 0x4000, 0x8000, 0x10000 };35303531static const U32 ML_base[MaxML+1] = {35323, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,353319, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,353435, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,35350x1003, 0x2003, 0x4003, 0x8003, 0x10003 };35363537static const U32 OF_base[MaxOff+1] = {35380, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,35390xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,35400xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,35410xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };35423543/* sequence */3544{ size_t offset;3545if (!ofCode)3546offset = 0;3547else {3548offset = OF_base[ofCode] + BITv07_readBits(&(seqState->DStream), ofBits); /* <= (ZSTDv07_WINDOWLOG_MAX-1) bits */3549if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));3550}35513552if (ofCode <= 1) {3553if ((llCode == 0) & (offset <= 1)) offset = 1-offset;3554if (offset) {3555size_t const temp = seqState->prevOffset[offset];3556if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];3557seqState->prevOffset[1] = seqState->prevOffset[0];3558seqState->prevOffset[0] = offset = temp;3559} else {3560offset = seqState->prevOffset[0];3561}3562} else {3563seqState->prevOffset[2] = seqState->prevOffset[1];3564seqState->prevOffset[1] = seqState->prevOffset[0];3565seqState->prevOffset[0] = offset;3566}3567seq.offset = offset;3568}35693570seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BITv07_readBits(&(seqState->DStream), mlBits) : 0); /* <= 16 bits */3571if (MEM_32bits() && (mlBits+llBits>24)) BITv07_reloadDStream(&(seqState->DStream));35723573seq.litLength = LL_base[llCode] + ((llCode>15) ? BITv07_readBits(&(seqState->DStream), llBits) : 0); /* <= 16 bits */3574if (MEM_32bits() ||3575(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv07_reloadDStream(&(seqState->DStream));35763577/* ANS state update */3578FSEv07_updateState(&(seqState->stateLL), &(seqState->DStream)); /* <= 9 bits */3579FSEv07_updateState(&(seqState->stateML), &(seqState->DStream)); /* <= 9 bits */3580if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream)); /* <= 18 bits */3581FSEv07_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <= 8 bits */35823583return seq;3584}358535863587static3588size_t ZSTDv07_execSequence(BYTE* op,3589BYTE* const oend, seq_t sequence,3590const BYTE** litPtr, const BYTE* const litLimit,3591const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)3592{3593BYTE* const oLitEnd = op + sequence.litLength;3594size_t const sequenceLength = sequence.litLength + sequence.matchLength;3595BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */3596BYTE* const oend_w = oend-WILDCOPY_OVERLENGTH;3597const BYTE* const iLitEnd = *litPtr + sequence.litLength;3598const BYTE* match = oLitEnd - sequence.offset;35993600/* check */3601if ((oLitEnd>oend_w) | (oMatchEnd>oend)) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */3602if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */36033604/* copy Literals */3605ZSTDv07_wildcopy(op, *litPtr, sequence.litLength); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */3606op = oLitEnd;3607*litPtr = iLitEnd; /* update for next sequence */36083609/* copy Match */3610if (sequence.offset > (size_t)(oLitEnd - base)) {3611/* offset beyond prefix */3612if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);3613match = dictEnd - (base-match);3614if (match + sequence.matchLength <= dictEnd) {3615memmove(oLitEnd, match, sequence.matchLength);3616return sequenceLength;3617}3618/* span extDict & currentPrefixSegment */3619{ size_t const length1 = dictEnd - match;3620memmove(oLitEnd, match, length1);3621op = oLitEnd + length1;3622sequence.matchLength -= length1;3623match = base;3624if (op > oend_w || sequence.matchLength < MINMATCH) {3625while (op < oMatchEnd) *op++ = *match++;3626return sequenceLength;3627}3628} }3629/* Requirement: op <= oend_w */36303631/* match within prefix */3632if (sequence.offset < 8) {3633/* close range match, overlap */3634static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */3635static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */3636int const sub2 = dec64table[sequence.offset];3637op[0] = match[0];3638op[1] = match[1];3639op[2] = match[2];3640op[3] = match[3];3641match += dec32table[sequence.offset];3642ZSTDv07_copy4(op+4, match);3643match -= sub2;3644} else {3645ZSTDv07_copy8(op, match);3646}3647op += 8; match += 8;36483649if (oMatchEnd > oend-(16-MINMATCH)) {3650if (op < oend_w) {3651ZSTDv07_wildcopy(op, match, oend_w - op);3652match += oend_w - op;3653op = oend_w;3654}3655while (op < oMatchEnd) *op++ = *match++;3656} else {3657ZSTDv07_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */3658}3659return sequenceLength;3660}366136623663static size_t ZSTDv07_decompressSequences(3664ZSTDv07_DCtx* dctx,3665void* dst, size_t maxDstSize,3666const void* seqStart, size_t seqSize)3667{3668const BYTE* ip = (const BYTE*)seqStart;3669const BYTE* const iend = ip + seqSize;3670BYTE* const ostart = (BYTE*)dst;3671BYTE* const oend = ostart + maxDstSize;3672BYTE* op = ostart;3673const BYTE* litPtr = dctx->litPtr;3674const BYTE* const litEnd = litPtr + dctx->litSize;3675FSEv07_DTable* DTableLL = dctx->LLTable;3676FSEv07_DTable* DTableML = dctx->MLTable;3677FSEv07_DTable* DTableOffb = dctx->OffTable;3678const BYTE* const base = (const BYTE*) (dctx->base);3679const BYTE* const vBase = (const BYTE*) (dctx->vBase);3680const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);3681int nbSeq;36823683/* Build Decoding Tables */3684{ size_t const seqHSize = ZSTDv07_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->fseEntropy, ip, seqSize);3685if (ZSTDv07_isError(seqHSize)) return seqHSize;3686ip += seqHSize;3687}36883689/* Regen sequences */3690if (nbSeq) {3691seqState_t seqState;3692dctx->fseEntropy = 1;3693{ U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) seqState.prevOffset[i] = dctx->rep[i]; }3694{ size_t const errorCode = BITv07_initDStream(&(seqState.DStream), ip, iend-ip);3695if (ERR_isError(errorCode)) return ERROR(corruption_detected); }3696FSEv07_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);3697FSEv07_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);3698FSEv07_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);36993700for ( ; (BITv07_reloadDStream(&(seqState.DStream)) <= BITv07_DStream_completed) && nbSeq ; ) {3701nbSeq--;3702{ seq_t const sequence = ZSTDv07_decodeSequence(&seqState);3703size_t const oneSeqSize = ZSTDv07_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);3704if (ZSTDv07_isError(oneSeqSize)) return oneSeqSize;3705op += oneSeqSize;3706} }37073708/* check if reached exact end */3709if (nbSeq) return ERROR(corruption_detected);3710/* save reps for next block */3711{ U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }3712}37133714/* last literal segment */3715{ size_t const lastLLSize = litEnd - litPtr;3716/* if (litPtr > litEnd) return ERROR(corruption_detected); */ /* too many literals already used */3717if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);3718if (lastLLSize > 0) {3719memcpy(op, litPtr, lastLLSize);3720op += lastLLSize;3721}3722}37233724return op-ostart;3725}372637273728static void ZSTDv07_checkContinuity(ZSTDv07_DCtx* dctx, const void* dst)3729{3730if (dst != dctx->previousDstEnd) { /* not contiguous */3731dctx->dictEnd = dctx->previousDstEnd;3732dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));3733dctx->base = dst;3734dctx->previousDstEnd = dst;3735}3736}373737383739static size_t ZSTDv07_decompressBlock_internal(ZSTDv07_DCtx* dctx,3740void* dst, size_t dstCapacity,3741const void* src, size_t srcSize)3742{ /* blockType == blockCompressed */3743const BYTE* ip = (const BYTE*)src;37443745if (srcSize >= ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);37463747/* Decode literals sub-block */3748{ size_t const litCSize = ZSTDv07_decodeLiteralsBlock(dctx, src, srcSize);3749if (ZSTDv07_isError(litCSize)) return litCSize;3750ip += litCSize;3751srcSize -= litCSize;3752}3753return ZSTDv07_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);3754}375537563757size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx,3758void* dst, size_t dstCapacity,3759const void* src, size_t srcSize)3760{3761size_t dSize;3762ZSTDv07_checkContinuity(dctx, dst);3763dSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);3764dctx->previousDstEnd = (char*)dst + dSize;3765return dSize;3766}376737683769/** ZSTDv07_insertBlock() :3770insert `src` block into `dctx` history. Useful to track uncompressed blocks. */3771ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)3772{3773ZSTDv07_checkContinuity(dctx, blockStart);3774dctx->previousDstEnd = (const char*)blockStart + blockSize;3775return blockSize;3776}377737783779static size_t ZSTDv07_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)3780{3781if (length > dstCapacity) return ERROR(dstSize_tooSmall);3782if (length > 0) {3783memset(dst, byte, length);3784}3785return length;3786}378737883789/*! ZSTDv07_decompressFrame() :3790* `dctx` must be properly initialized */3791static size_t ZSTDv07_decompressFrame(ZSTDv07_DCtx* dctx,3792void* dst, size_t dstCapacity,3793const void* src, size_t srcSize)3794{3795const BYTE* ip = (const BYTE*)src;3796const BYTE* const iend = ip + srcSize;3797BYTE* const ostart = (BYTE*)dst;3798BYTE* const oend = ostart + dstCapacity;3799BYTE* op = ostart;3800size_t remainingSize = srcSize;38013802/* check */3803if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);38043805/* Frame Header */3806{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);3807if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;3808if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);3809if (ZSTDv07_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);3810ip += frameHeaderSize; remainingSize -= frameHeaderSize;3811}38123813/* Loop on each block */3814while (1) {3815size_t decodedSize;3816blockProperties_t blockProperties;3817size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, iend-ip, &blockProperties);3818if (ZSTDv07_isError(cBlockSize)) return cBlockSize;38193820ip += ZSTDv07_blockHeaderSize;3821remainingSize -= ZSTDv07_blockHeaderSize;3822if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);38233824switch(blockProperties.blockType)3825{3826case bt_compressed:3827decodedSize = ZSTDv07_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);3828break;3829case bt_raw :3830decodedSize = ZSTDv07_copyRawBlock(op, oend-op, ip, cBlockSize);3831break;3832case bt_rle :3833decodedSize = ZSTDv07_generateNxBytes(op, oend-op, *ip, blockProperties.origSize);3834break;3835case bt_end :3836/* end of frame */3837if (remainingSize) return ERROR(srcSize_wrong);3838decodedSize = 0;3839break;3840default:3841return ERROR(GENERIC); /* impossible */3842}3843if (blockProperties.blockType == bt_end) break; /* bt_end */38443845if (ZSTDv07_isError(decodedSize)) return decodedSize;3846if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize);3847op += decodedSize;3848ip += cBlockSize;3849remainingSize -= cBlockSize;3850}38513852return op-ostart;3853}385438553856/*! ZSTDv07_decompress_usingPreparedDCtx() :3857* Same as ZSTDv07_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.3858* It avoids reloading the dictionary each time.3859* `preparedDCtx` must have been properly initialized using ZSTDv07_decompressBegin_usingDict().3860* Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */3861static size_t ZSTDv07_decompress_usingPreparedDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* refDCtx,3862void* dst, size_t dstCapacity,3863const void* src, size_t srcSize)3864{3865ZSTDv07_copyDCtx(dctx, refDCtx);3866ZSTDv07_checkContinuity(dctx, dst);3867return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);3868}386938703871size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,3872void* dst, size_t dstCapacity,3873const void* src, size_t srcSize,3874const void* dict, size_t dictSize)3875{3876ZSTDv07_decompressBegin_usingDict(dctx, dict, dictSize);3877ZSTDv07_checkContinuity(dctx, dst);3878return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);3879}388038813882size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)3883{3884return ZSTDv07_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);3885}388638873888size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)3889{3890#if defined(ZSTDv07_HEAPMODE) && (ZSTDv07_HEAPMODE==1)3891size_t regenSize;3892ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx();3893if (dctx==NULL) return ERROR(memory_allocation);3894regenSize = ZSTDv07_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);3895ZSTDv07_freeDCtx(dctx);3896return regenSize;3897#else /* stack mode */3898ZSTDv07_DCtx dctx;3899return ZSTDv07_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);3900#endif3901}39023903/* ZSTD_errorFrameSizeInfoLegacy() :3904assumes `cSize` and `dBound` are _not_ NULL */3905static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)3906{3907*cSize = ret;3908*dBound = ZSTD_CONTENTSIZE_ERROR;3909}39103911void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)3912{3913const BYTE* ip = (const BYTE*)src;3914size_t remainingSize = srcSize;3915size_t nbBlocks = 0;39163917/* check */3918if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {3919ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3920return;3921}39223923/* Frame Header */3924{ size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, srcSize);3925if (ZSTDv07_isError(frameHeaderSize)) {3926ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);3927return;3928}3929if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {3930ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));3931return;3932}3933if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {3934ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3935return;3936}3937ip += frameHeaderSize; remainingSize -= frameHeaderSize;3938}39393940/* Loop on each block */3941while (1) {3942blockProperties_t blockProperties;3943size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);3944if (ZSTDv07_isError(cBlockSize)) {3945ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);3946return;3947}39483949ip += ZSTDv07_blockHeaderSize;3950remainingSize -= ZSTDv07_blockHeaderSize;39513952if (blockProperties.blockType == bt_end) break;39533954if (cBlockSize > remainingSize) {3955ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));3956return;3957}39583959ip += cBlockSize;3960remainingSize -= cBlockSize;3961nbBlocks++;3962}39633964*cSize = ip - (const BYTE*)src;3965*dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;3966}39673968/*_******************************3969* Streaming Decompression API3970********************************/3971size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx)3972{3973return dctx->expected;3974}39753976int ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx)3977{3978return dctx->stage == ZSTDds_skipFrame;3979}39803981/** ZSTDv07_decompressContinue() :3982* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)3983* or an error code, which can be tested using ZSTDv07_isError() */3984size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)3985{3986/* Sanity check */3987if (srcSize != dctx->expected) return ERROR(srcSize_wrong);3988if (dstCapacity) ZSTDv07_checkContinuity(dctx, dst);39893990switch (dctx->stage)3991{3992case ZSTDds_getFrameHeaderSize :3993if (srcSize != ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */3994if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {3995memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);3996dctx->expected = ZSTDv07_skippableHeaderSize - ZSTDv07_frameHeaderSize_min; /* magic number + skippable frame length */3997dctx->stage = ZSTDds_decodeSkippableHeader;3998return 0;3999}4000dctx->headerSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);4001if (ZSTDv07_isError(dctx->headerSize)) return dctx->headerSize;4002memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);4003if (dctx->headerSize > ZSTDv07_frameHeaderSize_min) {4004dctx->expected = dctx->headerSize - ZSTDv07_frameHeaderSize_min;4005dctx->stage = ZSTDds_decodeFrameHeader;4006return 0;4007}4008dctx->expected = 0; /* not necessary to copy more */4009/* fall-through */4010case ZSTDds_decodeFrameHeader:4011{ size_t result;4012memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);4013result = ZSTDv07_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);4014if (ZSTDv07_isError(result)) return result;4015dctx->expected = ZSTDv07_blockHeaderSize;4016dctx->stage = ZSTDds_decodeBlockHeader;4017return 0;4018}4019case ZSTDds_decodeBlockHeader:4020{ blockProperties_t bp;4021size_t const cBlockSize = ZSTDv07_getcBlockSize(src, ZSTDv07_blockHeaderSize, &bp);4022if (ZSTDv07_isError(cBlockSize)) return cBlockSize;4023if (bp.blockType == bt_end) {4024if (dctx->fParams.checksumFlag) {4025U64 const h64 = XXH64_digest(&dctx->xxhState);4026U32 const h32 = (U32)(h64>>11) & ((1<<22)-1);4027const BYTE* const ip = (const BYTE*)src;4028U32 const check32 = ip[2] + (ip[1] << 8) + ((ip[0] & 0x3F) << 16);4029if (check32 != h32) return ERROR(checksum_wrong);4030}4031dctx->expected = 0;4032dctx->stage = ZSTDds_getFrameHeaderSize;4033} else {4034dctx->expected = cBlockSize;4035dctx->bType = bp.blockType;4036dctx->stage = ZSTDds_decompressBlock;4037}4038return 0;4039}4040case ZSTDds_decompressBlock:4041{ size_t rSize;4042switch(dctx->bType)4043{4044case bt_compressed:4045rSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);4046break;4047case bt_raw :4048rSize = ZSTDv07_copyRawBlock(dst, dstCapacity, src, srcSize);4049break;4050case bt_rle :4051return ERROR(GENERIC); /* not yet handled */4052break;4053case bt_end : /* should never happen (filtered at phase 1) */4054rSize = 0;4055break;4056default:4057return ERROR(GENERIC); /* impossible */4058}4059dctx->stage = ZSTDds_decodeBlockHeader;4060dctx->expected = ZSTDv07_blockHeaderSize;4061dctx->previousDstEnd = (char*)dst + rSize;4062if (ZSTDv07_isError(rSize)) return rSize;4063if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);4064return rSize;4065}4066case ZSTDds_decodeSkippableHeader:4067{ memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);4068dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);4069dctx->stage = ZSTDds_skipFrame;4070return 0;4071}4072case ZSTDds_skipFrame:4073{ dctx->expected = 0;4074dctx->stage = ZSTDds_getFrameHeaderSize;4075return 0;4076}4077default:4078return ERROR(GENERIC); /* impossible */4079}4080}408140824083static size_t ZSTDv07_refDictContent(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)4084{4085dctx->dictEnd = dctx->previousDstEnd;4086dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));4087dctx->base = dict;4088dctx->previousDstEnd = (const char*)dict + dictSize;4089return 0;4090}40914092static size_t ZSTDv07_loadEntropy(ZSTDv07_DCtx* dctx, const void* const dict, size_t const dictSize)4093{4094const BYTE* dictPtr = (const BYTE*)dict;4095const BYTE* const dictEnd = dictPtr + dictSize;40964097{ size_t const hSize = HUFv07_readDTableX4(dctx->hufTable, dict, dictSize);4098if (HUFv07_isError(hSize)) return ERROR(dictionary_corrupted);4099dictPtr += hSize;4100}41014102{ short offcodeNCount[MaxOff+1];4103U32 offcodeMaxValue=MaxOff, offcodeLog;4104size_t const offcodeHeaderSize = FSEv07_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);4105if (FSEv07_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);4106if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);4107{ size_t const errorCode = FSEv07_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);4108if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }4109dictPtr += offcodeHeaderSize;4110}41114112{ short matchlengthNCount[MaxML+1];4113unsigned matchlengthMaxValue = MaxML, matchlengthLog;4114size_t const matchlengthHeaderSize = FSEv07_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);4115if (FSEv07_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);4116if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);4117{ size_t const errorCode = FSEv07_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);4118if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }4119dictPtr += matchlengthHeaderSize;4120}41214122{ short litlengthNCount[MaxLL+1];4123unsigned litlengthMaxValue = MaxLL, litlengthLog;4124size_t const litlengthHeaderSize = FSEv07_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);4125if (FSEv07_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);4126if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);4127{ size_t const errorCode = FSEv07_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);4128if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }4129dictPtr += litlengthHeaderSize;4130}41314132if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);4133dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);4134dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);4135dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);4136dictPtr += 12;41374138dctx->litEntropy = dctx->fseEntropy = 1;4139return dictPtr - (const BYTE*)dict;4140}41414142static size_t ZSTDv07_decompress_insertDictionary(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)4143{4144if (dictSize < 8) return ZSTDv07_refDictContent(dctx, dict, dictSize);4145{ U32 const magic = MEM_readLE32(dict);4146if (magic != ZSTDv07_DICT_MAGIC) {4147return ZSTDv07_refDictContent(dctx, dict, dictSize); /* pure content mode */4148} }4149dctx->dictID = MEM_readLE32((const char*)dict + 4);41504151/* load entropy tables */4152dict = (const char*)dict + 8;4153dictSize -= 8;4154{ size_t const eSize = ZSTDv07_loadEntropy(dctx, dict, dictSize);4155if (ZSTDv07_isError(eSize)) return ERROR(dictionary_corrupted);4156dict = (const char*)dict + eSize;4157dictSize -= eSize;4158}41594160/* reference dictionary content */4161return ZSTDv07_refDictContent(dctx, dict, dictSize);4162}416341644165size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)4166{4167{ size_t const errorCode = ZSTDv07_decompressBegin(dctx);4168if (ZSTDv07_isError(errorCode)) return errorCode; }41694170if (dict && dictSize) {4171size_t const errorCode = ZSTDv07_decompress_insertDictionary(dctx, dict, dictSize);4172if (ZSTDv07_isError(errorCode)) return ERROR(dictionary_corrupted);4173}41744175return 0;4176}417741784179struct ZSTDv07_DDict_s {4180void* dict;4181size_t dictSize;4182ZSTDv07_DCtx* refContext;4183}; /* typedef'd tp ZSTDv07_CDict within zstd.h */41844185static ZSTDv07_DDict* ZSTDv07_createDDict_advanced(const void* dict, size_t dictSize, ZSTDv07_customMem customMem)4186{4187if (!customMem.customAlloc && !customMem.customFree)4188customMem = defaultCustomMem;41894190if (!customMem.customAlloc || !customMem.customFree)4191return NULL;41924193{ ZSTDv07_DDict* const ddict = (ZSTDv07_DDict*) customMem.customAlloc(customMem.opaque, sizeof(*ddict));4194void* const dictContent = customMem.customAlloc(customMem.opaque, dictSize);4195ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx_advanced(customMem);41964197if (!dictContent || !ddict || !dctx) {4198customMem.customFree(customMem.opaque, dictContent);4199customMem.customFree(customMem.opaque, ddict);4200customMem.customFree(customMem.opaque, dctx);4201return NULL;4202}42034204memcpy(dictContent, dict, dictSize);4205{ size_t const errorCode = ZSTDv07_decompressBegin_usingDict(dctx, dictContent, dictSize);4206if (ZSTDv07_isError(errorCode)) {4207customMem.customFree(customMem.opaque, dictContent);4208customMem.customFree(customMem.opaque, ddict);4209customMem.customFree(customMem.opaque, dctx);4210return NULL;4211} }42124213ddict->dict = dictContent;4214ddict->dictSize = dictSize;4215ddict->refContext = dctx;4216return ddict;4217}4218}42194220/*! ZSTDv07_createDDict() :4221* Create a digested dictionary, ready to start decompression without startup delay.4222* `dict` can be released after `ZSTDv07_DDict` creation */4223ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize)4224{4225ZSTDv07_customMem const allocator = { NULL, NULL, NULL };4226return ZSTDv07_createDDict_advanced(dict, dictSize, allocator);4227}42284229size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict)4230{4231ZSTDv07_freeFunction const cFree = ddict->refContext->customMem.customFree;4232void* const opaque = ddict->refContext->customMem.opaque;4233ZSTDv07_freeDCtx(ddict->refContext);4234cFree(opaque, ddict->dict);4235cFree(opaque, ddict);4236return 0;4237}42384239/*! ZSTDv07_decompress_usingDDict() :4240* Decompression using a pre-digested Dictionary4241* Use dictionary without significant overhead. */4242ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,4243void* dst, size_t dstCapacity,4244const void* src, size_t srcSize,4245const ZSTDv07_DDict* ddict)4246{4247return ZSTDv07_decompress_usingPreparedDCtx(dctx, ddict->refContext,4248dst, dstCapacity,4249src, srcSize);4250}4251/*4252Buffered version of Zstd compression library4253Copyright (C) 2015-2016, Yann Collet.42544255BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)42564257Redistribution and use in source and binary forms, with or without4258modification, are permitted provided that the following conditions are4259met:4260* Redistributions of source code must retain the above copyright4261notice, this list of conditions and the following disclaimer.4262* Redistributions in binary form must reproduce the above4263copyright notice, this list of conditions and the following disclaimer4264in the documentation and/or other materials provided with the4265distribution.4266THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS4267"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT4268LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR4269A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT4270OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,4271SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT4272LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,4273DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY4274THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT4275(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE4276OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.42774278You can contact the author at :4279- zstd homepage : http://www.zstd.net/4280*/4281428242834284/*-***************************************************************************4285* Streaming decompression howto4286*4287* A ZBUFFv07_DCtx object is required to track streaming operations.4288* Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.4289* Use ZBUFFv07_decompressInit() to start a new decompression operation,4290* or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.4291* Note that ZBUFFv07_DCtx objects can be re-init multiple times.4292*4293* Use ZBUFFv07_decompressContinue() repetitively to consume your input.4294* *srcSizePtr and *dstCapacityPtr can be any size.4295* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.4296* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.4297* The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.4298* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),4299* or 0 when a frame is completely decoded,4300* or an error code, which can be tested using ZBUFFv07_isError().4301*4302* Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()4303* output : ZBUFFv07_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.4304* input : ZBUFFv07_recommendedDInSize == 128KB + 3;4305* just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .4306* *******************************************************************************/43074308typedef enum { ZBUFFds_init, ZBUFFds_loadHeader,4309ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv07_dStage;43104311/* *** Resource management *** */4312struct ZBUFFv07_DCtx_s {4313ZSTDv07_DCtx* zd;4314ZSTDv07_frameParams fParams;4315ZBUFFv07_dStage stage;4316char* inBuff;4317size_t inBuffSize;4318size_t inPos;4319char* outBuff;4320size_t outBuffSize;4321size_t outStart;4322size_t outEnd;4323size_t blockSize;4324BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];4325size_t lhSize;4326ZSTDv07_customMem customMem;4327}; /* typedef'd to ZBUFFv07_DCtx within "zstd_buffered.h" */43284329ZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);43304331ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void)4332{4333return ZBUFFv07_createDCtx_advanced(defaultCustomMem);4334}43354336ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem)4337{4338ZBUFFv07_DCtx* zbd;43394340if (!customMem.customAlloc && !customMem.customFree)4341customMem = defaultCustomMem;43424343if (!customMem.customAlloc || !customMem.customFree)4344return NULL;43454346zbd = (ZBUFFv07_DCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFFv07_DCtx));4347if (zbd==NULL) return NULL;4348memset(zbd, 0, sizeof(ZBUFFv07_DCtx));4349memcpy(&zbd->customMem, &customMem, sizeof(ZSTDv07_customMem));4350zbd->zd = ZSTDv07_createDCtx_advanced(customMem);4351if (zbd->zd == NULL) { ZBUFFv07_freeDCtx(zbd); return NULL; }4352zbd->stage = ZBUFFds_init;4353return zbd;4354}43554356size_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* zbd)4357{4358if (zbd==NULL) return 0; /* support free on null */4359ZSTDv07_freeDCtx(zbd->zd);4360if (zbd->inBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);4361if (zbd->outBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);4362zbd->customMem.customFree(zbd->customMem.opaque, zbd);4363return 0;4364}436543664367/* *** Initialization *** */43684369size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* zbd, const void* dict, size_t dictSize)4370{4371zbd->stage = ZBUFFds_loadHeader;4372zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;4373return ZSTDv07_decompressBegin_usingDict(zbd->zd, dict, dictSize);4374}43754376size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* zbd)4377{4378return ZBUFFv07_decompressInitDictionary(zbd, NULL, 0);4379}438043814382/* internal util function */4383MEM_STATIC size_t ZBUFFv07_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)4384{4385size_t const length = MIN(dstCapacity, srcSize);4386if (length > 0) {4387memcpy(dst, src, length);4388}4389return length;4390}439143924393/* *** Decompression *** */43944395size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* zbd,4396void* dst, size_t* dstCapacityPtr,4397const void* src, size_t* srcSizePtr)4398{4399const char* const istart = (const char*)src;4400const char* const iend = istart + *srcSizePtr;4401const char* ip = istart;4402char* const ostart = (char*)dst;4403char* const oend = ostart + *dstCapacityPtr;4404char* op = ostart;4405U32 notDone = 1;44064407while (notDone) {4408switch(zbd->stage)4409{4410case ZBUFFds_init :4411return ERROR(init_missing);44124413case ZBUFFds_loadHeader :4414{ size_t const hSize = ZSTDv07_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);4415if (ZSTDv07_isError(hSize)) return hSize;4416if (hSize != 0) {4417size_t const toLoad = hSize - zbd->lhSize; /* if hSize!=0, hSize > zbd->lhSize */4418if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */4419memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);4420zbd->lhSize += iend-ip;4421*dstCapacityPtr = 0;4422return (hSize - zbd->lhSize) + ZSTDv07_blockHeaderSize; /* remaining header bytes + next block header */4423}4424memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;4425break;4426} }44274428/* Consume header */4429{ size_t const h1Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd); /* == ZSTDv07_frameHeaderSize_min */4430size_t const h1Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);4431if (ZSTDv07_isError(h1Result)) return h1Result;4432if (h1Size < zbd->lhSize) { /* long header */4433size_t const h2Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);4434size_t const h2Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);4435if (ZSTDv07_isError(h2Result)) return h2Result;4436} }44374438zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTDv07_WINDOWLOG_ABSOLUTEMIN);44394440/* Frame header instruct buffer sizes */4441{ size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTDv07_BLOCKSIZE_ABSOLUTEMAX);4442zbd->blockSize = blockSize;4443if (zbd->inBuffSize < blockSize) {4444zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);4445zbd->inBuffSize = blockSize;4446zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize);4447if (zbd->inBuff == NULL) return ERROR(memory_allocation);4448}4449{ size_t const neededOutSize = zbd->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;4450if (zbd->outBuffSize < neededOutSize) {4451zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);4452zbd->outBuffSize = neededOutSize;4453zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize);4454if (zbd->outBuff == NULL) return ERROR(memory_allocation);4455} } }4456zbd->stage = ZBUFFds_read;4457/* pass-through */4458/* fall-through */4459case ZBUFFds_read:4460{ size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);4461if (neededInSize==0) { /* end of frame */4462zbd->stage = ZBUFFds_init;4463notDone = 0;4464break;4465}4466if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */4467const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);4468size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,4469zbd->outBuff + zbd->outStart, (isSkipFrame ? 0 : zbd->outBuffSize - zbd->outStart),4470ip, neededInSize);4471if (ZSTDv07_isError(decodedSize)) return decodedSize;4472ip += neededInSize;4473if (!decodedSize && !isSkipFrame) break; /* this was just a header */4474zbd->outEnd = zbd->outStart + decodedSize;4475zbd->stage = ZBUFFds_flush;4476break;4477}4478if (ip==iend) { notDone = 0; break; } /* no more input */4479zbd->stage = ZBUFFds_load;4480}4481/* fall-through */4482case ZBUFFds_load:4483{ size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);4484size_t const toLoad = neededInSize - zbd->inPos; /* should always be <= remaining space within inBuff */4485size_t loadedSize;4486if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected); /* should never happen */4487loadedSize = ZBUFFv07_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);4488ip += loadedSize;4489zbd->inPos += loadedSize;4490if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */44914492/* decode loaded input */4493{ const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);4494size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,4495zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,4496zbd->inBuff, neededInSize);4497if (ZSTDv07_isError(decodedSize)) return decodedSize;4498zbd->inPos = 0; /* input is consumed */4499if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; } /* this was just a header */4500zbd->outEnd = zbd->outStart + decodedSize;4501zbd->stage = ZBUFFds_flush;4502/* break; */4503/* pass-through */4504}4505}4506/* fall-through */4507case ZBUFFds_flush:4508{ size_t const toFlushSize = zbd->outEnd - zbd->outStart;4509size_t const flushedSize = ZBUFFv07_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);4510op += flushedSize;4511zbd->outStart += flushedSize;4512if (flushedSize == toFlushSize) {4513zbd->stage = ZBUFFds_read;4514if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)4515zbd->outStart = zbd->outEnd = 0;4516break;4517}4518/* cannot flush everything */4519notDone = 0;4520break;4521}4522default: return ERROR(GENERIC); /* impossible */4523} }45244525/* result */4526*srcSizePtr = ip-istart;4527*dstCapacityPtr = op-ostart;4528{ size_t nextSrcSizeHint = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);4529nextSrcSizeHint -= zbd->inPos; /* already loaded*/4530return nextSrcSizeHint;4531}4532}4533453445354536/* *************************************4537* Tool functions4538***************************************/4539size_t ZBUFFv07_recommendedDInSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + ZSTDv07_blockHeaderSize /* block header size*/ ; }4540size_t ZBUFFv07_recommendedDOutSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX; }454145424543