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