10c16b537SWarner Losh /*
2*5ff13fbcSAllan Jude * Copyright (c) Yann Collet, Facebook, Inc.
30c16b537SWarner Losh * All rights reserved.
40c16b537SWarner Losh *
50c16b537SWarner Losh * This source code is licensed under both the BSD-style license (found in the
60c16b537SWarner Losh * LICENSE file in the root directory of this source tree) and the GPLv2 (found
70c16b537SWarner Losh * in the COPYING file in the root directory of this source tree).
80c16b537SWarner Losh * You may select, at your option, one of the above-listed licenses.
90c16b537SWarner Losh */
100c16b537SWarner Losh
110c16b537SWarner Losh
120c16b537SWarner Losh /*- Dependencies -*/
130c16b537SWarner Losh #include "zstd_v05.h"
1437f1f268SConrad Meyer #include "../common/error_private.h"
150c16b537SWarner Losh
160c16b537SWarner Losh
170c16b537SWarner Losh /* ******************************************************************
180c16b537SWarner Losh mem.h
190c16b537SWarner Losh low-level memory access routines
200c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet.
210c16b537SWarner Losh
220c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
230c16b537SWarner Losh
240c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
250c16b537SWarner Losh modification, are permitted provided that the following conditions are
260c16b537SWarner Losh met:
270c16b537SWarner Losh
280c16b537SWarner Losh * Redistributions of source code must retain the above copyright
290c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
300c16b537SWarner Losh * Redistributions in binary form must reproduce the above
310c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
320c16b537SWarner Losh in the documentation and/or other materials provided with the
330c16b537SWarner Losh distribution.
340c16b537SWarner Losh
350c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
360c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
370c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
380c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
390c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
400c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
410c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
420c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
430c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
440c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
450c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
460c16b537SWarner Losh
470c16b537SWarner Losh You can contact the author at :
480c16b537SWarner Losh - FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy
490c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c
500c16b537SWarner Losh ****************************************************************** */
510c16b537SWarner Losh #ifndef MEM_H_MODULE
520c16b537SWarner Losh #define MEM_H_MODULE
530c16b537SWarner Losh
540c16b537SWarner Losh #if defined (__cplusplus)
550c16b537SWarner Losh extern "C" {
560c16b537SWarner Losh #endif
570c16b537SWarner Losh
580c16b537SWarner Losh /*-****************************************
590c16b537SWarner Losh * Dependencies
600c16b537SWarner Losh ******************************************/
610c16b537SWarner Losh #include <stddef.h> /* size_t, ptrdiff_t */
620c16b537SWarner Losh #include <string.h> /* memcpy */
630c16b537SWarner Losh
640c16b537SWarner Losh
650c16b537SWarner Losh /*-****************************************
660c16b537SWarner Losh * Compiler specifics
670c16b537SWarner Losh ******************************************/
680c16b537SWarner Losh #if defined(__GNUC__)
690c16b537SWarner Losh # define MEM_STATIC static __attribute__((unused))
700c16b537SWarner Losh #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
710c16b537SWarner Losh # define MEM_STATIC static inline
720c16b537SWarner Losh #elif defined(_MSC_VER)
730c16b537SWarner Losh # define MEM_STATIC static __inline
740c16b537SWarner Losh #else
750c16b537SWarner Losh # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
760c16b537SWarner Losh #endif
770c16b537SWarner Losh
780c16b537SWarner Losh
790c16b537SWarner Losh /*-**************************************************************
800c16b537SWarner Losh * Basic Types
810c16b537SWarner Losh *****************************************************************/
820c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
83f7cd7fe5SConrad Meyer # if defined(_AIX)
84f7cd7fe5SConrad Meyer # include <inttypes.h>
85f7cd7fe5SConrad Meyer # else
86f7cd7fe5SConrad Meyer # include <stdint.h> /* intptr_t */
87f7cd7fe5SConrad Meyer # endif
880c16b537SWarner Losh typedef uint8_t BYTE;
890c16b537SWarner Losh typedef uint16_t U16;
900c16b537SWarner Losh typedef int16_t S16;
910c16b537SWarner Losh typedef uint32_t U32;
920c16b537SWarner Losh typedef int32_t S32;
930c16b537SWarner Losh typedef uint64_t U64;
940c16b537SWarner Losh typedef int64_t S64;
950c16b537SWarner Losh #else
960c16b537SWarner Losh typedef unsigned char BYTE;
970c16b537SWarner Losh typedef unsigned short U16;
980c16b537SWarner Losh typedef signed short S16;
990c16b537SWarner Losh typedef unsigned int U32;
1000c16b537SWarner Losh typedef signed int S32;
1010c16b537SWarner Losh typedef unsigned long long U64;
1020c16b537SWarner Losh typedef signed long long S64;
1030c16b537SWarner Losh #endif
1040c16b537SWarner Losh
1050c16b537SWarner Losh
1060c16b537SWarner Losh /*-**************************************************************
1070c16b537SWarner Losh * Memory I/O
1080c16b537SWarner Losh *****************************************************************/
1090c16b537SWarner Losh /* MEM_FORCE_MEMORY_ACCESS :
1100c16b537SWarner Losh * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
1110c16b537SWarner Losh * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
1120c16b537SWarner Losh * The below switch allow to select different access method for improved performance.
1130c16b537SWarner Losh * Method 0 (default) : use `memcpy()`. Safe and portable.
1140c16b537SWarner Losh * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
1150c16b537SWarner Losh * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
1160c16b537SWarner Losh * Method 2 : direct access. This method is portable but violate C standard.
1170c16b537SWarner Losh * It can generate buggy code on targets depending on alignment.
1180c16b537SWarner Losh * In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
1190c16b537SWarner Losh * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
1200c16b537SWarner Losh * Prefer these methods in priority order (0 > 1 > 2)
1210c16b537SWarner Losh */
1220c16b537SWarner Losh #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
123*5ff13fbcSAllan Jude # if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
1240c16b537SWarner Losh # define MEM_FORCE_MEMORY_ACCESS 1
1250c16b537SWarner Losh # endif
1260c16b537SWarner Losh #endif
1270c16b537SWarner Losh
MEM_32bits(void)1280c16b537SWarner Losh MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
MEM_64bits(void)1290c16b537SWarner Losh MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
1300c16b537SWarner Losh
MEM_isLittleEndian(void)1310c16b537SWarner Losh MEM_STATIC unsigned MEM_isLittleEndian(void)
1320c16b537SWarner Losh {
1330c16b537SWarner Losh const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
1340c16b537SWarner Losh return one.c[0];
1350c16b537SWarner Losh }
1360c16b537SWarner Losh
1370c16b537SWarner Losh #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
1380c16b537SWarner Losh
1390c16b537SWarner Losh /* violates C standard, by lying on structure alignment.
1400c16b537SWarner Losh Only use if no other choice to achieve best performance on target platform */
MEM_read16(const void * memPtr)1410c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
MEM_read32(const void * memPtr)1420c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
MEM_read64(const void * memPtr)1430c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
1440c16b537SWarner Losh
MEM_write16(void * memPtr,U16 value)1450c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
MEM_write32(void * memPtr,U32 value)1460c16b537SWarner Losh MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
MEM_write64(void * memPtr,U64 value)1470c16b537SWarner Losh MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
1480c16b537SWarner Losh
1490c16b537SWarner Losh #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
1500c16b537SWarner Losh
1510c16b537SWarner Losh /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
1520c16b537SWarner Losh /* currently only defined for gcc and icc */
1530c16b537SWarner Losh typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
1540c16b537SWarner Losh
MEM_read16(const void * ptr)1550c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
MEM_read32(const void * ptr)1560c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
MEM_read64(const void * ptr)1570c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
1580c16b537SWarner Losh
MEM_write16(void * memPtr,U16 value)1590c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
MEM_write32(void * memPtr,U32 value)1600c16b537SWarner Losh MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
MEM_write64(void * memPtr,U64 value)1610c16b537SWarner Losh MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }
1620c16b537SWarner Losh
1630c16b537SWarner Losh #else
1640c16b537SWarner Losh
1650c16b537SWarner Losh /* default method, safe and standard.
1660c16b537SWarner Losh can sometimes prove slower */
1670c16b537SWarner Losh
MEM_read16(const void * memPtr)1680c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* memPtr)
1690c16b537SWarner Losh {
1700c16b537SWarner Losh U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
1710c16b537SWarner Losh }
1720c16b537SWarner Losh
MEM_read32(const void * memPtr)1730c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* memPtr)
1740c16b537SWarner Losh {
1750c16b537SWarner Losh U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
1760c16b537SWarner Losh }
1770c16b537SWarner Losh
MEM_read64(const void * memPtr)1780c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* memPtr)
1790c16b537SWarner Losh {
1800c16b537SWarner Losh U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
1810c16b537SWarner Losh }
1820c16b537SWarner Losh
MEM_write16(void * memPtr,U16 value)1830c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value)
1840c16b537SWarner Losh {
1850c16b537SWarner Losh memcpy(memPtr, &value, sizeof(value));
1860c16b537SWarner Losh }
1870c16b537SWarner Losh
MEM_write32(void * memPtr,U32 value)1880c16b537SWarner Losh MEM_STATIC void MEM_write32(void* memPtr, U32 value)
1890c16b537SWarner Losh {
1900c16b537SWarner Losh memcpy(memPtr, &value, sizeof(value));
1910c16b537SWarner Losh }
1920c16b537SWarner Losh
MEM_write64(void * memPtr,U64 value)1930c16b537SWarner Losh MEM_STATIC void MEM_write64(void* memPtr, U64 value)
1940c16b537SWarner Losh {
1950c16b537SWarner Losh memcpy(memPtr, &value, sizeof(value));
1960c16b537SWarner Losh }
1970c16b537SWarner Losh
1980c16b537SWarner Losh #endif /* MEM_FORCE_MEMORY_ACCESS */
1990c16b537SWarner Losh
2000c16b537SWarner Losh
MEM_readLE16(const void * memPtr)2010c16b537SWarner Losh MEM_STATIC U16 MEM_readLE16(const void* memPtr)
2020c16b537SWarner Losh {
2030c16b537SWarner Losh if (MEM_isLittleEndian())
2040c16b537SWarner Losh return MEM_read16(memPtr);
2050c16b537SWarner Losh else {
2060c16b537SWarner Losh const BYTE* p = (const BYTE*)memPtr;
2070c16b537SWarner Losh return (U16)(p[0] + (p[1]<<8));
2080c16b537SWarner Losh }
2090c16b537SWarner Losh }
2100c16b537SWarner Losh
MEM_writeLE16(void * memPtr,U16 val)2110c16b537SWarner Losh MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
2120c16b537SWarner Losh {
2130c16b537SWarner Losh if (MEM_isLittleEndian()) {
2140c16b537SWarner Losh MEM_write16(memPtr, val);
2150c16b537SWarner Losh } else {
2160c16b537SWarner Losh BYTE* p = (BYTE*)memPtr;
2170c16b537SWarner Losh p[0] = (BYTE)val;
2180c16b537SWarner Losh p[1] = (BYTE)(val>>8);
2190c16b537SWarner Losh }
2200c16b537SWarner Losh }
2210c16b537SWarner Losh
MEM_readLE32(const void * memPtr)2220c16b537SWarner Losh MEM_STATIC U32 MEM_readLE32(const void* memPtr)
2230c16b537SWarner Losh {
2240c16b537SWarner Losh if (MEM_isLittleEndian())
2250c16b537SWarner Losh return MEM_read32(memPtr);
2260c16b537SWarner Losh else {
2270c16b537SWarner Losh const BYTE* p = (const BYTE*)memPtr;
2280c16b537SWarner Losh return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));
2290c16b537SWarner Losh }
2300c16b537SWarner Losh }
2310c16b537SWarner Losh
2320c16b537SWarner Losh
MEM_readLE64(const void * memPtr)2330c16b537SWarner Losh MEM_STATIC U64 MEM_readLE64(const void* memPtr)
2340c16b537SWarner Losh {
2350c16b537SWarner Losh if (MEM_isLittleEndian())
2360c16b537SWarner Losh return MEM_read64(memPtr);
2370c16b537SWarner Losh else {
2380c16b537SWarner Losh const BYTE* p = (const BYTE*)memPtr;
2390c16b537SWarner Losh return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)
2400c16b537SWarner Losh + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));
2410c16b537SWarner Losh }
2420c16b537SWarner Losh }
2430c16b537SWarner Losh
2440c16b537SWarner Losh
MEM_readLEST(const void * memPtr)2450c16b537SWarner Losh MEM_STATIC size_t MEM_readLEST(const void* memPtr)
2460c16b537SWarner Losh {
2470c16b537SWarner Losh if (MEM_32bits())
2480c16b537SWarner Losh return (size_t)MEM_readLE32(memPtr);
2490c16b537SWarner Losh else
2500c16b537SWarner Losh return (size_t)MEM_readLE64(memPtr);
2510c16b537SWarner Losh }
2520c16b537SWarner Losh
2530c16b537SWarner Losh
2540c16b537SWarner Losh #if defined (__cplusplus)
2550c16b537SWarner Losh }
2560c16b537SWarner Losh #endif
2570c16b537SWarner Losh
2580c16b537SWarner Losh #endif /* MEM_H_MODULE */
2590c16b537SWarner Losh
2600c16b537SWarner Losh /*
2610c16b537SWarner Losh zstd - standard compression library
2620c16b537SWarner Losh Header File for static linking only
2630c16b537SWarner Losh Copyright (C) 2014-2016, Yann Collet.
2640c16b537SWarner Losh
2650c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
2660c16b537SWarner Losh
2670c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
2680c16b537SWarner Losh modification, are permitted provided that the following conditions are
2690c16b537SWarner Losh met:
2700c16b537SWarner Losh * Redistributions of source code must retain the above copyright
2710c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
2720c16b537SWarner Losh * Redistributions in binary form must reproduce the above
2730c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
2740c16b537SWarner Losh in the documentation and/or other materials provided with the
2750c16b537SWarner Losh distribution.
2760c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2770c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2780c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2790c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2800c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2810c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2820c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2830c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2840c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2850c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2860c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2870c16b537SWarner Losh
2880c16b537SWarner Losh You can contact the author at :
2890c16b537SWarner Losh - zstd homepage : http://www.zstd.net
2900c16b537SWarner Losh */
2910c16b537SWarner Losh #ifndef ZSTD_STATIC_H
2920c16b537SWarner Losh #define ZSTD_STATIC_H
2930c16b537SWarner Losh
2940c16b537SWarner Losh /* The prototypes defined within this file are considered experimental.
2950c16b537SWarner Losh * They should not be used in the context DLL as they may change in the future.
2960c16b537SWarner Losh * Prefer static linking if you need them, to control breaking version changes issues.
2970c16b537SWarner Losh */
2980c16b537SWarner Losh
2990c16b537SWarner Losh #if defined (__cplusplus)
3000c16b537SWarner Losh extern "C" {
3010c16b537SWarner Losh #endif
3020c16b537SWarner Losh
3030c16b537SWarner Losh
3040c16b537SWarner Losh
3050c16b537SWarner Losh /*-*************************************
3060c16b537SWarner Losh * Types
3070c16b537SWarner Losh ***************************************/
3080c16b537SWarner Losh #define ZSTDv05_WINDOWLOG_ABSOLUTEMIN 11
3090c16b537SWarner Losh
3100c16b537SWarner Losh
3110c16b537SWarner Losh /*-*************************************
3120c16b537SWarner Losh * Advanced functions
3130c16b537SWarner Losh ***************************************/
3140c16b537SWarner Losh /*- Advanced Decompression functions -*/
3150c16b537SWarner Losh
3160c16b537SWarner Losh /*! ZSTDv05_decompress_usingPreparedDCtx() :
3170c16b537SWarner Losh * Same as ZSTDv05_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.
3180c16b537SWarner Losh * It avoids reloading the dictionary each time.
3190c16b537SWarner Losh * `preparedDCtx` must have been properly initialized using ZSTDv05_decompressBegin_usingDict().
3200c16b537SWarner Losh * Requires 2 contexts : 1 for reference, which will not be modified, and 1 to run the decompression operation */
3210c16b537SWarner Losh size_t ZSTDv05_decompress_usingPreparedDCtx(
3220c16b537SWarner Losh ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* preparedDCtx,
3230c16b537SWarner Losh void* dst, size_t dstCapacity,
3240c16b537SWarner Losh const void* src, size_t srcSize);
3250c16b537SWarner Losh
3260c16b537SWarner Losh
3270c16b537SWarner Losh /* **************************************
3280c16b537SWarner Losh * Streaming functions (direct mode)
3290c16b537SWarner Losh ****************************************/
3300c16b537SWarner Losh size_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx);
3310c16b537SWarner Losh
3320c16b537SWarner Losh /*
3330c16b537SWarner Losh Streaming decompression, direct mode (bufferless)
3340c16b537SWarner Losh
3350c16b537SWarner Losh A ZSTDv05_DCtx object is required to track streaming operations.
3360c16b537SWarner Losh Use ZSTDv05_createDCtx() / ZSTDv05_freeDCtx() to manage it.
3370c16b537SWarner Losh A ZSTDv05_DCtx object can be re-used multiple times.
3380c16b537SWarner Losh
3390c16b537SWarner Losh First typical operation is to retrieve frame parameters, using ZSTDv05_getFrameParams().
3400c16b537SWarner Losh This operation is independent, and just needs enough input data to properly decode the frame header.
3410c16b537SWarner Losh Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.
3420c16b537SWarner Losh Result : 0 when successful, it means the ZSTDv05_parameters structure has been filled.
3430c16b537SWarner Losh >0 : means there is not enough data into src. Provides the expected size to successfully decode header.
3440c16b537SWarner Losh errorCode, which can be tested using ZSTDv05_isError()
3450c16b537SWarner Losh
3460c16b537SWarner Losh Start decompression, with ZSTDv05_decompressBegin() or ZSTDv05_decompressBegin_usingDict()
3470c16b537SWarner Losh Alternatively, you can copy a prepared context, using ZSTDv05_copyDCtx()
3480c16b537SWarner Losh
3490c16b537SWarner Losh Then use ZSTDv05_nextSrcSizeToDecompress() and ZSTDv05_decompressContinue() alternatively.
3500c16b537SWarner Losh ZSTDv05_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv05_decompressContinue().
3510c16b537SWarner Losh ZSTDv05_decompressContinue() requires this exact amount of bytes, or it will fail.
3520c16b537SWarner Losh ZSTDv05_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).
3530c16b537SWarner Losh They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.
3540c16b537SWarner Losh
3550c16b537SWarner Losh @result of ZSTDv05_decompressContinue() is the number of bytes regenerated within 'dst'.
3560c16b537SWarner Losh It can be zero, which is not an error; it just means ZSTDv05_decompressContinue() has decoded some header.
3570c16b537SWarner Losh
3580c16b537SWarner Losh A frame is fully decoded when ZSTDv05_nextSrcSizeToDecompress() returns zero.
3590c16b537SWarner Losh Context can then be reset to start a new decompression.
3600c16b537SWarner Losh */
3610c16b537SWarner Losh
3620c16b537SWarner Losh
3630c16b537SWarner Losh /* **************************************
3640c16b537SWarner Losh * Block functions
3650c16b537SWarner Losh ****************************************/
3660c16b537SWarner Losh /*! Block functions produce and decode raw zstd blocks, without frame metadata.
3670c16b537SWarner Losh User will have to take in charge required information to regenerate data, such as block sizes.
3680c16b537SWarner Losh
3690c16b537SWarner Losh A few rules to respect :
3700c16b537SWarner Losh - Uncompressed block size must be <= 128 KB
3710c16b537SWarner Losh - Compressing or decompressing requires a context structure
3720c16b537SWarner Losh + Use ZSTDv05_createCCtx() and ZSTDv05_createDCtx()
3730c16b537SWarner Losh - It is necessary to init context before starting
3740c16b537SWarner Losh + compression : ZSTDv05_compressBegin()
3750c16b537SWarner Losh + decompression : ZSTDv05_decompressBegin()
3760c16b537SWarner Losh + variants _usingDict() are also allowed
3770c16b537SWarner Losh + copyCCtx() and copyDCtx() work too
3780c16b537SWarner Losh - When a block is considered not compressible enough, ZSTDv05_compressBlock() result will be zero.
3790c16b537SWarner Losh In which case, nothing is produced into `dst`.
3800c16b537SWarner Losh + User must test for such outcome and deal directly with uncompressed data
3810c16b537SWarner Losh + ZSTDv05_decompressBlock() doesn't accept uncompressed data as input !!
3820c16b537SWarner Losh */
3830c16b537SWarner Losh
3840c16b537SWarner Losh size_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
3850c16b537SWarner Losh
3860c16b537SWarner Losh
3870c16b537SWarner Losh
3880c16b537SWarner Losh
3890c16b537SWarner Losh #if defined (__cplusplus)
3900c16b537SWarner Losh }
3910c16b537SWarner Losh #endif
3920c16b537SWarner Losh
3930c16b537SWarner Losh #endif /* ZSTDv05_STATIC_H */
3940c16b537SWarner Losh
3950c16b537SWarner Losh
3960c16b537SWarner Losh /*
3970c16b537SWarner Losh zstd_internal - common functions to include
3980c16b537SWarner Losh Header File for include
3990c16b537SWarner Losh Copyright (C) 2014-2016, Yann Collet.
4000c16b537SWarner Losh
4010c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
4020c16b537SWarner Losh
4030c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
4040c16b537SWarner Losh modification, are permitted provided that the following conditions are
4050c16b537SWarner Losh met:
4060c16b537SWarner Losh * Redistributions of source code must retain the above copyright
4070c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
4080c16b537SWarner Losh * Redistributions in binary form must reproduce the above
4090c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
4100c16b537SWarner Losh in the documentation and/or other materials provided with the
4110c16b537SWarner Losh distribution.
4120c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4130c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4140c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4150c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4160c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4170c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4180c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4190c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4200c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4210c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4220c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4230c16b537SWarner Losh
4240c16b537SWarner Losh You can contact the author at :
4250c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd
4260c16b537SWarner Losh */
4270c16b537SWarner Losh #ifndef ZSTD_CCOMMON_H_MODULE
4280c16b537SWarner Losh #define ZSTD_CCOMMON_H_MODULE
4290c16b537SWarner Losh
4300c16b537SWarner Losh
4310c16b537SWarner Losh
4320c16b537SWarner Losh /*-*************************************
4330c16b537SWarner Losh * Common macros
4340c16b537SWarner Losh ***************************************/
4350c16b537SWarner Losh #define MIN(a,b) ((a)<(b) ? (a) : (b))
4360c16b537SWarner Losh #define MAX(a,b) ((a)>(b) ? (a) : (b))
4370c16b537SWarner Losh
4380c16b537SWarner Losh
4390c16b537SWarner Losh /*-*************************************
4400c16b537SWarner Losh * Common constants
4410c16b537SWarner Losh ***************************************/
4420c16b537SWarner Losh #define ZSTDv05_DICT_MAGIC 0xEC30A435
4430c16b537SWarner Losh
4440c16b537SWarner Losh #define KB *(1 <<10)
4450c16b537SWarner Losh #define MB *(1 <<20)
4460c16b537SWarner Losh #define GB *(1U<<30)
4470c16b537SWarner Losh
4480c16b537SWarner Losh #define BLOCKSIZE (128 KB) /* define, for static allocation */
4490c16b537SWarner Losh
4500c16b537SWarner Losh static const size_t ZSTDv05_blockHeaderSize = 3;
4510c16b537SWarner Losh static const size_t ZSTDv05_frameHeaderSize_min = 5;
4520c16b537SWarner Losh #define ZSTDv05_frameHeaderSize_max 5 /* define, for static allocation */
4530c16b537SWarner Losh
4540c16b537SWarner Losh #define BITv057 128
4550c16b537SWarner Losh #define BITv056 64
4560c16b537SWarner Losh #define BITv055 32
4570c16b537SWarner Losh #define BITv054 16
4580c16b537SWarner Losh #define BITv051 2
4590c16b537SWarner Losh #define BITv050 1
4600c16b537SWarner Losh
4610c16b537SWarner Losh #define IS_HUFv05 0
4620c16b537SWarner Losh #define IS_PCH 1
4630c16b537SWarner Losh #define IS_RAW 2
4640c16b537SWarner Losh #define IS_RLE 3
4650c16b537SWarner Losh
4660c16b537SWarner Losh #define MINMATCH 4
4670c16b537SWarner Losh #define REPCODE_STARTVALUE 1
4680c16b537SWarner Losh
4690c16b537SWarner Losh #define Litbits 8
4700c16b537SWarner Losh #define MLbits 7
4710c16b537SWarner Losh #define LLbits 6
4720c16b537SWarner Losh #define Offbits 5
4730c16b537SWarner Losh #define MaxLit ((1<<Litbits) - 1)
4740c16b537SWarner Losh #define MaxML ((1<<MLbits) - 1)
4750c16b537SWarner Losh #define MaxLL ((1<<LLbits) - 1)
4760c16b537SWarner Losh #define MaxOff ((1<<Offbits)- 1)
4770c16b537SWarner Losh #define MLFSEv05Log 10
4780c16b537SWarner Losh #define LLFSEv05Log 10
4790c16b537SWarner Losh #define OffFSEv05Log 9
4800c16b537SWarner Losh #define MaxSeq MAX(MaxLL, MaxML)
4810c16b537SWarner Losh
4820c16b537SWarner Losh #define FSEv05_ENCODING_RAW 0
4830c16b537SWarner Losh #define FSEv05_ENCODING_RLE 1
4840c16b537SWarner Losh #define FSEv05_ENCODING_STATIC 2
4850c16b537SWarner Losh #define FSEv05_ENCODING_DYNAMIC 3
4860c16b537SWarner Losh
4870c16b537SWarner Losh
4880c16b537SWarner Losh #define HufLog 12
4890c16b537SWarner Losh
4900c16b537SWarner Losh #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
4910c16b537SWarner Losh #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
4920c16b537SWarner Losh
4930c16b537SWarner Losh #define WILDCOPY_OVERLENGTH 8
4940c16b537SWarner Losh
4952b9c00cbSConrad Meyer #define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
4962b9c00cbSConrad Meyer
4970c16b537SWarner Losh typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
4980c16b537SWarner Losh
4990c16b537SWarner Losh
5000c16b537SWarner Losh /*-*******************************************
5010c16b537SWarner Losh * Shared functions to include for inlining
5020c16b537SWarner Losh *********************************************/
ZSTDv05_copy8(void * dst,const void * src)5030c16b537SWarner Losh static void ZSTDv05_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
5040c16b537SWarner Losh
5050c16b537SWarner Losh #define COPY8(d,s) { ZSTDv05_copy8(d,s); d+=8; s+=8; }
5060c16b537SWarner Losh
5070c16b537SWarner Losh /*! ZSTDv05_wildcopy() :
5080c16b537SWarner Losh * custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
ZSTDv05_wildcopy(void * dst,const void * src,ptrdiff_t length)5090c16b537SWarner Losh MEM_STATIC void ZSTDv05_wildcopy(void* dst, const void* src, ptrdiff_t length)
5100c16b537SWarner Losh {
5110c16b537SWarner Losh const BYTE* ip = (const BYTE*)src;
5120c16b537SWarner Losh BYTE* op = (BYTE*)dst;
5130c16b537SWarner Losh BYTE* const oend = op + length;
5140c16b537SWarner Losh do
5150c16b537SWarner Losh COPY8(op, ip)
5160c16b537SWarner Losh while (op < oend);
5170c16b537SWarner Losh }
5180c16b537SWarner Losh
5190c16b537SWarner Losh
5200c16b537SWarner Losh /*-*******************************************
5210c16b537SWarner Losh * Private interfaces
5220c16b537SWarner Losh *********************************************/
5230c16b537SWarner Losh typedef struct {
5240c16b537SWarner Losh void* buffer;
5250c16b537SWarner Losh U32* offsetStart;
5260c16b537SWarner Losh U32* offset;
5270c16b537SWarner Losh BYTE* offCodeStart;
5280c16b537SWarner Losh BYTE* offCode;
5290c16b537SWarner Losh BYTE* litStart;
5300c16b537SWarner Losh BYTE* lit;
5310c16b537SWarner Losh BYTE* litLengthStart;
5320c16b537SWarner Losh BYTE* litLength;
5330c16b537SWarner Losh BYTE* matchLengthStart;
5340c16b537SWarner Losh BYTE* matchLength;
5350c16b537SWarner Losh BYTE* dumpsStart;
5360c16b537SWarner Losh BYTE* dumps;
5370c16b537SWarner Losh /* opt */
5380c16b537SWarner Losh U32* matchLengthFreq;
5390c16b537SWarner Losh U32* litLengthFreq;
5400c16b537SWarner Losh U32* litFreq;
5410c16b537SWarner Losh U32* offCodeFreq;
5420c16b537SWarner Losh U32 matchLengthSum;
5430c16b537SWarner Losh U32 litLengthSum;
5440c16b537SWarner Losh U32 litSum;
5450c16b537SWarner Losh U32 offCodeSum;
5460c16b537SWarner Losh } seqStore_t;
5470c16b537SWarner Losh
5480c16b537SWarner Losh
5490c16b537SWarner Losh
5500c16b537SWarner Losh #endif /* ZSTDv05_CCOMMON_H_MODULE */
5510c16b537SWarner Losh /* ******************************************************************
5520c16b537SWarner Losh FSEv05 : Finite State Entropy coder
5530c16b537SWarner Losh header file
5540c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet.
5550c16b537SWarner Losh
5560c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
5570c16b537SWarner Losh
5580c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
5590c16b537SWarner Losh modification, are permitted provided that the following conditions are
5600c16b537SWarner Losh met:
5610c16b537SWarner Losh
5620c16b537SWarner Losh * Redistributions of source code must retain the above copyright
5630c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
5640c16b537SWarner Losh * Redistributions in binary form must reproduce the above
5650c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
5660c16b537SWarner Losh in the documentation and/or other materials provided with the
5670c16b537SWarner Losh distribution.
5680c16b537SWarner Losh
5690c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5700c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5710c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5720c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5730c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5740c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5750c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5760c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5770c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5780c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5790c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5800c16b537SWarner Losh
5810c16b537SWarner Losh You can contact the author at :
5820c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
5830c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c
5840c16b537SWarner Losh ****************************************************************** */
5850c16b537SWarner Losh #ifndef FSEv05_H
5860c16b537SWarner Losh #define FSEv05_H
5870c16b537SWarner Losh
5880c16b537SWarner Losh #if defined (__cplusplus)
5890c16b537SWarner Losh extern "C" {
5900c16b537SWarner Losh #endif
5910c16b537SWarner Losh
5920c16b537SWarner Losh
5930c16b537SWarner Losh /* *****************************************
5940c16b537SWarner Losh * Includes
5950c16b537SWarner Losh ******************************************/
5960c16b537SWarner Losh #include <stddef.h> /* size_t, ptrdiff_t */
5970c16b537SWarner Losh
5980c16b537SWarner Losh
5990c16b537SWarner Losh /*-****************************************
6000c16b537SWarner Losh * FSEv05 simple functions
6010c16b537SWarner Losh ******************************************/
6020c16b537SWarner Losh size_t FSEv05_decompress(void* dst, size_t maxDstSize,
6030c16b537SWarner Losh const void* cSrc, size_t cSrcSize);
6040c16b537SWarner Losh /*!
6050c16b537SWarner Losh FSEv05_decompress():
6060c16b537SWarner Losh Decompress FSEv05 data from buffer 'cSrc', of size 'cSrcSize',
6070c16b537SWarner Losh into already allocated destination buffer 'dst', of size 'maxDstSize'.
6080c16b537SWarner Losh return : size of regenerated data (<= maxDstSize)
6090c16b537SWarner Losh or an error code, which can be tested using FSEv05_isError()
6100c16b537SWarner Losh
6110c16b537SWarner Losh ** Important ** : FSEv05_decompress() doesn't decompress non-compressible nor RLE data !!!
6120c16b537SWarner Losh Why ? : making this distinction requires a header.
6130c16b537SWarner Losh Header management is intentionally delegated to the user layer, which can better manage special cases.
6140c16b537SWarner Losh */
6150c16b537SWarner Losh
6160c16b537SWarner Losh
6170c16b537SWarner Losh /* *****************************************
6180c16b537SWarner Losh * Tool functions
6190c16b537SWarner Losh ******************************************/
6200c16b537SWarner Losh /* Error Management */
6210c16b537SWarner Losh unsigned FSEv05_isError(size_t code); /* tells if a return value is an error code */
6220c16b537SWarner Losh const char* FSEv05_getErrorName(size_t code); /* provides error code string (useful for debugging) */
6230c16b537SWarner Losh
6240c16b537SWarner Losh
6250c16b537SWarner Losh
6260c16b537SWarner Losh
6270c16b537SWarner Losh /* *****************************************
6280c16b537SWarner Losh * FSEv05 detailed API
6290c16b537SWarner Losh ******************************************/
6300c16b537SWarner Losh /* *** DECOMPRESSION *** */
6310c16b537SWarner Losh
6320c16b537SWarner Losh /*!
6330c16b537SWarner Losh FSEv05_readNCount():
6340c16b537SWarner Losh Read compactly saved 'normalizedCounter' from 'rBuffer'.
6350c16b537SWarner Losh return : size read from 'rBuffer'
6360c16b537SWarner Losh or an errorCode, which can be tested using FSEv05_isError()
6370c16b537SWarner Losh maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
6380c16b537SWarner Losh size_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);
6390c16b537SWarner Losh
6400c16b537SWarner Losh /*!
6410c16b537SWarner Losh Constructor and Destructor of type FSEv05_DTable
6420c16b537SWarner Losh Note that its size depends on 'tableLog' */
6430c16b537SWarner Losh typedef unsigned FSEv05_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
6440c16b537SWarner Losh FSEv05_DTable* FSEv05_createDTable(unsigned tableLog);
6450c16b537SWarner Losh void FSEv05_freeDTable(FSEv05_DTable* dt);
6460c16b537SWarner Losh
6470c16b537SWarner Losh /*!
6480c16b537SWarner Losh FSEv05_buildDTable():
6490c16b537SWarner Losh Builds 'dt', which must be already allocated, using FSEv05_createDTable()
6500c16b537SWarner Losh @return : 0,
6510c16b537SWarner Losh or an errorCode, which can be tested using FSEv05_isError() */
6520c16b537SWarner Losh size_t FSEv05_buildDTable (FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
6530c16b537SWarner Losh
6540c16b537SWarner Losh /*!
6550c16b537SWarner Losh FSEv05_decompress_usingDTable():
6560c16b537SWarner Losh Decompress compressed source @cSrc of size @cSrcSize using `dt`
6570c16b537SWarner Losh into `dst` which must be already allocated.
6580c16b537SWarner Losh @return : size of regenerated data (necessarily <= @dstCapacity)
6590c16b537SWarner Losh or an errorCode, which can be tested using FSEv05_isError() */
6600c16b537SWarner Losh size_t FSEv05_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv05_DTable* dt);
6610c16b537SWarner Losh
6620c16b537SWarner Losh
6630c16b537SWarner Losh
6640c16b537SWarner Losh #if defined (__cplusplus)
6650c16b537SWarner Losh }
6660c16b537SWarner Losh #endif
6670c16b537SWarner Losh
6680c16b537SWarner Losh #endif /* FSEv05_H */
6690c16b537SWarner Losh /* ******************************************************************
6700c16b537SWarner Losh bitstream
6710c16b537SWarner Losh Part of FSEv05 library
6720c16b537SWarner Losh header file (to include)
6730c16b537SWarner Losh Copyright (C) 2013-2016, Yann Collet.
6740c16b537SWarner Losh
6750c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6760c16b537SWarner Losh
6770c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
6780c16b537SWarner Losh modification, are permitted provided that the following conditions are
6790c16b537SWarner Losh met:
6800c16b537SWarner Losh
6810c16b537SWarner Losh * Redistributions of source code must retain the above copyright
6820c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
6830c16b537SWarner Losh * Redistributions in binary form must reproduce the above
6840c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
6850c16b537SWarner Losh in the documentation and/or other materials provided with the
6860c16b537SWarner Losh distribution.
6870c16b537SWarner Losh
6880c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6890c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6900c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6910c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6920c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6930c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6940c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6950c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6960c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6970c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6980c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6990c16b537SWarner Losh
7000c16b537SWarner Losh You can contact the author at :
7010c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
7020c16b537SWarner Losh ****************************************************************** */
7030c16b537SWarner Losh #ifndef BITv05STREAM_H_MODULE
7040c16b537SWarner Losh #define BITv05STREAM_H_MODULE
7050c16b537SWarner Losh
7060c16b537SWarner Losh #if defined (__cplusplus)
7070c16b537SWarner Losh extern "C" {
7080c16b537SWarner Losh #endif
7090c16b537SWarner Losh
7100c16b537SWarner Losh
7110c16b537SWarner Losh /*
7120c16b537SWarner Losh * This API consists of small unitary functions, which highly benefit from being inlined.
7130c16b537SWarner Losh * Since link-time-optimization is not available for all compilers,
7140c16b537SWarner Losh * these functions are defined into a .h to be included.
7150c16b537SWarner Losh */
7160c16b537SWarner Losh
7170c16b537SWarner Losh
7180c16b537SWarner Losh
7190c16b537SWarner Losh /*-********************************************
7200c16b537SWarner Losh * bitStream decoding API (read backward)
7210c16b537SWarner Losh **********************************************/
7220c16b537SWarner Losh typedef struct
7230c16b537SWarner Losh {
7240c16b537SWarner Losh size_t bitContainer;
7250c16b537SWarner Losh unsigned bitsConsumed;
7260c16b537SWarner Losh const char* ptr;
7270c16b537SWarner Losh const char* start;
7280c16b537SWarner Losh } BITv05_DStream_t;
7290c16b537SWarner Losh
7300c16b537SWarner Losh typedef enum { BITv05_DStream_unfinished = 0,
7310c16b537SWarner Losh BITv05_DStream_endOfBuffer = 1,
7320c16b537SWarner Losh BITv05_DStream_completed = 2,
7330c16b537SWarner Losh BITv05_DStream_overflow = 3 } BITv05_DStream_status; /* result of BITv05_reloadDStream() */
7340c16b537SWarner Losh /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
7350c16b537SWarner Losh
7360c16b537SWarner Losh MEM_STATIC size_t BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
7370c16b537SWarner Losh MEM_STATIC size_t BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits);
7380c16b537SWarner Losh MEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD);
7390c16b537SWarner Losh MEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* bitD);
7400c16b537SWarner Losh
7410c16b537SWarner Losh
7420c16b537SWarner Losh /*-****************************************
7430c16b537SWarner Losh * unsafe API
7440c16b537SWarner Losh ******************************************/
7450c16b537SWarner Losh MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits);
7460c16b537SWarner Losh /* faster, but works only if nbBits >= 1 */
7470c16b537SWarner Losh
7480c16b537SWarner Losh
7490c16b537SWarner Losh
7500c16b537SWarner Losh /*-**************************************************************
7510c16b537SWarner Losh * Helper functions
7520c16b537SWarner Losh ****************************************************************/
BITv05_highbit32(U32 val)753052d3c12SConrad Meyer MEM_STATIC unsigned BITv05_highbit32 (U32 val)
7540c16b537SWarner Losh {
7550c16b537SWarner Losh # if defined(_MSC_VER) /* Visual */
756*5ff13fbcSAllan Jude unsigned long r;
757*5ff13fbcSAllan Jude return _BitScanReverse(&r, val) ? (unsigned)r : 0;
7580c16b537SWarner Losh # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
7599cbefe25SConrad Meyer return __builtin_clz (val) ^ 31;
7600c16b537SWarner Losh # else /* Software version */
7610c16b537SWarner Losh static 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 };
7620c16b537SWarner Losh U32 v = val;
7630c16b537SWarner Losh unsigned r;
7640c16b537SWarner Losh v |= v >> 1;
7650c16b537SWarner Losh v |= v >> 2;
7660c16b537SWarner Losh v |= v >> 4;
7670c16b537SWarner Losh v |= v >> 8;
7680c16b537SWarner Losh v |= v >> 16;
7690c16b537SWarner Losh r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
7700c16b537SWarner Losh return r;
7710c16b537SWarner Losh # endif
7720c16b537SWarner Losh }
7730c16b537SWarner Losh
7740c16b537SWarner Losh
7750c16b537SWarner Losh
7760c16b537SWarner Losh /*-********************************************************
7770c16b537SWarner Losh * bitStream decoding
7780c16b537SWarner Losh **********************************************************/
7790c16b537SWarner Losh /*!BITv05_initDStream
7800c16b537SWarner Losh * Initialize a BITv05_DStream_t.
7810c16b537SWarner Losh * @bitD : a pointer to an already allocated BITv05_DStream_t structure
7820c16b537SWarner Losh * @srcBuffer must point at the beginning of a bitStream
7830c16b537SWarner Losh * @srcSize must be the exact size of the bitStream
7840c16b537SWarner Losh * @result : size of stream (== srcSize) or an errorCode if a problem is detected
7850c16b537SWarner Losh */
BITv05_initDStream(BITv05_DStream_t * bitD,const void * srcBuffer,size_t srcSize)7860c16b537SWarner Losh MEM_STATIC size_t BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
7870c16b537SWarner Losh {
7880c16b537SWarner Losh if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
7890c16b537SWarner Losh
7900c16b537SWarner Losh if (srcSize >= sizeof(size_t)) { /* normal case */
7910c16b537SWarner Losh U32 contain32;
7920c16b537SWarner Losh bitD->start = (const char*)srcBuffer;
7930c16b537SWarner Losh bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t);
7940c16b537SWarner Losh bitD->bitContainer = MEM_readLEST(bitD->ptr);
7950c16b537SWarner Losh contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
7960c16b537SWarner Losh if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */
7970c16b537SWarner Losh bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);
7980c16b537SWarner Losh } else {
7990c16b537SWarner Losh U32 contain32;
8000c16b537SWarner Losh bitD->start = (const char*)srcBuffer;
8010c16b537SWarner Losh bitD->ptr = bitD->start;
8020c16b537SWarner Losh bitD->bitContainer = *(const BYTE*)(bitD->start);
8030c16b537SWarner Losh switch(srcSize)
8040c16b537SWarner Losh {
8050c16b537SWarner Losh case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */
8060c16b537SWarner Losh case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */
8070c16b537SWarner Losh case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */
8080c16b537SWarner Losh case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */
8090c16b537SWarner Losh case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */
8100c16b537SWarner Losh case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8; /* fall-through */
8110c16b537SWarner Losh default: break;
8120c16b537SWarner Losh }
8130c16b537SWarner Losh contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
8140c16b537SWarner Losh if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */
8150c16b537SWarner Losh bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);
8160c16b537SWarner Losh bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;
8170c16b537SWarner Losh }
8180c16b537SWarner Losh
8190c16b537SWarner Losh return srcSize;
8200c16b537SWarner Losh }
8210c16b537SWarner Losh
BITv05_lookBits(BITv05_DStream_t * bitD,U32 nbBits)8220c16b537SWarner Losh MEM_STATIC size_t BITv05_lookBits(BITv05_DStream_t* bitD, U32 nbBits)
8230c16b537SWarner Losh {
8240c16b537SWarner Losh const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
8250c16b537SWarner Losh return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
8260c16b537SWarner Losh }
8270c16b537SWarner Losh
8280c16b537SWarner Losh /*! BITv05_lookBitsFast :
8290c16b537SWarner Losh * unsafe version; only works only if nbBits >= 1 */
BITv05_lookBitsFast(BITv05_DStream_t * bitD,U32 nbBits)8300c16b537SWarner Losh MEM_STATIC size_t BITv05_lookBitsFast(BITv05_DStream_t* bitD, U32 nbBits)
8310c16b537SWarner Losh {
8320c16b537SWarner Losh const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
8330c16b537SWarner Losh return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
8340c16b537SWarner Losh }
8350c16b537SWarner Losh
BITv05_skipBits(BITv05_DStream_t * bitD,U32 nbBits)8360c16b537SWarner Losh MEM_STATIC void BITv05_skipBits(BITv05_DStream_t* bitD, U32 nbBits)
8370c16b537SWarner Losh {
8380c16b537SWarner Losh bitD->bitsConsumed += nbBits;
8390c16b537SWarner Losh }
8400c16b537SWarner Losh
BITv05_readBits(BITv05_DStream_t * bitD,unsigned nbBits)841a0483764SConrad Meyer MEM_STATIC size_t BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits)
8420c16b537SWarner Losh {
8430c16b537SWarner Losh size_t value = BITv05_lookBits(bitD, nbBits);
8440c16b537SWarner Losh BITv05_skipBits(bitD, nbBits);
8450c16b537SWarner Losh return value;
8460c16b537SWarner Losh }
8470c16b537SWarner Losh
8480c16b537SWarner Losh /*!BITv05_readBitsFast :
8490c16b537SWarner Losh * unsafe version; only works only if nbBits >= 1 */
BITv05_readBitsFast(BITv05_DStream_t * bitD,unsigned nbBits)850a0483764SConrad Meyer MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits)
8510c16b537SWarner Losh {
8520c16b537SWarner Losh size_t value = BITv05_lookBitsFast(bitD, nbBits);
8530c16b537SWarner Losh BITv05_skipBits(bitD, nbBits);
8540c16b537SWarner Losh return value;
8550c16b537SWarner Losh }
8560c16b537SWarner Losh
BITv05_reloadDStream(BITv05_DStream_t * bitD)8570c16b537SWarner Losh MEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD)
8580c16b537SWarner Losh {
8590c16b537SWarner Losh if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
8600c16b537SWarner Losh return BITv05_DStream_overflow;
8610c16b537SWarner Losh
8620c16b537SWarner Losh if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
8630c16b537SWarner Losh bitD->ptr -= bitD->bitsConsumed >> 3;
8640c16b537SWarner Losh bitD->bitsConsumed &= 7;
8650c16b537SWarner Losh bitD->bitContainer = MEM_readLEST(bitD->ptr);
8660c16b537SWarner Losh return BITv05_DStream_unfinished;
8670c16b537SWarner Losh }
8680c16b537SWarner Losh if (bitD->ptr == bitD->start) {
8690c16b537SWarner Losh if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv05_DStream_endOfBuffer;
8700c16b537SWarner Losh return BITv05_DStream_completed;
8710c16b537SWarner Losh }
8720c16b537SWarner Losh {
8730c16b537SWarner Losh U32 nbBytes = bitD->bitsConsumed >> 3;
8740c16b537SWarner Losh BITv05_DStream_status result = BITv05_DStream_unfinished;
8750c16b537SWarner Losh if (bitD->ptr - nbBytes < bitD->start) {
8760c16b537SWarner Losh nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
8770c16b537SWarner Losh result = BITv05_DStream_endOfBuffer;
8780c16b537SWarner Losh }
8790c16b537SWarner Losh bitD->ptr -= nbBytes;
8800c16b537SWarner Losh bitD->bitsConsumed -= nbBytes*8;
8810c16b537SWarner Losh bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
8820c16b537SWarner Losh return result;
8830c16b537SWarner Losh }
8840c16b537SWarner Losh }
8850c16b537SWarner Losh
8860c16b537SWarner Losh /*! BITv05_endOfDStream
8870c16b537SWarner Losh * @return Tells if DStream has reached its exact end
8880c16b537SWarner Losh */
BITv05_endOfDStream(const BITv05_DStream_t * DStream)8890c16b537SWarner Losh MEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* DStream)
8900c16b537SWarner Losh {
8910c16b537SWarner Losh return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
8920c16b537SWarner Losh }
8930c16b537SWarner Losh
8940c16b537SWarner Losh #if defined (__cplusplus)
8950c16b537SWarner Losh }
8960c16b537SWarner Losh #endif
8970c16b537SWarner Losh
8980c16b537SWarner Losh #endif /* BITv05STREAM_H_MODULE */
8990c16b537SWarner Losh /* ******************************************************************
9000c16b537SWarner Losh FSEv05 : Finite State Entropy coder
9010c16b537SWarner Losh header file for static linking (only)
9020c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet
9030c16b537SWarner Losh
9040c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
9050c16b537SWarner Losh
9060c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
9070c16b537SWarner Losh modification, are permitted provided that the following conditions are
9080c16b537SWarner Losh met:
9090c16b537SWarner Losh
9100c16b537SWarner Losh * Redistributions of source code must retain the above copyright
9110c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
9120c16b537SWarner Losh * Redistributions in binary form must reproduce the above
9130c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
9140c16b537SWarner Losh in the documentation and/or other materials provided with the
9150c16b537SWarner Losh distribution.
9160c16b537SWarner Losh
9170c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9180c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9190c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
9200c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9210c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9220c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9230c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9240c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9250c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9260c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
9270c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9280c16b537SWarner Losh
9290c16b537SWarner Losh You can contact the author at :
9300c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
9310c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c
9320c16b537SWarner Losh ****************************************************************** */
9330c16b537SWarner Losh #ifndef FSEv05_STATIC_H
9340c16b537SWarner Losh #define FSEv05_STATIC_H
9350c16b537SWarner Losh
9360c16b537SWarner Losh #if defined (__cplusplus)
9370c16b537SWarner Losh extern "C" {
9380c16b537SWarner Losh #endif
9390c16b537SWarner Losh
9400c16b537SWarner Losh
9410c16b537SWarner Losh
9420c16b537SWarner Losh /* *****************************************
9430c16b537SWarner Losh * Static allocation
9440c16b537SWarner Losh *******************************************/
9450c16b537SWarner Losh /* It is possible to statically allocate FSEv05 CTable/DTable as a table of unsigned using below macros */
9460c16b537SWarner Losh #define FSEv05_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))
9470c16b537SWarner Losh
9480c16b537SWarner Losh
9490c16b537SWarner Losh /* *****************************************
9500c16b537SWarner Losh * FSEv05 advanced API
9510c16b537SWarner Losh *******************************************/
9520c16b537SWarner Losh size_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits);
9530c16b537SWarner Losh /* build a fake FSEv05_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */
9540c16b537SWarner Losh
9550c16b537SWarner Losh size_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, unsigned char symbolValue);
9560c16b537SWarner Losh /* build a fake FSEv05_DTable, designed to always generate the same symbolValue */
9570c16b537SWarner Losh
9580c16b537SWarner Losh
9590c16b537SWarner Losh
9600c16b537SWarner Losh /* *****************************************
9610c16b537SWarner Losh * FSEv05 symbol decompression API
9620c16b537SWarner Losh *******************************************/
9630c16b537SWarner Losh typedef struct
9640c16b537SWarner Losh {
9650c16b537SWarner Losh size_t state;
9660c16b537SWarner Losh const void* table; /* precise table may vary, depending on U16 */
9670c16b537SWarner Losh } FSEv05_DState_t;
9680c16b537SWarner Losh
9690c16b537SWarner Losh
9700c16b537SWarner Losh static void FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt);
9710c16b537SWarner Losh
9720c16b537SWarner Losh static unsigned char FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);
9730c16b537SWarner Losh
9740c16b537SWarner Losh static unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr);
9750c16b537SWarner Losh
9760c16b537SWarner Losh
9770c16b537SWarner Losh
9780c16b537SWarner Losh /* *****************************************
9790c16b537SWarner Losh * FSEv05 unsafe API
9800c16b537SWarner Losh *******************************************/
9810c16b537SWarner Losh static unsigned char FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);
9820c16b537SWarner Losh /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
9830c16b537SWarner Losh
9840c16b537SWarner Losh
9850c16b537SWarner Losh /* *****************************************
9860c16b537SWarner Losh * Implementation of inlined functions
9870c16b537SWarner Losh *******************************************/
9880c16b537SWarner Losh /* decompression */
9890c16b537SWarner Losh
9900c16b537SWarner Losh typedef struct {
9910c16b537SWarner Losh U16 tableLog;
9920c16b537SWarner Losh U16 fastMode;
9930c16b537SWarner Losh } FSEv05_DTableHeader; /* sizeof U32 */
9940c16b537SWarner Losh
9950c16b537SWarner Losh typedef struct
9960c16b537SWarner Losh {
9970c16b537SWarner Losh unsigned short newState;
9980c16b537SWarner Losh unsigned char symbol;
9990c16b537SWarner Losh unsigned char nbBits;
10000c16b537SWarner Losh } FSEv05_decode_t; /* size == U32 */
10010c16b537SWarner Losh
FSEv05_initDState(FSEv05_DState_t * DStatePtr,BITv05_DStream_t * bitD,const FSEv05_DTable * dt)10020c16b537SWarner Losh MEM_STATIC void FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt)
10030c16b537SWarner Losh {
10040c16b537SWarner Losh const void* ptr = dt;
10050c16b537SWarner Losh const FSEv05_DTableHeader* const DTableH = (const FSEv05_DTableHeader*)ptr;
10060c16b537SWarner Losh DStatePtr->state = BITv05_readBits(bitD, DTableH->tableLog);
10070c16b537SWarner Losh BITv05_reloadDStream(bitD);
10080c16b537SWarner Losh DStatePtr->table = dt + 1;
10090c16b537SWarner Losh }
10100c16b537SWarner Losh
FSEv05_peakSymbol(FSEv05_DState_t * DStatePtr)10110c16b537SWarner Losh MEM_STATIC BYTE FSEv05_peakSymbol(FSEv05_DState_t* DStatePtr)
10120c16b537SWarner Losh {
10130c16b537SWarner Losh const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];
10140c16b537SWarner Losh return DInfo.symbol;
10150c16b537SWarner Losh }
10160c16b537SWarner Losh
FSEv05_decodeSymbol(FSEv05_DState_t * DStatePtr,BITv05_DStream_t * bitD)10170c16b537SWarner Losh MEM_STATIC BYTE FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)
10180c16b537SWarner Losh {
10190c16b537SWarner Losh const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];
10200c16b537SWarner Losh const U32 nbBits = DInfo.nbBits;
10210c16b537SWarner Losh BYTE symbol = DInfo.symbol;
10220c16b537SWarner Losh size_t lowBits = BITv05_readBits(bitD, nbBits);
10230c16b537SWarner Losh
10240c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits;
10250c16b537SWarner Losh return symbol;
10260c16b537SWarner Losh }
10270c16b537SWarner Losh
FSEv05_decodeSymbolFast(FSEv05_DState_t * DStatePtr,BITv05_DStream_t * bitD)10280c16b537SWarner Losh MEM_STATIC BYTE FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)
10290c16b537SWarner Losh {
10300c16b537SWarner Losh const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];
10310c16b537SWarner Losh const U32 nbBits = DInfo.nbBits;
10320c16b537SWarner Losh BYTE symbol = DInfo.symbol;
10330c16b537SWarner Losh size_t lowBits = BITv05_readBitsFast(bitD, nbBits);
10340c16b537SWarner Losh
10350c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits;
10360c16b537SWarner Losh return symbol;
10370c16b537SWarner Losh }
10380c16b537SWarner Losh
FSEv05_endOfDState(const FSEv05_DState_t * DStatePtr)10390c16b537SWarner Losh MEM_STATIC unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr)
10400c16b537SWarner Losh {
10410c16b537SWarner Losh return DStatePtr->state == 0;
10420c16b537SWarner Losh }
10430c16b537SWarner Losh
10440c16b537SWarner Losh
10450c16b537SWarner Losh #if defined (__cplusplus)
10460c16b537SWarner Losh }
10470c16b537SWarner Losh #endif
10480c16b537SWarner Losh
10490c16b537SWarner Losh #endif /* FSEv05_STATIC_H */
10500c16b537SWarner Losh /* ******************************************************************
10510c16b537SWarner Losh FSEv05 : Finite State Entropy coder
10520c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet.
10530c16b537SWarner Losh
10540c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
10550c16b537SWarner Losh
10560c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
10570c16b537SWarner Losh modification, are permitted provided that the following conditions are
10580c16b537SWarner Losh met:
10590c16b537SWarner Losh
10600c16b537SWarner Losh * Redistributions of source code must retain the above copyright
10610c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
10620c16b537SWarner Losh * Redistributions in binary form must reproduce the above
10630c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
10640c16b537SWarner Losh in the documentation and/or other materials provided with the
10650c16b537SWarner Losh distribution.
10660c16b537SWarner Losh
10670c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10680c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10690c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
10700c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
10710c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10720c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10730c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10740c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
10750c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10760c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
10770c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10780c16b537SWarner Losh
10790c16b537SWarner Losh You can contact the author at :
10800c16b537SWarner Losh - FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy
10810c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c
10820c16b537SWarner Losh ****************************************************************** */
10830c16b537SWarner Losh
10840c16b537SWarner Losh #ifndef FSEv05_COMMONDEFS_ONLY
10850c16b537SWarner Losh
10860c16b537SWarner Losh /* **************************************************************
10870c16b537SWarner Losh * Tuning parameters
10880c16b537SWarner Losh ****************************************************************/
10890c16b537SWarner Losh /*!MEMORY_USAGE :
10900c16b537SWarner Losh * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
10910c16b537SWarner Losh * Increasing memory usage improves compression ratio
10920c16b537SWarner Losh * Reduced memory usage can improve speed, due to cache effect
10930c16b537SWarner Losh * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
10940c16b537SWarner Losh #define FSEv05_MAX_MEMORY_USAGE 14
10950c16b537SWarner Losh #define FSEv05_DEFAULT_MEMORY_USAGE 13
10960c16b537SWarner Losh
10970c16b537SWarner Losh /*!FSEv05_MAX_SYMBOL_VALUE :
10980c16b537SWarner Losh * Maximum symbol value authorized.
10990c16b537SWarner Losh * Required for proper stack allocation */
11000c16b537SWarner Losh #define FSEv05_MAX_SYMBOL_VALUE 255
11010c16b537SWarner Losh
11020c16b537SWarner Losh
11030c16b537SWarner Losh /* **************************************************************
11040c16b537SWarner Losh * template functions type & suffix
11050c16b537SWarner Losh ****************************************************************/
11060c16b537SWarner Losh #define FSEv05_FUNCTION_TYPE BYTE
11070c16b537SWarner Losh #define FSEv05_FUNCTION_EXTENSION
11080c16b537SWarner Losh #define FSEv05_DECODE_TYPE FSEv05_decode_t
11090c16b537SWarner Losh
11100c16b537SWarner Losh
11110c16b537SWarner Losh #endif /* !FSEv05_COMMONDEFS_ONLY */
11120c16b537SWarner Losh
11130c16b537SWarner Losh /* **************************************************************
11140c16b537SWarner Losh * Compiler specifics
11150c16b537SWarner Losh ****************************************************************/
11160c16b537SWarner Losh #ifdef _MSC_VER /* Visual Studio */
11170c16b537SWarner Losh # define FORCE_INLINE static __forceinline
11180c16b537SWarner Losh # include <intrin.h> /* For Visual 2005 */
11190c16b537SWarner Losh # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
11200c16b537SWarner Losh # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
11210c16b537SWarner Losh #else
11220c16b537SWarner Losh # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
11230c16b537SWarner Losh # ifdef __GNUC__
11240c16b537SWarner Losh # define FORCE_INLINE static inline __attribute__((always_inline))
11250c16b537SWarner Losh # else
11260c16b537SWarner Losh # define FORCE_INLINE static inline
11270c16b537SWarner Losh # endif
11280c16b537SWarner Losh # else
11290c16b537SWarner Losh # define FORCE_INLINE static
11300c16b537SWarner Losh # endif /* __STDC_VERSION__ */
11310c16b537SWarner Losh #endif
11320c16b537SWarner Losh
11330c16b537SWarner Losh
11340c16b537SWarner Losh /* **************************************************************
11350c16b537SWarner Losh * Includes
11360c16b537SWarner Losh ****************************************************************/
11370c16b537SWarner Losh #include <stdlib.h> /* malloc, free, qsort */
11380c16b537SWarner Losh #include <string.h> /* memcpy, memset */
11390c16b537SWarner Losh #include <stdio.h> /* printf (debug) */
11400c16b537SWarner Losh
11410c16b537SWarner Losh
11420c16b537SWarner Losh
11430c16b537SWarner Losh /* ***************************************************************
11440c16b537SWarner Losh * Constants
11450c16b537SWarner Losh *****************************************************************/
11460c16b537SWarner Losh #define FSEv05_MAX_TABLELOG (FSEv05_MAX_MEMORY_USAGE-2)
11470c16b537SWarner Losh #define FSEv05_MAX_TABLESIZE (1U<<FSEv05_MAX_TABLELOG)
11480c16b537SWarner Losh #define FSEv05_MAXTABLESIZE_MASK (FSEv05_MAX_TABLESIZE-1)
11490c16b537SWarner Losh #define FSEv05_DEFAULT_TABLELOG (FSEv05_DEFAULT_MEMORY_USAGE-2)
11500c16b537SWarner Losh #define FSEv05_MIN_TABLELOG 5
11510c16b537SWarner Losh
11520c16b537SWarner Losh #define FSEv05_TABLELOG_ABSOLUTE_MAX 15
11530c16b537SWarner Losh #if FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX
11540c16b537SWarner Losh #error "FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX is not supported"
11550c16b537SWarner Losh #endif
11560c16b537SWarner Losh
11570c16b537SWarner Losh
11580c16b537SWarner Losh /* **************************************************************
11590c16b537SWarner Losh * Error Management
11600c16b537SWarner Losh ****************************************************************/
11610c16b537SWarner Losh #define FSEv05_STATIC_ASSERT(c) { enum { FSEv05_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
11620c16b537SWarner Losh
11630c16b537SWarner Losh
11640c16b537SWarner Losh /* **************************************************************
11650c16b537SWarner Losh * Complex types
11660c16b537SWarner Losh ****************************************************************/
1167a0483764SConrad Meyer typedef unsigned DTable_max_t[FSEv05_DTABLE_SIZE_U32(FSEv05_MAX_TABLELOG)];
11680c16b537SWarner Losh
11690c16b537SWarner Losh
11700c16b537SWarner Losh /* **************************************************************
11710c16b537SWarner Losh * Templates
11720c16b537SWarner Losh ****************************************************************/
11730c16b537SWarner Losh /*
11740c16b537SWarner Losh designed to be included
11750c16b537SWarner Losh for type-specific functions (template emulation in C)
11760c16b537SWarner Losh Objective is to write these functions only once, for improved maintenance
11770c16b537SWarner Losh */
11780c16b537SWarner Losh
11790c16b537SWarner Losh /* safety checks */
11800c16b537SWarner Losh #ifndef FSEv05_FUNCTION_EXTENSION
11810c16b537SWarner Losh # error "FSEv05_FUNCTION_EXTENSION must be defined"
11820c16b537SWarner Losh #endif
11830c16b537SWarner Losh #ifndef FSEv05_FUNCTION_TYPE
11840c16b537SWarner Losh # error "FSEv05_FUNCTION_TYPE must be defined"
11850c16b537SWarner Losh #endif
11860c16b537SWarner Losh
11870c16b537SWarner Losh /* Function names */
11880c16b537SWarner Losh #define FSEv05_CAT(X,Y) X##Y
11890c16b537SWarner Losh #define FSEv05_FUNCTION_NAME(X,Y) FSEv05_CAT(X,Y)
11900c16b537SWarner Losh #define FSEv05_TYPE_NAME(X,Y) FSEv05_CAT(X,Y)
11910c16b537SWarner Losh
11920c16b537SWarner Losh
11930c16b537SWarner Losh /* Function templates */
FSEv05_tableStep(U32 tableSize)11940c16b537SWarner Losh static U32 FSEv05_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }
11950c16b537SWarner Losh
11960c16b537SWarner Losh
11970c16b537SWarner Losh
FSEv05_createDTable(unsigned tableLog)11980c16b537SWarner Losh FSEv05_DTable* FSEv05_createDTable (unsigned tableLog)
11990c16b537SWarner Losh {
12000c16b537SWarner Losh if (tableLog > FSEv05_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv05_TABLELOG_ABSOLUTE_MAX;
12010c16b537SWarner Losh return (FSEv05_DTable*)malloc( FSEv05_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
12020c16b537SWarner Losh }
12030c16b537SWarner Losh
FSEv05_freeDTable(FSEv05_DTable * dt)12040c16b537SWarner Losh void FSEv05_freeDTable (FSEv05_DTable* dt)
12050c16b537SWarner Losh {
12060c16b537SWarner Losh free(dt);
12070c16b537SWarner Losh }
12080c16b537SWarner Losh
FSEv05_buildDTable(FSEv05_DTable * dt,const short * normalizedCounter,unsigned maxSymbolValue,unsigned tableLog)12090c16b537SWarner Losh size_t FSEv05_buildDTable(FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
12100c16b537SWarner Losh {
12110c16b537SWarner Losh FSEv05_DTableHeader DTableH;
12120c16b537SWarner Losh void* const tdPtr = dt+1; /* because dt is unsigned, 32-bits aligned on 32-bits */
12130c16b537SWarner Losh FSEv05_DECODE_TYPE* const tableDecode = (FSEv05_DECODE_TYPE*) (tdPtr);
12140c16b537SWarner Losh const U32 tableSize = 1 << tableLog;
12150c16b537SWarner Losh const U32 tableMask = tableSize-1;
12160c16b537SWarner Losh const U32 step = FSEv05_tableStep(tableSize);
12170c16b537SWarner Losh U16 symbolNext[FSEv05_MAX_SYMBOL_VALUE+1];
12180c16b537SWarner Losh U32 position = 0;
12190c16b537SWarner Losh U32 highThreshold = tableSize-1;
12200c16b537SWarner Losh const S16 largeLimit= (S16)(1 << (tableLog-1));
12210c16b537SWarner Losh U32 noLarge = 1;
12220c16b537SWarner Losh U32 s;
12230c16b537SWarner Losh
12240c16b537SWarner Losh /* Sanity Checks */
12250c16b537SWarner Losh if (maxSymbolValue > FSEv05_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
12260c16b537SWarner Losh if (tableLog > FSEv05_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
12270c16b537SWarner Losh
12280c16b537SWarner Losh /* Init, lay down lowprob symbols */
12290f743729SConrad Meyer memset(tableDecode, 0, sizeof(FSEv05_FUNCTION_TYPE) * (maxSymbolValue+1) ); /* useless init, but keep static analyzer happy, and we don't need to performance optimize legacy decoders */
12300c16b537SWarner Losh DTableH.tableLog = (U16)tableLog;
12310c16b537SWarner Losh for (s=0; s<=maxSymbolValue; s++) {
12320c16b537SWarner Losh if (normalizedCounter[s]==-1) {
12330c16b537SWarner Losh tableDecode[highThreshold--].symbol = (FSEv05_FUNCTION_TYPE)s;
12340c16b537SWarner Losh symbolNext[s] = 1;
12350c16b537SWarner Losh } else {
12360c16b537SWarner Losh if (normalizedCounter[s] >= largeLimit) noLarge=0;
12370c16b537SWarner Losh symbolNext[s] = normalizedCounter[s];
12380c16b537SWarner Losh } }
12390c16b537SWarner Losh
12400c16b537SWarner Losh /* Spread symbols */
12410c16b537SWarner Losh for (s=0; s<=maxSymbolValue; s++) {
12420c16b537SWarner Losh int i;
12430c16b537SWarner Losh for (i=0; i<normalizedCounter[s]; i++) {
12440c16b537SWarner Losh tableDecode[position].symbol = (FSEv05_FUNCTION_TYPE)s;
12450c16b537SWarner Losh position = (position + step) & tableMask;
12460c16b537SWarner Losh while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
12470c16b537SWarner Losh } }
12480c16b537SWarner Losh
12490c16b537SWarner Losh if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
12500c16b537SWarner Losh
12510c16b537SWarner Losh /* Build Decoding table */
12520c16b537SWarner Losh {
12530c16b537SWarner Losh U32 i;
12540c16b537SWarner Losh for (i=0; i<tableSize; i++) {
12550c16b537SWarner Losh FSEv05_FUNCTION_TYPE symbol = (FSEv05_FUNCTION_TYPE)(tableDecode[i].symbol);
12560c16b537SWarner Losh U16 nextState = symbolNext[symbol]++;
12570c16b537SWarner Losh tableDecode[i].nbBits = (BYTE) (tableLog - BITv05_highbit32 ((U32)nextState) );
12580c16b537SWarner Losh tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);
12590c16b537SWarner Losh } }
12600c16b537SWarner Losh
12610c16b537SWarner Losh DTableH.fastMode = (U16)noLarge;
12620c16b537SWarner Losh memcpy(dt, &DTableH, sizeof(DTableH));
12630c16b537SWarner Losh return 0;
12640c16b537SWarner Losh }
12650c16b537SWarner Losh
12660c16b537SWarner Losh
12670c16b537SWarner Losh #ifndef FSEv05_COMMONDEFS_ONLY
12680c16b537SWarner Losh /*-****************************************
12690c16b537SWarner Losh * FSEv05 helper functions
12700c16b537SWarner Losh ******************************************/
FSEv05_isError(size_t code)12710c16b537SWarner Losh unsigned FSEv05_isError(size_t code) { return ERR_isError(code); }
12720c16b537SWarner Losh
FSEv05_getErrorName(size_t code)12730c16b537SWarner Losh const char* FSEv05_getErrorName(size_t code) { return ERR_getErrorName(code); }
12740c16b537SWarner Losh
12750c16b537SWarner Losh
12760c16b537SWarner Losh /*-**************************************************************
12770c16b537SWarner Losh * FSEv05 NCount encoding-decoding
12780c16b537SWarner Losh ****************************************************************/
FSEv05_abs(short a)12790c16b537SWarner Losh static short FSEv05_abs(short a) { return a<0 ? -a : a; }
12800c16b537SWarner Losh
12810c16b537SWarner Losh
FSEv05_readNCount(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize)12820c16b537SWarner Losh size_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
12830c16b537SWarner Losh const void* headerBuffer, size_t hbSize)
12840c16b537SWarner Losh {
12850c16b537SWarner Losh const BYTE* const istart = (const BYTE*) headerBuffer;
12860c16b537SWarner Losh const BYTE* const iend = istart + hbSize;
12870c16b537SWarner Losh const BYTE* ip = istart;
12880c16b537SWarner Losh int nbBits;
12890c16b537SWarner Losh int remaining;
12900c16b537SWarner Losh int threshold;
12910c16b537SWarner Losh U32 bitStream;
12920c16b537SWarner Losh int bitCount;
12930c16b537SWarner Losh unsigned charnum = 0;
12940c16b537SWarner Losh int previous0 = 0;
12950c16b537SWarner Losh
12960c16b537SWarner Losh if (hbSize < 4) return ERROR(srcSize_wrong);
12970c16b537SWarner Losh bitStream = MEM_readLE32(ip);
12980c16b537SWarner Losh nbBits = (bitStream & 0xF) + FSEv05_MIN_TABLELOG; /* extract tableLog */
12990c16b537SWarner Losh if (nbBits > FSEv05_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
13000c16b537SWarner Losh bitStream >>= 4;
13010c16b537SWarner Losh bitCount = 4;
13020c16b537SWarner Losh *tableLogPtr = nbBits;
13030c16b537SWarner Losh remaining = (1<<nbBits)+1;
13040c16b537SWarner Losh threshold = 1<<nbBits;
13050c16b537SWarner Losh nbBits++;
13060c16b537SWarner Losh
13070c16b537SWarner Losh while ((remaining>1) && (charnum<=*maxSVPtr)) {
13080c16b537SWarner Losh if (previous0) {
13090c16b537SWarner Losh unsigned n0 = charnum;
13100c16b537SWarner Losh while ((bitStream & 0xFFFF) == 0xFFFF) {
13110c16b537SWarner Losh n0+=24;
13120c16b537SWarner Losh if (ip < iend-5) {
13130c16b537SWarner Losh ip+=2;
13140c16b537SWarner Losh bitStream = MEM_readLE32(ip) >> bitCount;
13150c16b537SWarner Losh } else {
13160c16b537SWarner Losh bitStream >>= 16;
13170c16b537SWarner Losh bitCount+=16;
13180c16b537SWarner Losh } }
13190c16b537SWarner Losh while ((bitStream & 3) == 3) {
13200c16b537SWarner Losh n0+=3;
13210c16b537SWarner Losh bitStream>>=2;
13220c16b537SWarner Losh bitCount+=2;
13230c16b537SWarner Losh }
13240c16b537SWarner Losh n0 += bitStream & 3;
13250c16b537SWarner Losh bitCount += 2;
13260c16b537SWarner Losh if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
13270c16b537SWarner Losh while (charnum < n0) normalizedCounter[charnum++] = 0;
13280c16b537SWarner Losh if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
13290c16b537SWarner Losh ip += bitCount>>3;
13300c16b537SWarner Losh bitCount &= 7;
13310c16b537SWarner Losh bitStream = MEM_readLE32(ip) >> bitCount;
13320c16b537SWarner Losh }
13330c16b537SWarner Losh else
13340c16b537SWarner Losh bitStream >>= 2;
13350c16b537SWarner Losh }
13360c16b537SWarner Losh {
13370c16b537SWarner Losh const short max = (short)((2*threshold-1)-remaining);
13380c16b537SWarner Losh short count;
13390c16b537SWarner Losh
13400c16b537SWarner Losh if ((bitStream & (threshold-1)) < (U32)max) {
13410c16b537SWarner Losh count = (short)(bitStream & (threshold-1));
13420c16b537SWarner Losh bitCount += nbBits-1;
13430c16b537SWarner Losh } else {
13440c16b537SWarner Losh count = (short)(bitStream & (2*threshold-1));
13450c16b537SWarner Losh if (count >= threshold) count -= max;
13460c16b537SWarner Losh bitCount += nbBits;
13470c16b537SWarner Losh }
13480c16b537SWarner Losh
13490c16b537SWarner Losh count--; /* extra accuracy */
13500c16b537SWarner Losh remaining -= FSEv05_abs(count);
13510c16b537SWarner Losh normalizedCounter[charnum++] = count;
13520c16b537SWarner Losh previous0 = !count;
13530c16b537SWarner Losh while (remaining < threshold) {
13540c16b537SWarner Losh nbBits--;
13550c16b537SWarner Losh threshold >>= 1;
13560c16b537SWarner Losh }
13570c16b537SWarner Losh
13580c16b537SWarner Losh if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
13590c16b537SWarner Losh ip += bitCount>>3;
13600c16b537SWarner Losh bitCount &= 7;
13610c16b537SWarner Losh } else {
13620c16b537SWarner Losh bitCount -= (int)(8 * (iend - 4 - ip));
13630c16b537SWarner Losh ip = iend - 4;
13640c16b537SWarner Losh }
13650c16b537SWarner Losh bitStream = MEM_readLE32(ip) >> (bitCount & 31);
13660c16b537SWarner Losh } }
13670c16b537SWarner Losh if (remaining != 1) return ERROR(GENERIC);
13680c16b537SWarner Losh *maxSVPtr = charnum-1;
13690c16b537SWarner Losh
13700c16b537SWarner Losh ip += (bitCount+7)>>3;
13710c16b537SWarner Losh if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);
13720c16b537SWarner Losh return ip-istart;
13730c16b537SWarner Losh }
13740c16b537SWarner Losh
13750c16b537SWarner Losh
13760c16b537SWarner Losh
13770c16b537SWarner Losh /*-*******************************************************
13780c16b537SWarner Losh * Decompression (Byte symbols)
13790c16b537SWarner Losh *********************************************************/
FSEv05_buildDTable_rle(FSEv05_DTable * dt,BYTE symbolValue)13800c16b537SWarner Losh size_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, BYTE symbolValue)
13810c16b537SWarner Losh {
13820c16b537SWarner Losh void* ptr = dt;
13830c16b537SWarner Losh FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;
13840c16b537SWarner Losh void* dPtr = dt + 1;
13850c16b537SWarner Losh FSEv05_decode_t* const cell = (FSEv05_decode_t*)dPtr;
13860c16b537SWarner Losh
13870c16b537SWarner Losh DTableH->tableLog = 0;
13880c16b537SWarner Losh DTableH->fastMode = 0;
13890c16b537SWarner Losh
13900c16b537SWarner Losh cell->newState = 0;
13910c16b537SWarner Losh cell->symbol = symbolValue;
13920c16b537SWarner Losh cell->nbBits = 0;
13930c16b537SWarner Losh
13940c16b537SWarner Losh return 0;
13950c16b537SWarner Losh }
13960c16b537SWarner Losh
13970c16b537SWarner Losh
FSEv05_buildDTable_raw(FSEv05_DTable * dt,unsigned nbBits)13980c16b537SWarner Losh size_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits)
13990c16b537SWarner Losh {
14000c16b537SWarner Losh void* ptr = dt;
14010c16b537SWarner Losh FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;
14020c16b537SWarner Losh void* dPtr = dt + 1;
14030c16b537SWarner Losh FSEv05_decode_t* const dinfo = (FSEv05_decode_t*)dPtr;
14040c16b537SWarner Losh const unsigned tableSize = 1 << nbBits;
14050c16b537SWarner Losh const unsigned tableMask = tableSize - 1;
14060c16b537SWarner Losh const unsigned maxSymbolValue = tableMask;
14070c16b537SWarner Losh unsigned s;
14080c16b537SWarner Losh
14090c16b537SWarner Losh /* Sanity checks */
14100c16b537SWarner Losh if (nbBits < 1) return ERROR(GENERIC); /* min size */
14110c16b537SWarner Losh
14120c16b537SWarner Losh /* Build Decoding Table */
14130c16b537SWarner Losh DTableH->tableLog = (U16)nbBits;
14140c16b537SWarner Losh DTableH->fastMode = 1;
14150c16b537SWarner Losh for (s=0; s<=maxSymbolValue; s++) {
14160c16b537SWarner Losh dinfo[s].newState = 0;
14170c16b537SWarner Losh dinfo[s].symbol = (BYTE)s;
14180c16b537SWarner Losh dinfo[s].nbBits = (BYTE)nbBits;
14190c16b537SWarner Losh }
14200c16b537SWarner Losh
14210c16b537SWarner Losh return 0;
14220c16b537SWarner Losh }
14230c16b537SWarner Losh
FSEv05_decompress_usingDTable_generic(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const FSEv05_DTable * dt,const unsigned fast)14240c16b537SWarner Losh FORCE_INLINE size_t FSEv05_decompress_usingDTable_generic(
14250c16b537SWarner Losh void* dst, size_t maxDstSize,
14260c16b537SWarner Losh const void* cSrc, size_t cSrcSize,
14270c16b537SWarner Losh const FSEv05_DTable* dt, const unsigned fast)
14280c16b537SWarner Losh {
14290c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst;
14300c16b537SWarner Losh BYTE* op = ostart;
14310c16b537SWarner Losh BYTE* const omax = op + maxDstSize;
14320c16b537SWarner Losh BYTE* const olimit = omax-3;
14330c16b537SWarner Losh
14340c16b537SWarner Losh BITv05_DStream_t bitD;
14350c16b537SWarner Losh FSEv05_DState_t state1;
14360c16b537SWarner Losh FSEv05_DState_t state2;
14370c16b537SWarner Losh size_t errorCode;
14380c16b537SWarner Losh
14390c16b537SWarner Losh /* Init */
14400c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */
14410c16b537SWarner Losh if (FSEv05_isError(errorCode)) return errorCode;
14420c16b537SWarner Losh
14430c16b537SWarner Losh FSEv05_initDState(&state1, &bitD, dt);
14440c16b537SWarner Losh FSEv05_initDState(&state2, &bitD, dt);
14450c16b537SWarner Losh
14460c16b537SWarner Losh #define FSEv05_GETSYMBOL(statePtr) fast ? FSEv05_decodeSymbolFast(statePtr, &bitD) : FSEv05_decodeSymbol(statePtr, &bitD)
14470c16b537SWarner Losh
14480c16b537SWarner Losh /* 4 symbols per loop */
14490c16b537SWarner Losh for ( ; (BITv05_reloadDStream(&bitD)==BITv05_DStream_unfinished) && (op<olimit) ; op+=4) {
14500c16b537SWarner Losh op[0] = FSEv05_GETSYMBOL(&state1);
14510c16b537SWarner Losh
14520c16b537SWarner Losh if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
14530c16b537SWarner Losh BITv05_reloadDStream(&bitD);
14540c16b537SWarner Losh
14550c16b537SWarner Losh op[1] = FSEv05_GETSYMBOL(&state2);
14560c16b537SWarner Losh
14570c16b537SWarner Losh if (FSEv05_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
14580c16b537SWarner Losh { if (BITv05_reloadDStream(&bitD) > BITv05_DStream_unfinished) { op+=2; break; } }
14590c16b537SWarner Losh
14600c16b537SWarner Losh op[2] = FSEv05_GETSYMBOL(&state1);
14610c16b537SWarner Losh
14620c16b537SWarner Losh if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
14630c16b537SWarner Losh BITv05_reloadDStream(&bitD);
14640c16b537SWarner Losh
14650c16b537SWarner Losh op[3] = FSEv05_GETSYMBOL(&state2);
14660c16b537SWarner Losh }
14670c16b537SWarner Losh
14680c16b537SWarner Losh /* tail */
14690c16b537SWarner Losh /* note : BITv05_reloadDStream(&bitD) >= FSEv05_DStream_partiallyFilled; Ends at exactly BITv05_DStream_completed */
14700c16b537SWarner Losh while (1) {
14710c16b537SWarner Losh if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state1))) )
14720c16b537SWarner Losh break;
14730c16b537SWarner Losh
14740c16b537SWarner Losh *op++ = FSEv05_GETSYMBOL(&state1);
14750c16b537SWarner Losh
14760c16b537SWarner Losh if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state2))) )
14770c16b537SWarner Losh break;
14780c16b537SWarner Losh
14790c16b537SWarner Losh *op++ = FSEv05_GETSYMBOL(&state2);
14800c16b537SWarner Losh }
14810c16b537SWarner Losh
14820c16b537SWarner Losh /* end ? */
14830c16b537SWarner Losh if (BITv05_endOfDStream(&bitD) && FSEv05_endOfDState(&state1) && FSEv05_endOfDState(&state2))
14840c16b537SWarner Losh return op-ostart;
14850c16b537SWarner Losh
14860c16b537SWarner Losh if (op==omax) return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */
14870c16b537SWarner Losh
14880c16b537SWarner Losh return ERROR(corruption_detected);
14890c16b537SWarner Losh }
14900c16b537SWarner Losh
14910c16b537SWarner Losh
FSEv05_decompress_usingDTable(void * dst,size_t originalSize,const void * cSrc,size_t cSrcSize,const FSEv05_DTable * dt)14920c16b537SWarner Losh size_t FSEv05_decompress_usingDTable(void* dst, size_t originalSize,
14930c16b537SWarner Losh const void* cSrc, size_t cSrcSize,
14940c16b537SWarner Losh const FSEv05_DTable* dt)
14950c16b537SWarner Losh {
14960c16b537SWarner Losh const void* ptr = dt;
14970c16b537SWarner Losh const FSEv05_DTableHeader* DTableH = (const FSEv05_DTableHeader*)ptr;
14980c16b537SWarner Losh const U32 fastMode = DTableH->fastMode;
14990c16b537SWarner Losh
15000c16b537SWarner Losh /* select fast mode (static) */
15010c16b537SWarner Losh if (fastMode) return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
15020c16b537SWarner Losh return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
15030c16b537SWarner Losh }
15040c16b537SWarner Losh
15050c16b537SWarner Losh
FSEv05_decompress(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize)15060c16b537SWarner Losh size_t FSEv05_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
15070c16b537SWarner Losh {
15080c16b537SWarner Losh const BYTE* const istart = (const BYTE*)cSrc;
15090c16b537SWarner Losh const BYTE* ip = istart;
15100c16b537SWarner Losh short counting[FSEv05_MAX_SYMBOL_VALUE+1];
15110c16b537SWarner Losh DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */
15120c16b537SWarner Losh unsigned tableLog;
15130c16b537SWarner Losh unsigned maxSymbolValue = FSEv05_MAX_SYMBOL_VALUE;
15140c16b537SWarner Losh size_t errorCode;
15150c16b537SWarner Losh
15160c16b537SWarner Losh if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */
15170c16b537SWarner Losh
15180c16b537SWarner Losh /* normal FSEv05 decoding mode */
15190c16b537SWarner Losh errorCode = FSEv05_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
15200c16b537SWarner Losh if (FSEv05_isError(errorCode)) return errorCode;
15210c16b537SWarner Losh if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */
15220c16b537SWarner Losh ip += errorCode;
15230c16b537SWarner Losh cSrcSize -= errorCode;
15240c16b537SWarner Losh
15250c16b537SWarner Losh errorCode = FSEv05_buildDTable (dt, counting, maxSymbolValue, tableLog);
15260c16b537SWarner Losh if (FSEv05_isError(errorCode)) return errorCode;
15270c16b537SWarner Losh
15280c16b537SWarner Losh /* always return, even if it is an error code */
15290c16b537SWarner Losh return FSEv05_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);
15300c16b537SWarner Losh }
15310c16b537SWarner Losh
15320c16b537SWarner Losh
15330c16b537SWarner Losh
15340c16b537SWarner Losh #endif /* FSEv05_COMMONDEFS_ONLY */
15350c16b537SWarner Losh /* ******************************************************************
15360c16b537SWarner Losh Huff0 : Huffman coder, part of New Generation Entropy library
15370c16b537SWarner Losh header file
15380c16b537SWarner Losh Copyright (C) 2013-2016, Yann Collet.
15390c16b537SWarner Losh
15400c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
15410c16b537SWarner Losh
15420c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
15430c16b537SWarner Losh modification, are permitted provided that the following conditions are
15440c16b537SWarner Losh met:
15450c16b537SWarner Losh
15460c16b537SWarner Losh * Redistributions of source code must retain the above copyright
15470c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
15480c16b537SWarner Losh * Redistributions in binary form must reproduce the above
15490c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
15500c16b537SWarner Losh in the documentation and/or other materials provided with the
15510c16b537SWarner Losh distribution.
15520c16b537SWarner Losh
15530c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15540c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15550c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
15560c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
15570c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
15580c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
15590c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15600c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
15610c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15620c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15630c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15640c16b537SWarner Losh
15650c16b537SWarner Losh You can contact the author at :
15660c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
15670c16b537SWarner Losh ****************************************************************** */
15680c16b537SWarner Losh #ifndef HUFF0_H
15690c16b537SWarner Losh #define HUFF0_H
15700c16b537SWarner Losh
15710c16b537SWarner Losh #if defined (__cplusplus)
15720c16b537SWarner Losh extern "C" {
15730c16b537SWarner Losh #endif
15740c16b537SWarner Losh
15750c16b537SWarner Losh
15760c16b537SWarner Losh
15770c16b537SWarner Losh /* ****************************************
15780c16b537SWarner Losh * Huff0 simple functions
15790c16b537SWarner Losh ******************************************/
15800c16b537SWarner Losh size_t HUFv05_decompress(void* dst, size_t dstSize,
15810c16b537SWarner Losh const void* cSrc, size_t cSrcSize);
15820c16b537SWarner Losh /*!
15830c16b537SWarner Losh HUFv05_decompress():
15840c16b537SWarner Losh Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',
15850c16b537SWarner Losh into already allocated destination buffer 'dst', of size 'dstSize'.
15860c16b537SWarner Losh @dstSize : must be the **exact** size of original (uncompressed) data.
15870c16b537SWarner Losh Note : in contrast with FSEv05, HUFv05_decompress can regenerate
15880c16b537SWarner Losh RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
15890c16b537SWarner Losh because it knows size to regenerate.
15900c16b537SWarner Losh @return : size of regenerated data (== dstSize)
15910c16b537SWarner Losh or an error code, which can be tested using HUFv05_isError()
15920c16b537SWarner Losh */
15930c16b537SWarner Losh
15940c16b537SWarner Losh
15950c16b537SWarner Losh /* ****************************************
15960c16b537SWarner Losh * Tool functions
15970c16b537SWarner Losh ******************************************/
15980c16b537SWarner Losh /* Error Management */
15990c16b537SWarner Losh unsigned HUFv05_isError(size_t code); /* tells if a return value is an error code */
16000c16b537SWarner Losh const char* HUFv05_getErrorName(size_t code); /* provides error code string (useful for debugging) */
16010c16b537SWarner Losh
16020c16b537SWarner Losh
16030c16b537SWarner Losh #if defined (__cplusplus)
16040c16b537SWarner Losh }
16050c16b537SWarner Losh #endif
16060c16b537SWarner Losh
16070c16b537SWarner Losh #endif /* HUF0_H */
16080c16b537SWarner Losh /* ******************************************************************
16090c16b537SWarner Losh Huff0 : Huffman codec, part of New Generation Entropy library
16100c16b537SWarner Losh header file, for static linking only
16110c16b537SWarner Losh Copyright (C) 2013-2016, Yann Collet
16120c16b537SWarner Losh
16130c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
16140c16b537SWarner Losh
16150c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
16160c16b537SWarner Losh modification, are permitted provided that the following conditions are
16170c16b537SWarner Losh met:
16180c16b537SWarner Losh
16190c16b537SWarner Losh * Redistributions of source code must retain the above copyright
16200c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
16210c16b537SWarner Losh * Redistributions in binary form must reproduce the above
16220c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
16230c16b537SWarner Losh in the documentation and/or other materials provided with the
16240c16b537SWarner Losh distribution.
16250c16b537SWarner Losh
16260c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16270c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16280c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16290c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
16300c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
16310c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
16320c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
16330c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16340c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16350c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
16360c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16370c16b537SWarner Losh
16380c16b537SWarner Losh You can contact the author at :
16390c16b537SWarner Losh - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
16400c16b537SWarner Losh ****************************************************************** */
16410c16b537SWarner Losh #ifndef HUF0_STATIC_H
16420c16b537SWarner Losh #define HUF0_STATIC_H
16430c16b537SWarner Losh
16440c16b537SWarner Losh #if defined (__cplusplus)
16450c16b537SWarner Losh extern "C" {
16460c16b537SWarner Losh #endif
16470c16b537SWarner Losh
16480c16b537SWarner Losh
16490c16b537SWarner Losh
16500c16b537SWarner Losh /* ****************************************
16510c16b537SWarner Losh * Static allocation
16520c16b537SWarner Losh ******************************************/
16530c16b537SWarner Losh /* static allocation of Huff0's DTable */
16540c16b537SWarner Losh #define HUFv05_DTABLE_SIZE(maxTableLog) (1 + (1<<maxTableLog))
16550c16b537SWarner Losh #define HUFv05_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
16560c16b537SWarner Losh unsigned short DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }
16570c16b537SWarner Losh #define HUFv05_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
16580c16b537SWarner Losh unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }
16590c16b537SWarner Losh #define HUFv05_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \
16600c16b537SWarner Losh unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }
16610c16b537SWarner Losh
16620c16b537SWarner Losh
16630c16b537SWarner Losh /* ****************************************
16640c16b537SWarner Losh * Advanced decompression functions
16650c16b537SWarner Losh ******************************************/
16660c16b537SWarner Losh size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
16670c16b537SWarner Losh size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */
16680c16b537SWarner Losh
16690c16b537SWarner Losh
16700c16b537SWarner Losh /* ****************************************
16710c16b537SWarner Losh * Huff0 detailed API
16720c16b537SWarner Losh ******************************************/
16730c16b537SWarner Losh /*!
16740c16b537SWarner Losh HUFv05_decompress() does the following:
16750c16b537SWarner Losh 1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics
16760c16b537SWarner Losh 2. build Huffman table from save, using HUFv05_readDTableXn()
16770c16b537SWarner Losh 3. decode 1 or 4 segments in parallel using HUFv05_decompressSXn_usingDTable
16780c16b537SWarner Losh */
16790c16b537SWarner Losh size_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);
16800c16b537SWarner Losh size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);
16810c16b537SWarner Losh
16820c16b537SWarner Losh size_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);
16830c16b537SWarner Losh size_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);
16840c16b537SWarner Losh
16850c16b537SWarner Losh
16860c16b537SWarner Losh /* single stream variants */
16870c16b537SWarner Losh
16880c16b537SWarner Losh size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
16890c16b537SWarner Losh size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
16900c16b537SWarner Losh
16910c16b537SWarner Losh size_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);
16920c16b537SWarner Losh size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);
16930c16b537SWarner Losh
16940c16b537SWarner Losh
16950c16b537SWarner Losh
16960c16b537SWarner Losh #if defined (__cplusplus)
16970c16b537SWarner Losh }
16980c16b537SWarner Losh #endif
16990c16b537SWarner Losh
17000c16b537SWarner Losh #endif /* HUF0_STATIC_H */
17010c16b537SWarner Losh /* ******************************************************************
17020c16b537SWarner Losh Huff0 : Huffman coder, part of New Generation Entropy library
17030c16b537SWarner Losh Copyright (C) 2013-2015, Yann Collet.
17040c16b537SWarner Losh
17050c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
17060c16b537SWarner Losh
17070c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
17080c16b537SWarner Losh modification, are permitted provided that the following conditions are
17090c16b537SWarner Losh met:
17100c16b537SWarner Losh
17110c16b537SWarner Losh * Redistributions of source code must retain the above copyright
17120c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
17130c16b537SWarner Losh * Redistributions in binary form must reproduce the above
17140c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
17150c16b537SWarner Losh in the documentation and/or other materials provided with the
17160c16b537SWarner Losh distribution.
17170c16b537SWarner Losh
17180c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17190c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17200c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17210c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17220c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17230c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
17240c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
17250c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
17260c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17270c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
17280c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17290c16b537SWarner Losh
17300c16b537SWarner Losh You can contact the author at :
17310c16b537SWarner Losh - FSEv05+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy
17320c16b537SWarner Losh - Public forum : https://groups.google.com/forum/#!forum/lz4c
17330c16b537SWarner Losh ****************************************************************** */
17340c16b537SWarner Losh
17350c16b537SWarner Losh /* **************************************************************
17360c16b537SWarner Losh * Compiler specifics
17370c16b537SWarner Losh ****************************************************************/
17380c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
17390c16b537SWarner Losh /* inline is defined */
17400c16b537SWarner Losh #elif defined(_MSC_VER)
17410c16b537SWarner Losh # define inline __inline
17420c16b537SWarner Losh #else
17430c16b537SWarner Losh # define inline /* disable inline */
17440c16b537SWarner Losh #endif
17450c16b537SWarner Losh
17460c16b537SWarner Losh
17470c16b537SWarner Losh #ifdef _MSC_VER /* Visual Studio */
17480c16b537SWarner Losh # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
17490c16b537SWarner Losh #endif
17500c16b537SWarner Losh
17510c16b537SWarner Losh
17520c16b537SWarner Losh /* **************************************************************
17530c16b537SWarner Losh * Includes
17540c16b537SWarner Losh ****************************************************************/
17550c16b537SWarner Losh #include <stdlib.h> /* malloc, free, qsort */
17560c16b537SWarner Losh #include <string.h> /* memcpy, memset */
17570c16b537SWarner Losh #include <stdio.h> /* printf (debug) */
17580c16b537SWarner Losh
17590c16b537SWarner Losh
17600c16b537SWarner Losh /* **************************************************************
17610c16b537SWarner Losh * Constants
17620c16b537SWarner Losh ****************************************************************/
17630c16b537SWarner Losh #define HUFv05_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUFv05_MAX_TABLELOG. Beyond that value, code does not work */
17640c16b537SWarner Losh #define HUFv05_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUFv05_ABSOLUTEMAX_TABLELOG */
17650c16b537SWarner Losh #define HUFv05_DEFAULT_TABLELOG HUFv05_MAX_TABLELOG /* tableLog by default, when not specified */
17660c16b537SWarner Losh #define HUFv05_MAX_SYMBOL_VALUE 255
17670c16b537SWarner Losh #if (HUFv05_MAX_TABLELOG > HUFv05_ABSOLUTEMAX_TABLELOG)
17680c16b537SWarner Losh # error "HUFv05_MAX_TABLELOG is too large !"
17690c16b537SWarner Losh #endif
17700c16b537SWarner Losh
17710c16b537SWarner Losh
17720c16b537SWarner Losh /* **************************************************************
17730c16b537SWarner Losh * Error Management
17740c16b537SWarner Losh ****************************************************************/
HUFv05_isError(size_t code)17750c16b537SWarner Losh unsigned HUFv05_isError(size_t code) { return ERR_isError(code); }
HUFv05_getErrorName(size_t code)17760c16b537SWarner Losh const char* HUFv05_getErrorName(size_t code) { return ERR_getErrorName(code); }
17770c16b537SWarner Losh #define HUFv05_STATIC_ASSERT(c) { enum { HUFv05_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
17780c16b537SWarner Losh
17790c16b537SWarner Losh
17800c16b537SWarner Losh /* *******************************************************
17810c16b537SWarner Losh * Huff0 : Huffman block decompression
17820c16b537SWarner Losh *********************************************************/
17830c16b537SWarner Losh typedef struct { BYTE byte; BYTE nbBits; } HUFv05_DEltX2; /* single-symbol decoding */
17840c16b537SWarner Losh
17850c16b537SWarner Losh typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv05_DEltX4; /* double-symbols decoding */
17860c16b537SWarner Losh
17870c16b537SWarner Losh typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
17880c16b537SWarner Losh
17890c16b537SWarner Losh /*! HUFv05_readStats
17900c16b537SWarner Losh Read compact Huffman tree, saved by HUFv05_writeCTable
17910c16b537SWarner Losh @huffWeight : destination buffer
17920c16b537SWarner Losh @return : size read from `src`
17930c16b537SWarner Losh */
HUFv05_readStats(BYTE * huffWeight,size_t hwSize,U32 * rankStats,U32 * nbSymbolsPtr,U32 * tableLogPtr,const void * src,size_t srcSize)17940c16b537SWarner Losh static size_t HUFv05_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
17950c16b537SWarner Losh U32* nbSymbolsPtr, U32* tableLogPtr,
17960c16b537SWarner Losh const void* src, size_t srcSize)
17970c16b537SWarner Losh {
17980c16b537SWarner Losh U32 weightTotal;
17990c16b537SWarner Losh U32 tableLog;
18000c16b537SWarner Losh const BYTE* ip = (const BYTE*) src;
18010c16b537SWarner Losh size_t iSize;
18020c16b537SWarner Losh size_t oSize;
18030c16b537SWarner Losh U32 n;
18040c16b537SWarner Losh
18050c16b537SWarner Losh if (!srcSize) return ERROR(srcSize_wrong);
18060c16b537SWarner Losh iSize = ip[0];
180737f1f268SConrad Meyer /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */
18080c16b537SWarner Losh
18090c16b537SWarner Losh if (iSize >= 128) { /* special header */
18100c16b537SWarner Losh if (iSize >= (242)) { /* RLE */
18110c16b537SWarner Losh static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
18120c16b537SWarner Losh oSize = l[iSize-242];
18130c16b537SWarner Losh memset(huffWeight, 1, hwSize);
18140c16b537SWarner Losh iSize = 0;
18150c16b537SWarner Losh }
18160c16b537SWarner Losh else { /* Incompressible */
18170c16b537SWarner Losh oSize = iSize - 127;
18180c16b537SWarner Losh iSize = ((oSize+1)/2);
18190c16b537SWarner Losh if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
18200c16b537SWarner Losh if (oSize >= hwSize) return ERROR(corruption_detected);
18210c16b537SWarner Losh ip += 1;
18220c16b537SWarner Losh for (n=0; n<oSize; n+=2) {
18230c16b537SWarner Losh huffWeight[n] = ip[n/2] >> 4;
18240c16b537SWarner Losh huffWeight[n+1] = ip[n/2] & 15;
18250c16b537SWarner Losh } } }
18260c16b537SWarner Losh else { /* header compressed with FSEv05 (normal case) */
18270c16b537SWarner Losh if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
18280c16b537SWarner Losh oSize = FSEv05_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */
18290c16b537SWarner Losh if (FSEv05_isError(oSize)) return oSize;
18300c16b537SWarner Losh }
18310c16b537SWarner Losh
18320c16b537SWarner Losh /* collect weight stats */
18330c16b537SWarner Losh memset(rankStats, 0, (HUFv05_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));
18340c16b537SWarner Losh weightTotal = 0;
18350c16b537SWarner Losh for (n=0; n<oSize; n++) {
18360c16b537SWarner Losh if (huffWeight[n] >= HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);
18370c16b537SWarner Losh rankStats[huffWeight[n]]++;
18380c16b537SWarner Losh weightTotal += (1 << huffWeight[n]) >> 1;
18390c16b537SWarner Losh }
18400c16b537SWarner Losh if (weightTotal == 0) return ERROR(corruption_detected);
18410c16b537SWarner Losh
18420c16b537SWarner Losh /* get last non-null symbol weight (implied, total must be 2^n) */
18430c16b537SWarner Losh tableLog = BITv05_highbit32(weightTotal) + 1;
18440c16b537SWarner Losh if (tableLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);
18450c16b537SWarner Losh { /* determine last weight */
18460c16b537SWarner Losh U32 total = 1 << tableLog;
18470c16b537SWarner Losh U32 rest = total - weightTotal;
18480c16b537SWarner Losh U32 verif = 1 << BITv05_highbit32(rest);
18490c16b537SWarner Losh U32 lastWeight = BITv05_highbit32(rest) + 1;
18500c16b537SWarner Losh if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */
18510c16b537SWarner Losh huffWeight[oSize] = (BYTE)lastWeight;
18520c16b537SWarner Losh rankStats[lastWeight]++;
18530c16b537SWarner Losh }
18540c16b537SWarner Losh
18550c16b537SWarner Losh /* check tree construction validity */
18560c16b537SWarner Losh if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
18570c16b537SWarner Losh
18580c16b537SWarner Losh /* results */
18590c16b537SWarner Losh *nbSymbolsPtr = (U32)(oSize+1);
18600c16b537SWarner Losh *tableLogPtr = tableLog;
18610c16b537SWarner Losh return iSize+1;
18620c16b537SWarner Losh }
18630c16b537SWarner Losh
18640c16b537SWarner Losh
18650c16b537SWarner Losh /*-***************************/
18660c16b537SWarner Losh /* single-symbol decoding */
18670c16b537SWarner Losh /*-***************************/
18680c16b537SWarner Losh
HUFv05_readDTableX2(U16 * DTable,const void * src,size_t srcSize)18690c16b537SWarner Losh size_t HUFv05_readDTableX2 (U16* DTable, const void* src, size_t srcSize)
18700c16b537SWarner Losh {
18710c16b537SWarner Losh BYTE huffWeight[HUFv05_MAX_SYMBOL_VALUE + 1];
18720c16b537SWarner Losh U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */
18730c16b537SWarner Losh U32 tableLog = 0;
18740c16b537SWarner Losh size_t iSize;
18750c16b537SWarner Losh U32 nbSymbols = 0;
18760c16b537SWarner Losh U32 n;
18770c16b537SWarner Losh U32 nextRankStart;
18780c16b537SWarner Losh void* const dtPtr = DTable + 1;
18790c16b537SWarner Losh HUFv05_DEltX2* const dt = (HUFv05_DEltX2*)dtPtr;
18800c16b537SWarner Losh
18810c16b537SWarner Losh HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */
188237f1f268SConrad Meyer /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
18830c16b537SWarner Losh
18840c16b537SWarner Losh iSize = HUFv05_readStats(huffWeight, HUFv05_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
18850c16b537SWarner Losh if (HUFv05_isError(iSize)) return iSize;
18860c16b537SWarner Losh
18870c16b537SWarner Losh /* check result */
18880c16b537SWarner Losh if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge); /* DTable is too small */
18890c16b537SWarner Losh DTable[0] = (U16)tableLog; /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */
18900c16b537SWarner Losh
18910c16b537SWarner Losh /* Prepare ranks */
18920c16b537SWarner Losh nextRankStart = 0;
18930c16b537SWarner Losh for (n=1; n<=tableLog; n++) {
18940c16b537SWarner Losh U32 current = nextRankStart;
18950c16b537SWarner Losh nextRankStart += (rankVal[n] << (n-1));
18960c16b537SWarner Losh rankVal[n] = current;
18970c16b537SWarner Losh }
18980c16b537SWarner Losh
18990c16b537SWarner Losh /* fill DTable */
19000c16b537SWarner Losh for (n=0; n<nbSymbols; n++) {
19010c16b537SWarner Losh const U32 w = huffWeight[n];
19020c16b537SWarner Losh const U32 length = (1 << w) >> 1;
19030c16b537SWarner Losh U32 i;
19040c16b537SWarner Losh HUFv05_DEltX2 D;
19050c16b537SWarner Losh D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
19060c16b537SWarner Losh for (i = rankVal[w]; i < rankVal[w] + length; i++)
19070c16b537SWarner Losh dt[i] = D;
19080c16b537SWarner Losh rankVal[w] += length;
19090c16b537SWarner Losh }
19100c16b537SWarner Losh
19110c16b537SWarner Losh return iSize;
19120c16b537SWarner Losh }
19130c16b537SWarner Losh
HUFv05_decodeSymbolX2(BITv05_DStream_t * Dstream,const HUFv05_DEltX2 * dt,const U32 dtLog)19140c16b537SWarner Losh static BYTE HUFv05_decodeSymbolX2(BITv05_DStream_t* Dstream, const HUFv05_DEltX2* dt, const U32 dtLog)
19150c16b537SWarner Losh {
19160c16b537SWarner Losh const size_t val = BITv05_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
19170c16b537SWarner Losh const BYTE c = dt[val].byte;
19180c16b537SWarner Losh BITv05_skipBits(Dstream, dt[val].nbBits);
19190c16b537SWarner Losh return c;
19200c16b537SWarner Losh }
19210c16b537SWarner Losh
19220c16b537SWarner Losh #define HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
19230c16b537SWarner Losh *ptr++ = HUFv05_decodeSymbolX2(DStreamPtr, dt, dtLog)
19240c16b537SWarner Losh
19250c16b537SWarner Losh #define HUFv05_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
19260c16b537SWarner Losh if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \
19270c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
19280c16b537SWarner Losh
19290c16b537SWarner Losh #define HUFv05_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
19300c16b537SWarner Losh if (MEM_64bits()) \
19310c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
19320c16b537SWarner Losh
HUFv05_decodeStreamX2(BYTE * p,BITv05_DStream_t * const bitDPtr,BYTE * const pEnd,const HUFv05_DEltX2 * const dt,const U32 dtLog)19330c16b537SWarner Losh static inline size_t HUFv05_decodeStreamX2(BYTE* p, BITv05_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv05_DEltX2* const dt, const U32 dtLog)
19340c16b537SWarner Losh {
19350c16b537SWarner Losh BYTE* const pStart = p;
19360c16b537SWarner Losh
19370c16b537SWarner Losh /* up to 4 symbols at a time */
19380c16b537SWarner Losh while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-4)) {
19390c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);
19400c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_1(p, bitDPtr);
19410c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);
19420c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);
19430c16b537SWarner Losh }
19440c16b537SWarner Losh
19450c16b537SWarner Losh /* closer to the end */
19460c16b537SWarner Losh while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd))
19470c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);
19480c16b537SWarner Losh
19490c16b537SWarner Losh /* no more data to retrieve from bitstream, hence no need to reload */
19500c16b537SWarner Losh while (p < pEnd)
19510c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);
19520c16b537SWarner Losh
19530c16b537SWarner Losh return pEnd-pStart;
19540c16b537SWarner Losh }
19550c16b537SWarner Losh
HUFv05_decompress1X2_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const U16 * DTable)19560c16b537SWarner Losh size_t HUFv05_decompress1X2_usingDTable(
19570c16b537SWarner Losh void* dst, size_t dstSize,
19580c16b537SWarner Losh const void* cSrc, size_t cSrcSize,
19590c16b537SWarner Losh const U16* DTable)
19600c16b537SWarner Losh {
19610c16b537SWarner Losh BYTE* op = (BYTE*)dst;
19620c16b537SWarner Losh BYTE* const oend = op + dstSize;
19630c16b537SWarner Losh const U32 dtLog = DTable[0];
19640c16b537SWarner Losh const void* dtPtr = DTable;
19650c16b537SWarner Losh const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr)+1;
19660c16b537SWarner Losh BITv05_DStream_t bitD;
19670c16b537SWarner Losh
19680c16b537SWarner Losh if (dstSize <= cSrcSize) return ERROR(dstSize_tooSmall);
19690c16b537SWarner Losh { size_t const errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);
19700c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode; }
19710c16b537SWarner Losh
19720c16b537SWarner Losh HUFv05_decodeStreamX2(op, &bitD, oend, dt, dtLog);
19730c16b537SWarner Losh
19740c16b537SWarner Losh /* check */
19750c16b537SWarner Losh if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);
19760c16b537SWarner Losh
19770c16b537SWarner Losh return dstSize;
19780c16b537SWarner Losh }
19790c16b537SWarner Losh
HUFv05_decompress1X2(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)19800c16b537SWarner Losh size_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
19810c16b537SWarner Losh {
19820c16b537SWarner Losh HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);
19830c16b537SWarner Losh const BYTE* ip = (const BYTE*) cSrc;
19840c16b537SWarner Losh size_t errorCode;
19850c16b537SWarner Losh
19860c16b537SWarner Losh errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);
19870c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
19880c16b537SWarner Losh if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);
19890c16b537SWarner Losh ip += errorCode;
19900c16b537SWarner Losh cSrcSize -= errorCode;
19910c16b537SWarner Losh
19920c16b537SWarner Losh return HUFv05_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
19930c16b537SWarner Losh }
19940c16b537SWarner Losh
19950c16b537SWarner Losh
HUFv05_decompress4X2_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const U16 * DTable)19960c16b537SWarner Losh size_t HUFv05_decompress4X2_usingDTable(
19970c16b537SWarner Losh void* dst, size_t dstSize,
19980c16b537SWarner Losh const void* cSrc, size_t cSrcSize,
19990c16b537SWarner Losh const U16* DTable)
20000c16b537SWarner Losh {
20014d3f1eafSConrad Meyer /* Check */
20024d3f1eafSConrad Meyer if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
20034d3f1eafSConrad Meyer {
20040c16b537SWarner Losh const BYTE* const istart = (const BYTE*) cSrc;
20050c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst;
20060c16b537SWarner Losh BYTE* const oend = ostart + dstSize;
20070c16b537SWarner Losh const void* const dtPtr = DTable;
20080c16b537SWarner Losh const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1;
20090c16b537SWarner Losh const U32 dtLog = DTable[0];
20100c16b537SWarner Losh size_t errorCode;
20110c16b537SWarner Losh
20120c16b537SWarner Losh /* Init */
20130c16b537SWarner Losh BITv05_DStream_t bitD1;
20140c16b537SWarner Losh BITv05_DStream_t bitD2;
20150c16b537SWarner Losh BITv05_DStream_t bitD3;
20160c16b537SWarner Losh BITv05_DStream_t bitD4;
20170c16b537SWarner Losh const size_t length1 = MEM_readLE16(istart);
20180c16b537SWarner Losh const size_t length2 = MEM_readLE16(istart+2);
20190c16b537SWarner Losh const size_t length3 = MEM_readLE16(istart+4);
20200c16b537SWarner Losh size_t length4;
20210c16b537SWarner Losh const BYTE* const istart1 = istart + 6; /* jumpTable */
20220c16b537SWarner Losh const BYTE* const istart2 = istart1 + length1;
20230c16b537SWarner Losh const BYTE* const istart3 = istart2 + length2;
20240c16b537SWarner Losh const BYTE* const istart4 = istart3 + length3;
20250c16b537SWarner Losh const size_t segmentSize = (dstSize+3) / 4;
20260c16b537SWarner Losh BYTE* const opStart2 = ostart + segmentSize;
20270c16b537SWarner Losh BYTE* const opStart3 = opStart2 + segmentSize;
20280c16b537SWarner Losh BYTE* const opStart4 = opStart3 + segmentSize;
20290c16b537SWarner Losh BYTE* op1 = ostart;
20300c16b537SWarner Losh BYTE* op2 = opStart2;
20310c16b537SWarner Losh BYTE* op3 = opStart3;
20320c16b537SWarner Losh BYTE* op4 = opStart4;
20330c16b537SWarner Losh U32 endSignal;
20340c16b537SWarner Losh
20350c16b537SWarner Losh length4 = cSrcSize - (length1 + length2 + length3 + 6);
20360c16b537SWarner Losh if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
20370c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD1, istart1, length1);
20380c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
20390c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD2, istart2, length2);
20400c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
20410c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD3, istart3, length3);
20420c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
20430c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD4, istart4, length4);
20440c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
20450c16b537SWarner Losh
20460c16b537SWarner Losh /* 16-32 symbols per loop (4-8 symbols per stream) */
20470c16b537SWarner Losh endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
20480c16b537SWarner Losh for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {
20490c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);
20500c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);
20510c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);
20520c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);
20530c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1);
20540c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2);
20550c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3);
20560c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4);
20570c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);
20580c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);
20590c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);
20600c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);
20610c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1);
20620c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2);
20630c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3);
20640c16b537SWarner Losh HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4);
20650c16b537SWarner Losh endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
20660c16b537SWarner Losh }
20670c16b537SWarner Losh
20680c16b537SWarner Losh /* check corruption */
20690c16b537SWarner Losh if (op1 > opStart2) return ERROR(corruption_detected);
20700c16b537SWarner Losh if (op2 > opStart3) return ERROR(corruption_detected);
20710c16b537SWarner Losh if (op3 > opStart4) return ERROR(corruption_detected);
20720c16b537SWarner Losh /* note : op4 supposed already verified within main loop */
20730c16b537SWarner Losh
20740c16b537SWarner Losh /* finish bitStreams one by one */
20750c16b537SWarner Losh HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
20760c16b537SWarner Losh HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
20770c16b537SWarner Losh HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
20780c16b537SWarner Losh HUFv05_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
20790c16b537SWarner Losh
20800c16b537SWarner Losh /* check */
20810c16b537SWarner Losh endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);
20820c16b537SWarner Losh if (!endSignal) return ERROR(corruption_detected);
20830c16b537SWarner Losh
20840c16b537SWarner Losh /* decoded size */
20850c16b537SWarner Losh return dstSize;
20860c16b537SWarner Losh }
20874d3f1eafSConrad Meyer }
20880c16b537SWarner Losh
20890c16b537SWarner Losh
HUFv05_decompress4X2(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)20900c16b537SWarner Losh size_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
20910c16b537SWarner Losh {
20920c16b537SWarner Losh HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);
20930c16b537SWarner Losh const BYTE* ip = (const BYTE*) cSrc;
20940c16b537SWarner Losh size_t errorCode;
20950c16b537SWarner Losh
20960c16b537SWarner Losh errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);
20970c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
20980c16b537SWarner Losh if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);
20990c16b537SWarner Losh ip += errorCode;
21000c16b537SWarner Losh cSrcSize -= errorCode;
21010c16b537SWarner Losh
21020c16b537SWarner Losh return HUFv05_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
21030c16b537SWarner Losh }
21040c16b537SWarner Losh
21050c16b537SWarner Losh
21060c16b537SWarner Losh /* *************************/
21070c16b537SWarner Losh /* double-symbols decoding */
21080c16b537SWarner Losh /* *************************/
21090c16b537SWarner Losh
HUFv05_fillDTableX4Level2(HUFv05_DEltX4 * DTable,U32 sizeLog,const U32 consumed,const U32 * rankValOrigin,const int minWeight,const sortedSymbol_t * sortedSymbols,const U32 sortedListSize,U32 nbBitsBaseline,U16 baseSeq)21100c16b537SWarner Losh static void HUFv05_fillDTableX4Level2(HUFv05_DEltX4* DTable, U32 sizeLog, const U32 consumed,
21110c16b537SWarner Losh const U32* rankValOrigin, const int minWeight,
21120c16b537SWarner Losh const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
21130c16b537SWarner Losh U32 nbBitsBaseline, U16 baseSeq)
21140c16b537SWarner Losh {
21150c16b537SWarner Losh HUFv05_DEltX4 DElt;
21160c16b537SWarner Losh U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];
21170c16b537SWarner Losh U32 s;
21180c16b537SWarner Losh
21190c16b537SWarner Losh /* get pre-calculated rankVal */
21200c16b537SWarner Losh memcpy(rankVal, rankValOrigin, sizeof(rankVal));
21210c16b537SWarner Losh
21220c16b537SWarner Losh /* fill skipped values */
21230c16b537SWarner Losh if (minWeight>1) {
21240c16b537SWarner Losh U32 i, skipSize = rankVal[minWeight];
21250c16b537SWarner Losh MEM_writeLE16(&(DElt.sequence), baseSeq);
21260c16b537SWarner Losh DElt.nbBits = (BYTE)(consumed);
21270c16b537SWarner Losh DElt.length = 1;
21280c16b537SWarner Losh for (i = 0; i < skipSize; i++)
21290c16b537SWarner Losh DTable[i] = DElt;
21300c16b537SWarner Losh }
21310c16b537SWarner Losh
21320c16b537SWarner Losh /* fill DTable */
21330c16b537SWarner Losh for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */
21340c16b537SWarner Losh const U32 symbol = sortedSymbols[s].symbol;
21350c16b537SWarner Losh const U32 weight = sortedSymbols[s].weight;
21360c16b537SWarner Losh const U32 nbBits = nbBitsBaseline - weight;
21370c16b537SWarner Losh const U32 length = 1 << (sizeLog-nbBits);
21380c16b537SWarner Losh const U32 start = rankVal[weight];
21390c16b537SWarner Losh U32 i = start;
21400c16b537SWarner Losh const U32 end = start + length;
21410c16b537SWarner Losh
21420c16b537SWarner Losh MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
21430c16b537SWarner Losh DElt.nbBits = (BYTE)(nbBits + consumed);
21440c16b537SWarner Losh DElt.length = 2;
21450c16b537SWarner Losh do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */
21460c16b537SWarner Losh
21470c16b537SWarner Losh rankVal[weight] += length;
21480c16b537SWarner Losh }
21490c16b537SWarner Losh }
21500c16b537SWarner Losh
21510c16b537SWarner Losh typedef U32 rankVal_t[HUFv05_ABSOLUTEMAX_TABLELOG][HUFv05_ABSOLUTEMAX_TABLELOG + 1];
21520c16b537SWarner Losh
HUFv05_fillDTableX4(HUFv05_DEltX4 * DTable,const U32 targetLog,const sortedSymbol_t * sortedList,const U32 sortedListSize,const U32 * rankStart,rankVal_t rankValOrigin,const U32 maxWeight,const U32 nbBitsBaseline)21530c16b537SWarner Losh static void HUFv05_fillDTableX4(HUFv05_DEltX4* DTable, const U32 targetLog,
21540c16b537SWarner Losh const sortedSymbol_t* sortedList, const U32 sortedListSize,
21550c16b537SWarner Losh const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
21560c16b537SWarner Losh const U32 nbBitsBaseline)
21570c16b537SWarner Losh {
21580c16b537SWarner Losh U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];
21590c16b537SWarner Losh const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
21600c16b537SWarner Losh const U32 minBits = nbBitsBaseline - maxWeight;
21610c16b537SWarner Losh U32 s;
21620c16b537SWarner Losh
21630c16b537SWarner Losh memcpy(rankVal, rankValOrigin, sizeof(rankVal));
21640c16b537SWarner Losh
21650c16b537SWarner Losh /* fill DTable */
21660c16b537SWarner Losh for (s=0; s<sortedListSize; s++) {
21670c16b537SWarner Losh const U16 symbol = sortedList[s].symbol;
21680c16b537SWarner Losh const U32 weight = sortedList[s].weight;
21690c16b537SWarner Losh const U32 nbBits = nbBitsBaseline - weight;
21700c16b537SWarner Losh const U32 start = rankVal[weight];
21710c16b537SWarner Losh const U32 length = 1 << (targetLog-nbBits);
21720c16b537SWarner Losh
21730c16b537SWarner Losh if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */
21740c16b537SWarner Losh U32 sortedRank;
21750c16b537SWarner Losh int minWeight = nbBits + scaleLog;
21760c16b537SWarner Losh if (minWeight < 1) minWeight = 1;
21770c16b537SWarner Losh sortedRank = rankStart[minWeight];
21780c16b537SWarner Losh HUFv05_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,
21790c16b537SWarner Losh rankValOrigin[nbBits], minWeight,
21800c16b537SWarner Losh sortedList+sortedRank, sortedListSize-sortedRank,
21810c16b537SWarner Losh nbBitsBaseline, symbol);
21820c16b537SWarner Losh } else {
21830c16b537SWarner Losh U32 i;
21840c16b537SWarner Losh const U32 end = start + length;
21850c16b537SWarner Losh HUFv05_DEltX4 DElt;
21860c16b537SWarner Losh
21870c16b537SWarner Losh MEM_writeLE16(&(DElt.sequence), symbol);
21880c16b537SWarner Losh DElt.nbBits = (BYTE)(nbBits);
21890c16b537SWarner Losh DElt.length = 1;
21900c16b537SWarner Losh for (i = start; i < end; i++)
21910c16b537SWarner Losh DTable[i] = DElt;
21920c16b537SWarner Losh }
21930c16b537SWarner Losh rankVal[weight] += length;
21940c16b537SWarner Losh }
21950c16b537SWarner Losh }
21960c16b537SWarner Losh
HUFv05_readDTableX4(unsigned * DTable,const void * src,size_t srcSize)2197a0483764SConrad Meyer size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize)
21980c16b537SWarner Losh {
21990c16b537SWarner Losh BYTE weightList[HUFv05_MAX_SYMBOL_VALUE + 1];
22000c16b537SWarner Losh sortedSymbol_t sortedSymbol[HUFv05_MAX_SYMBOL_VALUE + 1];
22010c16b537SWarner Losh U32 rankStats[HUFv05_ABSOLUTEMAX_TABLELOG + 1] = { 0 };
22020c16b537SWarner Losh U32 rankStart0[HUFv05_ABSOLUTEMAX_TABLELOG + 2] = { 0 };
22030c16b537SWarner Losh U32* const rankStart = rankStart0+1;
22040c16b537SWarner Losh rankVal_t rankVal;
22050c16b537SWarner Losh U32 tableLog, maxW, sizeOfSort, nbSymbols;
22060c16b537SWarner Losh const U32 memLog = DTable[0];
22070c16b537SWarner Losh size_t iSize;
22080c16b537SWarner Losh void* dtPtr = DTable;
22090c16b537SWarner Losh HUFv05_DEltX4* const dt = ((HUFv05_DEltX4*)dtPtr) + 1;
22100c16b537SWarner Losh
2211a0483764SConrad Meyer HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX4) == sizeof(unsigned)); /* if compilation fails here, assertion is false */
22120c16b537SWarner Losh if (memLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);
221337f1f268SConrad Meyer /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
22140c16b537SWarner Losh
22150c16b537SWarner Losh iSize = HUFv05_readStats(weightList, HUFv05_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
22160c16b537SWarner Losh if (HUFv05_isError(iSize)) return iSize;
22170c16b537SWarner Losh
22180c16b537SWarner Losh /* check result */
22190c16b537SWarner Losh if (tableLog > memLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
22200c16b537SWarner Losh
22210c16b537SWarner Losh /* find maxWeight */
22220c16b537SWarner Losh for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
22230c16b537SWarner Losh
22240c16b537SWarner Losh /* Get start index of each weight */
22250c16b537SWarner Losh {
22260c16b537SWarner Losh U32 w, nextRankStart = 0;
22270c16b537SWarner Losh for (w=1; w<=maxW; w++) {
22280c16b537SWarner Losh U32 current = nextRankStart;
22290c16b537SWarner Losh nextRankStart += rankStats[w];
22300c16b537SWarner Losh rankStart[w] = current;
22310c16b537SWarner Losh }
22320c16b537SWarner Losh rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
22330c16b537SWarner Losh sizeOfSort = nextRankStart;
22340c16b537SWarner Losh }
22350c16b537SWarner Losh
22360c16b537SWarner Losh /* sort symbols by weight */
22370c16b537SWarner Losh {
22380c16b537SWarner Losh U32 s;
22390c16b537SWarner Losh for (s=0; s<nbSymbols; s++) {
22400c16b537SWarner Losh U32 w = weightList[s];
22410c16b537SWarner Losh U32 r = rankStart[w]++;
22420c16b537SWarner Losh sortedSymbol[r].symbol = (BYTE)s;
22430c16b537SWarner Losh sortedSymbol[r].weight = (BYTE)w;
22440c16b537SWarner Losh }
22450c16b537SWarner Losh rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
22460c16b537SWarner Losh }
22470c16b537SWarner Losh
22480c16b537SWarner Losh /* Build rankVal */
22490c16b537SWarner Losh {
22500c16b537SWarner Losh const U32 minBits = tableLog+1 - maxW;
22510c16b537SWarner Losh U32 nextRankVal = 0;
22520c16b537SWarner Losh U32 w, consumed;
22530c16b537SWarner Losh const int rescale = (memLog-tableLog) - 1; /* tableLog <= memLog */
22540c16b537SWarner Losh U32* rankVal0 = rankVal[0];
22550c16b537SWarner Losh for (w=1; w<=maxW; w++) {
22560c16b537SWarner Losh U32 current = nextRankVal;
22570c16b537SWarner Losh nextRankVal += rankStats[w] << (w+rescale);
22580c16b537SWarner Losh rankVal0[w] = current;
22590c16b537SWarner Losh }
22600c16b537SWarner Losh for (consumed = minBits; consumed <= memLog - minBits; consumed++) {
22610c16b537SWarner Losh U32* rankValPtr = rankVal[consumed];
22620c16b537SWarner Losh for (w = 1; w <= maxW; w++) {
22630c16b537SWarner Losh rankValPtr[w] = rankVal0[w] >> consumed;
22640c16b537SWarner Losh } } }
22650c16b537SWarner Losh
22660c16b537SWarner Losh HUFv05_fillDTableX4(dt, memLog,
22670c16b537SWarner Losh sortedSymbol, sizeOfSort,
22680c16b537SWarner Losh rankStart0, rankVal, maxW,
22690c16b537SWarner Losh tableLog+1);
22700c16b537SWarner Losh
22710c16b537SWarner Losh return iSize;
22720c16b537SWarner Losh }
22730c16b537SWarner Losh
22740c16b537SWarner Losh
HUFv05_decodeSymbolX4(void * op,BITv05_DStream_t * DStream,const HUFv05_DEltX4 * dt,const U32 dtLog)22750c16b537SWarner Losh static U32 HUFv05_decodeSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)
22760c16b537SWarner Losh {
22770c16b537SWarner Losh const size_t val = BITv05_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
22780c16b537SWarner Losh memcpy(op, dt+val, 2);
22790c16b537SWarner Losh BITv05_skipBits(DStream, dt[val].nbBits);
22800c16b537SWarner Losh return dt[val].length;
22810c16b537SWarner Losh }
22820c16b537SWarner Losh
HUFv05_decodeLastSymbolX4(void * op,BITv05_DStream_t * DStream,const HUFv05_DEltX4 * dt,const U32 dtLog)22830c16b537SWarner Losh static U32 HUFv05_decodeLastSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)
22840c16b537SWarner Losh {
22850c16b537SWarner Losh const size_t val = BITv05_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
22860c16b537SWarner Losh memcpy(op, dt+val, 1);
22870c16b537SWarner Losh if (dt[val].length==1) BITv05_skipBits(DStream, dt[val].nbBits);
22880c16b537SWarner Losh else {
22890c16b537SWarner Losh if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
22900c16b537SWarner Losh BITv05_skipBits(DStream, dt[val].nbBits);
22910c16b537SWarner Losh if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
22920c16b537SWarner Losh DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
22930c16b537SWarner Losh } }
22940c16b537SWarner Losh return 1;
22950c16b537SWarner Losh }
22960c16b537SWarner Losh
22970c16b537SWarner Losh
22980c16b537SWarner Losh #define HUFv05_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
22990c16b537SWarner Losh ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
23000c16b537SWarner Losh
23010c16b537SWarner Losh #define HUFv05_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
23020c16b537SWarner Losh if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \
23030c16b537SWarner Losh ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
23040c16b537SWarner Losh
23050c16b537SWarner Losh #define HUFv05_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
23060c16b537SWarner Losh if (MEM_64bits()) \
23070c16b537SWarner Losh ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
23080c16b537SWarner Losh
HUFv05_decodeStreamX4(BYTE * p,BITv05_DStream_t * bitDPtr,BYTE * const pEnd,const HUFv05_DEltX4 * const dt,const U32 dtLog)23090c16b537SWarner Losh static inline size_t HUFv05_decodeStreamX4(BYTE* p, BITv05_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv05_DEltX4* const dt, const U32 dtLog)
23100c16b537SWarner Losh {
23110c16b537SWarner Losh BYTE* const pStart = p;
23120c16b537SWarner Losh
23130c16b537SWarner Losh /* up to 8 symbols at a time */
23140c16b537SWarner Losh while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd-7)) {
23150c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);
23160c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_1(p, bitDPtr);
23170c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);
23180c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);
23190c16b537SWarner Losh }
23200c16b537SWarner Losh
23210c16b537SWarner Losh /* closer to the end */
23220c16b537SWarner Losh while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-2))
23230c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);
23240c16b537SWarner Losh
23250c16b537SWarner Losh while (p <= pEnd-2)
23260c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
23270c16b537SWarner Losh
23280c16b537SWarner Losh if (p < pEnd)
23290c16b537SWarner Losh p += HUFv05_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
23300c16b537SWarner Losh
23310c16b537SWarner Losh return p-pStart;
23320c16b537SWarner Losh }
23330c16b537SWarner Losh
23340c16b537SWarner Losh
HUFv05_decompress1X4_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const unsigned * DTable)23350c16b537SWarner Losh size_t HUFv05_decompress1X4_usingDTable(
23360c16b537SWarner Losh void* dst, size_t dstSize,
23370c16b537SWarner Losh const void* cSrc, size_t cSrcSize,
2338a0483764SConrad Meyer const unsigned* DTable)
23390c16b537SWarner Losh {
23400c16b537SWarner Losh const BYTE* const istart = (const BYTE*) cSrc;
23410c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst;
23420c16b537SWarner Losh BYTE* const oend = ostart + dstSize;
23430c16b537SWarner Losh
23440c16b537SWarner Losh const U32 dtLog = DTable[0];
23450c16b537SWarner Losh const void* const dtPtr = DTable;
23460c16b537SWarner Losh const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;
23470c16b537SWarner Losh size_t errorCode;
23480c16b537SWarner Losh
23490c16b537SWarner Losh /* Init */
23500c16b537SWarner Losh BITv05_DStream_t bitD;
23510c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD, istart, cSrcSize);
23520c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
23530c16b537SWarner Losh
23540c16b537SWarner Losh /* finish bitStreams one by one */
23550c16b537SWarner Losh HUFv05_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);
23560c16b537SWarner Losh
23570c16b537SWarner Losh /* check */
23580c16b537SWarner Losh if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);
23590c16b537SWarner Losh
23600c16b537SWarner Losh /* decoded size */
23610c16b537SWarner Losh return dstSize;
23620c16b537SWarner Losh }
23630c16b537SWarner Losh
HUFv05_decompress1X4(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)23640c16b537SWarner Losh size_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
23650c16b537SWarner Losh {
23660c16b537SWarner Losh HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);
23670c16b537SWarner Losh const BYTE* ip = (const BYTE*) cSrc;
23680c16b537SWarner Losh
23690c16b537SWarner Losh size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);
23700c16b537SWarner Losh if (HUFv05_isError(hSize)) return hSize;
23710c16b537SWarner Losh if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
23720c16b537SWarner Losh ip += hSize;
23730c16b537SWarner Losh cSrcSize -= hSize;
23740c16b537SWarner Losh
23750c16b537SWarner Losh return HUFv05_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
23760c16b537SWarner Losh }
23770c16b537SWarner Losh
HUFv05_decompress4X4_usingDTable(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize,const unsigned * DTable)23780c16b537SWarner Losh size_t HUFv05_decompress4X4_usingDTable(
23790c16b537SWarner Losh void* dst, size_t dstSize,
23800c16b537SWarner Losh const void* cSrc, size_t cSrcSize,
2381a0483764SConrad Meyer const unsigned* DTable)
23820c16b537SWarner Losh {
23830c16b537SWarner Losh if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
23840c16b537SWarner Losh
23850c16b537SWarner Losh {
23860c16b537SWarner Losh const BYTE* const istart = (const BYTE*) cSrc;
23870c16b537SWarner Losh BYTE* const ostart = (BYTE*) dst;
23880c16b537SWarner Losh BYTE* const oend = ostart + dstSize;
23890c16b537SWarner Losh const void* const dtPtr = DTable;
23900c16b537SWarner Losh const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;
23910c16b537SWarner Losh const U32 dtLog = DTable[0];
23920c16b537SWarner Losh size_t errorCode;
23930c16b537SWarner Losh
23940c16b537SWarner Losh /* Init */
23950c16b537SWarner Losh BITv05_DStream_t bitD1;
23960c16b537SWarner Losh BITv05_DStream_t bitD2;
23970c16b537SWarner Losh BITv05_DStream_t bitD3;
23980c16b537SWarner Losh BITv05_DStream_t bitD4;
23990c16b537SWarner Losh const size_t length1 = MEM_readLE16(istart);
24000c16b537SWarner Losh const size_t length2 = MEM_readLE16(istart+2);
24010c16b537SWarner Losh const size_t length3 = MEM_readLE16(istart+4);
24020c16b537SWarner Losh size_t length4;
24030c16b537SWarner Losh const BYTE* const istart1 = istart + 6; /* jumpTable */
24040c16b537SWarner Losh const BYTE* const istart2 = istart1 + length1;
24050c16b537SWarner Losh const BYTE* const istart3 = istart2 + length2;
24060c16b537SWarner Losh const BYTE* const istart4 = istart3 + length3;
24070c16b537SWarner Losh const size_t segmentSize = (dstSize+3) / 4;
24080c16b537SWarner Losh BYTE* const opStart2 = ostart + segmentSize;
24090c16b537SWarner Losh BYTE* const opStart3 = opStart2 + segmentSize;
24100c16b537SWarner Losh BYTE* const opStart4 = opStart3 + segmentSize;
24110c16b537SWarner Losh BYTE* op1 = ostart;
24120c16b537SWarner Losh BYTE* op2 = opStart2;
24130c16b537SWarner Losh BYTE* op3 = opStart3;
24140c16b537SWarner Losh BYTE* op4 = opStart4;
24150c16b537SWarner Losh U32 endSignal;
24160c16b537SWarner Losh
24170c16b537SWarner Losh length4 = cSrcSize - (length1 + length2 + length3 + 6);
24180c16b537SWarner Losh if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
24190c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD1, istart1, length1);
24200c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
24210c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD2, istart2, length2);
24220c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
24230c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD3, istart3, length3);
24240c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
24250c16b537SWarner Losh errorCode = BITv05_initDStream(&bitD4, istart4, length4);
24260c16b537SWarner Losh if (HUFv05_isError(errorCode)) return errorCode;
24270c16b537SWarner Losh
24280c16b537SWarner Losh /* 16-32 symbols per loop (4-8 symbols per stream) */
24290c16b537SWarner Losh endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
24300c16b537SWarner Losh for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {
24310c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);
24320c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);
24330c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);
24340c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);
24350c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_1(op1, &bitD1);
24360c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_1(op2, &bitD2);
24370c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_1(op3, &bitD3);
24380c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_1(op4, &bitD4);
24390c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);
24400c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);
24410c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);
24420c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);
24430c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(op1, &bitD1);
24440c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(op2, &bitD2);
24450c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(op3, &bitD3);
24460c16b537SWarner Losh HUFv05_DECODE_SYMBOLX4_0(op4, &bitD4);
24470c16b537SWarner Losh
24480c16b537SWarner Losh endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);
24490c16b537SWarner Losh }
24500c16b537SWarner Losh
24510c16b537SWarner Losh /* check corruption */
24520c16b537SWarner Losh if (op1 > opStart2) return ERROR(corruption_detected);
24530c16b537SWarner Losh if (op2 > opStart3) return ERROR(corruption_detected);
24540c16b537SWarner Losh if (op3 > opStart4) return ERROR(corruption_detected);
24550c16b537SWarner Losh /* note : op4 supposed already verified within main loop */
24560c16b537SWarner Losh
24570c16b537SWarner Losh /* finish bitStreams one by one */
24580c16b537SWarner Losh HUFv05_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
24590c16b537SWarner Losh HUFv05_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
24600c16b537SWarner Losh HUFv05_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
24610c16b537SWarner Losh HUFv05_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
24620c16b537SWarner Losh
24630c16b537SWarner Losh /* check */
24640c16b537SWarner Losh endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);
24650c16b537SWarner Losh if (!endSignal) return ERROR(corruption_detected);
24660c16b537SWarner Losh
24670c16b537SWarner Losh /* decoded size */
24680c16b537SWarner Losh return dstSize;
24690c16b537SWarner Losh }
24700c16b537SWarner Losh }
24710c16b537SWarner Losh
24720c16b537SWarner Losh
HUFv05_decompress4X4(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)24730c16b537SWarner Losh size_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
24740c16b537SWarner Losh {
24750c16b537SWarner Losh HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);
24760c16b537SWarner Losh const BYTE* ip = (const BYTE*) cSrc;
24770c16b537SWarner Losh
24780c16b537SWarner Losh size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);
24790c16b537SWarner Losh if (HUFv05_isError(hSize)) return hSize;
24800c16b537SWarner Losh if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
24810c16b537SWarner Losh ip += hSize;
24820c16b537SWarner Losh cSrcSize -= hSize;
24830c16b537SWarner Losh
24840c16b537SWarner Losh return HUFv05_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
24850c16b537SWarner Losh }
24860c16b537SWarner Losh
24870c16b537SWarner Losh
24880c16b537SWarner Losh /* ********************************/
24890c16b537SWarner Losh /* Generic decompression selector */
24900c16b537SWarner Losh /* ********************************/
24910c16b537SWarner Losh
24920c16b537SWarner Losh typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
24930c16b537SWarner Losh static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
24940c16b537SWarner Losh {
24950c16b537SWarner Losh /* single, double, quad */
24960c16b537SWarner Losh {{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */
24970c16b537SWarner Losh {{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */
24980c16b537SWarner Losh {{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
24990c16b537SWarner Losh {{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
25000c16b537SWarner Losh {{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
25010c16b537SWarner Losh {{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
25020c16b537SWarner Losh {{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
25030c16b537SWarner Losh {{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
25040c16b537SWarner Losh {{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
25050c16b537SWarner Losh {{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
25060c16b537SWarner Losh {{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
25070c16b537SWarner Losh {{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
25080c16b537SWarner Losh {{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
25090c16b537SWarner Losh {{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */
25100c16b537SWarner Losh {{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */
25110c16b537SWarner Losh {{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */
25120c16b537SWarner Losh };
25130c16b537SWarner Losh
25140c16b537SWarner Losh typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
25150c16b537SWarner Losh
HUFv05_decompress(void * dst,size_t dstSize,const void * cSrc,size_t cSrcSize)25160c16b537SWarner Losh size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
25170c16b537SWarner Losh {
25180c16b537SWarner Losh static const decompressionAlgo decompress[3] = { HUFv05_decompress4X2, HUFv05_decompress4X4, NULL };
25190c16b537SWarner Losh /* estimate decompression time */
25200c16b537SWarner Losh U32 Q;
25210c16b537SWarner Losh const U32 D256 = (U32)(dstSize >> 8);
25220c16b537SWarner Losh U32 Dtime[3];
25230c16b537SWarner Losh U32 algoNb = 0;
25240c16b537SWarner Losh int n;
25250c16b537SWarner Losh
25260c16b537SWarner Losh /* validation checks */
25270c16b537SWarner Losh if (dstSize == 0) return ERROR(dstSize_tooSmall);
25280c16b537SWarner Losh if (cSrcSize >= dstSize) return ERROR(corruption_detected); /* invalid, or not compressed, but not compressed already dealt with */
25290c16b537SWarner Losh if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
25300c16b537SWarner Losh
25310c16b537SWarner Losh /* decoder timing evaluation */
25320c16b537SWarner Losh Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
25330c16b537SWarner Losh for (n=0; n<3; n++)
25340c16b537SWarner Losh Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);
25350c16b537SWarner Losh
25360c16b537SWarner Losh Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */
25370c16b537SWarner Losh
25380c16b537SWarner Losh if (Dtime[1] < Dtime[0]) algoNb = 1;
25390c16b537SWarner Losh
25400c16b537SWarner Losh return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
25410c16b537SWarner Losh
254237f1f268SConrad Meyer /* return HUFv05_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */
254337f1f268SConrad Meyer /* return HUFv05_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */
254437f1f268SConrad Meyer /* return HUFv05_decompress4X6(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams quad-symbols decoding */
25450c16b537SWarner Losh }
25460c16b537SWarner Losh /*
25470c16b537SWarner Losh zstd - standard compression library
25480c16b537SWarner Losh Copyright (C) 2014-2016, Yann Collet.
25490c16b537SWarner Losh
25500c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
25510c16b537SWarner Losh
25520c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
25530c16b537SWarner Losh modification, are permitted provided that the following conditions are
25540c16b537SWarner Losh met:
25550c16b537SWarner Losh * Redistributions of source code must retain the above copyright
25560c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
25570c16b537SWarner Losh * Redistributions in binary form must reproduce the above
25580c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
25590c16b537SWarner Losh in the documentation and/or other materials provided with the
25600c16b537SWarner Losh distribution.
25610c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25620c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25630c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25640c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25650c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25660c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25670c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25680c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25690c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25700c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25710c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25720c16b537SWarner Losh
25730c16b537SWarner Losh You can contact the author at :
25740c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd
25750c16b537SWarner Losh */
25760c16b537SWarner Losh
25770c16b537SWarner Losh /* ***************************************************************
25780c16b537SWarner Losh * Tuning parameters
25790c16b537SWarner Losh *****************************************************************/
25800c16b537SWarner Losh /*!
25810c16b537SWarner Losh * HEAPMODE :
25820c16b537SWarner Losh * Select how default decompression function ZSTDv05_decompress() will allocate memory,
25830c16b537SWarner Losh * in memory stack (0), or in memory heap (1, requires malloc())
25840c16b537SWarner Losh */
25850c16b537SWarner Losh #ifndef ZSTDv05_HEAPMODE
25860c16b537SWarner Losh # define ZSTDv05_HEAPMODE 1
25870c16b537SWarner Losh #endif
25880c16b537SWarner Losh
25890c16b537SWarner Losh
25900c16b537SWarner Losh /*-*******************************************************
25910c16b537SWarner Losh * Dependencies
25920c16b537SWarner Losh *********************************************************/
25930c16b537SWarner Losh #include <stdlib.h> /* calloc */
25940c16b537SWarner Losh #include <string.h> /* memcpy, memmove */
25950c16b537SWarner Losh #include <stdio.h> /* debug only : printf */
25960c16b537SWarner Losh
25970c16b537SWarner Losh
25980c16b537SWarner Losh /*-*******************************************************
25990c16b537SWarner Losh * Compiler specifics
26000c16b537SWarner Losh *********************************************************/
26010c16b537SWarner Losh #ifdef _MSC_VER /* Visual Studio */
26020c16b537SWarner Losh # include <intrin.h> /* For Visual 2005 */
26030c16b537SWarner Losh # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
26040c16b537SWarner Losh # pragma warning(disable : 4324) /* disable: C4324: padded structure */
26050c16b537SWarner Losh #endif
26060c16b537SWarner Losh
26070c16b537SWarner Losh
26080c16b537SWarner Losh /*-*************************************
26090c16b537SWarner Losh * Local types
26100c16b537SWarner Losh ***************************************/
26110c16b537SWarner Losh typedef struct
26120c16b537SWarner Losh {
26130c16b537SWarner Losh blockType_t blockType;
26140c16b537SWarner Losh U32 origSize;
26150c16b537SWarner Losh } blockProperties_t;
26160c16b537SWarner Losh
26170c16b537SWarner Losh
26180c16b537SWarner Losh /* *******************************************************
26190c16b537SWarner Losh * Memory operations
26200c16b537SWarner Losh **********************************************************/
ZSTDv05_copy4(void * dst,const void * src)26210c16b537SWarner Losh static void ZSTDv05_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
26220c16b537SWarner Losh
26230c16b537SWarner Losh
26240c16b537SWarner Losh /* *************************************
26250c16b537SWarner Losh * Error Management
26260c16b537SWarner Losh ***************************************/
26270c16b537SWarner Losh /*! ZSTDv05_isError() :
26280c16b537SWarner Losh * tells if a return value is an error code */
ZSTDv05_isError(size_t code)26290c16b537SWarner Losh unsigned ZSTDv05_isError(size_t code) { return ERR_isError(code); }
26300c16b537SWarner Losh
26310c16b537SWarner Losh
26320c16b537SWarner Losh /*! ZSTDv05_getErrorName() :
26330c16b537SWarner Losh * provides error code string (useful for debugging) */
ZSTDv05_getErrorName(size_t code)26340c16b537SWarner Losh const char* ZSTDv05_getErrorName(size_t code) { return ERR_getErrorName(code); }
26350c16b537SWarner Losh
26360c16b537SWarner Losh
26370c16b537SWarner Losh /* *************************************************************
26380c16b537SWarner Losh * Context management
26390c16b537SWarner Losh ***************************************************************/
26400c16b537SWarner Losh typedef enum { ZSTDv05ds_getFrameHeaderSize, ZSTDv05ds_decodeFrameHeader,
26410c16b537SWarner Losh ZSTDv05ds_decodeBlockHeader, ZSTDv05ds_decompressBlock } ZSTDv05_dStage;
26420c16b537SWarner Losh
26430c16b537SWarner Losh struct ZSTDv05_DCtx_s
26440c16b537SWarner Losh {
26450c16b537SWarner Losh FSEv05_DTable LLTable[FSEv05_DTABLE_SIZE_U32(LLFSEv05Log)];
26460c16b537SWarner Losh FSEv05_DTable OffTable[FSEv05_DTABLE_SIZE_U32(OffFSEv05Log)];
26470c16b537SWarner Losh FSEv05_DTable MLTable[FSEv05_DTABLE_SIZE_U32(MLFSEv05Log)];
26480c16b537SWarner Losh unsigned hufTableX4[HUFv05_DTABLE_SIZE(HufLog)];
26490c16b537SWarner Losh const void* previousDstEnd;
26500c16b537SWarner Losh const void* base;
26510c16b537SWarner Losh const void* vBase;
26520c16b537SWarner Losh const void* dictEnd;
26530c16b537SWarner Losh size_t expected;
26540c16b537SWarner Losh size_t headerSize;
26550c16b537SWarner Losh ZSTDv05_parameters params;
26560c16b537SWarner Losh blockType_t bType; /* used in ZSTDv05_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
26570c16b537SWarner Losh ZSTDv05_dStage stage;
26580c16b537SWarner Losh U32 flagStaticTables;
26590c16b537SWarner Losh const BYTE* litPtr;
26600c16b537SWarner Losh size_t litSize;
26610c16b537SWarner Losh BYTE litBuffer[BLOCKSIZE + WILDCOPY_OVERLENGTH];
26620c16b537SWarner Losh BYTE headerBuffer[ZSTDv05_frameHeaderSize_max];
26630c16b537SWarner Losh }; /* typedef'd to ZSTDv05_DCtx within "zstd_static.h" */
26640c16b537SWarner Losh
26650f743729SConrad Meyer size_t ZSTDv05_sizeofDCtx (void); /* Hidden declaration */
ZSTDv05_sizeofDCtx(void)26660c16b537SWarner Losh size_t ZSTDv05_sizeofDCtx (void) { return sizeof(ZSTDv05_DCtx); }
26670c16b537SWarner Losh
ZSTDv05_decompressBegin(ZSTDv05_DCtx * dctx)26680c16b537SWarner Losh size_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx)
26690c16b537SWarner Losh {
26700c16b537SWarner Losh dctx->expected = ZSTDv05_frameHeaderSize_min;
26710c16b537SWarner Losh dctx->stage = ZSTDv05ds_getFrameHeaderSize;
26720c16b537SWarner Losh dctx->previousDstEnd = NULL;
26730c16b537SWarner Losh dctx->base = NULL;
26740c16b537SWarner Losh dctx->vBase = NULL;
26750c16b537SWarner Losh dctx->dictEnd = NULL;
26760c16b537SWarner Losh dctx->hufTableX4[0] = HufLog;
26770c16b537SWarner Losh dctx->flagStaticTables = 0;
26780c16b537SWarner Losh return 0;
26790c16b537SWarner Losh }
26800c16b537SWarner Losh
ZSTDv05_createDCtx(void)26810c16b537SWarner Losh ZSTDv05_DCtx* ZSTDv05_createDCtx(void)
26820c16b537SWarner Losh {
26830c16b537SWarner Losh ZSTDv05_DCtx* dctx = (ZSTDv05_DCtx*)malloc(sizeof(ZSTDv05_DCtx));
26840c16b537SWarner Losh if (dctx==NULL) return NULL;
26850c16b537SWarner Losh ZSTDv05_decompressBegin(dctx);
26860c16b537SWarner Losh return dctx;
26870c16b537SWarner Losh }
26880c16b537SWarner Losh
ZSTDv05_freeDCtx(ZSTDv05_DCtx * dctx)26890c16b537SWarner Losh size_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx)
26900c16b537SWarner Losh {
26910c16b537SWarner Losh free(dctx);
26920c16b537SWarner Losh return 0; /* reserved as a potential error code in the future */
26930c16b537SWarner Losh }
26940c16b537SWarner Losh
ZSTDv05_copyDCtx(ZSTDv05_DCtx * dstDCtx,const ZSTDv05_DCtx * srcDCtx)26950c16b537SWarner Losh void ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx)
26960c16b537SWarner Losh {
26970c16b537SWarner Losh memcpy(dstDCtx, srcDCtx,
26980c16b537SWarner Losh sizeof(ZSTDv05_DCtx) - (BLOCKSIZE+WILDCOPY_OVERLENGTH + ZSTDv05_frameHeaderSize_max)); /* no need to copy workspace */
26990c16b537SWarner Losh }
27000c16b537SWarner Losh
27010c16b537SWarner Losh
27020c16b537SWarner Losh /* *************************************************************
27030c16b537SWarner Losh * Decompression section
27040c16b537SWarner Losh ***************************************************************/
27050c16b537SWarner Losh
27060c16b537SWarner Losh /* Frame format description
27070c16b537SWarner Losh Frame Header - [ Block Header - Block ] - Frame End
27080c16b537SWarner Losh 1) Frame Header
27090c16b537SWarner Losh - 4 bytes - Magic Number : ZSTDv05_MAGICNUMBER (defined within zstd_internal.h)
27100c16b537SWarner Losh - 1 byte - Window Descriptor
27110c16b537SWarner Losh 2) Block Header
27120c16b537SWarner Losh - 3 bytes, starting with a 2-bits descriptor
27130c16b537SWarner Losh Uncompressed, Compressed, Frame End, unused
27140c16b537SWarner Losh 3) Block
27150c16b537SWarner Losh See Block Format Description
27160c16b537SWarner Losh 4) Frame End
27170c16b537SWarner Losh - 3 bytes, compatible with Block Header
27180c16b537SWarner Losh */
27190c16b537SWarner Losh
27200c16b537SWarner Losh /* Block format description
27210c16b537SWarner Losh
27220c16b537SWarner Losh Block = Literal Section - Sequences Section
27230c16b537SWarner Losh Prerequisite : size of (compressed) block, maximum size of regenerated data
27240c16b537SWarner Losh
27250c16b537SWarner Losh 1) Literal Section
27260c16b537SWarner Losh
27270c16b537SWarner Losh 1.1) Header : 1-5 bytes
27280c16b537SWarner Losh flags: 2 bits
27290c16b537SWarner Losh 00 compressed by Huff0
27300c16b537SWarner Losh 01 unused
27310c16b537SWarner Losh 10 is Raw (uncompressed)
27320c16b537SWarner Losh 11 is Rle
27330c16b537SWarner Losh Note : using 01 => Huff0 with precomputed table ?
27340c16b537SWarner Losh Note : delta map ? => compressed ?
27350c16b537SWarner Losh
27360c16b537SWarner Losh 1.1.1) Huff0-compressed literal block : 3-5 bytes
27370c16b537SWarner Losh srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
27380c16b537SWarner Losh srcSize < 1 KB => 3 bytes (2-2-10-10)
27390c16b537SWarner Losh srcSize < 16KB => 4 bytes (2-2-14-14)
27400c16b537SWarner Losh else => 5 bytes (2-2-18-18)
27410c16b537SWarner Losh big endian convention
27420c16b537SWarner Losh
27430c16b537SWarner Losh 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
27440c16b537SWarner Losh size : 5 bits: (IS_RAW<<6) + (0<<4) + size
27450c16b537SWarner Losh 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
27460c16b537SWarner Losh size&255
27470c16b537SWarner Losh 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
27480c16b537SWarner Losh size>>8&255
27490c16b537SWarner Losh size&255
27500c16b537SWarner Losh
27510c16b537SWarner Losh 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
27520c16b537SWarner Losh size : 5 bits: (IS_RLE<<6) + (0<<4) + size
27530c16b537SWarner Losh 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
27540c16b537SWarner Losh size&255
27550c16b537SWarner Losh 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
27560c16b537SWarner Losh size>>8&255
27570c16b537SWarner Losh size&255
27580c16b537SWarner Losh
27590c16b537SWarner Losh 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
27600c16b537SWarner Losh srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
27610c16b537SWarner Losh srcSize < 1 KB => 3 bytes (2-2-10-10)
27620c16b537SWarner Losh srcSize < 16KB => 4 bytes (2-2-14-14)
27630c16b537SWarner Losh else => 5 bytes (2-2-18-18)
27640c16b537SWarner Losh big endian convention
27650c16b537SWarner Losh
27660c16b537SWarner Losh 1- CTable available (stored into workspace ?)
27670c16b537SWarner Losh 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
27680c16b537SWarner Losh
27690c16b537SWarner Losh
27700c16b537SWarner Losh 1.2) Literal block content
27710c16b537SWarner Losh
27720c16b537SWarner Losh 1.2.1) Huff0 block, using sizes from header
27730c16b537SWarner Losh See Huff0 format
27740c16b537SWarner Losh
27750c16b537SWarner Losh 1.2.2) Huff0 block, using prepared table
27760c16b537SWarner Losh
27770c16b537SWarner Losh 1.2.3) Raw content
27780c16b537SWarner Losh
27790c16b537SWarner Losh 1.2.4) single byte
27800c16b537SWarner Losh
27810c16b537SWarner Losh
27820c16b537SWarner Losh 2) Sequences section
27830c16b537SWarner Losh TO DO
27840c16b537SWarner Losh */
27850c16b537SWarner Losh
27860c16b537SWarner Losh
27870c16b537SWarner Losh /** ZSTDv05_decodeFrameHeader_Part1() :
27880c16b537SWarner Losh * decode the 1st part of the Frame Header, which tells Frame Header size.
27890c16b537SWarner Losh * srcSize must be == ZSTDv05_frameHeaderSize_min.
27900c16b537SWarner Losh * @return : the full size of the Frame Header */
ZSTDv05_decodeFrameHeader_Part1(ZSTDv05_DCtx * zc,const void * src,size_t srcSize)27910c16b537SWarner Losh static size_t ZSTDv05_decodeFrameHeader_Part1(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)
27920c16b537SWarner Losh {
27930c16b537SWarner Losh U32 magicNumber;
27940c16b537SWarner Losh if (srcSize != ZSTDv05_frameHeaderSize_min)
27950c16b537SWarner Losh return ERROR(srcSize_wrong);
27960c16b537SWarner Losh magicNumber = MEM_readLE32(src);
27970c16b537SWarner Losh if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);
27980c16b537SWarner Losh zc->headerSize = ZSTDv05_frameHeaderSize_min;
27990c16b537SWarner Losh return zc->headerSize;
28000c16b537SWarner Losh }
28010c16b537SWarner Losh
28020c16b537SWarner Losh
ZSTDv05_getFrameParams(ZSTDv05_parameters * params,const void * src,size_t srcSize)28030c16b537SWarner Losh size_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize)
28040c16b537SWarner Losh {
28050c16b537SWarner Losh U32 magicNumber;
28060c16b537SWarner Losh if (srcSize < ZSTDv05_frameHeaderSize_min) return ZSTDv05_frameHeaderSize_max;
28070c16b537SWarner Losh magicNumber = MEM_readLE32(src);
28080c16b537SWarner Losh if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);
28090c16b537SWarner Losh memset(params, 0, sizeof(*params));
28100c16b537SWarner Losh params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTDv05_WINDOWLOG_ABSOLUTEMIN;
28110c16b537SWarner Losh if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported); /* reserved bits */
28120c16b537SWarner Losh return 0;
28130c16b537SWarner Losh }
28140c16b537SWarner Losh
28150c16b537SWarner Losh /** ZSTDv05_decodeFrameHeader_Part2() :
28160c16b537SWarner Losh * decode the full Frame Header.
28170c16b537SWarner Losh * srcSize must be the size provided by ZSTDv05_decodeFrameHeader_Part1().
28180c16b537SWarner Losh * @return : 0, or an error code, which can be tested using ZSTDv05_isError() */
ZSTDv05_decodeFrameHeader_Part2(ZSTDv05_DCtx * zc,const void * src,size_t srcSize)28190c16b537SWarner Losh static size_t ZSTDv05_decodeFrameHeader_Part2(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)
28200c16b537SWarner Losh {
28210c16b537SWarner Losh size_t result;
28220c16b537SWarner Losh if (srcSize != zc->headerSize)
28230c16b537SWarner Losh return ERROR(srcSize_wrong);
28240c16b537SWarner Losh result = ZSTDv05_getFrameParams(&(zc->params), src, srcSize);
28250c16b537SWarner Losh if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported);
28260c16b537SWarner Losh return result;
28270c16b537SWarner Losh }
28280c16b537SWarner Losh
28290c16b537SWarner Losh
ZSTDv05_getcBlockSize(const void * src,size_t srcSize,blockProperties_t * bpPtr)28300f743729SConrad Meyer static size_t ZSTDv05_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
28310c16b537SWarner Losh {
2832*5ff13fbcSAllan Jude const BYTE* const in = (const BYTE*)src;
28330c16b537SWarner Losh BYTE headerFlags;
28340c16b537SWarner Losh U32 cSize;
28350c16b537SWarner Losh
28360c16b537SWarner Losh if (srcSize < 3)
28370c16b537SWarner Losh return ERROR(srcSize_wrong);
28380c16b537SWarner Losh
28390c16b537SWarner Losh headerFlags = *in;
28400c16b537SWarner Losh cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
28410c16b537SWarner Losh
28420c16b537SWarner Losh bpPtr->blockType = (blockType_t)(headerFlags >> 6);
28430c16b537SWarner Losh bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
28440c16b537SWarner Losh
28450c16b537SWarner Losh if (bpPtr->blockType == bt_end) return 0;
28460c16b537SWarner Losh if (bpPtr->blockType == bt_rle) return 1;
28470c16b537SWarner Losh return cSize;
28480c16b537SWarner Losh }
28490c16b537SWarner Losh
28500c16b537SWarner Losh
ZSTDv05_copyRawBlock(void * dst,size_t maxDstSize,const void * src,size_t srcSize)28510c16b537SWarner Losh static size_t ZSTDv05_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
28520c16b537SWarner Losh {
28530f743729SConrad Meyer if (dst==NULL) return ERROR(dstSize_tooSmall);
28540c16b537SWarner Losh if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
28550c16b537SWarner Losh memcpy(dst, src, srcSize);
28560c16b537SWarner Losh return srcSize;
28570c16b537SWarner Losh }
28580c16b537SWarner Losh
28590c16b537SWarner Losh
28600c16b537SWarner Losh /*! ZSTDv05_decodeLiteralsBlock() :
28610c16b537SWarner Losh @return : nb of bytes read from src (< srcSize ) */
ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx * dctx,const void * src,size_t srcSize)28620f743729SConrad Meyer static size_t ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx* dctx,
28630c16b537SWarner Losh const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
28640c16b537SWarner Losh {
28650c16b537SWarner Losh const BYTE* const istart = (const BYTE*) src;
28660c16b537SWarner Losh
28670c16b537SWarner Losh /* any compressed block with literals segment must be at least this size */
28680c16b537SWarner Losh if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
28690c16b537SWarner Losh
28700c16b537SWarner Losh switch(istart[0]>> 6)
28710c16b537SWarner Losh {
28720c16b537SWarner Losh case IS_HUFv05:
28730c16b537SWarner Losh {
28740c16b537SWarner Losh size_t litSize, litCSize, singleStream=0;
28750c16b537SWarner Losh U32 lhSize = ((istart[0]) >> 4) & 3;
28760c16b537SWarner Losh if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
28770c16b537SWarner Losh switch(lhSize)
28780c16b537SWarner Losh {
28790c16b537SWarner Losh case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
28800c16b537SWarner Losh /* 2 - 2 - 10 - 10 */
28810c16b537SWarner Losh lhSize=3;
28820c16b537SWarner Losh singleStream = istart[0] & 16;
28830c16b537SWarner Losh litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
28840c16b537SWarner Losh litCSize = ((istart[1] & 3) << 8) + istart[2];
28850c16b537SWarner Losh break;
28860c16b537SWarner Losh case 2:
28870c16b537SWarner Losh /* 2 - 2 - 14 - 14 */
28880c16b537SWarner Losh lhSize=4;
28890c16b537SWarner Losh litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
28900c16b537SWarner Losh litCSize = ((istart[2] & 63) << 8) + istart[3];
28910c16b537SWarner Losh break;
28920c16b537SWarner Losh case 3:
28930c16b537SWarner Losh /* 2 - 2 - 18 - 18 */
28940c16b537SWarner Losh lhSize=5;
28950c16b537SWarner Losh litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
28960c16b537SWarner Losh litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
28970c16b537SWarner Losh break;
28980c16b537SWarner Losh }
28990c16b537SWarner Losh if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
29000c16b537SWarner Losh if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
29010c16b537SWarner Losh
29020c16b537SWarner Losh if (HUFv05_isError(singleStream ?
29030c16b537SWarner Losh HUFv05_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :
29040c16b537SWarner Losh HUFv05_decompress (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
29050c16b537SWarner Losh return ERROR(corruption_detected);
29060c16b537SWarner Losh
29070c16b537SWarner Losh dctx->litPtr = dctx->litBuffer;
29080c16b537SWarner Losh dctx->litSize = litSize;
29090c16b537SWarner Losh memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
29100c16b537SWarner Losh return litCSize + lhSize;
29110c16b537SWarner Losh }
29120c16b537SWarner Losh case IS_PCH:
29130c16b537SWarner Losh {
29140c16b537SWarner Losh size_t errorCode;
29150c16b537SWarner Losh size_t litSize, litCSize;
29160c16b537SWarner Losh U32 lhSize = ((istart[0]) >> 4) & 3;
29170c16b537SWarner Losh if (lhSize != 1) /* only case supported for now : small litSize, single stream */
29180c16b537SWarner Losh return ERROR(corruption_detected);
29190c16b537SWarner Losh if (!dctx->flagStaticTables)
29200c16b537SWarner Losh return ERROR(dictionary_corrupted);
29210c16b537SWarner Losh
29220c16b537SWarner Losh /* 2 - 2 - 10 - 10 */
29230c16b537SWarner Losh lhSize=3;
29240c16b537SWarner Losh litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
29250c16b537SWarner Losh litCSize = ((istart[1] & 3) << 8) + istart[2];
29260c16b537SWarner Losh if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
29270c16b537SWarner Losh
29280c16b537SWarner Losh errorCode = HUFv05_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
29290c16b537SWarner Losh if (HUFv05_isError(errorCode)) return ERROR(corruption_detected);
29300c16b537SWarner Losh
29310c16b537SWarner Losh dctx->litPtr = dctx->litBuffer;
29320c16b537SWarner Losh dctx->litSize = litSize;
29330c16b537SWarner Losh memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
29340c16b537SWarner Losh return litCSize + lhSize;
29350c16b537SWarner Losh }
29360c16b537SWarner Losh case IS_RAW:
29370c16b537SWarner Losh {
29380c16b537SWarner Losh size_t litSize;
29390c16b537SWarner Losh U32 lhSize = ((istart[0]) >> 4) & 3;
29400c16b537SWarner Losh switch(lhSize)
29410c16b537SWarner Losh {
29420c16b537SWarner Losh case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
29430c16b537SWarner Losh lhSize=1;
29440c16b537SWarner Losh litSize = istart[0] & 31;
29450c16b537SWarner Losh break;
29460c16b537SWarner Losh case 2:
29470c16b537SWarner Losh litSize = ((istart[0] & 15) << 8) + istart[1];
29480c16b537SWarner Losh break;
29490c16b537SWarner Losh case 3:
29500c16b537SWarner Losh litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
29510c16b537SWarner Losh break;
29520c16b537SWarner Losh }
29530c16b537SWarner Losh
29540c16b537SWarner Losh if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
29550c16b537SWarner Losh if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
29560c16b537SWarner Losh memcpy(dctx->litBuffer, istart+lhSize, litSize);
29570c16b537SWarner Losh dctx->litPtr = dctx->litBuffer;
29580c16b537SWarner Losh dctx->litSize = litSize;
29590c16b537SWarner Losh memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
29600c16b537SWarner Losh return lhSize+litSize;
29610c16b537SWarner Losh }
29620c16b537SWarner Losh /* direct reference into compressed stream */
29630c16b537SWarner Losh dctx->litPtr = istart+lhSize;
29640c16b537SWarner Losh dctx->litSize = litSize;
29650c16b537SWarner Losh return lhSize+litSize;
29660c16b537SWarner Losh }
29670c16b537SWarner Losh case IS_RLE:
29680c16b537SWarner Losh {
29690c16b537SWarner Losh size_t litSize;
29700c16b537SWarner Losh U32 lhSize = ((istart[0]) >> 4) & 3;
29710c16b537SWarner Losh switch(lhSize)
29720c16b537SWarner Losh {
29730c16b537SWarner Losh case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
29740c16b537SWarner Losh lhSize = 1;
29750c16b537SWarner Losh litSize = istart[0] & 31;
29760c16b537SWarner Losh break;
29770c16b537SWarner Losh case 2:
29780c16b537SWarner Losh litSize = ((istart[0] & 15) << 8) + istart[1];
29790c16b537SWarner Losh break;
29800c16b537SWarner Losh case 3:
29810c16b537SWarner Losh litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
29820c16b537SWarner Losh if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
29830c16b537SWarner Losh break;
29840c16b537SWarner Losh }
29850c16b537SWarner Losh if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
29860c16b537SWarner Losh memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
29870c16b537SWarner Losh dctx->litPtr = dctx->litBuffer;
29880c16b537SWarner Losh dctx->litSize = litSize;
29890c16b537SWarner Losh return lhSize+1;
29900c16b537SWarner Losh }
29910c16b537SWarner Losh default:
29920c16b537SWarner Losh return ERROR(corruption_detected); /* impossible */
29930c16b537SWarner Losh }
29940c16b537SWarner Losh }
29950c16b537SWarner Losh
29960c16b537SWarner Losh
ZSTDv05_decodeSeqHeaders(int * nbSeq,const BYTE ** dumpsPtr,size_t * dumpsLengthPtr,FSEv05_DTable * DTableLL,FSEv05_DTable * DTableML,FSEv05_DTable * DTableOffb,const void * src,size_t srcSize,U32 flagStaticTable)29970f743729SConrad Meyer static size_t ZSTDv05_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
29980c16b537SWarner Losh FSEv05_DTable* DTableLL, FSEv05_DTable* DTableML, FSEv05_DTable* DTableOffb,
29990c16b537SWarner Losh const void* src, size_t srcSize, U32 flagStaticTable)
30000c16b537SWarner Losh {
3001*5ff13fbcSAllan Jude const BYTE* const istart = (const BYTE*)src;
30020c16b537SWarner Losh const BYTE* ip = istart;
30030c16b537SWarner Losh const BYTE* const iend = istart + srcSize;
30040c16b537SWarner Losh U32 LLtype, Offtype, MLtype;
3005a0483764SConrad Meyer unsigned LLlog, Offlog, MLlog;
30060c16b537SWarner Losh size_t dumpsLength;
30070c16b537SWarner Losh
30080c16b537SWarner Losh /* check */
30090c16b537SWarner Losh if (srcSize < MIN_SEQUENCES_SIZE)
30100c16b537SWarner Losh return ERROR(srcSize_wrong);
30110c16b537SWarner Losh
30120c16b537SWarner Losh /* SeqHead */
30130c16b537SWarner Losh *nbSeq = *ip++;
30140c16b537SWarner Losh if (*nbSeq==0) return 1;
30150c16b537SWarner Losh if (*nbSeq >= 128) {
30160c16b537SWarner Losh if (ip >= iend) return ERROR(srcSize_wrong);
30170c16b537SWarner Losh *nbSeq = ((nbSeq[0]-128)<<8) + *ip++;
30180c16b537SWarner Losh }
30190c16b537SWarner Losh
30200c16b537SWarner Losh if (ip >= iend) return ERROR(srcSize_wrong);
30210c16b537SWarner Losh LLtype = *ip >> 6;
30220c16b537SWarner Losh Offtype = (*ip >> 4) & 3;
30230c16b537SWarner Losh MLtype = (*ip >> 2) & 3;
30240c16b537SWarner Losh if (*ip & 2) {
30250c16b537SWarner Losh if (ip+3 > iend) return ERROR(srcSize_wrong);
30260c16b537SWarner Losh dumpsLength = ip[2];
30270c16b537SWarner Losh dumpsLength += ip[1] << 8;
30280c16b537SWarner Losh ip += 3;
30290c16b537SWarner Losh } else {
30300c16b537SWarner Losh if (ip+2 > iend) return ERROR(srcSize_wrong);
30310c16b537SWarner Losh dumpsLength = ip[1];
30320c16b537SWarner Losh dumpsLength += (ip[0] & 1) << 8;
30330c16b537SWarner Losh ip += 2;
30340c16b537SWarner Losh }
30350c16b537SWarner Losh *dumpsPtr = ip;
30360c16b537SWarner Losh ip += dumpsLength;
30370c16b537SWarner Losh *dumpsLengthPtr = dumpsLength;
30380c16b537SWarner Losh
30390c16b537SWarner Losh /* check */
30400c16b537SWarner Losh if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
30410c16b537SWarner Losh
30420c16b537SWarner Losh /* sequences */
30430c16b537SWarner Losh {
30440c16b537SWarner Losh S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */
30450c16b537SWarner Losh size_t headerSize;
30460c16b537SWarner Losh
30470c16b537SWarner Losh /* Build DTables */
30480c16b537SWarner Losh switch(LLtype)
30490c16b537SWarner Losh {
30500c16b537SWarner Losh case FSEv05_ENCODING_RLE :
30510c16b537SWarner Losh LLlog = 0;
30520c16b537SWarner Losh FSEv05_buildDTable_rle(DTableLL, *ip++);
30530c16b537SWarner Losh break;
30540c16b537SWarner Losh case FSEv05_ENCODING_RAW :
30550c16b537SWarner Losh LLlog = LLbits;
30560c16b537SWarner Losh FSEv05_buildDTable_raw(DTableLL, LLbits);
30570c16b537SWarner Losh break;
30580c16b537SWarner Losh case FSEv05_ENCODING_STATIC:
30590c16b537SWarner Losh if (!flagStaticTable) return ERROR(corruption_detected);
30600c16b537SWarner Losh break;
30610c16b537SWarner Losh case FSEv05_ENCODING_DYNAMIC :
30620c16b537SWarner Losh default : /* impossible */
3063a0483764SConrad Meyer { unsigned max = MaxLL;
30640c16b537SWarner Losh headerSize = FSEv05_readNCount(norm, &max, &LLlog, ip, iend-ip);
30650c16b537SWarner Losh if (FSEv05_isError(headerSize)) return ERROR(GENERIC);
30660c16b537SWarner Losh if (LLlog > LLFSEv05Log) return ERROR(corruption_detected);
30670c16b537SWarner Losh ip += headerSize;
30680c16b537SWarner Losh FSEv05_buildDTable(DTableLL, norm, max, LLlog);
30690c16b537SWarner Losh } }
30700c16b537SWarner Losh
30710c16b537SWarner Losh switch(Offtype)
30720c16b537SWarner Losh {
30730c16b537SWarner Losh case FSEv05_ENCODING_RLE :
30740c16b537SWarner Losh Offlog = 0;
30750c16b537SWarner Losh if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
30760c16b537SWarner Losh FSEv05_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
30770c16b537SWarner Losh break;
30780c16b537SWarner Losh case FSEv05_ENCODING_RAW :
30790c16b537SWarner Losh Offlog = Offbits;
30800c16b537SWarner Losh FSEv05_buildDTable_raw(DTableOffb, Offbits);
30810c16b537SWarner Losh break;
30820c16b537SWarner Losh case FSEv05_ENCODING_STATIC:
30830c16b537SWarner Losh if (!flagStaticTable) return ERROR(corruption_detected);
30840c16b537SWarner Losh break;
30850c16b537SWarner Losh case FSEv05_ENCODING_DYNAMIC :
30860c16b537SWarner Losh default : /* impossible */
3087a0483764SConrad Meyer { unsigned max = MaxOff;
30880c16b537SWarner Losh headerSize = FSEv05_readNCount(norm, &max, &Offlog, ip, iend-ip);
30890c16b537SWarner Losh if (FSEv05_isError(headerSize)) return ERROR(GENERIC);
30900c16b537SWarner Losh if (Offlog > OffFSEv05Log) return ERROR(corruption_detected);
30910c16b537SWarner Losh ip += headerSize;
30920c16b537SWarner Losh FSEv05_buildDTable(DTableOffb, norm, max, Offlog);
30930c16b537SWarner Losh } }
30940c16b537SWarner Losh
30950c16b537SWarner Losh switch(MLtype)
30960c16b537SWarner Losh {
30970c16b537SWarner Losh case FSEv05_ENCODING_RLE :
30980c16b537SWarner Losh MLlog = 0;
30990c16b537SWarner Losh if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
31000c16b537SWarner Losh FSEv05_buildDTable_rle(DTableML, *ip++);
31010c16b537SWarner Losh break;
31020c16b537SWarner Losh case FSEv05_ENCODING_RAW :
31030c16b537SWarner Losh MLlog = MLbits;
31040c16b537SWarner Losh FSEv05_buildDTable_raw(DTableML, MLbits);
31050c16b537SWarner Losh break;
31060c16b537SWarner Losh case FSEv05_ENCODING_STATIC:
31070c16b537SWarner Losh if (!flagStaticTable) return ERROR(corruption_detected);
31080c16b537SWarner Losh break;
31090c16b537SWarner Losh case FSEv05_ENCODING_DYNAMIC :
31100c16b537SWarner Losh default : /* impossible */
3111a0483764SConrad Meyer { unsigned max = MaxML;
31120c16b537SWarner Losh headerSize = FSEv05_readNCount(norm, &max, &MLlog, ip, iend-ip);
31130c16b537SWarner Losh if (FSEv05_isError(headerSize)) return ERROR(GENERIC);
31140c16b537SWarner Losh if (MLlog > MLFSEv05Log) return ERROR(corruption_detected);
31150c16b537SWarner Losh ip += headerSize;
31160c16b537SWarner Losh FSEv05_buildDTable(DTableML, norm, max, MLlog);
31170c16b537SWarner Losh } } }
31180c16b537SWarner Losh
31190c16b537SWarner Losh return ip-istart;
31200c16b537SWarner Losh }
31210c16b537SWarner Losh
31220c16b537SWarner Losh
31230c16b537SWarner Losh typedef struct {
31240c16b537SWarner Losh size_t litLength;
31250c16b537SWarner Losh size_t matchLength;
31260c16b537SWarner Losh size_t offset;
31270c16b537SWarner Losh } seq_t;
31280c16b537SWarner Losh
31290c16b537SWarner Losh typedef struct {
31300c16b537SWarner Losh BITv05_DStream_t DStream;
31310c16b537SWarner Losh FSEv05_DState_t stateLL;
31320c16b537SWarner Losh FSEv05_DState_t stateOffb;
31330c16b537SWarner Losh FSEv05_DState_t stateML;
31340c16b537SWarner Losh size_t prevOffset;
31350c16b537SWarner Losh const BYTE* dumps;
31360c16b537SWarner Losh const BYTE* dumpsEnd;
31370c16b537SWarner Losh } seqState_t;
31380c16b537SWarner Losh
31390c16b537SWarner Losh
31400c16b537SWarner Losh
ZSTDv05_decodeSequence(seq_t * seq,seqState_t * seqState)31410c16b537SWarner Losh static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
31420c16b537SWarner Losh {
31430c16b537SWarner Losh size_t litLength;
31440c16b537SWarner Losh size_t prevOffset;
31450c16b537SWarner Losh size_t offset;
31460c16b537SWarner Losh size_t matchLength;
31470c16b537SWarner Losh const BYTE* dumps = seqState->dumps;
31480c16b537SWarner Losh const BYTE* const de = seqState->dumpsEnd;
31490c16b537SWarner Losh
31500c16b537SWarner Losh /* Literal length */
31510c16b537SWarner Losh litLength = FSEv05_peakSymbol(&(seqState->stateLL));
31520c16b537SWarner Losh prevOffset = litLength ? seq->offset : seqState->prevOffset;
31530c16b537SWarner Losh if (litLength == MaxLL) {
31544d3f1eafSConrad Meyer const U32 add = *dumps++;
31550c16b537SWarner Losh if (add < 255) litLength += add;
31564d3f1eafSConrad Meyer else if (dumps + 2 <= de) {
31574d3f1eafSConrad Meyer litLength = MEM_readLE16(dumps);
31584d3f1eafSConrad Meyer dumps += 2;
31594d3f1eafSConrad Meyer if ((litLength & 1) && dumps < de) {
31604d3f1eafSConrad Meyer litLength += *dumps << 16;
31614d3f1eafSConrad Meyer dumps += 1;
31620c16b537SWarner Losh }
31634d3f1eafSConrad Meyer litLength>>=1;
31644d3f1eafSConrad Meyer }
31650c16b537SWarner Losh if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
31660c16b537SWarner Losh }
31670c16b537SWarner Losh
31680c16b537SWarner Losh /* Offset */
31690c16b537SWarner Losh {
31700c16b537SWarner Losh static const U32 offsetPrefix[MaxOff+1] = {
31710c16b537SWarner Losh 1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,
31720c16b537SWarner Losh 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
31730c16b537SWarner Losh 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };
31740c16b537SWarner Losh U32 offsetCode = FSEv05_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
31750c16b537SWarner Losh U32 nbBits = offsetCode - 1;
31760c16b537SWarner Losh if (offsetCode==0) nbBits = 0; /* cmove */
31770c16b537SWarner Losh offset = offsetPrefix[offsetCode] + BITv05_readBits(&(seqState->DStream), nbBits);
31780c16b537SWarner Losh if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));
31790c16b537SWarner Losh if (offsetCode==0) offset = prevOffset; /* repcode, cmove */
31800c16b537SWarner Losh if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */
31810c16b537SWarner Losh FSEv05_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */
31820c16b537SWarner Losh }
31830c16b537SWarner Losh
31840c16b537SWarner Losh /* Literal length update */
31850c16b537SWarner Losh FSEv05_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */
31860c16b537SWarner Losh if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));
31870c16b537SWarner Losh
31880c16b537SWarner Losh /* MatchLength */
31890c16b537SWarner Losh matchLength = FSEv05_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
31900c16b537SWarner Losh if (matchLength == MaxML) {
31914d3f1eafSConrad Meyer const U32 add = dumps<de ? *dumps++ : 0;
31920c16b537SWarner Losh if (add < 255) matchLength += add;
31934d3f1eafSConrad Meyer else if (dumps + 2 <= de) {
31944d3f1eafSConrad Meyer matchLength = MEM_readLE16(dumps);
31954d3f1eafSConrad Meyer dumps += 2;
31964d3f1eafSConrad Meyer if ((matchLength & 1) && dumps < de) {
31974d3f1eafSConrad Meyer matchLength += *dumps << 16;
31984d3f1eafSConrad Meyer dumps += 1;
31990c16b537SWarner Losh }
32004d3f1eafSConrad Meyer matchLength >>= 1;
32014d3f1eafSConrad Meyer }
32020c16b537SWarner Losh if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
32030c16b537SWarner Losh }
32040c16b537SWarner Losh matchLength += MINMATCH;
32050c16b537SWarner Losh
32060c16b537SWarner Losh /* save result */
32070c16b537SWarner Losh seq->litLength = litLength;
32080c16b537SWarner Losh seq->offset = offset;
32090c16b537SWarner Losh seq->matchLength = matchLength;
32100c16b537SWarner Losh seqState->dumps = dumps;
32110c16b537SWarner Losh
32120c16b537SWarner Losh #if 0 /* debug */
32130c16b537SWarner Losh {
32140c16b537SWarner Losh static U64 totalDecoded = 0;
32150c16b537SWarner Losh printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
32160c16b537SWarner Losh (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
32170c16b537SWarner Losh totalDecoded += litLength + matchLength;
32180c16b537SWarner Losh }
32190c16b537SWarner Losh #endif
32200c16b537SWarner Losh }
32210c16b537SWarner Losh
32220c16b537SWarner Losh
ZSTDv05_execSequence(BYTE * op,BYTE * const oend,seq_t sequence,const BYTE ** litPtr,const BYTE * const litLimit,const BYTE * const base,const BYTE * const vBase,const BYTE * const dictEnd)32230c16b537SWarner Losh static size_t ZSTDv05_execSequence(BYTE* op,
32240c16b537SWarner Losh BYTE* const oend, seq_t sequence,
32250c16b537SWarner Losh const BYTE** litPtr, const BYTE* const litLimit,
32260c16b537SWarner Losh const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
32270c16b537SWarner Losh {
32280c16b537SWarner Losh static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
32292b9c00cbSConrad Meyer static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
32300c16b537SWarner Losh BYTE* const oLitEnd = op + sequence.litLength;
32310c16b537SWarner Losh const size_t sequenceLength = sequence.litLength + sequence.matchLength;
32320c16b537SWarner Losh BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
32330c16b537SWarner Losh BYTE* const oend_8 = oend-8;
32340c16b537SWarner Losh const BYTE* const litEnd = *litPtr + sequence.litLength;
32350c16b537SWarner Losh const BYTE* match = oLitEnd - sequence.offset;
32360c16b537SWarner Losh
32370c16b537SWarner Losh /* check */
32380c16b537SWarner Losh if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
32390c16b537SWarner Losh if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
32400c16b537SWarner Losh if (litEnd > litLimit) return ERROR(corruption_detected); /* risk read beyond lit buffer */
32410c16b537SWarner Losh
32420c16b537SWarner Losh /* copy Literals */
32430c16b537SWarner Losh ZSTDv05_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
32440c16b537SWarner Losh op = oLitEnd;
32450c16b537SWarner Losh *litPtr = litEnd; /* update for next sequence */
32460c16b537SWarner Losh
32470c16b537SWarner Losh /* copy Match */
32480c16b537SWarner Losh if (sequence.offset > (size_t)(oLitEnd - base)) {
32490c16b537SWarner Losh /* offset beyond prefix */
32500c16b537SWarner Losh if (sequence.offset > (size_t)(oLitEnd - vBase))
32510c16b537SWarner Losh return ERROR(corruption_detected);
32520c16b537SWarner Losh match = dictEnd - (base-match);
32530c16b537SWarner Losh if (match + sequence.matchLength <= dictEnd) {
32540c16b537SWarner Losh memmove(oLitEnd, match, sequence.matchLength);
32550c16b537SWarner Losh return sequenceLength;
32560c16b537SWarner Losh }
32570c16b537SWarner Losh /* span extDict & currentPrefixSegment */
32580c16b537SWarner Losh {
32590c16b537SWarner Losh size_t length1 = dictEnd - match;
32600c16b537SWarner Losh memmove(oLitEnd, match, length1);
32610c16b537SWarner Losh op = oLitEnd + length1;
32620c16b537SWarner Losh sequence.matchLength -= length1;
32630c16b537SWarner Losh match = base;
32640c16b537SWarner Losh if (op > oend_8 || sequence.matchLength < MINMATCH) {
32650c16b537SWarner Losh while (op < oMatchEnd) *op++ = *match++;
32660c16b537SWarner Losh return sequenceLength;
32670c16b537SWarner Losh }
32680c16b537SWarner Losh } }
32690c16b537SWarner Losh /* Requirement: op <= oend_8 */
32700c16b537SWarner Losh
32710c16b537SWarner Losh /* match within prefix */
32720c16b537SWarner Losh if (sequence.offset < 8) {
32730c16b537SWarner Losh /* close range match, overlap */
32740c16b537SWarner Losh const int sub2 = dec64table[sequence.offset];
32750c16b537SWarner Losh op[0] = match[0];
32760c16b537SWarner Losh op[1] = match[1];
32770c16b537SWarner Losh op[2] = match[2];
32780c16b537SWarner Losh op[3] = match[3];
32790c16b537SWarner Losh match += dec32table[sequence.offset];
32800c16b537SWarner Losh ZSTDv05_copy4(op+4, match);
32810c16b537SWarner Losh match -= sub2;
32820c16b537SWarner Losh } else {
32830c16b537SWarner Losh ZSTDv05_copy8(op, match);
32840c16b537SWarner Losh }
32850c16b537SWarner Losh op += 8; match += 8;
32860c16b537SWarner Losh
32870c16b537SWarner Losh if (oMatchEnd > oend-(16-MINMATCH)) {
32880c16b537SWarner Losh if (op < oend_8) {
32890c16b537SWarner Losh ZSTDv05_wildcopy(op, match, oend_8 - op);
32900c16b537SWarner Losh match += oend_8 - op;
32910c16b537SWarner Losh op = oend_8;
32920c16b537SWarner Losh }
32930c16b537SWarner Losh while (op < oMatchEnd)
32940c16b537SWarner Losh *op++ = *match++;
32950c16b537SWarner Losh } else {
32960c16b537SWarner Losh ZSTDv05_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
32970c16b537SWarner Losh }
32980c16b537SWarner Losh return sequenceLength;
32990c16b537SWarner Losh }
33000c16b537SWarner Losh
33010c16b537SWarner Losh
ZSTDv05_decompressSequences(ZSTDv05_DCtx * dctx,void * dst,size_t maxDstSize,const void * seqStart,size_t seqSize)33020c16b537SWarner Losh static size_t ZSTDv05_decompressSequences(
33030c16b537SWarner Losh ZSTDv05_DCtx* dctx,
33040c16b537SWarner Losh void* dst, size_t maxDstSize,
33050c16b537SWarner Losh const void* seqStart, size_t seqSize)
33060c16b537SWarner Losh {
33070c16b537SWarner Losh const BYTE* ip = (const BYTE*)seqStart;
33080c16b537SWarner Losh const BYTE* const iend = ip + seqSize;
3309*5ff13fbcSAllan Jude BYTE* const ostart = (BYTE*)dst;
33100c16b537SWarner Losh BYTE* op = ostart;
33110c16b537SWarner Losh BYTE* const oend = ostart + maxDstSize;
33120f743729SConrad Meyer size_t errorCode, dumpsLength=0;
33130c16b537SWarner Losh const BYTE* litPtr = dctx->litPtr;
33140c16b537SWarner Losh const BYTE* const litEnd = litPtr + dctx->litSize;
33150f743729SConrad Meyer int nbSeq=0;
33160f743729SConrad Meyer const BYTE* dumps = NULL;
3317a0483764SConrad Meyer unsigned* DTableLL = dctx->LLTable;
3318a0483764SConrad Meyer unsigned* DTableML = dctx->MLTable;
3319a0483764SConrad Meyer unsigned* DTableOffb = dctx->OffTable;
33200c16b537SWarner Losh const BYTE* const base = (const BYTE*) (dctx->base);
33210c16b537SWarner Losh const BYTE* const vBase = (const BYTE*) (dctx->vBase);
33220c16b537SWarner Losh const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
33230c16b537SWarner Losh
33240c16b537SWarner Losh /* Build Decoding Tables */
33250c16b537SWarner Losh errorCode = ZSTDv05_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
33260c16b537SWarner Losh DTableLL, DTableML, DTableOffb,
33270c16b537SWarner Losh ip, seqSize, dctx->flagStaticTables);
33280c16b537SWarner Losh if (ZSTDv05_isError(errorCode)) return errorCode;
33290c16b537SWarner Losh ip += errorCode;
33300c16b537SWarner Losh
33310c16b537SWarner Losh /* Regen sequences */
33320c16b537SWarner Losh if (nbSeq) {
33330c16b537SWarner Losh seq_t sequence;
33340c16b537SWarner Losh seqState_t seqState;
33350c16b537SWarner Losh
33360c16b537SWarner Losh memset(&sequence, 0, sizeof(sequence));
33370c16b537SWarner Losh sequence.offset = REPCODE_STARTVALUE;
33380c16b537SWarner Losh seqState.dumps = dumps;
33390c16b537SWarner Losh seqState.dumpsEnd = dumps + dumpsLength;
33400c16b537SWarner Losh seqState.prevOffset = REPCODE_STARTVALUE;
33410c16b537SWarner Losh errorCode = BITv05_initDStream(&(seqState.DStream), ip, iend-ip);
33420c16b537SWarner Losh if (ERR_isError(errorCode)) return ERROR(corruption_detected);
33430c16b537SWarner Losh FSEv05_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
33440c16b537SWarner Losh FSEv05_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
33450c16b537SWarner Losh FSEv05_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
33460c16b537SWarner Losh
33470c16b537SWarner Losh for ( ; (BITv05_reloadDStream(&(seqState.DStream)) <= BITv05_DStream_completed) && nbSeq ; ) {
33480c16b537SWarner Losh size_t oneSeqSize;
33490c16b537SWarner Losh nbSeq--;
33500c16b537SWarner Losh ZSTDv05_decodeSequence(&sequence, &seqState);
33510c16b537SWarner Losh oneSeqSize = ZSTDv05_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
33520c16b537SWarner Losh if (ZSTDv05_isError(oneSeqSize)) return oneSeqSize;
33530c16b537SWarner Losh op += oneSeqSize;
33540c16b537SWarner Losh }
33550c16b537SWarner Losh
33560c16b537SWarner Losh /* check if reached exact end */
33570c16b537SWarner Losh if (nbSeq) return ERROR(corruption_detected);
33580c16b537SWarner Losh }
33590c16b537SWarner Losh
33600c16b537SWarner Losh /* last literal segment */
33610c16b537SWarner Losh {
33620c16b537SWarner Losh size_t lastLLSize = litEnd - litPtr;
33630c16b537SWarner Losh if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */
33640c16b537SWarner Losh if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
336537f1f268SConrad Meyer if (lastLLSize > 0) {
33660c16b537SWarner Losh memcpy(op, litPtr, lastLLSize);
33670c16b537SWarner Losh op += lastLLSize;
33680c16b537SWarner Losh }
336937f1f268SConrad Meyer }
33700c16b537SWarner Losh
33710c16b537SWarner Losh return op-ostart;
33720c16b537SWarner Losh }
33730c16b537SWarner Losh
33740c16b537SWarner Losh
ZSTDv05_checkContinuity(ZSTDv05_DCtx * dctx,const void * dst)33750c16b537SWarner Losh static void ZSTDv05_checkContinuity(ZSTDv05_DCtx* dctx, const void* dst)
33760c16b537SWarner Losh {
33770c16b537SWarner Losh if (dst != dctx->previousDstEnd) { /* not contiguous */
33780c16b537SWarner Losh dctx->dictEnd = dctx->previousDstEnd;
33790c16b537SWarner Losh dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
33800c16b537SWarner Losh dctx->base = dst;
33810c16b537SWarner Losh dctx->previousDstEnd = dst;
33820c16b537SWarner Losh }
33830c16b537SWarner Losh }
33840c16b537SWarner Losh
33850c16b537SWarner Losh
ZSTDv05_decompressBlock_internal(ZSTDv05_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize)33860c16b537SWarner Losh static size_t ZSTDv05_decompressBlock_internal(ZSTDv05_DCtx* dctx,
33870c16b537SWarner Losh void* dst, size_t dstCapacity,
33880c16b537SWarner Losh const void* src, size_t srcSize)
33890c16b537SWarner Losh { /* blockType == blockCompressed */
33900c16b537SWarner Losh const BYTE* ip = (const BYTE*)src;
33910c16b537SWarner Losh size_t litCSize;
33920c16b537SWarner Losh
33930c16b537SWarner Losh if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);
33940c16b537SWarner Losh
33950c16b537SWarner Losh /* Decode literals sub-block */
33960c16b537SWarner Losh litCSize = ZSTDv05_decodeLiteralsBlock(dctx, src, srcSize);
33970c16b537SWarner Losh if (ZSTDv05_isError(litCSize)) return litCSize;
33980c16b537SWarner Losh ip += litCSize;
33990c16b537SWarner Losh srcSize -= litCSize;
34000c16b537SWarner Losh
34010c16b537SWarner Losh return ZSTDv05_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
34020c16b537SWarner Losh }
34030c16b537SWarner Losh
34040c16b537SWarner Losh
ZSTDv05_decompressBlock(ZSTDv05_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize)34050c16b537SWarner Losh size_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx,
34060c16b537SWarner Losh void* dst, size_t dstCapacity,
34070c16b537SWarner Losh const void* src, size_t srcSize)
34080c16b537SWarner Losh {
34090c16b537SWarner Losh ZSTDv05_checkContinuity(dctx, dst);
34100c16b537SWarner Losh return ZSTDv05_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
34110c16b537SWarner Losh }
34120c16b537SWarner Losh
34130c16b537SWarner Losh
34140c16b537SWarner Losh /*! ZSTDv05_decompress_continueDCtx
34150c16b537SWarner Losh * dctx must have been properly initialized */
ZSTDv05_decompress_continueDCtx(ZSTDv05_DCtx * dctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)34160c16b537SWarner Losh static size_t ZSTDv05_decompress_continueDCtx(ZSTDv05_DCtx* dctx,
34170c16b537SWarner Losh void* dst, size_t maxDstSize,
34180c16b537SWarner Losh const void* src, size_t srcSize)
34190c16b537SWarner Losh {
34200c16b537SWarner Losh const BYTE* ip = (const BYTE*)src;
34210c16b537SWarner Losh const BYTE* iend = ip + srcSize;
3422*5ff13fbcSAllan Jude BYTE* const ostart = (BYTE*)dst;
34230c16b537SWarner Losh BYTE* op = ostart;
34240c16b537SWarner Losh BYTE* const oend = ostart + maxDstSize;
34250c16b537SWarner Losh size_t remainingSize = srcSize;
34260c16b537SWarner Losh blockProperties_t blockProperties;
34270f743729SConrad Meyer memset(&blockProperties, 0, sizeof(blockProperties));
34280c16b537SWarner Losh
34290c16b537SWarner Losh /* Frame Header */
34300f743729SConrad Meyer { size_t frameHeaderSize;
34310c16b537SWarner Losh if (srcSize < ZSTDv05_frameHeaderSize_min+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);
34320c16b537SWarner Losh frameHeaderSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);
34330c16b537SWarner Losh if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;
34340c16b537SWarner Losh if (srcSize < frameHeaderSize+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);
34350c16b537SWarner Losh ip += frameHeaderSize; remainingSize -= frameHeaderSize;
34360c16b537SWarner Losh frameHeaderSize = ZSTDv05_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);
34370c16b537SWarner Losh if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;
34380c16b537SWarner Losh }
34390c16b537SWarner Losh
34400c16b537SWarner Losh /* Loop on each block */
34410c16b537SWarner Losh while (1)
34420c16b537SWarner Losh {
34430c16b537SWarner Losh size_t decodedSize=0;
34440c16b537SWarner Losh size_t cBlockSize = ZSTDv05_getcBlockSize(ip, iend-ip, &blockProperties);
34450c16b537SWarner Losh if (ZSTDv05_isError(cBlockSize)) return cBlockSize;
34460c16b537SWarner Losh
34470c16b537SWarner Losh ip += ZSTDv05_blockHeaderSize;
34480c16b537SWarner Losh remainingSize -= ZSTDv05_blockHeaderSize;
34490c16b537SWarner Losh if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
34500c16b537SWarner Losh
34510c16b537SWarner Losh switch(blockProperties.blockType)
34520c16b537SWarner Losh {
34530c16b537SWarner Losh case bt_compressed:
34540c16b537SWarner Losh decodedSize = ZSTDv05_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
34550c16b537SWarner Losh break;
34560c16b537SWarner Losh case bt_raw :
34570c16b537SWarner Losh decodedSize = ZSTDv05_copyRawBlock(op, oend-op, ip, cBlockSize);
34580c16b537SWarner Losh break;
34590c16b537SWarner Losh case bt_rle :
34600c16b537SWarner Losh return ERROR(GENERIC); /* not yet supported */
34610c16b537SWarner Losh break;
34620c16b537SWarner Losh case bt_end :
34630c16b537SWarner Losh /* end of frame */
34640c16b537SWarner Losh if (remainingSize) return ERROR(srcSize_wrong);
34650c16b537SWarner Losh break;
34660c16b537SWarner Losh default:
34670c16b537SWarner Losh return ERROR(GENERIC); /* impossible */
34680c16b537SWarner Losh }
34690c16b537SWarner Losh if (cBlockSize == 0) break; /* bt_end */
34700c16b537SWarner Losh
34710c16b537SWarner Losh if (ZSTDv05_isError(decodedSize)) return decodedSize;
34720c16b537SWarner Losh op += decodedSize;
34730c16b537SWarner Losh ip += cBlockSize;
34740c16b537SWarner Losh remainingSize -= cBlockSize;
34750c16b537SWarner Losh }
34760c16b537SWarner Losh
34770c16b537SWarner Losh return op-ostart;
34780c16b537SWarner Losh }
34790c16b537SWarner Losh
34800c16b537SWarner Losh
ZSTDv05_decompress_usingPreparedDCtx(ZSTDv05_DCtx * dctx,const ZSTDv05_DCtx * refDCtx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)34810c16b537SWarner Losh size_t ZSTDv05_decompress_usingPreparedDCtx(ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* refDCtx,
34820c16b537SWarner Losh void* dst, size_t maxDstSize,
34830c16b537SWarner Losh const void* src, size_t srcSize)
34840c16b537SWarner Losh {
34850c16b537SWarner Losh ZSTDv05_copyDCtx(dctx, refDCtx);
34860c16b537SWarner Losh ZSTDv05_checkContinuity(dctx, dst);
34870c16b537SWarner Losh return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
34880c16b537SWarner Losh }
34890c16b537SWarner Losh
34900c16b537SWarner Losh
ZSTDv05_decompress_usingDict(ZSTDv05_DCtx * dctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize,const void * dict,size_t dictSize)34910c16b537SWarner Losh size_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,
34920c16b537SWarner Losh void* dst, size_t maxDstSize,
34930c16b537SWarner Losh const void* src, size_t srcSize,
34940c16b537SWarner Losh const void* dict, size_t dictSize)
34950c16b537SWarner Losh {
34960c16b537SWarner Losh ZSTDv05_decompressBegin_usingDict(dctx, dict, dictSize);
34970c16b537SWarner Losh ZSTDv05_checkContinuity(dctx, dst);
34980c16b537SWarner Losh return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
34990c16b537SWarner Losh }
35000c16b537SWarner Losh
35010c16b537SWarner Losh
ZSTDv05_decompressDCtx(ZSTDv05_DCtx * dctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)35020c16b537SWarner Losh size_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
35030c16b537SWarner Losh {
35040c16b537SWarner Losh return ZSTDv05_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);
35050c16b537SWarner Losh }
35060c16b537SWarner Losh
ZSTDv05_decompress(void * dst,size_t maxDstSize,const void * src,size_t srcSize)35070c16b537SWarner Losh size_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
35080c16b537SWarner Losh {
35090c16b537SWarner Losh #if defined(ZSTDv05_HEAPMODE) && (ZSTDv05_HEAPMODE==1)
35100c16b537SWarner Losh size_t regenSize;
35110c16b537SWarner Losh ZSTDv05_DCtx* dctx = ZSTDv05_createDCtx();
35120c16b537SWarner Losh if (dctx==NULL) return ERROR(memory_allocation);
35130c16b537SWarner Losh regenSize = ZSTDv05_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);
35140c16b537SWarner Losh ZSTDv05_freeDCtx(dctx);
35150c16b537SWarner Losh return regenSize;
35160c16b537SWarner Losh #else
35170c16b537SWarner Losh ZSTDv05_DCtx dctx;
35180c16b537SWarner Losh return ZSTDv05_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);
35190c16b537SWarner Losh #endif
35200c16b537SWarner Losh }
35210c16b537SWarner Losh
35222b9c00cbSConrad Meyer /* ZSTD_errorFrameSizeInfoLegacy() :
35232b9c00cbSConrad Meyer assumes `cSize` and `dBound` are _not_ NULL */
ZSTD_errorFrameSizeInfoLegacy(size_t * cSize,unsigned long long * dBound,size_t ret)35242b9c00cbSConrad Meyer static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
35252b9c00cbSConrad Meyer {
35262b9c00cbSConrad Meyer *cSize = ret;
35272b9c00cbSConrad Meyer *dBound = ZSTD_CONTENTSIZE_ERROR;
35282b9c00cbSConrad Meyer }
35292b9c00cbSConrad Meyer
ZSTDv05_findFrameSizeInfoLegacy(const void * src,size_t srcSize,size_t * cSize,unsigned long long * dBound)35302b9c00cbSConrad Meyer void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
35310c16b537SWarner Losh {
35320c16b537SWarner Losh const BYTE* ip = (const BYTE*)src;
35330c16b537SWarner Losh size_t remainingSize = srcSize;
35342b9c00cbSConrad Meyer size_t nbBlocks = 0;
35350c16b537SWarner Losh blockProperties_t blockProperties;
35360c16b537SWarner Losh
35370c16b537SWarner Losh /* Frame Header */
35382b9c00cbSConrad Meyer if (srcSize < ZSTDv05_frameHeaderSize_min) {
35392b9c00cbSConrad Meyer ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
35402b9c00cbSConrad Meyer return;
35412b9c00cbSConrad Meyer }
35422b9c00cbSConrad Meyer if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {
35432b9c00cbSConrad Meyer ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
35442b9c00cbSConrad Meyer return;
35452b9c00cbSConrad Meyer }
35460c16b537SWarner Losh ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;
35470c16b537SWarner Losh
35480c16b537SWarner Losh /* Loop on each block */
35490c16b537SWarner Losh while (1)
35500c16b537SWarner Losh {
35510c16b537SWarner Losh size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);
35522b9c00cbSConrad Meyer if (ZSTDv05_isError(cBlockSize)) {
35532b9c00cbSConrad Meyer ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
35542b9c00cbSConrad Meyer return;
35552b9c00cbSConrad Meyer }
35560c16b537SWarner Losh
35570c16b537SWarner Losh ip += ZSTDv05_blockHeaderSize;
35580c16b537SWarner Losh remainingSize -= ZSTDv05_blockHeaderSize;
35592b9c00cbSConrad Meyer if (cBlockSize > remainingSize) {
35602b9c00cbSConrad Meyer ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
35612b9c00cbSConrad Meyer return;
35622b9c00cbSConrad Meyer }
35630c16b537SWarner Losh
35640c16b537SWarner Losh if (cBlockSize == 0) break; /* bt_end */
35650c16b537SWarner Losh
35660c16b537SWarner Losh ip += cBlockSize;
35670c16b537SWarner Losh remainingSize -= cBlockSize;
35682b9c00cbSConrad Meyer nbBlocks++;
35690c16b537SWarner Losh }
35700c16b537SWarner Losh
35712b9c00cbSConrad Meyer *cSize = ip - (const BYTE*)src;
35722b9c00cbSConrad Meyer *dBound = nbBlocks * BLOCKSIZE;
35730c16b537SWarner Losh }
35740c16b537SWarner Losh
35750c16b537SWarner Losh /* ******************************
35760c16b537SWarner Losh * Streaming Decompression API
35770c16b537SWarner Losh ********************************/
ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx * dctx)35780c16b537SWarner Losh size_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx)
35790c16b537SWarner Losh {
35800c16b537SWarner Losh return dctx->expected;
35810c16b537SWarner Losh }
35820c16b537SWarner Losh
ZSTDv05_decompressContinue(ZSTDv05_DCtx * dctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)35830c16b537SWarner Losh size_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
35840c16b537SWarner Losh {
35850c16b537SWarner Losh /* Sanity check */
35860c16b537SWarner Losh if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
35870c16b537SWarner Losh ZSTDv05_checkContinuity(dctx, dst);
35880c16b537SWarner Losh
35890c16b537SWarner Losh /* Decompress : frame header; part 1 */
35900c16b537SWarner Losh switch (dctx->stage)
35910c16b537SWarner Losh {
35920c16b537SWarner Losh case ZSTDv05ds_getFrameHeaderSize :
35930c16b537SWarner Losh /* get frame header size */
35940c16b537SWarner Losh if (srcSize != ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
35950c16b537SWarner Losh dctx->headerSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);
35960c16b537SWarner Losh if (ZSTDv05_isError(dctx->headerSize)) return dctx->headerSize;
35970c16b537SWarner Losh memcpy(dctx->headerBuffer, src, ZSTDv05_frameHeaderSize_min);
35980c16b537SWarner Losh if (dctx->headerSize > ZSTDv05_frameHeaderSize_min) return ERROR(GENERIC); /* should never happen */
35990c16b537SWarner Losh dctx->expected = 0; /* not necessary to copy more */
36000c16b537SWarner Losh /* fallthrough */
36010c16b537SWarner Losh case ZSTDv05ds_decodeFrameHeader:
36020c16b537SWarner Losh /* get frame header */
36030c16b537SWarner Losh { size_t const result = ZSTDv05_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);
36040c16b537SWarner Losh if (ZSTDv05_isError(result)) return result;
36050c16b537SWarner Losh dctx->expected = ZSTDv05_blockHeaderSize;
36060c16b537SWarner Losh dctx->stage = ZSTDv05ds_decodeBlockHeader;
36070c16b537SWarner Losh return 0;
36080c16b537SWarner Losh }
36090c16b537SWarner Losh case ZSTDv05ds_decodeBlockHeader:
36100c16b537SWarner Losh {
36110c16b537SWarner Losh /* Decode block header */
36120c16b537SWarner Losh blockProperties_t bp;
36130c16b537SWarner Losh size_t blockSize = ZSTDv05_getcBlockSize(src, ZSTDv05_blockHeaderSize, &bp);
36140c16b537SWarner Losh if (ZSTDv05_isError(blockSize)) return blockSize;
36150c16b537SWarner Losh if (bp.blockType == bt_end) {
36160c16b537SWarner Losh dctx->expected = 0;
36170c16b537SWarner Losh dctx->stage = ZSTDv05ds_getFrameHeaderSize;
36180c16b537SWarner Losh }
36190c16b537SWarner Losh else {
36200c16b537SWarner Losh dctx->expected = blockSize;
36210c16b537SWarner Losh dctx->bType = bp.blockType;
36220c16b537SWarner Losh dctx->stage = ZSTDv05ds_decompressBlock;
36230c16b537SWarner Losh }
36240c16b537SWarner Losh return 0;
36250c16b537SWarner Losh }
36260c16b537SWarner Losh case ZSTDv05ds_decompressBlock:
36270c16b537SWarner Losh {
36280c16b537SWarner Losh /* Decompress : block content */
36290c16b537SWarner Losh size_t rSize;
36300c16b537SWarner Losh switch(dctx->bType)
36310c16b537SWarner Losh {
36320c16b537SWarner Losh case bt_compressed:
36330c16b537SWarner Losh rSize = ZSTDv05_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);
36340c16b537SWarner Losh break;
36350c16b537SWarner Losh case bt_raw :
36360c16b537SWarner Losh rSize = ZSTDv05_copyRawBlock(dst, maxDstSize, src, srcSize);
36370c16b537SWarner Losh break;
36380c16b537SWarner Losh case bt_rle :
36390c16b537SWarner Losh return ERROR(GENERIC); /* not yet handled */
36400c16b537SWarner Losh break;
36410c16b537SWarner Losh case bt_end : /* should never happen (filtered at phase 1) */
36420c16b537SWarner Losh rSize = 0;
36430c16b537SWarner Losh break;
36440c16b537SWarner Losh default:
36450c16b537SWarner Losh return ERROR(GENERIC); /* impossible */
36460c16b537SWarner Losh }
36470c16b537SWarner Losh dctx->stage = ZSTDv05ds_decodeBlockHeader;
36480c16b537SWarner Losh dctx->expected = ZSTDv05_blockHeaderSize;
36490c16b537SWarner Losh dctx->previousDstEnd = (char*)dst + rSize;
36500c16b537SWarner Losh return rSize;
36510c16b537SWarner Losh }
36520c16b537SWarner Losh default:
36530c16b537SWarner Losh return ERROR(GENERIC); /* impossible */
36540c16b537SWarner Losh }
36550c16b537SWarner Losh }
36560c16b537SWarner Losh
36570c16b537SWarner Losh
ZSTDv05_refDictContent(ZSTDv05_DCtx * dctx,const void * dict,size_t dictSize)36580c16b537SWarner Losh static void ZSTDv05_refDictContent(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)
36590c16b537SWarner Losh {
36600c16b537SWarner Losh dctx->dictEnd = dctx->previousDstEnd;
36610c16b537SWarner Losh dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
36620c16b537SWarner Losh dctx->base = dict;
36630c16b537SWarner Losh dctx->previousDstEnd = (const char*)dict + dictSize;
36640c16b537SWarner Losh }
36650c16b537SWarner Losh
ZSTDv05_loadEntropy(ZSTDv05_DCtx * dctx,const void * dict,size_t dictSize)36660c16b537SWarner Losh static size_t ZSTDv05_loadEntropy(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)
36670c16b537SWarner Losh {
36680c16b537SWarner Losh size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;
36690c16b537SWarner Losh short offcodeNCount[MaxOff+1];
3670a0483764SConrad Meyer unsigned offcodeMaxValue=MaxOff, offcodeLog;
36710c16b537SWarner Losh short matchlengthNCount[MaxML+1];
36720c16b537SWarner Losh unsigned matchlengthMaxValue = MaxML, matchlengthLog;
36730c16b537SWarner Losh short litlengthNCount[MaxLL+1];
36740c16b537SWarner Losh unsigned litlengthMaxValue = MaxLL, litlengthLog;
36750c16b537SWarner Losh
36760c16b537SWarner Losh hSize = HUFv05_readDTableX4(dctx->hufTableX4, dict, dictSize);
36770c16b537SWarner Losh if (HUFv05_isError(hSize)) return ERROR(dictionary_corrupted);
36780c16b537SWarner Losh dict = (const char*)dict + hSize;
36790c16b537SWarner Losh dictSize -= hSize;
36800c16b537SWarner Losh
36810c16b537SWarner Losh offcodeHeaderSize = FSEv05_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
36820c16b537SWarner Losh if (FSEv05_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
36830c16b537SWarner Losh if (offcodeLog > OffFSEv05Log) return ERROR(dictionary_corrupted);
36840c16b537SWarner Losh errorCode = FSEv05_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
36850c16b537SWarner Losh if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);
36860c16b537SWarner Losh dict = (const char*)dict + offcodeHeaderSize;
36870c16b537SWarner Losh dictSize -= offcodeHeaderSize;
36880c16b537SWarner Losh
36890c16b537SWarner Losh matchlengthHeaderSize = FSEv05_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
36900c16b537SWarner Losh if (FSEv05_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
36910c16b537SWarner Losh if (matchlengthLog > MLFSEv05Log) return ERROR(dictionary_corrupted);
36920c16b537SWarner Losh errorCode = FSEv05_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
36930c16b537SWarner Losh if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);
36940c16b537SWarner Losh dict = (const char*)dict + matchlengthHeaderSize;
36950c16b537SWarner Losh dictSize -= matchlengthHeaderSize;
36960c16b537SWarner Losh
36970c16b537SWarner Losh litlengthHeaderSize = FSEv05_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
36980c16b537SWarner Losh if (litlengthLog > LLFSEv05Log) return ERROR(dictionary_corrupted);
36990c16b537SWarner Losh if (FSEv05_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
37000c16b537SWarner Losh errorCode = FSEv05_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
37010c16b537SWarner Losh if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);
37020c16b537SWarner Losh
37030c16b537SWarner Losh dctx->flagStaticTables = 1;
37040c16b537SWarner Losh return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
37050c16b537SWarner Losh }
37060c16b537SWarner Losh
ZSTDv05_decompress_insertDictionary(ZSTDv05_DCtx * dctx,const void * dict,size_t dictSize)37070c16b537SWarner Losh static size_t ZSTDv05_decompress_insertDictionary(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)
37080c16b537SWarner Losh {
37090c16b537SWarner Losh size_t eSize;
37100c16b537SWarner Losh U32 magic = MEM_readLE32(dict);
37110c16b537SWarner Losh if (magic != ZSTDv05_DICT_MAGIC) {
37120c16b537SWarner Losh /* pure content mode */
37130c16b537SWarner Losh ZSTDv05_refDictContent(dctx, dict, dictSize);
37140c16b537SWarner Losh return 0;
37150c16b537SWarner Losh }
37160c16b537SWarner Losh /* load entropy tables */
37170c16b537SWarner Losh dict = (const char*)dict + 4;
37180c16b537SWarner Losh dictSize -= 4;
37190c16b537SWarner Losh eSize = ZSTDv05_loadEntropy(dctx, dict, dictSize);
37200c16b537SWarner Losh if (ZSTDv05_isError(eSize)) return ERROR(dictionary_corrupted);
37210c16b537SWarner Losh
37220c16b537SWarner Losh /* reference dictionary content */
37230c16b537SWarner Losh dict = (const char*)dict + eSize;
37240c16b537SWarner Losh dictSize -= eSize;
37250c16b537SWarner Losh ZSTDv05_refDictContent(dctx, dict, dictSize);
37260c16b537SWarner Losh
37270c16b537SWarner Losh return 0;
37280c16b537SWarner Losh }
37290c16b537SWarner Losh
37300c16b537SWarner Losh
ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx * dctx,const void * dict,size_t dictSize)37310c16b537SWarner Losh size_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)
37320c16b537SWarner Losh {
37330c16b537SWarner Losh size_t errorCode;
37340c16b537SWarner Losh errorCode = ZSTDv05_decompressBegin(dctx);
37350c16b537SWarner Losh if (ZSTDv05_isError(errorCode)) return errorCode;
37360c16b537SWarner Losh
37370c16b537SWarner Losh if (dict && dictSize) {
37380c16b537SWarner Losh errorCode = ZSTDv05_decompress_insertDictionary(dctx, dict, dictSize);
37390c16b537SWarner Losh if (ZSTDv05_isError(errorCode)) return ERROR(dictionary_corrupted);
37400c16b537SWarner Losh }
37410c16b537SWarner Losh
37420c16b537SWarner Losh return 0;
37430c16b537SWarner Losh }
37440c16b537SWarner Losh
37450c16b537SWarner Losh /*
37460c16b537SWarner Losh Buffered version of Zstd compression library
37470c16b537SWarner Losh Copyright (C) 2015-2016, Yann Collet.
37480c16b537SWarner Losh
37490c16b537SWarner Losh BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
37500c16b537SWarner Losh
37510c16b537SWarner Losh Redistribution and use in source and binary forms, with or without
37520c16b537SWarner Losh modification, are permitted provided that the following conditions are
37530c16b537SWarner Losh met:
37540c16b537SWarner Losh * Redistributions of source code must retain the above copyright
37550c16b537SWarner Losh notice, this list of conditions and the following disclaimer.
37560c16b537SWarner Losh * Redistributions in binary form must reproduce the above
37570c16b537SWarner Losh copyright notice, this list of conditions and the following disclaimer
37580c16b537SWarner Losh in the documentation and/or other materials provided with the
37590c16b537SWarner Losh distribution.
37600c16b537SWarner Losh THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37610c16b537SWarner Losh "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37620c16b537SWarner Losh LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37630c16b537SWarner Losh A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37640c16b537SWarner Losh OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37650c16b537SWarner Losh SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37660c16b537SWarner Losh LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37670c16b537SWarner Losh DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37680c16b537SWarner Losh THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37690c16b537SWarner Losh (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37700c16b537SWarner Losh OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37710c16b537SWarner Losh
37720c16b537SWarner Losh You can contact the author at :
37730c16b537SWarner Losh - zstd source repository : https://github.com/Cyan4973/zstd
37740c16b537SWarner Losh - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
37750c16b537SWarner Losh */
37760c16b537SWarner Losh
37770c16b537SWarner Losh /* The objects defined into this file should be considered experimental.
37780c16b537SWarner Losh * They are not labelled stable, as their prototype may change in the future.
37790c16b537SWarner Losh * You can use them for tests, provide feedback, or if you can endure risk of future changes.
37800c16b537SWarner Losh */
37810c16b537SWarner Losh
37820c16b537SWarner Losh
37830c16b537SWarner Losh
37840c16b537SWarner Losh /* *************************************
37850c16b537SWarner Losh * Constants
37860c16b537SWarner Losh ***************************************/
37870c16b537SWarner Losh static size_t ZBUFFv05_blockHeaderSize = 3;
37880c16b537SWarner Losh
37890c16b537SWarner Losh
37900c16b537SWarner Losh
37910c16b537SWarner Losh /* *** Compression *** */
37920c16b537SWarner Losh
ZBUFFv05_limitCopy(void * dst,size_t maxDstSize,const void * src,size_t srcSize)37930c16b537SWarner Losh static size_t ZBUFFv05_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
37940c16b537SWarner Losh {
37950c16b537SWarner Losh size_t length = MIN(maxDstSize, srcSize);
379637f1f268SConrad Meyer if (length > 0) {
37970c16b537SWarner Losh memcpy(dst, src, length);
379837f1f268SConrad Meyer }
37990c16b537SWarner Losh return length;
38000c16b537SWarner Losh }
38010c16b537SWarner Losh
38020c16b537SWarner Losh
38030c16b537SWarner Losh
38040c16b537SWarner Losh
38050c16b537SWarner Losh /** ************************************************
38060c16b537SWarner Losh * Streaming decompression
38070c16b537SWarner Losh *
38080c16b537SWarner Losh * A ZBUFFv05_DCtx object is required to track streaming operation.
38090c16b537SWarner Losh * Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources.
38100c16b537SWarner Losh * Use ZBUFFv05_decompressInit() to start a new decompression operation.
38110c16b537SWarner Losh * ZBUFFv05_DCtx objects can be reused multiple times.
38120c16b537SWarner Losh *
38130c16b537SWarner Losh * Use ZBUFFv05_decompressContinue() repetitively to consume your input.
38140c16b537SWarner Losh * *srcSizePtr and *maxDstSizePtr can be any size.
38150c16b537SWarner Losh * The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.
38160c16b537SWarner Losh * Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.
38170c16b537SWarner Losh * The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst .
38180c16b537SWarner Losh * return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)
38190c16b537SWarner Losh * or 0 when a frame is completely decoded
38200c16b537SWarner Losh * or an error code, which can be tested using ZBUFFv05_isError().
38210c16b537SWarner Losh *
38220c16b537SWarner Losh * Hint : recommended buffer sizes (not compulsory)
38230c16b537SWarner Losh * output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.
38240c16b537SWarner Losh * input : just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .
38250c16b537SWarner Losh * **************************************************/
38260c16b537SWarner Losh
38270c16b537SWarner Losh typedef enum { ZBUFFv05ds_init, ZBUFFv05ds_readHeader, ZBUFFv05ds_loadHeader, ZBUFFv05ds_decodeHeader,
38280c16b537SWarner Losh ZBUFFv05ds_read, ZBUFFv05ds_load, ZBUFFv05ds_flush } ZBUFFv05_dStage;
38290c16b537SWarner Losh
38300c16b537SWarner Losh /* *** Resource management *** */
38310c16b537SWarner Losh
38320c16b537SWarner Losh #define ZSTDv05_frameHeaderSize_max 5 /* too magical, should come from reference */
38330c16b537SWarner Losh struct ZBUFFv05_DCtx_s {
38340c16b537SWarner Losh ZSTDv05_DCtx* zc;
38350c16b537SWarner Losh ZSTDv05_parameters params;
38360c16b537SWarner Losh char* inBuff;
38370c16b537SWarner Losh size_t inBuffSize;
38380c16b537SWarner Losh size_t inPos;
38390c16b537SWarner Losh char* outBuff;
38400c16b537SWarner Losh size_t outBuffSize;
38410c16b537SWarner Losh size_t outStart;
38420c16b537SWarner Losh size_t outEnd;
38430c16b537SWarner Losh size_t hPos;
38440c16b537SWarner Losh ZBUFFv05_dStage stage;
38450c16b537SWarner Losh unsigned char headerBuffer[ZSTDv05_frameHeaderSize_max];
38460c16b537SWarner Losh }; /* typedef'd to ZBUFFv05_DCtx within "zstd_buffered.h" */
38470c16b537SWarner Losh
38480c16b537SWarner Losh
ZBUFFv05_createDCtx(void)38490c16b537SWarner Losh ZBUFFv05_DCtx* ZBUFFv05_createDCtx(void)
38500c16b537SWarner Losh {
38510c16b537SWarner Losh ZBUFFv05_DCtx* zbc = (ZBUFFv05_DCtx*)malloc(sizeof(ZBUFFv05_DCtx));
38520c16b537SWarner Losh if (zbc==NULL) return NULL;
38530c16b537SWarner Losh memset(zbc, 0, sizeof(*zbc));
38540c16b537SWarner Losh zbc->zc = ZSTDv05_createDCtx();
38550c16b537SWarner Losh zbc->stage = ZBUFFv05ds_init;
38560c16b537SWarner Losh return zbc;
38570c16b537SWarner Losh }
38580c16b537SWarner Losh
ZBUFFv05_freeDCtx(ZBUFFv05_DCtx * zbc)38590c16b537SWarner Losh size_t ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* zbc)
38600c16b537SWarner Losh {
38610c16b537SWarner Losh if (zbc==NULL) return 0; /* support free on null */
38620c16b537SWarner Losh ZSTDv05_freeDCtx(zbc->zc);
38630c16b537SWarner Losh free(zbc->inBuff);
38640c16b537SWarner Losh free(zbc->outBuff);
38650c16b537SWarner Losh free(zbc);
38660c16b537SWarner Losh return 0;
38670c16b537SWarner Losh }
38680c16b537SWarner Losh
38690c16b537SWarner Losh
38700c16b537SWarner Losh /* *** Initialization *** */
38710c16b537SWarner Losh
ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx * zbc,const void * dict,size_t dictSize)38720c16b537SWarner Losh size_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* zbc, const void* dict, size_t dictSize)
38730c16b537SWarner Losh {
38740c16b537SWarner Losh zbc->stage = ZBUFFv05ds_readHeader;
38750c16b537SWarner Losh zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = 0;
38760c16b537SWarner Losh return ZSTDv05_decompressBegin_usingDict(zbc->zc, dict, dictSize);
38770c16b537SWarner Losh }
38780c16b537SWarner Losh
ZBUFFv05_decompressInit(ZBUFFv05_DCtx * zbc)38790c16b537SWarner Losh size_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* zbc)
38800c16b537SWarner Losh {
38810c16b537SWarner Losh return ZBUFFv05_decompressInitDictionary(zbc, NULL, 0);
38820c16b537SWarner Losh }
38830c16b537SWarner Losh
38840c16b537SWarner Losh
38850c16b537SWarner Losh /* *** Decompression *** */
38860c16b537SWarner Losh
ZBUFFv05_decompressContinue(ZBUFFv05_DCtx * zbc,void * dst,size_t * maxDstSizePtr,const void * src,size_t * srcSizePtr)38870c16b537SWarner Losh size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)
38880c16b537SWarner Losh {
38890c16b537SWarner Losh const char* const istart = (const char*)src;
38900c16b537SWarner Losh const char* ip = istart;
38910c16b537SWarner Losh const char* const iend = istart + *srcSizePtr;
38920c16b537SWarner Losh char* const ostart = (char*)dst;
38930c16b537SWarner Losh char* op = ostart;
38940c16b537SWarner Losh char* const oend = ostart + *maxDstSizePtr;
38950c16b537SWarner Losh U32 notDone = 1;
38960c16b537SWarner Losh
38970c16b537SWarner Losh while (notDone) {
38980c16b537SWarner Losh switch(zbc->stage)
38990c16b537SWarner Losh {
39000c16b537SWarner Losh case ZBUFFv05ds_init :
39010c16b537SWarner Losh return ERROR(init_missing);
39020c16b537SWarner Losh
39030c16b537SWarner Losh case ZBUFFv05ds_readHeader :
39040c16b537SWarner Losh /* read header from src */
39050c16b537SWarner Losh {
39060c16b537SWarner Losh size_t headerSize = ZSTDv05_getFrameParams(&(zbc->params), src, *srcSizePtr);
39070c16b537SWarner Losh if (ZSTDv05_isError(headerSize)) return headerSize;
39080c16b537SWarner Losh if (headerSize) {
39090c16b537SWarner Losh /* not enough input to decode header : tell how many bytes would be necessary */
39100c16b537SWarner Losh memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr);
39110c16b537SWarner Losh zbc->hPos += *srcSizePtr;
39120c16b537SWarner Losh *maxDstSizePtr = 0;
39130c16b537SWarner Losh zbc->stage = ZBUFFv05ds_loadHeader;
39140c16b537SWarner Losh return headerSize - zbc->hPos;
39150c16b537SWarner Losh }
39160c16b537SWarner Losh zbc->stage = ZBUFFv05ds_decodeHeader;
39170c16b537SWarner Losh break;
39180c16b537SWarner Losh }
39190c16b537SWarner Losh /* fall-through */
39200c16b537SWarner Losh case ZBUFFv05ds_loadHeader:
39210c16b537SWarner Losh /* complete header from src */
39220c16b537SWarner Losh {
39230c16b537SWarner Losh size_t headerSize = ZBUFFv05_limitCopy(
39240c16b537SWarner Losh zbc->headerBuffer + zbc->hPos, ZSTDv05_frameHeaderSize_max - zbc->hPos,
39250c16b537SWarner Losh src, *srcSizePtr);
39260c16b537SWarner Losh zbc->hPos += headerSize;
39270c16b537SWarner Losh ip += headerSize;
39280c16b537SWarner Losh headerSize = ZSTDv05_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos);
39290c16b537SWarner Losh if (ZSTDv05_isError(headerSize)) return headerSize;
39300c16b537SWarner Losh if (headerSize) {
39310c16b537SWarner Losh /* not enough input to decode header : tell how many bytes would be necessary */
39320c16b537SWarner Losh *maxDstSizePtr = 0;
39330c16b537SWarner Losh return headerSize - zbc->hPos;
39340c16b537SWarner Losh }
393537f1f268SConrad Meyer /* zbc->stage = ZBUFFv05ds_decodeHeader; break; */ /* useless : stage follows */
39360c16b537SWarner Losh }
39370c16b537SWarner Losh /* fall-through */
39380c16b537SWarner Losh case ZBUFFv05ds_decodeHeader:
39390c16b537SWarner Losh /* apply header to create / resize buffers */
39400c16b537SWarner Losh {
39410c16b537SWarner Losh size_t neededOutSize = (size_t)1 << zbc->params.windowLog;
39420c16b537SWarner Losh size_t neededInSize = BLOCKSIZE; /* a block is never > BLOCKSIZE */
39430c16b537SWarner Losh if (zbc->inBuffSize < neededInSize) {
39440c16b537SWarner Losh free(zbc->inBuff);
39450c16b537SWarner Losh zbc->inBuffSize = neededInSize;
39460c16b537SWarner Losh zbc->inBuff = (char*)malloc(neededInSize);
39470c16b537SWarner Losh if (zbc->inBuff == NULL) return ERROR(memory_allocation);
39480c16b537SWarner Losh }
39490c16b537SWarner Losh if (zbc->outBuffSize < neededOutSize) {
39500c16b537SWarner Losh free(zbc->outBuff);
39510c16b537SWarner Losh zbc->outBuffSize = neededOutSize;
39520c16b537SWarner Losh zbc->outBuff = (char*)malloc(neededOutSize);
39530c16b537SWarner Losh if (zbc->outBuff == NULL) return ERROR(memory_allocation);
39540c16b537SWarner Losh } }
39550c16b537SWarner Losh if (zbc->hPos) {
39560c16b537SWarner Losh /* some data already loaded into headerBuffer : transfer into inBuff */
39570c16b537SWarner Losh memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos);
39580c16b537SWarner Losh zbc->inPos = zbc->hPos;
39590c16b537SWarner Losh zbc->hPos = 0;
39600c16b537SWarner Losh zbc->stage = ZBUFFv05ds_load;
39610c16b537SWarner Losh break;
39620c16b537SWarner Losh }
39630c16b537SWarner Losh zbc->stage = ZBUFFv05ds_read;
39640c16b537SWarner Losh /* fall-through */
39650c16b537SWarner Losh case ZBUFFv05ds_read:
39660c16b537SWarner Losh {
39670c16b537SWarner Losh size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);
39680c16b537SWarner Losh if (neededInSize==0) { /* end of frame */
39690c16b537SWarner Losh zbc->stage = ZBUFFv05ds_init;
39700c16b537SWarner Losh notDone = 0;
39710c16b537SWarner Losh break;
39720c16b537SWarner Losh }
39730c16b537SWarner Losh if ((size_t)(iend-ip) >= neededInSize) {
39740c16b537SWarner Losh /* directly decode from src */
39750c16b537SWarner Losh size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,
39760c16b537SWarner Losh zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,
39770c16b537SWarner Losh ip, neededInSize);
39780c16b537SWarner Losh if (ZSTDv05_isError(decodedSize)) return decodedSize;
39790c16b537SWarner Losh ip += neededInSize;
39800c16b537SWarner Losh if (!decodedSize) break; /* this was just a header */
39810c16b537SWarner Losh zbc->outEnd = zbc->outStart + decodedSize;
39820c16b537SWarner Losh zbc->stage = ZBUFFv05ds_flush;
39830c16b537SWarner Losh break;
39840c16b537SWarner Losh }
39850c16b537SWarner Losh if (ip==iend) { notDone = 0; break; } /* no more input */
39860c16b537SWarner Losh zbc->stage = ZBUFFv05ds_load;
39870c16b537SWarner Losh }
39880c16b537SWarner Losh /* fall-through */
39890c16b537SWarner Losh case ZBUFFv05ds_load:
39900c16b537SWarner Losh {
39910c16b537SWarner Losh size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);
39920c16b537SWarner Losh size_t toLoad = neededInSize - zbc->inPos; /* should always be <= remaining space within inBuff */
39930c16b537SWarner Losh size_t loadedSize;
39940c16b537SWarner Losh if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected); /* should never happen */
39950c16b537SWarner Losh loadedSize = ZBUFFv05_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip);
39960c16b537SWarner Losh ip += loadedSize;
39970c16b537SWarner Losh zbc->inPos += loadedSize;
39980c16b537SWarner Losh if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */
39990c16b537SWarner Losh {
40000c16b537SWarner Losh size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,
40010c16b537SWarner Losh zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,
40020c16b537SWarner Losh zbc->inBuff, neededInSize);
40030c16b537SWarner Losh if (ZSTDv05_isError(decodedSize)) return decodedSize;
40040c16b537SWarner Losh zbc->inPos = 0; /* input is consumed */
40050c16b537SWarner Losh if (!decodedSize) { zbc->stage = ZBUFFv05ds_read; break; } /* this was just a header */
40060c16b537SWarner Losh zbc->outEnd = zbc->outStart + decodedSize;
40070c16b537SWarner Losh zbc->stage = ZBUFFv05ds_flush;
400837f1f268SConrad Meyer /* break; */ /* ZBUFFv05ds_flush follows */
40090c16b537SWarner Losh }
40100c16b537SWarner Losh }
40110c16b537SWarner Losh /* fall-through */
40120c16b537SWarner Losh case ZBUFFv05ds_flush:
40130c16b537SWarner Losh {
40140c16b537SWarner Losh size_t toFlushSize = zbc->outEnd - zbc->outStart;
40150c16b537SWarner Losh size_t flushedSize = ZBUFFv05_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);
40160c16b537SWarner Losh op += flushedSize;
40170c16b537SWarner Losh zbc->outStart += flushedSize;
40180c16b537SWarner Losh if (flushedSize == toFlushSize) {
40190c16b537SWarner Losh zbc->stage = ZBUFFv05ds_read;
40200c16b537SWarner Losh if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)
40210c16b537SWarner Losh zbc->outStart = zbc->outEnd = 0;
40220c16b537SWarner Losh break;
40230c16b537SWarner Losh }
40240c16b537SWarner Losh /* cannot flush everything */
40250c16b537SWarner Losh notDone = 0;
40260c16b537SWarner Losh break;
40270c16b537SWarner Losh }
40280c16b537SWarner Losh default: return ERROR(GENERIC); /* impossible */
40290c16b537SWarner Losh } }
40300c16b537SWarner Losh
40310c16b537SWarner Losh *srcSizePtr = ip-istart;
40320c16b537SWarner Losh *maxDstSizePtr = op-ostart;
40330c16b537SWarner Losh
40340c16b537SWarner Losh { size_t nextSrcSizeHint = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);
40350c16b537SWarner Losh if (nextSrcSizeHint > ZBUFFv05_blockHeaderSize) nextSrcSizeHint+= ZBUFFv05_blockHeaderSize; /* get next block header too */
40360c16b537SWarner Losh nextSrcSizeHint -= zbc->inPos; /* already loaded*/
40370c16b537SWarner Losh return nextSrcSizeHint;
40380c16b537SWarner Losh }
40390c16b537SWarner Losh }
40400c16b537SWarner Losh
40410c16b537SWarner Losh
40420c16b537SWarner Losh
40430c16b537SWarner Losh /* *************************************
40440c16b537SWarner Losh * Tool functions
40450c16b537SWarner Losh ***************************************/
ZBUFFv05_isError(size_t errorCode)40460c16b537SWarner Losh unsigned ZBUFFv05_isError(size_t errorCode) { return ERR_isError(errorCode); }
ZBUFFv05_getErrorName(size_t errorCode)40470c16b537SWarner Losh const char* ZBUFFv05_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
40480c16b537SWarner Losh
ZBUFFv05_recommendedDInSize(void)40490c16b537SWarner Losh size_t ZBUFFv05_recommendedDInSize(void) { return BLOCKSIZE + ZBUFFv05_blockHeaderSize /* block header size*/ ; }
ZBUFFv05_recommendedDOutSize(void)40500c16b537SWarner Losh size_t ZBUFFv05_recommendedDOutSize(void) { return BLOCKSIZE; }
4051