xref: /freebsd/sys/contrib/zstd/lib/legacy/zstd_v02.c (revision f7cd7fe51c4140960ebea00410ed62894f5625d1)
10c16b537SWarner Losh /*
237f1f268SConrad Meyer  * Copyright (c) 2016-2020, 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 #include <stddef.h>    /* size_t, ptrdiff_t */
130c16b537SWarner Losh #include "zstd_v02.h"
1437f1f268SConrad Meyer #include "../common/error_private.h"
150c16b537SWarner Losh 
160c16b537SWarner Losh 
170c16b537SWarner Losh /******************************************
180c16b537SWarner Losh *  Compiler-specific
190c16b537SWarner Losh ******************************************/
200c16b537SWarner Losh #if defined(_MSC_VER)   /* Visual Studio */
210c16b537SWarner Losh #   include <stdlib.h>  /* _byteswap_ulong */
220c16b537SWarner Losh #   include <intrin.h>  /* _byteswap_* */
230c16b537SWarner Losh #endif
240c16b537SWarner Losh 
250c16b537SWarner Losh 
260c16b537SWarner Losh /* ******************************************************************
270c16b537SWarner Losh    mem.h
280c16b537SWarner Losh    low-level memory access routines
290c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet.
300c16b537SWarner Losh 
310c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
320c16b537SWarner Losh 
330c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
340c16b537SWarner Losh    modification, are permitted provided that the following conditions are
350c16b537SWarner Losh    met:
360c16b537SWarner Losh 
370c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
380c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
390c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
400c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
410c16b537SWarner Losh    in the documentation and/or other materials provided with the
420c16b537SWarner Losh    distribution.
430c16b537SWarner Losh 
440c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
450c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
460c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
470c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
480c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
490c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
500c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
510c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
520c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
530c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
540c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
550c16b537SWarner Losh 
560c16b537SWarner Losh     You can contact the author at :
570c16b537SWarner Losh     - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
580c16b537SWarner Losh     - Public forum : https://groups.google.com/forum/#!forum/lz4c
590c16b537SWarner Losh ****************************************************************** */
600c16b537SWarner Losh #ifndef MEM_H_MODULE
610c16b537SWarner Losh #define MEM_H_MODULE
620c16b537SWarner Losh 
630c16b537SWarner Losh #if defined (__cplusplus)
640c16b537SWarner Losh extern "C" {
650c16b537SWarner Losh #endif
660c16b537SWarner Losh 
670c16b537SWarner Losh /******************************************
680c16b537SWarner Losh *  Includes
690c16b537SWarner Losh ******************************************/
700c16b537SWarner Losh #include <stddef.h>    /* size_t, ptrdiff_t */
710c16b537SWarner Losh #include <string.h>    /* memcpy */
720c16b537SWarner Losh 
730c16b537SWarner Losh 
740c16b537SWarner Losh /******************************************
750c16b537SWarner Losh *  Compiler-specific
760c16b537SWarner Losh ******************************************/
770c16b537SWarner Losh #if defined(__GNUC__)
780c16b537SWarner Losh #  define MEM_STATIC static __attribute__((unused))
790c16b537SWarner Losh #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
800c16b537SWarner Losh #  define MEM_STATIC static inline
810c16b537SWarner Losh #elif defined(_MSC_VER)
820c16b537SWarner Losh #  define MEM_STATIC static __inline
830c16b537SWarner Losh #else
840c16b537SWarner Losh #  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */
850c16b537SWarner Losh #endif
860c16b537SWarner Losh 
870c16b537SWarner Losh 
880c16b537SWarner Losh /****************************************************************
890c16b537SWarner Losh *  Basic Types
900c16b537SWarner Losh *****************************************************************/
910c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
92*f7cd7fe5SConrad Meyer # if defined(_AIX)
93*f7cd7fe5SConrad Meyer #  include <inttypes.h>
94*f7cd7fe5SConrad Meyer # else
95*f7cd7fe5SConrad Meyer #  include <stdint.h> /* intptr_t */
96*f7cd7fe5SConrad Meyer # endif
970c16b537SWarner Losh   typedef  uint8_t BYTE;
980c16b537SWarner Losh   typedef uint16_t U16;
990c16b537SWarner Losh   typedef  int16_t S16;
1000c16b537SWarner Losh   typedef uint32_t U32;
1010c16b537SWarner Losh   typedef  int32_t S32;
1020c16b537SWarner Losh   typedef uint64_t U64;
1030c16b537SWarner Losh   typedef  int64_t S64;
1040c16b537SWarner Losh #else
1050c16b537SWarner Losh   typedef unsigned char       BYTE;
1060c16b537SWarner Losh   typedef unsigned short      U16;
1070c16b537SWarner Losh   typedef   signed short      S16;
1080c16b537SWarner Losh   typedef unsigned int        U32;
1090c16b537SWarner Losh   typedef   signed int        S32;
1100c16b537SWarner Losh   typedef unsigned long long  U64;
1110c16b537SWarner Losh   typedef   signed long long  S64;
1120c16b537SWarner Losh #endif
1130c16b537SWarner Losh 
1140c16b537SWarner Losh 
1150c16b537SWarner Losh /****************************************************************
1160c16b537SWarner Losh *  Memory I/O
1170c16b537SWarner Losh *****************************************************************/
1180c16b537SWarner Losh /* MEM_FORCE_MEMORY_ACCESS
1190c16b537SWarner Losh  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
1200c16b537SWarner Losh  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
1210c16b537SWarner Losh  * The below switch allow to select different access method for improved performance.
1220c16b537SWarner Losh  * Method 0 (default) : use `memcpy()`. Safe and portable.
1230c16b537SWarner Losh  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
1240c16b537SWarner Losh  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
1250c16b537SWarner Losh  * Method 2 : direct access. This method is portable but violate C standard.
1260c16b537SWarner Losh  *            It can generate buggy code on targets generating assembly depending on alignment.
1270c16b537SWarner Losh  *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
1280c16b537SWarner Losh  * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
1290c16b537SWarner Losh  * Prefer these methods in priority order (0 > 1 > 2)
1300c16b537SWarner Losh  */
1310c16b537SWarner Losh #ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
1320c16b537SWarner Losh #  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
1330c16b537SWarner Losh #    define MEM_FORCE_MEMORY_ACCESS 2
1340c16b537SWarner Losh #  elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
1350c16b537SWarner Losh   (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
1360c16b537SWarner Losh #    define MEM_FORCE_MEMORY_ACCESS 1
1370c16b537SWarner Losh #  endif
1380c16b537SWarner Losh #endif
1390c16b537SWarner Losh 
1400c16b537SWarner Losh MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
1410c16b537SWarner Losh MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
1420c16b537SWarner Losh 
1430c16b537SWarner Losh MEM_STATIC unsigned MEM_isLittleEndian(void)
1440c16b537SWarner Losh {
1450c16b537SWarner Losh     const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
1460c16b537SWarner Losh     return one.c[0];
1470c16b537SWarner Losh }
1480c16b537SWarner Losh 
1490c16b537SWarner Losh #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
1500c16b537SWarner Losh 
1510c16b537SWarner Losh /* violates C standard on structure alignment.
1520c16b537SWarner Losh Only use if no other choice to achieve best performance on target platform */
1530c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
1540c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
1550c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
1560c16b537SWarner Losh 
1570c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
1580c16b537SWarner Losh 
1590c16b537SWarner Losh #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
1600c16b537SWarner Losh 
1610c16b537SWarner Losh /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
1620c16b537SWarner Losh /* currently only defined for gcc and icc */
1630c16b537SWarner Losh typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
1640c16b537SWarner Losh 
1650c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
1660c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
1670c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
1680c16b537SWarner Losh 
1690c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
1700c16b537SWarner Losh 
1710c16b537SWarner Losh #else
1720c16b537SWarner Losh 
1730c16b537SWarner Losh /* default method, safe and standard.
1740c16b537SWarner Losh    can sometimes prove slower */
1750c16b537SWarner Losh 
1760c16b537SWarner Losh MEM_STATIC U16 MEM_read16(const void* memPtr)
1770c16b537SWarner Losh {
1780c16b537SWarner Losh     U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
1790c16b537SWarner Losh }
1800c16b537SWarner Losh 
1810c16b537SWarner Losh MEM_STATIC U32 MEM_read32(const void* memPtr)
1820c16b537SWarner Losh {
1830c16b537SWarner Losh     U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
1840c16b537SWarner Losh }
1850c16b537SWarner Losh 
1860c16b537SWarner Losh MEM_STATIC U64 MEM_read64(const void* memPtr)
1870c16b537SWarner Losh {
1880c16b537SWarner Losh     U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
1890c16b537SWarner Losh }
1900c16b537SWarner Losh 
1910c16b537SWarner Losh MEM_STATIC void MEM_write16(void* memPtr, U16 value)
1920c16b537SWarner Losh {
1930c16b537SWarner Losh     memcpy(memPtr, &value, sizeof(value));
1940c16b537SWarner Losh }
1950c16b537SWarner Losh 
19637f1f268SConrad Meyer #endif /* MEM_FORCE_MEMORY_ACCESS */
1970c16b537SWarner Losh 
1980c16b537SWarner Losh 
1990c16b537SWarner Losh MEM_STATIC U16 MEM_readLE16(const void* memPtr)
2000c16b537SWarner Losh {
2010c16b537SWarner Losh     if (MEM_isLittleEndian())
2020c16b537SWarner Losh         return MEM_read16(memPtr);
2030c16b537SWarner Losh     else
2040c16b537SWarner Losh     {
2050c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
2060c16b537SWarner Losh         return (U16)(p[0] + (p[1]<<8));
2070c16b537SWarner Losh     }
2080c16b537SWarner Losh }
2090c16b537SWarner Losh 
2100c16b537SWarner Losh MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
2110c16b537SWarner Losh {
2120c16b537SWarner Losh     if (MEM_isLittleEndian())
2130c16b537SWarner Losh     {
2140c16b537SWarner Losh         MEM_write16(memPtr, val);
2150c16b537SWarner Losh     }
2160c16b537SWarner Losh     else
2170c16b537SWarner Losh     {
2180c16b537SWarner Losh         BYTE* p = (BYTE*)memPtr;
2190c16b537SWarner Losh         p[0] = (BYTE)val;
2200c16b537SWarner Losh         p[1] = (BYTE)(val>>8);
2210c16b537SWarner Losh     }
2220c16b537SWarner Losh }
2230c16b537SWarner Losh 
2244d3f1eafSConrad Meyer MEM_STATIC U32 MEM_readLE24(const void* memPtr)
2254d3f1eafSConrad Meyer {
2264d3f1eafSConrad Meyer     return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
2274d3f1eafSConrad Meyer }
2284d3f1eafSConrad Meyer 
2290c16b537SWarner Losh MEM_STATIC U32 MEM_readLE32(const void* memPtr)
2300c16b537SWarner Losh {
2310c16b537SWarner Losh     if (MEM_isLittleEndian())
2320c16b537SWarner Losh         return MEM_read32(memPtr);
2330c16b537SWarner Losh     else
2340c16b537SWarner Losh     {
2350c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
2360c16b537SWarner Losh         return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));
2370c16b537SWarner Losh     }
2380c16b537SWarner Losh }
2390c16b537SWarner Losh 
2400c16b537SWarner Losh 
2410c16b537SWarner Losh MEM_STATIC U64 MEM_readLE64(const void* memPtr)
2420c16b537SWarner Losh {
2430c16b537SWarner Losh     if (MEM_isLittleEndian())
2440c16b537SWarner Losh         return MEM_read64(memPtr);
2450c16b537SWarner Losh     else
2460c16b537SWarner Losh     {
2470c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
2480c16b537SWarner Losh         return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)
2490c16b537SWarner Losh                      + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));
2500c16b537SWarner Losh     }
2510c16b537SWarner Losh }
2520c16b537SWarner Losh 
2530c16b537SWarner Losh 
2540c16b537SWarner Losh MEM_STATIC size_t MEM_readLEST(const void* memPtr)
2550c16b537SWarner Losh {
2560c16b537SWarner Losh     if (MEM_32bits())
2570c16b537SWarner Losh         return (size_t)MEM_readLE32(memPtr);
2580c16b537SWarner Losh     else
2590c16b537SWarner Losh         return (size_t)MEM_readLE64(memPtr);
2600c16b537SWarner Losh }
2610c16b537SWarner Losh 
2620c16b537SWarner Losh #if defined (__cplusplus)
2630c16b537SWarner Losh }
2640c16b537SWarner Losh #endif
2650c16b537SWarner Losh 
2660c16b537SWarner Losh #endif /* MEM_H_MODULE */
2670c16b537SWarner Losh 
2680c16b537SWarner Losh 
2690c16b537SWarner Losh /* ******************************************************************
2700c16b537SWarner Losh    bitstream
2710c16b537SWarner Losh    Part of NewGen Entropy library
2720c16b537SWarner Losh    header file (to include)
2730c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet.
2740c16b537SWarner Losh 
2750c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
2760c16b537SWarner Losh 
2770c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
2780c16b537SWarner Losh    modification, are permitted provided that the following conditions are
2790c16b537SWarner Losh    met:
2800c16b537SWarner Losh 
2810c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
2820c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
2830c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
2840c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
2850c16b537SWarner Losh    in the documentation and/or other materials provided with the
2860c16b537SWarner Losh    distribution.
2870c16b537SWarner Losh 
2880c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2890c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2900c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2910c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2920c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2930c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2940c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2950c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2960c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2970c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2980c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2990c16b537SWarner Losh 
3000c16b537SWarner Losh    You can contact the author at :
3010c16b537SWarner Losh    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
3020c16b537SWarner Losh    - Public forum : https://groups.google.com/forum/#!forum/lz4c
3030c16b537SWarner Losh ****************************************************************** */
3040c16b537SWarner Losh #ifndef BITSTREAM_H_MODULE
3050c16b537SWarner Losh #define BITSTREAM_H_MODULE
3060c16b537SWarner Losh 
3070c16b537SWarner Losh #if defined (__cplusplus)
3080c16b537SWarner Losh extern "C" {
3090c16b537SWarner Losh #endif
3100c16b537SWarner Losh 
3110c16b537SWarner Losh 
3120c16b537SWarner Losh /*
3130c16b537SWarner Losh *  This API consists of small unitary functions, which highly benefit from being inlined.
3140c16b537SWarner Losh *  Since link-time-optimization is not available for all compilers,
3150c16b537SWarner Losh *  these functions are defined into a .h to be included.
3160c16b537SWarner Losh */
3170c16b537SWarner Losh 
3180c16b537SWarner Losh 
3190c16b537SWarner Losh /**********************************************
3200c16b537SWarner Losh *  bitStream decompression API (read backward)
3210c16b537SWarner Losh **********************************************/
3220c16b537SWarner Losh typedef struct
3230c16b537SWarner Losh {
3240c16b537SWarner Losh     size_t   bitContainer;
3250c16b537SWarner Losh     unsigned bitsConsumed;
3260c16b537SWarner Losh     const char* ptr;
3270c16b537SWarner Losh     const char* start;
3280c16b537SWarner Losh } BIT_DStream_t;
3290c16b537SWarner Losh 
3300c16b537SWarner Losh typedef enum { BIT_DStream_unfinished = 0,
3310c16b537SWarner Losh                BIT_DStream_endOfBuffer = 1,
3320c16b537SWarner Losh                BIT_DStream_completed = 2,
3330c16b537SWarner Losh                BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */
3340c16b537SWarner Losh                /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
3350c16b537SWarner Losh 
3360c16b537SWarner Losh MEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
3370c16b537SWarner Losh MEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
3380c16b537SWarner Losh MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
3390c16b537SWarner Losh MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
3400c16b537SWarner Losh 
3410c16b537SWarner Losh 
3420c16b537SWarner Losh /******************************************
3430c16b537SWarner Losh *  unsafe API
3440c16b537SWarner Losh ******************************************/
3450c16b537SWarner Losh MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
3460c16b537SWarner Losh /* faster, but works only if nbBits >= 1 */
3470c16b537SWarner Losh 
3480c16b537SWarner Losh 
3490c16b537SWarner Losh 
3500c16b537SWarner Losh /****************************************************************
3510c16b537SWarner Losh *  Helper functions
3520c16b537SWarner Losh ****************************************************************/
353052d3c12SConrad Meyer MEM_STATIC unsigned BIT_highbit32 (U32 val)
3540c16b537SWarner Losh {
3550c16b537SWarner Losh #   if defined(_MSC_VER)   /* Visual */
3560c16b537SWarner Losh     unsigned long r=0;
3570c16b537SWarner Losh     _BitScanReverse ( &r, val );
3580c16b537SWarner Losh     return (unsigned) r;
3590c16b537SWarner Losh #   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */
3609cbefe25SConrad Meyer     return __builtin_clz (val) ^ 31;
3610c16b537SWarner Losh #   else   /* Software version */
3620c16b537SWarner 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 };
3630c16b537SWarner Losh     U32 v = val;
3640c16b537SWarner Losh     unsigned r;
3650c16b537SWarner Losh     v |= v >> 1;
3660c16b537SWarner Losh     v |= v >> 2;
3670c16b537SWarner Losh     v |= v >> 4;
3680c16b537SWarner Losh     v |= v >> 8;
3690c16b537SWarner Losh     v |= v >> 16;
3700c16b537SWarner Losh     r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
3710c16b537SWarner Losh     return r;
3720c16b537SWarner Losh #   endif
3730c16b537SWarner Losh }
3740c16b537SWarner Losh 
3750c16b537SWarner Losh 
3760c16b537SWarner Losh 
3770c16b537SWarner Losh /**********************************************************
3780c16b537SWarner Losh * bitStream decoding
3790c16b537SWarner Losh **********************************************************/
3800c16b537SWarner Losh 
3810c16b537SWarner Losh /*!BIT_initDStream
3820c16b537SWarner Losh *  Initialize a BIT_DStream_t.
3830c16b537SWarner Losh *  @bitD : a pointer to an already allocated BIT_DStream_t structure
3840c16b537SWarner Losh *  @srcBuffer must point at the beginning of a bitStream
3850c16b537SWarner Losh *  @srcSize must be the exact size of the bitStream
3860c16b537SWarner Losh *  @result : size of stream (== srcSize) or an errorCode if a problem is detected
3870c16b537SWarner Losh */
3880c16b537SWarner Losh MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
3890c16b537SWarner Losh {
3900c16b537SWarner Losh     if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
3910c16b537SWarner Losh 
3920c16b537SWarner Losh     if (srcSize >=  sizeof(size_t))   /* normal case */
3930c16b537SWarner Losh     {
3940c16b537SWarner Losh         U32 contain32;
3950c16b537SWarner Losh         bitD->start = (const char*)srcBuffer;
3960c16b537SWarner Losh         bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);
3970c16b537SWarner Losh         bitD->bitContainer = MEM_readLEST(bitD->ptr);
3980c16b537SWarner Losh         contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
3990c16b537SWarner Losh         if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */
4000c16b537SWarner Losh         bitD->bitsConsumed = 8 - BIT_highbit32(contain32);
4010c16b537SWarner Losh     }
4020c16b537SWarner Losh     else
4030c16b537SWarner Losh     {
4040c16b537SWarner Losh         U32 contain32;
4050c16b537SWarner Losh         bitD->start = (const char*)srcBuffer;
4060c16b537SWarner Losh         bitD->ptr   = bitD->start;
4070c16b537SWarner Losh         bitD->bitContainer = *(const BYTE*)(bitD->start);
4080c16b537SWarner Losh         switch(srcSize)
4090c16b537SWarner Losh         {
4100c16b537SWarner Losh             case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);
4110f743729SConrad Meyer                     /* fallthrough */
4120c16b537SWarner Losh             case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);
4130f743729SConrad Meyer                     /* fallthrough */
4140c16b537SWarner Losh             case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);
4150f743729SConrad Meyer                     /* fallthrough */
4160c16b537SWarner Losh             case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;
4170f743729SConrad Meyer                     /* fallthrough */
4180c16b537SWarner Losh             case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;
4190f743729SConrad Meyer                     /* fallthrough */
4200c16b537SWarner Losh             case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;
4210f743729SConrad Meyer                     /* fallthrough */
4220c16b537SWarner Losh             default:;
4230c16b537SWarner Losh         }
4240c16b537SWarner Losh         contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
4250c16b537SWarner Losh         if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */
4260c16b537SWarner Losh         bitD->bitsConsumed = 8 - BIT_highbit32(contain32);
4270c16b537SWarner Losh         bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;
4280c16b537SWarner Losh     }
4290c16b537SWarner Losh 
4300c16b537SWarner Losh     return srcSize;
4310c16b537SWarner Losh }
4320c16b537SWarner Losh 
4330c16b537SWarner Losh MEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)
4340c16b537SWarner Losh {
4350c16b537SWarner Losh     const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
4360c16b537SWarner Losh     return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
4370c16b537SWarner Losh }
4380c16b537SWarner Losh 
4390c16b537SWarner Losh /*! BIT_lookBitsFast :
4400c16b537SWarner Losh *   unsafe version; only works only if nbBits >= 1 */
4410c16b537SWarner Losh MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)
4420c16b537SWarner Losh {
4430c16b537SWarner Losh     const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
4440c16b537SWarner Losh     return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
4450c16b537SWarner Losh }
4460c16b537SWarner Losh 
4470c16b537SWarner Losh MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
4480c16b537SWarner Losh {
4490c16b537SWarner Losh     bitD->bitsConsumed += nbBits;
4500c16b537SWarner Losh }
4510c16b537SWarner Losh 
4520c16b537SWarner Losh MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
4530c16b537SWarner Losh {
4540c16b537SWarner Losh     size_t value = BIT_lookBits(bitD, nbBits);
4550c16b537SWarner Losh     BIT_skipBits(bitD, nbBits);
4560c16b537SWarner Losh     return value;
4570c16b537SWarner Losh }
4580c16b537SWarner Losh 
4590c16b537SWarner Losh /*!BIT_readBitsFast :
4600c16b537SWarner Losh *  unsafe version; only works only if nbBits >= 1 */
4610c16b537SWarner Losh MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
4620c16b537SWarner Losh {
4630c16b537SWarner Losh     size_t value = BIT_lookBitsFast(bitD, nbBits);
4640c16b537SWarner Losh     BIT_skipBits(bitD, nbBits);
4650c16b537SWarner Losh     return value;
4660c16b537SWarner Losh }
4670c16b537SWarner Losh 
4680c16b537SWarner Losh MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
4690c16b537SWarner Losh {
4700c16b537SWarner Losh     if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
4710c16b537SWarner Losh         return BIT_DStream_overflow;
4720c16b537SWarner Losh 
4730c16b537SWarner Losh     if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
4740c16b537SWarner Losh     {
4750c16b537SWarner Losh         bitD->ptr -= bitD->bitsConsumed >> 3;
4760c16b537SWarner Losh         bitD->bitsConsumed &= 7;
4770c16b537SWarner Losh         bitD->bitContainer = MEM_readLEST(bitD->ptr);
4780c16b537SWarner Losh         return BIT_DStream_unfinished;
4790c16b537SWarner Losh     }
4800c16b537SWarner Losh     if (bitD->ptr == bitD->start)
4810c16b537SWarner Losh     {
4820c16b537SWarner Losh         if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
4830c16b537SWarner Losh         return BIT_DStream_completed;
4840c16b537SWarner Losh     }
4850c16b537SWarner Losh     {
4860c16b537SWarner Losh         U32 nbBytes = bitD->bitsConsumed >> 3;
4870c16b537SWarner Losh         BIT_DStream_status result = BIT_DStream_unfinished;
4880c16b537SWarner Losh         if (bitD->ptr - nbBytes < bitD->start)
4890c16b537SWarner Losh         {
4900c16b537SWarner Losh             nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */
4910c16b537SWarner Losh             result = BIT_DStream_endOfBuffer;
4920c16b537SWarner Losh         }
4930c16b537SWarner Losh         bitD->ptr -= nbBytes;
4940c16b537SWarner Losh         bitD->bitsConsumed -= nbBytes*8;
4950c16b537SWarner Losh         bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */
4960c16b537SWarner Losh         return result;
4970c16b537SWarner Losh     }
4980c16b537SWarner Losh }
4990c16b537SWarner Losh 
5000c16b537SWarner Losh /*! BIT_endOfDStream
5010c16b537SWarner Losh *   @return Tells if DStream has reached its exact end
5020c16b537SWarner Losh */
5030c16b537SWarner Losh MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
5040c16b537SWarner Losh {
5050c16b537SWarner Losh     return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
5060c16b537SWarner Losh }
5070c16b537SWarner Losh 
5080c16b537SWarner Losh #if defined (__cplusplus)
5090c16b537SWarner Losh }
5100c16b537SWarner Losh #endif
5110c16b537SWarner Losh 
5120c16b537SWarner Losh #endif /* BITSTREAM_H_MODULE */
5130c16b537SWarner Losh /* ******************************************************************
5140c16b537SWarner Losh    Error codes and messages
5150c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet
5160c16b537SWarner Losh 
5170c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
5180c16b537SWarner Losh 
5190c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
5200c16b537SWarner Losh    modification, are permitted provided that the following conditions are
5210c16b537SWarner Losh    met:
5220c16b537SWarner Losh 
5230c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
5240c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
5250c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
5260c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
5270c16b537SWarner Losh    in the documentation and/or other materials provided with the
5280c16b537SWarner Losh    distribution.
5290c16b537SWarner Losh 
5300c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5310c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5320c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5330c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5340c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5350c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5360c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5370c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5380c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5390c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5400c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5410c16b537SWarner Losh 
5420c16b537SWarner Losh    You can contact the author at :
5430c16b537SWarner Losh    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
5440c16b537SWarner Losh    - Public forum : https://groups.google.com/forum/#!forum/lz4c
5450c16b537SWarner Losh ****************************************************************** */
5460c16b537SWarner Losh #ifndef ERROR_H_MODULE
5470c16b537SWarner Losh #define ERROR_H_MODULE
5480c16b537SWarner Losh 
5490c16b537SWarner Losh #if defined (__cplusplus)
5500c16b537SWarner Losh extern "C" {
5510c16b537SWarner Losh #endif
5520c16b537SWarner Losh 
5530c16b537SWarner Losh 
5540c16b537SWarner Losh /******************************************
5550c16b537SWarner Losh *  Compiler-specific
5560c16b537SWarner Losh ******************************************/
5570c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
5580c16b537SWarner Losh #  define ERR_STATIC static inline
5590c16b537SWarner Losh #elif defined(_MSC_VER)
5600c16b537SWarner Losh #  define ERR_STATIC static __inline
5610c16b537SWarner Losh #elif defined(__GNUC__)
5620c16b537SWarner Losh #  define ERR_STATIC static __attribute__((unused))
5630c16b537SWarner Losh #else
5640c16b537SWarner Losh #  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */
5650c16b537SWarner Losh #endif
5660c16b537SWarner Losh 
5670c16b537SWarner Losh 
5680c16b537SWarner Losh /******************************************
5690c16b537SWarner Losh *  Error Management
5700c16b537SWarner Losh ******************************************/
5710c16b537SWarner Losh #define PREFIX(name) ZSTD_error_##name
5720c16b537SWarner Losh 
5730c16b537SWarner Losh #define ERROR(name) (size_t)-PREFIX(name)
5740c16b537SWarner Losh 
5750c16b537SWarner Losh #define ERROR_LIST(ITEM) \
5760c16b537SWarner Losh         ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \
5770c16b537SWarner Losh         ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \
5780c16b537SWarner Losh         ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \
5790c16b537SWarner Losh         ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \
5800c16b537SWarner Losh         ITEM(PREFIX(maxCode))
5810c16b537SWarner Losh 
5820c16b537SWarner Losh #define ERROR_GENERATE_ENUM(ENUM) ENUM,
5830c16b537SWarner Losh typedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */
5840c16b537SWarner Losh 
5850c16b537SWarner Losh #define ERROR_CONVERTTOSTRING(STRING) #STRING,
5860c16b537SWarner Losh #define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)
5870c16b537SWarner Losh static const char* ERR_strings[] = { ERROR_LIST(ERROR_GENERATE_STRING) };
5880c16b537SWarner Losh 
5890c16b537SWarner Losh ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
5900c16b537SWarner Losh 
5910c16b537SWarner Losh ERR_STATIC const char* ERR_getErrorName(size_t code)
5920c16b537SWarner Losh {
5930c16b537SWarner Losh     static const char* codeError = "Unspecified error code";
5940c16b537SWarner Losh     if (ERR_isError(code)) return ERR_strings[-(int)(code)];
5950c16b537SWarner Losh     return codeError;
5960c16b537SWarner Losh }
5970c16b537SWarner Losh 
5980c16b537SWarner Losh 
5990c16b537SWarner Losh #if defined (__cplusplus)
6000c16b537SWarner Losh }
6010c16b537SWarner Losh #endif
6020c16b537SWarner Losh 
6030c16b537SWarner Losh #endif /* ERROR_H_MODULE */
6040c16b537SWarner Losh /*
6050c16b537SWarner Losh Constructor and Destructor of type FSE_CTable
6060c16b537SWarner Losh     Note that its size depends on 'tableLog' and 'maxSymbolValue' */
6070c16b537SWarner Losh typedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */
6080c16b537SWarner Losh typedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */
6090c16b537SWarner Losh 
6100c16b537SWarner Losh 
6110c16b537SWarner Losh /* ******************************************************************
6120c16b537SWarner Losh    FSE : Finite State Entropy coder
6130c16b537SWarner Losh    header file for static linking (only)
6140c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet
6150c16b537SWarner Losh 
6160c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6170c16b537SWarner Losh 
6180c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
6190c16b537SWarner Losh    modification, are permitted provided that the following conditions are
6200c16b537SWarner Losh    met:
6210c16b537SWarner Losh 
6220c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
6230c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
6240c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
6250c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
6260c16b537SWarner Losh    in the documentation and/or other materials provided with the
6270c16b537SWarner Losh    distribution.
6280c16b537SWarner Losh 
6290c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6300c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6310c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6320c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6330c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6340c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6350c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6360c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6370c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6380c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6390c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6400c16b537SWarner Losh 
6410c16b537SWarner Losh    You can contact the author at :
6420c16b537SWarner Losh    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
6430c16b537SWarner Losh    - Public forum : https://groups.google.com/forum/#!forum/lz4c
6440c16b537SWarner Losh ****************************************************************** */
6450c16b537SWarner Losh #if defined (__cplusplus)
6460c16b537SWarner Losh extern "C" {
6470c16b537SWarner Losh #endif
6480c16b537SWarner Losh 
6490c16b537SWarner Losh 
6500c16b537SWarner Losh /******************************************
6510c16b537SWarner Losh *  Static allocation
6520c16b537SWarner Losh ******************************************/
6530c16b537SWarner Losh /* FSE buffer bounds */
6540c16b537SWarner Losh #define FSE_NCOUNTBOUND 512
6550c16b537SWarner Losh #define FSE_BLOCKBOUND(size) (size + (size>>7))
6560c16b537SWarner Losh #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */
6570c16b537SWarner Losh 
6580c16b537SWarner Losh /* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */
6590c16b537SWarner Losh #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))
6600c16b537SWarner Losh #define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))
6610c16b537SWarner Losh 
6620c16b537SWarner Losh 
6630c16b537SWarner Losh /******************************************
6640c16b537SWarner Losh *  FSE advanced API
6650c16b537SWarner Losh ******************************************/
6660c16b537SWarner Losh static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
6670c16b537SWarner Losh /* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */
6680c16b537SWarner Losh 
6690c16b537SWarner Losh static size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
6700c16b537SWarner Losh /* build a fake FSE_DTable, designed to always generate the same symbolValue */
6710c16b537SWarner Losh 
6720c16b537SWarner Losh 
6730c16b537SWarner Losh /******************************************
6740c16b537SWarner Losh *  FSE symbol decompression API
6750c16b537SWarner Losh ******************************************/
6760c16b537SWarner Losh typedef struct
6770c16b537SWarner Losh {
6780c16b537SWarner Losh     size_t      state;
6790c16b537SWarner Losh     const void* table;   /* precise table may vary, depending on U16 */
6800c16b537SWarner Losh } FSE_DState_t;
6810c16b537SWarner Losh 
6820c16b537SWarner Losh 
6830c16b537SWarner Losh static void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
6840c16b537SWarner Losh 
6850c16b537SWarner Losh static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
6860c16b537SWarner Losh 
6870c16b537SWarner Losh static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
6880c16b537SWarner Losh 
6890c16b537SWarner Losh 
6900c16b537SWarner Losh /******************************************
6910c16b537SWarner Losh *  FSE unsafe API
6920c16b537SWarner Losh ******************************************/
6930c16b537SWarner Losh static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
6940c16b537SWarner Losh /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
6950c16b537SWarner Losh 
6960c16b537SWarner Losh 
6970c16b537SWarner Losh /******************************************
6980c16b537SWarner Losh *  Implementation of inline functions
6990c16b537SWarner Losh ******************************************/
7000c16b537SWarner Losh 
7010c16b537SWarner Losh /* decompression */
7020c16b537SWarner Losh 
7030c16b537SWarner Losh typedef struct {
7040c16b537SWarner Losh     U16 tableLog;
7050c16b537SWarner Losh     U16 fastMode;
7060c16b537SWarner Losh } FSE_DTableHeader;   /* sizeof U32 */
7070c16b537SWarner Losh 
7080c16b537SWarner Losh typedef struct
7090c16b537SWarner Losh {
7100c16b537SWarner Losh     unsigned short newState;
7110c16b537SWarner Losh     unsigned char  symbol;
7120c16b537SWarner Losh     unsigned char  nbBits;
7130c16b537SWarner Losh } FSE_decode_t;   /* size == U32 */
7140c16b537SWarner Losh 
7150c16b537SWarner Losh MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
7160c16b537SWarner Losh {
7170c16b537SWarner Losh     FSE_DTableHeader DTableH;
7180c16b537SWarner Losh     memcpy(&DTableH, dt, sizeof(DTableH));
7190c16b537SWarner Losh     DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);
7200c16b537SWarner Losh     BIT_reloadDStream(bitD);
7210c16b537SWarner Losh     DStatePtr->table = dt + 1;
7220c16b537SWarner Losh }
7230c16b537SWarner Losh 
7240c16b537SWarner Losh MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
7250c16b537SWarner Losh {
7260c16b537SWarner Losh     const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
7270c16b537SWarner Losh     const U32  nbBits = DInfo.nbBits;
7280c16b537SWarner Losh     BYTE symbol = DInfo.symbol;
7290c16b537SWarner Losh     size_t lowBits = BIT_readBits(bitD, nbBits);
7300c16b537SWarner Losh 
7310c16b537SWarner Losh     DStatePtr->state = DInfo.newState + lowBits;
7320c16b537SWarner Losh     return symbol;
7330c16b537SWarner Losh }
7340c16b537SWarner Losh 
7350c16b537SWarner Losh MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
7360c16b537SWarner Losh {
7370c16b537SWarner Losh     const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
7380c16b537SWarner Losh     const U32 nbBits = DInfo.nbBits;
7390c16b537SWarner Losh     BYTE symbol = DInfo.symbol;
7400c16b537SWarner Losh     size_t lowBits = BIT_readBitsFast(bitD, nbBits);
7410c16b537SWarner Losh 
7420c16b537SWarner Losh     DStatePtr->state = DInfo.newState + lowBits;
7430c16b537SWarner Losh     return symbol;
7440c16b537SWarner Losh }
7450c16b537SWarner Losh 
7460c16b537SWarner Losh MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
7470c16b537SWarner Losh {
7480c16b537SWarner Losh     return DStatePtr->state == 0;
7490c16b537SWarner Losh }
7500c16b537SWarner Losh 
7510c16b537SWarner Losh 
7520c16b537SWarner Losh #if defined (__cplusplus)
7530c16b537SWarner Losh }
7540c16b537SWarner Losh #endif
7550c16b537SWarner Losh /* ******************************************************************
7560c16b537SWarner Losh    Huff0 : Huffman coder, part of New Generation Entropy library
7570c16b537SWarner Losh    header file for static linking (only)
7580c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet
7590c16b537SWarner Losh 
7600c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7610c16b537SWarner Losh 
7620c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
7630c16b537SWarner Losh    modification, are permitted provided that the following conditions are
7640c16b537SWarner Losh    met:
7650c16b537SWarner Losh 
7660c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
7670c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
7680c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
7690c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
7700c16b537SWarner Losh    in the documentation and/or other materials provided with the
7710c16b537SWarner Losh    distribution.
7720c16b537SWarner Losh 
7730c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7740c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7750c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7760c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7770c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7780c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7790c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7800c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7810c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7820c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
7830c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7840c16b537SWarner Losh 
7850c16b537SWarner Losh    You can contact the author at :
7860c16b537SWarner Losh    - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
7870c16b537SWarner Losh    - Public forum : https://groups.google.com/forum/#!forum/lz4c
7880c16b537SWarner Losh ****************************************************************** */
7890c16b537SWarner Losh 
7900c16b537SWarner Losh #if defined (__cplusplus)
7910c16b537SWarner Losh extern "C" {
7920c16b537SWarner Losh #endif
7930c16b537SWarner Losh 
7940c16b537SWarner Losh /******************************************
7950c16b537SWarner Losh *  Static allocation macros
7960c16b537SWarner Losh ******************************************/
7970c16b537SWarner Losh /* Huff0 buffer bounds */
7980c16b537SWarner Losh #define HUF_CTABLEBOUND 129
7990c16b537SWarner Losh #define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */
8000c16b537SWarner Losh #define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */
8010c16b537SWarner Losh 
8020c16b537SWarner Losh /* static allocation of Huff0's DTable */
8030c16b537SWarner Losh #define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */
8040c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
8050c16b537SWarner Losh         unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }
8060c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
8070c16b537SWarner Losh         unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }
8080c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \
8090c16b537SWarner Losh         unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }
8100c16b537SWarner Losh 
8110c16b537SWarner Losh 
8120c16b537SWarner Losh /******************************************
8130c16b537SWarner Losh *  Advanced functions
8140c16b537SWarner Losh ******************************************/
8150c16b537SWarner Losh static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */
8160c16b537SWarner Losh static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */
8170c16b537SWarner Losh static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbols decoder */
8180c16b537SWarner Losh 
8190c16b537SWarner Losh 
8200c16b537SWarner Losh #if defined (__cplusplus)
8210c16b537SWarner Losh }
8220c16b537SWarner Losh #endif
8230c16b537SWarner Losh 
8240c16b537SWarner Losh /*
8250c16b537SWarner Losh     zstd - standard compression library
8260c16b537SWarner Losh     Header File
8270c16b537SWarner Losh     Copyright (C) 2014-2015, Yann Collet.
8280c16b537SWarner Losh 
8290c16b537SWarner Losh     BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8300c16b537SWarner Losh 
8310c16b537SWarner Losh     Redistribution and use in source and binary forms, with or without
8320c16b537SWarner Losh     modification, are permitted provided that the following conditions are
8330c16b537SWarner Losh     met:
8340c16b537SWarner Losh     * Redistributions of source code must retain the above copyright
8350c16b537SWarner Losh     notice, this list of conditions and the following disclaimer.
8360c16b537SWarner Losh     * Redistributions in binary form must reproduce the above
8370c16b537SWarner Losh     copyright notice, this list of conditions and the following disclaimer
8380c16b537SWarner Losh     in the documentation and/or other materials provided with the
8390c16b537SWarner Losh     distribution.
8400c16b537SWarner Losh     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
8410c16b537SWarner Losh     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
8420c16b537SWarner Losh     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8430c16b537SWarner Losh     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8440c16b537SWarner Losh     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8450c16b537SWarner Losh     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
8460c16b537SWarner Losh     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
8470c16b537SWarner Losh     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8480c16b537SWarner Losh     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
8490c16b537SWarner Losh     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
8500c16b537SWarner Losh     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8510c16b537SWarner Losh 
8520c16b537SWarner Losh     You can contact the author at :
8530c16b537SWarner Losh     - zstd source repository : https://github.com/Cyan4973/zstd
8540c16b537SWarner Losh     - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
8550c16b537SWarner Losh */
8560c16b537SWarner Losh 
8570c16b537SWarner Losh #if defined (__cplusplus)
8580c16b537SWarner Losh extern "C" {
8590c16b537SWarner Losh #endif
8600c16b537SWarner Losh 
8610c16b537SWarner Losh /* *************************************
8620c16b537SWarner Losh *  Includes
8630c16b537SWarner Losh ***************************************/
8640c16b537SWarner Losh #include <stddef.h>   /* size_t */
8650c16b537SWarner Losh 
8660c16b537SWarner Losh 
8670c16b537SWarner Losh /* *************************************
8680c16b537SWarner Losh *  Version
8690c16b537SWarner Losh ***************************************/
8700c16b537SWarner Losh #define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */
8710c16b537SWarner Losh #define ZSTD_VERSION_MINOR    2    /* for new (non-breaking) interface capabilities */
8720c16b537SWarner Losh #define ZSTD_VERSION_RELEASE  2    /* for tweaks, bug-fixes, or development */
8730c16b537SWarner Losh #define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
8740c16b537SWarner Losh 
8750c16b537SWarner Losh 
8760c16b537SWarner Losh /* *************************************
8770c16b537SWarner Losh *  Advanced functions
8780c16b537SWarner Losh ***************************************/
8790c16b537SWarner Losh typedef struct ZSTD_CCtx_s ZSTD_CCtx;   /* incomplete type */
8800c16b537SWarner Losh 
8810c16b537SWarner Losh #if defined (__cplusplus)
8820c16b537SWarner Losh }
8830c16b537SWarner Losh #endif
8840c16b537SWarner Losh /*
8850c16b537SWarner Losh     zstd - standard compression library
8860c16b537SWarner Losh     Header File for static linking only
8870c16b537SWarner Losh     Copyright (C) 2014-2015, Yann Collet.
8880c16b537SWarner Losh 
8890c16b537SWarner Losh     BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8900c16b537SWarner Losh 
8910c16b537SWarner Losh     Redistribution and use in source and binary forms, with or without
8920c16b537SWarner Losh     modification, are permitted provided that the following conditions are
8930c16b537SWarner Losh     met:
8940c16b537SWarner Losh     * Redistributions of source code must retain the above copyright
8950c16b537SWarner Losh     notice, this list of conditions and the following disclaimer.
8960c16b537SWarner Losh     * Redistributions in binary form must reproduce the above
8970c16b537SWarner Losh     copyright notice, this list of conditions and the following disclaimer
8980c16b537SWarner Losh     in the documentation and/or other materials provided with the
8990c16b537SWarner Losh     distribution.
9000c16b537SWarner Losh     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9010c16b537SWarner Losh     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9020c16b537SWarner Losh     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
9030c16b537SWarner Losh     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9040c16b537SWarner Losh     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9050c16b537SWarner Losh     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9060c16b537SWarner Losh     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9070c16b537SWarner Losh     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9080c16b537SWarner Losh     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9090c16b537SWarner Losh     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
9100c16b537SWarner Losh     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9110c16b537SWarner Losh 
9120c16b537SWarner Losh     You can contact the author at :
9130c16b537SWarner Losh     - zstd source repository : https://github.com/Cyan4973/zstd
9140c16b537SWarner Losh     - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
9150c16b537SWarner Losh */
9160c16b537SWarner Losh 
9170c16b537SWarner Losh /* The objects defined into this file should be considered experimental.
9180c16b537SWarner Losh  * They are not labelled stable, as their prototype may change in the future.
9190c16b537SWarner Losh  * You can use them for tests, provide feedback, or if you can endure risk of future changes.
9200c16b537SWarner Losh  */
9210c16b537SWarner Losh 
9220c16b537SWarner Losh #if defined (__cplusplus)
9230c16b537SWarner Losh extern "C" {
9240c16b537SWarner Losh #endif
9250c16b537SWarner Losh 
9260c16b537SWarner Losh /* *************************************
9270c16b537SWarner Losh *  Streaming functions
9280c16b537SWarner Losh ***************************************/
9290c16b537SWarner Losh 
9300c16b537SWarner Losh typedef struct ZSTD_DCtx_s ZSTD_DCtx;
9310c16b537SWarner Losh 
9320c16b537SWarner Losh /*
9330c16b537SWarner Losh   Use above functions alternatively.
9340c16b537SWarner Losh   ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().
9350c16b537SWarner Losh   ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.
9360c16b537SWarner Losh   Result is the number of bytes regenerated within 'dst'.
9370c16b537SWarner Losh   It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.
9380c16b537SWarner Losh */
9390c16b537SWarner Losh 
9400c16b537SWarner Losh /* *************************************
9410c16b537SWarner Losh *  Prefix - version detection
9420c16b537SWarner Losh ***************************************/
9430c16b537SWarner Losh #define ZSTD_magicNumber 0xFD2FB522   /* v0.2 (current)*/
9440c16b537SWarner Losh 
9450c16b537SWarner Losh 
9460c16b537SWarner Losh #if defined (__cplusplus)
9470c16b537SWarner Losh }
9480c16b537SWarner Losh #endif
9490c16b537SWarner Losh /* ******************************************************************
9500c16b537SWarner Losh    FSE : Finite State Entropy coder
9510c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet.
9520c16b537SWarner Losh 
9530c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
9540c16b537SWarner Losh 
9550c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
9560c16b537SWarner Losh    modification, are permitted provided that the following conditions are
9570c16b537SWarner Losh    met:
9580c16b537SWarner Losh 
9590c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
9600c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
9610c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
9620c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
9630c16b537SWarner Losh    in the documentation and/or other materials provided with the
9640c16b537SWarner Losh    distribution.
9650c16b537SWarner Losh 
9660c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9670c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9680c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
9690c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9700c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9710c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9720c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9730c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9740c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9750c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
9760c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9770c16b537SWarner Losh 
9780c16b537SWarner Losh     You can contact the author at :
9790c16b537SWarner Losh     - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
9800c16b537SWarner Losh     - Public forum : https://groups.google.com/forum/#!forum/lz4c
9810c16b537SWarner Losh ****************************************************************** */
9820c16b537SWarner Losh 
9830c16b537SWarner Losh #ifndef FSE_COMMONDEFS_ONLY
9840c16b537SWarner Losh 
9850c16b537SWarner Losh /****************************************************************
9860c16b537SWarner Losh *  Tuning parameters
9870c16b537SWarner Losh ****************************************************************/
9880c16b537SWarner Losh /* MEMORY_USAGE :
9890c16b537SWarner Losh *  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
9900c16b537SWarner Losh *  Increasing memory usage improves compression ratio
9910c16b537SWarner Losh *  Reduced memory usage can improve speed, due to cache effect
9920c16b537SWarner Losh *  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
9930c16b537SWarner Losh #define FSE_MAX_MEMORY_USAGE 14
9940c16b537SWarner Losh #define FSE_DEFAULT_MEMORY_USAGE 13
9950c16b537SWarner Losh 
9960c16b537SWarner Losh /* FSE_MAX_SYMBOL_VALUE :
9970c16b537SWarner Losh *  Maximum symbol value authorized.
9980c16b537SWarner Losh *  Required for proper stack allocation */
9990c16b537SWarner Losh #define FSE_MAX_SYMBOL_VALUE 255
10000c16b537SWarner Losh 
10010c16b537SWarner Losh 
10020c16b537SWarner Losh /****************************************************************
10030c16b537SWarner Losh *  template functions type & suffix
10040c16b537SWarner Losh ****************************************************************/
10050c16b537SWarner Losh #define FSE_FUNCTION_TYPE BYTE
10060c16b537SWarner Losh #define FSE_FUNCTION_EXTENSION
10070c16b537SWarner Losh 
10080c16b537SWarner Losh 
10090c16b537SWarner Losh /****************************************************************
10100c16b537SWarner Losh *  Byte symbol type
10110c16b537SWarner Losh ****************************************************************/
10120c16b537SWarner Losh #endif   /* !FSE_COMMONDEFS_ONLY */
10130c16b537SWarner Losh 
10140c16b537SWarner Losh 
10150c16b537SWarner Losh /****************************************************************
10160c16b537SWarner Losh *  Compiler specifics
10170c16b537SWarner Losh ****************************************************************/
10180c16b537SWarner Losh #ifdef _MSC_VER    /* Visual Studio */
10190c16b537SWarner Losh #  define FORCE_INLINE static __forceinline
10200c16b537SWarner Losh #  include <intrin.h>                    /* For Visual 2005 */
10210c16b537SWarner Losh #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
10220c16b537SWarner Losh #  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */
10230c16b537SWarner Losh #else
10240c16b537SWarner Losh #  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
10250c16b537SWarner Losh #    ifdef __GNUC__
10260c16b537SWarner Losh #      define FORCE_INLINE static inline __attribute__((always_inline))
10270c16b537SWarner Losh #    else
10280c16b537SWarner Losh #      define FORCE_INLINE static inline
10290c16b537SWarner Losh #    endif
10300c16b537SWarner Losh #  else
10310c16b537SWarner Losh #    define FORCE_INLINE static
10320c16b537SWarner Losh #  endif /* __STDC_VERSION__ */
10330c16b537SWarner Losh #endif
10340c16b537SWarner Losh 
10350c16b537SWarner Losh 
10360c16b537SWarner Losh /****************************************************************
10370c16b537SWarner Losh *  Includes
10380c16b537SWarner Losh ****************************************************************/
10390c16b537SWarner Losh #include <stdlib.h>     /* malloc, free, qsort */
10400c16b537SWarner Losh #include <string.h>     /* memcpy, memset */
10410c16b537SWarner Losh #include <stdio.h>      /* printf (debug) */
10420c16b537SWarner Losh 
10430c16b537SWarner Losh /****************************************************************
10440c16b537SWarner Losh *  Constants
10450c16b537SWarner Losh *****************************************************************/
10460c16b537SWarner Losh #define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)
10470c16b537SWarner Losh #define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
10480c16b537SWarner Losh #define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
10490c16b537SWarner Losh #define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
10500c16b537SWarner Losh #define FSE_MIN_TABLELOG 5
10510c16b537SWarner Losh 
10520c16b537SWarner Losh #define FSE_TABLELOG_ABSOLUTE_MAX 15
10530c16b537SWarner Losh #if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
10540c16b537SWarner Losh #error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
10550c16b537SWarner Losh #endif
10560c16b537SWarner Losh 
10570c16b537SWarner Losh 
10580c16b537SWarner Losh /****************************************************************
10590c16b537SWarner Losh *  Error Management
10600c16b537SWarner Losh ****************************************************************/
10610c16b537SWarner Losh #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
10620c16b537SWarner Losh 
10630c16b537SWarner Losh 
10640c16b537SWarner Losh /****************************************************************
10650c16b537SWarner Losh *  Complex types
10660c16b537SWarner Losh ****************************************************************/
10670c16b537SWarner Losh typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
10680c16b537SWarner Losh 
10690c16b537SWarner Losh 
10700c16b537SWarner Losh /****************************************************************
10710c16b537SWarner Losh *  Templates
10720c16b537SWarner Losh ****************************************************************/
10730c16b537SWarner Losh /*
10740c16b537SWarner Losh   designed to be included
10750c16b537SWarner Losh   for type-specific functions (template emulation in C)
10760c16b537SWarner Losh   Objective is to write these functions only once, for improved maintenance
10770c16b537SWarner Losh */
10780c16b537SWarner Losh 
10790c16b537SWarner Losh /* safety checks */
10800c16b537SWarner Losh #ifndef FSE_FUNCTION_EXTENSION
10810c16b537SWarner Losh #  error "FSE_FUNCTION_EXTENSION must be defined"
10820c16b537SWarner Losh #endif
10830c16b537SWarner Losh #ifndef FSE_FUNCTION_TYPE
10840c16b537SWarner Losh #  error "FSE_FUNCTION_TYPE must be defined"
10850c16b537SWarner Losh #endif
10860c16b537SWarner Losh 
10870c16b537SWarner Losh /* Function names */
10880c16b537SWarner Losh #define FSE_CAT(X,Y) X##Y
10890c16b537SWarner Losh #define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
10900c16b537SWarner Losh #define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
10910c16b537SWarner Losh 
10920c16b537SWarner Losh 
10930c16b537SWarner Losh /* Function templates */
10940c16b537SWarner Losh 
10950c16b537SWarner Losh #define FSE_DECODE_TYPE FSE_decode_t
10960c16b537SWarner Losh 
10970c16b537SWarner Losh static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }
10980c16b537SWarner Losh 
10990c16b537SWarner Losh static size_t FSE_buildDTable
11000c16b537SWarner Losh (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
11010c16b537SWarner Losh {
11020c16b537SWarner Losh     void* ptr = dt+1;
11030c16b537SWarner Losh     FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)ptr;
11040c16b537SWarner Losh     FSE_DTableHeader DTableH;
11050c16b537SWarner Losh     const U32 tableSize = 1 << tableLog;
11060c16b537SWarner Losh     const U32 tableMask = tableSize-1;
11070c16b537SWarner Losh     const U32 step = FSE_tableStep(tableSize);
11080c16b537SWarner Losh     U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];
11090c16b537SWarner Losh     U32 position = 0;
11100c16b537SWarner Losh     U32 highThreshold = tableSize-1;
11110c16b537SWarner Losh     const S16 largeLimit= (S16)(1 << (tableLog-1));
11120c16b537SWarner Losh     U32 noLarge = 1;
11130c16b537SWarner Losh     U32 s;
11140c16b537SWarner Losh 
11150c16b537SWarner Losh     /* Sanity Checks */
11160c16b537SWarner Losh     if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
11170c16b537SWarner Losh     if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
11180c16b537SWarner Losh 
11190c16b537SWarner Losh     /* Init, lay down lowprob symbols */
11200c16b537SWarner Losh     DTableH.tableLog = (U16)tableLog;
11210c16b537SWarner Losh     for (s=0; s<=maxSymbolValue; s++)
11220c16b537SWarner Losh     {
11230c16b537SWarner Losh         if (normalizedCounter[s]==-1)
11240c16b537SWarner Losh         {
11250c16b537SWarner Losh             tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
11260c16b537SWarner Losh             symbolNext[s] = 1;
11270c16b537SWarner Losh         }
11280c16b537SWarner Losh         else
11290c16b537SWarner Losh         {
11300c16b537SWarner Losh             if (normalizedCounter[s] >= largeLimit) noLarge=0;
11310c16b537SWarner Losh             symbolNext[s] = normalizedCounter[s];
11320c16b537SWarner Losh         }
11330c16b537SWarner Losh     }
11340c16b537SWarner Losh 
11350c16b537SWarner Losh     /* Spread symbols */
11360c16b537SWarner Losh     for (s=0; s<=maxSymbolValue; s++)
11370c16b537SWarner Losh     {
11380c16b537SWarner Losh         int i;
11390c16b537SWarner Losh         for (i=0; i<normalizedCounter[s]; i++)
11400c16b537SWarner Losh         {
11410c16b537SWarner Losh             tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
11420c16b537SWarner Losh             position = (position + step) & tableMask;
11430c16b537SWarner Losh             while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */
11440c16b537SWarner Losh         }
11450c16b537SWarner Losh     }
11460c16b537SWarner Losh 
11470c16b537SWarner Losh     if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */
11480c16b537SWarner Losh 
11490c16b537SWarner Losh     /* Build Decoding table */
11500c16b537SWarner Losh     {
11510c16b537SWarner Losh         U32 i;
11520c16b537SWarner Losh         for (i=0; i<tableSize; i++)
11530c16b537SWarner Losh         {
11540c16b537SWarner Losh             FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);
11550c16b537SWarner Losh             U16 nextState = symbolNext[symbol]++;
11560c16b537SWarner Losh             tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );
11570c16b537SWarner Losh             tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);
11580c16b537SWarner Losh         }
11590c16b537SWarner Losh     }
11600c16b537SWarner Losh 
11610c16b537SWarner Losh     DTableH.fastMode = (U16)noLarge;
11620c16b537SWarner Losh     memcpy(dt, &DTableH, sizeof(DTableH));   /* memcpy(), to avoid strict aliasing warnings */
11630c16b537SWarner Losh     return 0;
11640c16b537SWarner Losh }
11650c16b537SWarner Losh 
11660c16b537SWarner Losh 
11670c16b537SWarner Losh #ifndef FSE_COMMONDEFS_ONLY
11680c16b537SWarner Losh /******************************************
11690c16b537SWarner Losh *  FSE helper functions
11700c16b537SWarner Losh ******************************************/
11710c16b537SWarner Losh static unsigned FSE_isError(size_t code) { return ERR_isError(code); }
11720c16b537SWarner Losh 
11730c16b537SWarner Losh 
11740c16b537SWarner Losh /****************************************************************
11750c16b537SWarner Losh *  FSE NCount encoding-decoding
11760c16b537SWarner Losh ****************************************************************/
11770c16b537SWarner Losh static short FSE_abs(short a)
11780c16b537SWarner Losh {
11790c16b537SWarner Losh     return (short)(a<0 ? -a : a);
11800c16b537SWarner Losh }
11810c16b537SWarner Losh 
11820c16b537SWarner Losh static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
11830c16b537SWarner Losh                  const void* headerBuffer, size_t hbSize)
11840c16b537SWarner Losh {
11850c16b537SWarner Losh     const BYTE* const istart = (const BYTE*) headerBuffer;
11860c16b537SWarner Losh     const BYTE* const iend = istart + hbSize;
11870c16b537SWarner Losh     const BYTE* ip = istart;
11880c16b537SWarner Losh     int nbBits;
11890c16b537SWarner Losh     int remaining;
11900c16b537SWarner Losh     int threshold;
11910c16b537SWarner Losh     U32 bitStream;
11920c16b537SWarner Losh     int bitCount;
11930c16b537SWarner Losh     unsigned charnum = 0;
11940c16b537SWarner Losh     int previous0 = 0;
11950c16b537SWarner Losh 
11960c16b537SWarner Losh     if (hbSize < 4) return ERROR(srcSize_wrong);
11970c16b537SWarner Losh     bitStream = MEM_readLE32(ip);
11980c16b537SWarner Losh     nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */
11990c16b537SWarner Losh     if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
12000c16b537SWarner Losh     bitStream >>= 4;
12010c16b537SWarner Losh     bitCount = 4;
12020c16b537SWarner Losh     *tableLogPtr = nbBits;
12030c16b537SWarner Losh     remaining = (1<<nbBits)+1;
12040c16b537SWarner Losh     threshold = 1<<nbBits;
12050c16b537SWarner Losh     nbBits++;
12060c16b537SWarner Losh 
12070c16b537SWarner Losh     while ((remaining>1) && (charnum<=*maxSVPtr))
12080c16b537SWarner Losh     {
12090c16b537SWarner Losh         if (previous0)
12100c16b537SWarner Losh         {
12110c16b537SWarner Losh             unsigned n0 = charnum;
12120c16b537SWarner Losh             while ((bitStream & 0xFFFF) == 0xFFFF)
12130c16b537SWarner Losh             {
12140c16b537SWarner Losh                 n0+=24;
12150c16b537SWarner Losh                 if (ip < iend-5)
12160c16b537SWarner Losh                 {
12170c16b537SWarner Losh                     ip+=2;
12180c16b537SWarner Losh                     bitStream = MEM_readLE32(ip) >> bitCount;
12190c16b537SWarner Losh                 }
12200c16b537SWarner Losh                 else
12210c16b537SWarner Losh                 {
12220c16b537SWarner Losh                     bitStream >>= 16;
12230c16b537SWarner Losh                     bitCount+=16;
12240c16b537SWarner Losh                 }
12250c16b537SWarner Losh             }
12260c16b537SWarner Losh             while ((bitStream & 3) == 3)
12270c16b537SWarner Losh             {
12280c16b537SWarner Losh                 n0+=3;
12290c16b537SWarner Losh                 bitStream>>=2;
12300c16b537SWarner Losh                 bitCount+=2;
12310c16b537SWarner Losh             }
12320c16b537SWarner Losh             n0 += bitStream & 3;
12330c16b537SWarner Losh             bitCount += 2;
12340c16b537SWarner Losh             if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
12350c16b537SWarner Losh             while (charnum < n0) normalizedCounter[charnum++] = 0;
12360c16b537SWarner Losh             if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))
12370c16b537SWarner Losh             {
12380c16b537SWarner Losh                 ip += bitCount>>3;
12390c16b537SWarner Losh                 bitCount &= 7;
12400c16b537SWarner Losh                 bitStream = MEM_readLE32(ip) >> bitCount;
12410c16b537SWarner Losh             }
12420c16b537SWarner Losh             else
12430c16b537SWarner Losh                 bitStream >>= 2;
12440c16b537SWarner Losh         }
12450c16b537SWarner Losh         {
12460c16b537SWarner Losh             const short max = (short)((2*threshold-1)-remaining);
12470c16b537SWarner Losh             short count;
12480c16b537SWarner Losh 
12490c16b537SWarner Losh             if ((bitStream & (threshold-1)) < (U32)max)
12500c16b537SWarner Losh             {
12510c16b537SWarner Losh                 count = (short)(bitStream & (threshold-1));
12520c16b537SWarner Losh                 bitCount   += nbBits-1;
12530c16b537SWarner Losh             }
12540c16b537SWarner Losh             else
12550c16b537SWarner Losh             {
12560c16b537SWarner Losh                 count = (short)(bitStream & (2*threshold-1));
12570c16b537SWarner Losh                 if (count >= threshold) count -= max;
12580c16b537SWarner Losh                 bitCount   += nbBits;
12590c16b537SWarner Losh             }
12600c16b537SWarner Losh 
12610c16b537SWarner Losh             count--;   /* extra accuracy */
12620c16b537SWarner Losh             remaining -= FSE_abs(count);
12630c16b537SWarner Losh             normalizedCounter[charnum++] = count;
12640c16b537SWarner Losh             previous0 = !count;
12650c16b537SWarner Losh             while (remaining < threshold)
12660c16b537SWarner Losh             {
12670c16b537SWarner Losh                 nbBits--;
12680c16b537SWarner Losh                 threshold >>= 1;
12690c16b537SWarner Losh             }
12700c16b537SWarner Losh 
12710c16b537SWarner Losh             {
12720c16b537SWarner Losh                 if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))
12730c16b537SWarner Losh                 {
12740c16b537SWarner Losh                     ip += bitCount>>3;
12750c16b537SWarner Losh                     bitCount &= 7;
12760c16b537SWarner Losh                 }
12770c16b537SWarner Losh                 else
12780c16b537SWarner Losh                 {
12790c16b537SWarner Losh                     bitCount -= (int)(8 * (iend - 4 - ip));
12800c16b537SWarner Losh                     ip = iend - 4;
12810c16b537SWarner Losh                 }
12820c16b537SWarner Losh                 bitStream = MEM_readLE32(ip) >> (bitCount & 31);
12830c16b537SWarner Losh             }
12840c16b537SWarner Losh         }
12850c16b537SWarner Losh     }
12860c16b537SWarner Losh     if (remaining != 1) return ERROR(GENERIC);
12870c16b537SWarner Losh     *maxSVPtr = charnum-1;
12880c16b537SWarner Losh 
12890c16b537SWarner Losh     ip += (bitCount+7)>>3;
12900c16b537SWarner Losh     if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);
12910c16b537SWarner Losh     return ip-istart;
12920c16b537SWarner Losh }
12930c16b537SWarner Losh 
12940c16b537SWarner Losh 
12950c16b537SWarner Losh /*********************************************************
12960c16b537SWarner Losh *  Decompression (Byte symbols)
12970c16b537SWarner Losh *********************************************************/
12980c16b537SWarner Losh static size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
12990c16b537SWarner Losh {
13000c16b537SWarner Losh     void* ptr = dt;
13010c16b537SWarner Losh     FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
13020c16b537SWarner Losh     FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */
13030c16b537SWarner Losh 
13040c16b537SWarner Losh     DTableH->tableLog = 0;
13050c16b537SWarner Losh     DTableH->fastMode = 0;
13060c16b537SWarner Losh 
13070c16b537SWarner Losh     cell->newState = 0;
13080c16b537SWarner Losh     cell->symbol = symbolValue;
13090c16b537SWarner Losh     cell->nbBits = 0;
13100c16b537SWarner Losh 
13110c16b537SWarner Losh     return 0;
13120c16b537SWarner Losh }
13130c16b537SWarner Losh 
13140c16b537SWarner Losh 
13150c16b537SWarner Losh static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
13160c16b537SWarner Losh {
13170c16b537SWarner Losh     void* ptr = dt;
13180c16b537SWarner Losh     FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
13190c16b537SWarner Losh     FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */
13200c16b537SWarner Losh     const unsigned tableSize = 1 << nbBits;
13210c16b537SWarner Losh     const unsigned tableMask = tableSize - 1;
13220c16b537SWarner Losh     const unsigned maxSymbolValue = tableMask;
13230c16b537SWarner Losh     unsigned s;
13240c16b537SWarner Losh 
13250c16b537SWarner Losh     /* Sanity checks */
13260c16b537SWarner Losh     if (nbBits < 1) return ERROR(GENERIC);         /* min size */
13270c16b537SWarner Losh 
13280c16b537SWarner Losh     /* Build Decoding Table */
13290c16b537SWarner Losh     DTableH->tableLog = (U16)nbBits;
13300c16b537SWarner Losh     DTableH->fastMode = 1;
13310c16b537SWarner Losh     for (s=0; s<=maxSymbolValue; s++)
13320c16b537SWarner Losh     {
13330c16b537SWarner Losh         dinfo[s].newState = 0;
13340c16b537SWarner Losh         dinfo[s].symbol = (BYTE)s;
13350c16b537SWarner Losh         dinfo[s].nbBits = (BYTE)nbBits;
13360c16b537SWarner Losh     }
13370c16b537SWarner Losh 
13380c16b537SWarner Losh     return 0;
13390c16b537SWarner Losh }
13400c16b537SWarner Losh 
13410c16b537SWarner Losh FORCE_INLINE size_t FSE_decompress_usingDTable_generic(
13420c16b537SWarner Losh           void* dst, size_t maxDstSize,
13430c16b537SWarner Losh     const void* cSrc, size_t cSrcSize,
13440c16b537SWarner Losh     const FSE_DTable* dt, const unsigned fast)
13450c16b537SWarner Losh {
13460c16b537SWarner Losh     BYTE* const ostart = (BYTE*) dst;
13470c16b537SWarner Losh     BYTE* op = ostart;
13480c16b537SWarner Losh     BYTE* const omax = op + maxDstSize;
13490c16b537SWarner Losh     BYTE* const olimit = omax-3;
13500c16b537SWarner Losh 
13510c16b537SWarner Losh     BIT_DStream_t bitD;
13520c16b537SWarner Losh     FSE_DState_t state1;
13530c16b537SWarner Losh     FSE_DState_t state2;
13540c16b537SWarner Losh     size_t errorCode;
13550c16b537SWarner Losh 
13560c16b537SWarner Losh     /* Init */
13570c16b537SWarner Losh     errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */
13580c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
13590c16b537SWarner Losh 
13600c16b537SWarner Losh     FSE_initDState(&state1, &bitD, dt);
13610c16b537SWarner Losh     FSE_initDState(&state2, &bitD, dt);
13620c16b537SWarner Losh 
13630c16b537SWarner Losh #define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
13640c16b537SWarner Losh 
13650c16b537SWarner Losh     /* 4 symbols per loop */
13660c16b537SWarner Losh     for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)
13670c16b537SWarner Losh     {
13680c16b537SWarner Losh         op[0] = FSE_GETSYMBOL(&state1);
13690c16b537SWarner Losh 
13700c16b537SWarner Losh         if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
13710c16b537SWarner Losh             BIT_reloadDStream(&bitD);
13720c16b537SWarner Losh 
13730c16b537SWarner Losh         op[1] = FSE_GETSYMBOL(&state2);
13740c16b537SWarner Losh 
13750c16b537SWarner Losh         if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
13760c16b537SWarner Losh             { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }
13770c16b537SWarner Losh 
13780c16b537SWarner Losh         op[2] = FSE_GETSYMBOL(&state1);
13790c16b537SWarner Losh 
13800c16b537SWarner Losh         if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
13810c16b537SWarner Losh             BIT_reloadDStream(&bitD);
13820c16b537SWarner Losh 
13830c16b537SWarner Losh         op[3] = FSE_GETSYMBOL(&state2);
13840c16b537SWarner Losh     }
13850c16b537SWarner Losh 
13860c16b537SWarner Losh     /* tail */
13870c16b537SWarner Losh     /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
13880c16b537SWarner Losh     while (1)
13890c16b537SWarner Losh     {
13900c16b537SWarner Losh         if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )
13910c16b537SWarner Losh             break;
13920c16b537SWarner Losh 
13930c16b537SWarner Losh         *op++ = FSE_GETSYMBOL(&state1);
13940c16b537SWarner Losh 
13950c16b537SWarner Losh         if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )
13960c16b537SWarner Losh             break;
13970c16b537SWarner Losh 
13980c16b537SWarner Losh         *op++ = FSE_GETSYMBOL(&state2);
13990c16b537SWarner Losh     }
14000c16b537SWarner Losh 
14010c16b537SWarner Losh     /* end ? */
14020c16b537SWarner Losh     if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))
14030c16b537SWarner Losh         return op-ostart;
14040c16b537SWarner Losh 
14050c16b537SWarner Losh     if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */
14060c16b537SWarner Losh 
14070c16b537SWarner Losh     return ERROR(corruption_detected);
14080c16b537SWarner Losh }
14090c16b537SWarner Losh 
14100c16b537SWarner Losh 
14110c16b537SWarner Losh static size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
14120c16b537SWarner Losh                             const void* cSrc, size_t cSrcSize,
14130c16b537SWarner Losh                             const FSE_DTable* dt)
14140c16b537SWarner Losh {
14150c16b537SWarner Losh     FSE_DTableHeader DTableH;
14160c16b537SWarner Losh     memcpy(&DTableH, dt, sizeof(DTableH));
14170c16b537SWarner Losh 
14180c16b537SWarner Losh     /* select fast mode (static) */
14190c16b537SWarner Losh     if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
14200c16b537SWarner Losh     return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
14210c16b537SWarner Losh }
14220c16b537SWarner Losh 
14230c16b537SWarner Losh 
14240c16b537SWarner Losh static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
14250c16b537SWarner Losh {
14260c16b537SWarner Losh     const BYTE* const istart = (const BYTE*)cSrc;
14270c16b537SWarner Losh     const BYTE* ip = istart;
14280c16b537SWarner Losh     short counting[FSE_MAX_SYMBOL_VALUE+1];
14290c16b537SWarner Losh     DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */
14300c16b537SWarner Losh     unsigned tableLog;
14310c16b537SWarner Losh     unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
14320c16b537SWarner Losh     size_t errorCode;
14330c16b537SWarner Losh 
14340c16b537SWarner Losh     if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */
14350c16b537SWarner Losh 
14360c16b537SWarner Losh     /* normal FSE decoding mode */
14370c16b537SWarner Losh     errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
14380c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
14390c16b537SWarner Losh     if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */
14400c16b537SWarner Losh     ip += errorCode;
14410c16b537SWarner Losh     cSrcSize -= errorCode;
14420c16b537SWarner Losh 
14430c16b537SWarner Losh     errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);
14440c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
14450c16b537SWarner Losh 
14460c16b537SWarner Losh     /* always return, even if it is an error code */
14470c16b537SWarner Losh     return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);
14480c16b537SWarner Losh }
14490c16b537SWarner Losh 
14500c16b537SWarner Losh 
14510c16b537SWarner Losh 
14520c16b537SWarner Losh #endif   /* FSE_COMMONDEFS_ONLY */
14530c16b537SWarner Losh /* ******************************************************************
14540c16b537SWarner Losh    Huff0 : Huffman coder, part of New Generation Entropy library
14550c16b537SWarner Losh    Copyright (C) 2013-2015, Yann Collet.
14560c16b537SWarner Losh 
14570c16b537SWarner Losh    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
14580c16b537SWarner Losh 
14590c16b537SWarner Losh    Redistribution and use in source and binary forms, with or without
14600c16b537SWarner Losh    modification, are permitted provided that the following conditions are
14610c16b537SWarner Losh    met:
14620c16b537SWarner Losh 
14630c16b537SWarner Losh        * Redistributions of source code must retain the above copyright
14640c16b537SWarner Losh    notice, this list of conditions and the following disclaimer.
14650c16b537SWarner Losh        * Redistributions in binary form must reproduce the above
14660c16b537SWarner Losh    copyright notice, this list of conditions and the following disclaimer
14670c16b537SWarner Losh    in the documentation and/or other materials provided with the
14680c16b537SWarner Losh    distribution.
14690c16b537SWarner Losh 
14700c16b537SWarner Losh    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14710c16b537SWarner Losh    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
14720c16b537SWarner Losh    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14730c16b537SWarner Losh    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
14740c16b537SWarner Losh    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
14750c16b537SWarner Losh    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14760c16b537SWarner Losh    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
14770c16b537SWarner Losh    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14780c16b537SWarner Losh    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14790c16b537SWarner Losh    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14800c16b537SWarner Losh    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14810c16b537SWarner Losh 
14820c16b537SWarner Losh     You can contact the author at :
14830c16b537SWarner Losh     - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy
14840c16b537SWarner Losh     - Public forum : https://groups.google.com/forum/#!forum/lz4c
14850c16b537SWarner Losh ****************************************************************** */
14860c16b537SWarner Losh 
14870c16b537SWarner Losh /****************************************************************
14880c16b537SWarner Losh *  Compiler specifics
14890c16b537SWarner Losh ****************************************************************/
14900c16b537SWarner Losh #if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
14910c16b537SWarner Losh /* inline is defined */
14920c16b537SWarner Losh #elif defined(_MSC_VER)
14930c16b537SWarner Losh #  define inline __inline
14940c16b537SWarner Losh #else
14950c16b537SWarner Losh #  define inline /* disable inline */
14960c16b537SWarner Losh #endif
14970c16b537SWarner Losh 
14980c16b537SWarner Losh 
14990c16b537SWarner Losh #ifdef _MSC_VER    /* Visual Studio */
15000c16b537SWarner Losh #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
15010c16b537SWarner Losh #endif
15020c16b537SWarner Losh 
15030c16b537SWarner Losh 
15040c16b537SWarner Losh /****************************************************************
15050c16b537SWarner Losh *  Includes
15060c16b537SWarner Losh ****************************************************************/
15070c16b537SWarner Losh #include <stdlib.h>     /* malloc, free, qsort */
15080c16b537SWarner Losh #include <string.h>     /* memcpy, memset */
15090c16b537SWarner Losh #include <stdio.h>      /* printf (debug) */
15100c16b537SWarner Losh 
15110c16b537SWarner Losh /****************************************************************
15120c16b537SWarner Losh *  Error Management
15130c16b537SWarner Losh ****************************************************************/
15140c16b537SWarner Losh #define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
15150c16b537SWarner Losh 
15160c16b537SWarner Losh 
15170c16b537SWarner Losh /******************************************
15180c16b537SWarner Losh *  Helper functions
15190c16b537SWarner Losh ******************************************/
15200c16b537SWarner Losh static unsigned HUF_isError(size_t code) { return ERR_isError(code); }
15210c16b537SWarner Losh 
15220c16b537SWarner Losh #define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
15230c16b537SWarner Losh #define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
15240c16b537SWarner Losh #define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */
15250c16b537SWarner Losh #define HUF_MAX_SYMBOL_VALUE 255
15260c16b537SWarner Losh #if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)
15270c16b537SWarner Losh #  error "HUF_MAX_TABLELOG is too large !"
15280c16b537SWarner Losh #endif
15290c16b537SWarner Losh 
15300c16b537SWarner Losh 
15310c16b537SWarner Losh 
15320c16b537SWarner Losh /*********************************************************
15330c16b537SWarner Losh *  Huff0 : Huffman block decompression
15340c16b537SWarner Losh *********************************************************/
15350c16b537SWarner Losh typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */
15360c16b537SWarner Losh 
15370c16b537SWarner Losh typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */
15380c16b537SWarner Losh 
15390c16b537SWarner Losh typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
15400c16b537SWarner Losh 
15410c16b537SWarner Losh /*! HUF_readStats
15420c16b537SWarner Losh     Read compact Huffman tree, saved by HUF_writeCTable
15430c16b537SWarner Losh     @huffWeight : destination buffer
15440c16b537SWarner Losh     @return : size read from `src`
15450c16b537SWarner Losh */
15460c16b537SWarner Losh static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
15470c16b537SWarner Losh                             U32* nbSymbolsPtr, U32* tableLogPtr,
15480c16b537SWarner Losh                             const void* src, size_t srcSize)
15490c16b537SWarner Losh {
15500c16b537SWarner Losh     U32 weightTotal;
15510c16b537SWarner Losh     U32 tableLog;
15520c16b537SWarner Losh     const BYTE* ip = (const BYTE*) src;
15530c16b537SWarner Losh     size_t iSize;
15540c16b537SWarner Losh     size_t oSize;
15550c16b537SWarner Losh     U32 n;
15560c16b537SWarner Losh 
15570c16b537SWarner Losh     if (!srcSize) return ERROR(srcSize_wrong);
15580c16b537SWarner Losh     iSize = ip[0];
15590c16b537SWarner Losh     //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */
15600c16b537SWarner Losh 
15610c16b537SWarner Losh     if (iSize >= 128)  /* special header */
15620c16b537SWarner Losh     {
15630c16b537SWarner Losh         if (iSize >= (242))   /* RLE */
15640c16b537SWarner Losh         {
15650c16b537SWarner Losh             static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
15660c16b537SWarner Losh             oSize = l[iSize-242];
15670c16b537SWarner Losh             memset(huffWeight, 1, hwSize);
15680c16b537SWarner Losh             iSize = 0;
15690c16b537SWarner Losh         }
15700c16b537SWarner Losh         else   /* Incompressible */
15710c16b537SWarner Losh         {
15720c16b537SWarner Losh             oSize = iSize - 127;
15730c16b537SWarner Losh             iSize = ((oSize+1)/2);
15740c16b537SWarner Losh             if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
15750c16b537SWarner Losh             if (oSize >= hwSize) return ERROR(corruption_detected);
15760c16b537SWarner Losh             ip += 1;
15770c16b537SWarner Losh             for (n=0; n<oSize; n+=2)
15780c16b537SWarner Losh             {
15790c16b537SWarner Losh                 huffWeight[n]   = ip[n/2] >> 4;
15800c16b537SWarner Losh                 huffWeight[n+1] = ip[n/2] & 15;
15810c16b537SWarner Losh             }
15820c16b537SWarner Losh         }
15830c16b537SWarner Losh     }
15840c16b537SWarner Losh     else  /* header compressed with FSE (normal case) */
15850c16b537SWarner Losh     {
15860c16b537SWarner Losh         if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
15870c16b537SWarner Losh         oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */
15880c16b537SWarner Losh         if (FSE_isError(oSize)) return oSize;
15890c16b537SWarner Losh     }
15900c16b537SWarner Losh 
15910c16b537SWarner Losh     /* collect weight stats */
15920c16b537SWarner Losh     memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));
15930c16b537SWarner Losh     weightTotal = 0;
15940c16b537SWarner Losh     for (n=0; n<oSize; n++)
15950c16b537SWarner Losh     {
15960c16b537SWarner Losh         if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);
15970c16b537SWarner Losh         rankStats[huffWeight[n]]++;
15980c16b537SWarner Losh         weightTotal += (1 << huffWeight[n]) >> 1;
15990c16b537SWarner Losh     }
16000c16b537SWarner Losh     if (weightTotal == 0) return ERROR(corruption_detected);
16010c16b537SWarner Losh 
16020c16b537SWarner Losh     /* get last non-null symbol weight (implied, total must be 2^n) */
16030c16b537SWarner Losh     tableLog = BIT_highbit32(weightTotal) + 1;
16040c16b537SWarner Losh     if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);
16050c16b537SWarner Losh     {
16060c16b537SWarner Losh         U32 total = 1 << tableLog;
16070c16b537SWarner Losh         U32 rest = total - weightTotal;
16080c16b537SWarner Losh         U32 verif = 1 << BIT_highbit32(rest);
16090c16b537SWarner Losh         U32 lastWeight = BIT_highbit32(rest) + 1;
16100c16b537SWarner Losh         if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */
16110c16b537SWarner Losh         huffWeight[oSize] = (BYTE)lastWeight;
16120c16b537SWarner Losh         rankStats[lastWeight]++;
16130c16b537SWarner Losh     }
16140c16b537SWarner Losh 
16150c16b537SWarner Losh     /* check tree construction validity */
16160c16b537SWarner Losh     if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */
16170c16b537SWarner Losh 
16180c16b537SWarner Losh     /* results */
16190c16b537SWarner Losh     *nbSymbolsPtr = (U32)(oSize+1);
16200c16b537SWarner Losh     *tableLogPtr = tableLog;
16210c16b537SWarner Losh     return iSize+1;
16220c16b537SWarner Losh }
16230c16b537SWarner Losh 
16240c16b537SWarner Losh 
16250c16b537SWarner Losh /**************************/
16260c16b537SWarner Losh /* single-symbol decoding */
16270c16b537SWarner Losh /**************************/
16280c16b537SWarner Losh 
16290c16b537SWarner Losh static size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)
16300c16b537SWarner Losh {
16310c16b537SWarner Losh     BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];
16320c16b537SWarner Losh     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */
16330c16b537SWarner Losh     U32 tableLog = 0;
16340c16b537SWarner Losh     const BYTE* ip = (const BYTE*) src;
16350c16b537SWarner Losh     size_t iSize = ip[0];
16360c16b537SWarner Losh     U32 nbSymbols = 0;
16370c16b537SWarner Losh     U32 n;
16380c16b537SWarner Losh     U32 nextRankStart;
16390c16b537SWarner Losh     void* ptr = DTable+1;
16400c16b537SWarner Losh     HUF_DEltX2* const dt = (HUF_DEltX2*)ptr;
16410c16b537SWarner Losh 
16420c16b537SWarner Losh     HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */
16430c16b537SWarner Losh     //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */
16440c16b537SWarner Losh 
16450c16b537SWarner Losh     iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
16460c16b537SWarner Losh     if (HUF_isError(iSize)) return iSize;
16470c16b537SWarner Losh 
16480c16b537SWarner Losh     /* check result */
16490c16b537SWarner Losh     if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */
16500c16b537SWarner Losh     DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */
16510c16b537SWarner Losh 
16520c16b537SWarner Losh     /* Prepare ranks */
16530c16b537SWarner Losh     nextRankStart = 0;
16540c16b537SWarner Losh     for (n=1; n<=tableLog; n++)
16550c16b537SWarner Losh     {
16560c16b537SWarner Losh         U32 current = nextRankStart;
16570c16b537SWarner Losh         nextRankStart += (rankVal[n] << (n-1));
16580c16b537SWarner Losh         rankVal[n] = current;
16590c16b537SWarner Losh     }
16600c16b537SWarner Losh 
16610c16b537SWarner Losh     /* fill DTable */
16620c16b537SWarner Losh     for (n=0; n<nbSymbols; n++)
16630c16b537SWarner Losh     {
16640c16b537SWarner Losh         const U32 w = huffWeight[n];
16650c16b537SWarner Losh         const U32 length = (1 << w) >> 1;
16660c16b537SWarner Losh         U32 i;
16670c16b537SWarner Losh         HUF_DEltX2 D;
16680c16b537SWarner Losh         D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
16690c16b537SWarner Losh         for (i = rankVal[w]; i < rankVal[w] + length; i++)
16700c16b537SWarner Losh             dt[i] = D;
16710c16b537SWarner Losh         rankVal[w] += length;
16720c16b537SWarner Losh     }
16730c16b537SWarner Losh 
16740c16b537SWarner Losh     return iSize;
16750c16b537SWarner Losh }
16760c16b537SWarner Losh 
16770c16b537SWarner Losh static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)
16780c16b537SWarner Losh {
16790c16b537SWarner Losh         const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
16800c16b537SWarner Losh         const BYTE c = dt[val].byte;
16810c16b537SWarner Losh         BIT_skipBits(Dstream, dt[val].nbBits);
16820c16b537SWarner Losh         return c;
16830c16b537SWarner Losh }
16840c16b537SWarner Losh 
16850c16b537SWarner Losh #define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
16860c16b537SWarner Losh     *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
16870c16b537SWarner Losh 
16880c16b537SWarner Losh #define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
16890c16b537SWarner Losh     if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \
16900c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
16910c16b537SWarner Losh 
16920c16b537SWarner Losh #define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
16930c16b537SWarner Losh     if (MEM_64bits()) \
16940c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
16950c16b537SWarner Losh 
16960c16b537SWarner Losh static inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)
16970c16b537SWarner Losh {
16980c16b537SWarner Losh     BYTE* const pStart = p;
16990c16b537SWarner Losh 
17000c16b537SWarner Losh     /* up to 4 symbols at a time */
17010c16b537SWarner Losh     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))
17020c16b537SWarner Losh     {
17030c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
17040c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
17050c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
17060c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
17070c16b537SWarner Losh     }
17080c16b537SWarner Losh 
17090c16b537SWarner Losh     /* closer to the end */
17100c16b537SWarner Losh     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
17110c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
17120c16b537SWarner Losh 
17130c16b537SWarner Losh     /* no more data to retrieve from bitstream, hence no need to reload */
17140c16b537SWarner Losh     while (p < pEnd)
17150c16b537SWarner Losh         HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
17160c16b537SWarner Losh 
17170c16b537SWarner Losh     return pEnd-pStart;
17180c16b537SWarner Losh }
17190c16b537SWarner Losh 
17200c16b537SWarner Losh 
17210c16b537SWarner Losh static size_t HUF_decompress4X2_usingDTable(
17220c16b537SWarner Losh           void* dst,  size_t dstSize,
17230c16b537SWarner Losh     const void* cSrc, size_t cSrcSize,
17240c16b537SWarner Losh     const U16* DTable)
17250c16b537SWarner Losh {
17260c16b537SWarner Losh     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
17270c16b537SWarner Losh 
17280c16b537SWarner Losh     {
17290c16b537SWarner Losh         const BYTE* const istart = (const BYTE*) cSrc;
17300c16b537SWarner Losh         BYTE* const ostart = (BYTE*) dst;
17310c16b537SWarner Losh         BYTE* const oend = ostart + dstSize;
17320c16b537SWarner Losh 
17330c16b537SWarner Losh         const void* ptr = DTable;
17340c16b537SWarner Losh         const HUF_DEltX2* const dt = ((const HUF_DEltX2*)ptr) +1;
17350c16b537SWarner Losh         const U32 dtLog = DTable[0];
17360c16b537SWarner Losh         size_t errorCode;
17370c16b537SWarner Losh 
17380c16b537SWarner Losh         /* Init */
17390c16b537SWarner Losh         BIT_DStream_t bitD1;
17400c16b537SWarner Losh         BIT_DStream_t bitD2;
17410c16b537SWarner Losh         BIT_DStream_t bitD3;
17420c16b537SWarner Losh         BIT_DStream_t bitD4;
17430c16b537SWarner Losh         const size_t length1 = MEM_readLE16(istart);
17440c16b537SWarner Losh         const size_t length2 = MEM_readLE16(istart+2);
17450c16b537SWarner Losh         const size_t length3 = MEM_readLE16(istart+4);
17460c16b537SWarner Losh         size_t length4;
17470c16b537SWarner Losh         const BYTE* const istart1 = istart + 6;  /* jumpTable */
17480c16b537SWarner Losh         const BYTE* const istart2 = istart1 + length1;
17490c16b537SWarner Losh         const BYTE* const istart3 = istart2 + length2;
17500c16b537SWarner Losh         const BYTE* const istart4 = istart3 + length3;
17510c16b537SWarner Losh         const size_t segmentSize = (dstSize+3) / 4;
17520c16b537SWarner Losh         BYTE* const opStart2 = ostart + segmentSize;
17530c16b537SWarner Losh         BYTE* const opStart3 = opStart2 + segmentSize;
17540c16b537SWarner Losh         BYTE* const opStart4 = opStart3 + segmentSize;
17550c16b537SWarner Losh         BYTE* op1 = ostart;
17560c16b537SWarner Losh         BYTE* op2 = opStart2;
17570c16b537SWarner Losh         BYTE* op3 = opStart3;
17580c16b537SWarner Losh         BYTE* op4 = opStart4;
17590c16b537SWarner Losh         U32 endSignal;
17600c16b537SWarner Losh 
17610c16b537SWarner Losh         length4 = cSrcSize - (length1 + length2 + length3 + 6);
17620c16b537SWarner Losh         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
17630c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD1, istart1, length1);
17640c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
17650c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD2, istart2, length2);
17660c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
17670c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD3, istart3, length3);
17680c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
17690c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD4, istart4, length4);
17700c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
17710c16b537SWarner Losh 
17720c16b537SWarner Losh         /* 16-32 symbols per loop (4-8 symbols per stream) */
17730c16b537SWarner Losh         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
17740c16b537SWarner Losh         for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )
17750c16b537SWarner Losh         {
17760c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
17770c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
17780c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
17790c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
17800c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
17810c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
17820c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
17830c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
17840c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
17850c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
17860c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
17870c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
17880c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
17890c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
17900c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
17910c16b537SWarner Losh             HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
17920c16b537SWarner Losh 
17930c16b537SWarner Losh             endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
17940c16b537SWarner Losh         }
17950c16b537SWarner Losh 
17960c16b537SWarner Losh         /* check corruption */
17970c16b537SWarner Losh         if (op1 > opStart2) return ERROR(corruption_detected);
17980c16b537SWarner Losh         if (op2 > opStart3) return ERROR(corruption_detected);
17990c16b537SWarner Losh         if (op3 > opStart4) return ERROR(corruption_detected);
18000c16b537SWarner Losh         /* note : op4 supposed already verified within main loop */
18010c16b537SWarner Losh 
18020c16b537SWarner Losh         /* finish bitStreams one by one */
18030c16b537SWarner Losh         HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
18040c16b537SWarner Losh         HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
18050c16b537SWarner Losh         HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
18060c16b537SWarner Losh         HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);
18070c16b537SWarner Losh 
18080c16b537SWarner Losh         /* check */
18090c16b537SWarner Losh         endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
18100c16b537SWarner Losh         if (!endSignal) return ERROR(corruption_detected);
18110c16b537SWarner Losh 
18120c16b537SWarner Losh         /* decoded size */
18130c16b537SWarner Losh         return dstSize;
18140c16b537SWarner Losh     }
18150c16b537SWarner Losh }
18160c16b537SWarner Losh 
18170c16b537SWarner Losh 
18180c16b537SWarner Losh static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
18190c16b537SWarner Losh {
18200c16b537SWarner Losh     HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);
18210c16b537SWarner Losh     const BYTE* ip = (const BYTE*) cSrc;
18220c16b537SWarner Losh     size_t errorCode;
18230c16b537SWarner Losh 
18240c16b537SWarner Losh     errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);
18250c16b537SWarner Losh     if (HUF_isError(errorCode)) return errorCode;
18260c16b537SWarner Losh     if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);
18270c16b537SWarner Losh     ip += errorCode;
18280c16b537SWarner Losh     cSrcSize -= errorCode;
18290c16b537SWarner Losh 
18300c16b537SWarner Losh     return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
18310c16b537SWarner Losh }
18320c16b537SWarner Losh 
18330c16b537SWarner Losh 
18340c16b537SWarner Losh /***************************/
18350c16b537SWarner Losh /* double-symbols decoding */
18360c16b537SWarner Losh /***************************/
18370c16b537SWarner Losh 
18380c16b537SWarner Losh static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,
18390c16b537SWarner Losh                            const U32* rankValOrigin, const int minWeight,
18400c16b537SWarner Losh                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
18410c16b537SWarner Losh                            U32 nbBitsBaseline, U16 baseSeq)
18420c16b537SWarner Losh {
18430c16b537SWarner Losh     HUF_DEltX4 DElt;
18440c16b537SWarner Losh     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];
18450c16b537SWarner Losh     U32 s;
18460c16b537SWarner Losh 
18470c16b537SWarner Losh     /* get pre-calculated rankVal */
18480c16b537SWarner Losh     memcpy(rankVal, rankValOrigin, sizeof(rankVal));
18490c16b537SWarner Losh 
18500c16b537SWarner Losh     /* fill skipped values */
18510c16b537SWarner Losh     if (minWeight>1)
18520c16b537SWarner Losh     {
18530c16b537SWarner Losh         U32 i, skipSize = rankVal[minWeight];
18540c16b537SWarner Losh         MEM_writeLE16(&(DElt.sequence), baseSeq);
18550c16b537SWarner Losh         DElt.nbBits   = (BYTE)(consumed);
18560c16b537SWarner Losh         DElt.length   = 1;
18570c16b537SWarner Losh         for (i = 0; i < skipSize; i++)
18580c16b537SWarner Losh             DTable[i] = DElt;
18590c16b537SWarner Losh     }
18600c16b537SWarner Losh 
18610c16b537SWarner Losh     /* fill DTable */
18620c16b537SWarner Losh     for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */
18630c16b537SWarner Losh     {
18640c16b537SWarner Losh         const U32 symbol = sortedSymbols[s].symbol;
18650c16b537SWarner Losh         const U32 weight = sortedSymbols[s].weight;
18660c16b537SWarner Losh         const U32 nbBits = nbBitsBaseline - weight;
18670c16b537SWarner Losh         const U32 length = 1 << (sizeLog-nbBits);
18680c16b537SWarner Losh         const U32 start = rankVal[weight];
18690c16b537SWarner Losh         U32 i = start;
18700c16b537SWarner Losh         const U32 end = start + length;
18710c16b537SWarner Losh 
18720c16b537SWarner Losh         MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
18730c16b537SWarner Losh         DElt.nbBits = (BYTE)(nbBits + consumed);
18740c16b537SWarner Losh         DElt.length = 2;
18750c16b537SWarner Losh         do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */
18760c16b537SWarner Losh 
18770c16b537SWarner Losh         rankVal[weight] += length;
18780c16b537SWarner Losh     }
18790c16b537SWarner Losh }
18800c16b537SWarner Losh 
18810c16b537SWarner Losh typedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];
18820c16b537SWarner Losh 
18830c16b537SWarner Losh static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,
18840c16b537SWarner Losh                            const sortedSymbol_t* sortedList, const U32 sortedListSize,
18850c16b537SWarner Losh                            const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
18860c16b537SWarner Losh                            const U32 nbBitsBaseline)
18870c16b537SWarner Losh {
18880c16b537SWarner Losh     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];
18890c16b537SWarner Losh     const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */
18900c16b537SWarner Losh     const U32 minBits  = nbBitsBaseline - maxWeight;
18910c16b537SWarner Losh     U32 s;
18920c16b537SWarner Losh 
18930c16b537SWarner Losh     memcpy(rankVal, rankValOrigin, sizeof(rankVal));
18940c16b537SWarner Losh 
18950c16b537SWarner Losh     /* fill DTable */
18960c16b537SWarner Losh     for (s=0; s<sortedListSize; s++)
18970c16b537SWarner Losh     {
18980c16b537SWarner Losh         const U16 symbol = sortedList[s].symbol;
18990c16b537SWarner Losh         const U32 weight = sortedList[s].weight;
19000c16b537SWarner Losh         const U32 nbBits = nbBitsBaseline - weight;
19010c16b537SWarner Losh         const U32 start = rankVal[weight];
19020c16b537SWarner Losh         const U32 length = 1 << (targetLog-nbBits);
19030c16b537SWarner Losh 
19040c16b537SWarner Losh         if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */
19050c16b537SWarner Losh         {
19060c16b537SWarner Losh             U32 sortedRank;
19070c16b537SWarner Losh             int minWeight = nbBits + scaleLog;
19080c16b537SWarner Losh             if (minWeight < 1) minWeight = 1;
19090c16b537SWarner Losh             sortedRank = rankStart[minWeight];
19100c16b537SWarner Losh             HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,
19110c16b537SWarner Losh                            rankValOrigin[nbBits], minWeight,
19120c16b537SWarner Losh                            sortedList+sortedRank, sortedListSize-sortedRank,
19130c16b537SWarner Losh                            nbBitsBaseline, symbol);
19140c16b537SWarner Losh         }
19150c16b537SWarner Losh         else
19160c16b537SWarner Losh         {
19170c16b537SWarner Losh             U32 i;
19180c16b537SWarner Losh             const U32 end = start + length;
19190c16b537SWarner Losh             HUF_DEltX4 DElt;
19200c16b537SWarner Losh 
19210c16b537SWarner Losh             MEM_writeLE16(&(DElt.sequence), symbol);
19220c16b537SWarner Losh             DElt.nbBits   = (BYTE)(nbBits);
19230c16b537SWarner Losh             DElt.length   = 1;
19240c16b537SWarner Losh             for (i = start; i < end; i++)
19250c16b537SWarner Losh                 DTable[i] = DElt;
19260c16b537SWarner Losh         }
19270c16b537SWarner Losh         rankVal[weight] += length;
19280c16b537SWarner Losh     }
19290c16b537SWarner Losh }
19300c16b537SWarner Losh 
19310c16b537SWarner Losh static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
19320c16b537SWarner Losh {
19330c16b537SWarner Losh     BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];
19340c16b537SWarner Losh     sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];
19350c16b537SWarner Losh     U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };
19360c16b537SWarner Losh     U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };
19370c16b537SWarner Losh     U32* const rankStart = rankStart0+1;
19380c16b537SWarner Losh     rankVal_t rankVal;
19390c16b537SWarner Losh     U32 tableLog, maxW, sizeOfSort, nbSymbols;
19400c16b537SWarner Losh     const U32 memLog = DTable[0];
19410c16b537SWarner Losh     const BYTE* ip = (const BYTE*) src;
19420c16b537SWarner Losh     size_t iSize = ip[0];
19430c16b537SWarner Losh     void* ptr = DTable;
19440c16b537SWarner Losh     HUF_DEltX4* const dt = ((HUF_DEltX4*)ptr) + 1;
19450c16b537SWarner Losh 
19460c16b537SWarner Losh     HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */
19470c16b537SWarner Losh     if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);
19480c16b537SWarner Losh     //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */
19490c16b537SWarner Losh 
19500c16b537SWarner Losh     iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
19510c16b537SWarner Losh     if (HUF_isError(iSize)) return iSize;
19520c16b537SWarner Losh 
19530c16b537SWarner Losh     /* check result */
19540c16b537SWarner Losh     if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */
19550c16b537SWarner Losh 
19560c16b537SWarner Losh     /* find maxWeight */
19570c16b537SWarner Losh     for (maxW = tableLog; rankStats[maxW]==0; maxW--)
19580c16b537SWarner Losh         {if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */
19590c16b537SWarner Losh 
19600c16b537SWarner Losh     /* Get start index of each weight */
19610c16b537SWarner Losh     {
19620c16b537SWarner Losh         U32 w, nextRankStart = 0;
19630c16b537SWarner Losh         for (w=1; w<=maxW; w++)
19640c16b537SWarner Losh         {
19650c16b537SWarner Losh             U32 current = nextRankStart;
19660c16b537SWarner Losh             nextRankStart += rankStats[w];
19670c16b537SWarner Losh             rankStart[w] = current;
19680c16b537SWarner Losh         }
19690c16b537SWarner Losh         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
19700c16b537SWarner Losh         sizeOfSort = nextRankStart;
19710c16b537SWarner Losh     }
19720c16b537SWarner Losh 
19730c16b537SWarner Losh     /* sort symbols by weight */
19740c16b537SWarner Losh     {
19750c16b537SWarner Losh         U32 s;
19760c16b537SWarner Losh         for (s=0; s<nbSymbols; s++)
19770c16b537SWarner Losh         {
19780c16b537SWarner Losh             U32 w = weightList[s];
19790c16b537SWarner Losh             U32 r = rankStart[w]++;
19800c16b537SWarner Losh             sortedSymbol[r].symbol = (BYTE)s;
19810c16b537SWarner Losh             sortedSymbol[r].weight = (BYTE)w;
19820c16b537SWarner Losh         }
19830c16b537SWarner Losh         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
19840c16b537SWarner Losh     }
19850c16b537SWarner Losh 
19860c16b537SWarner Losh     /* Build rankVal */
19870c16b537SWarner Losh     {
19880c16b537SWarner Losh         const U32 minBits = tableLog+1 - maxW;
19890c16b537SWarner Losh         U32 nextRankVal = 0;
19900c16b537SWarner Losh         U32 w, consumed;
19910c16b537SWarner Losh         const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */
19920c16b537SWarner Losh         U32* rankVal0 = rankVal[0];
19930c16b537SWarner Losh         for (w=1; w<=maxW; w++)
19940c16b537SWarner Losh         {
19950c16b537SWarner Losh             U32 current = nextRankVal;
19960c16b537SWarner Losh             nextRankVal += rankStats[w] << (w+rescale);
19970c16b537SWarner Losh             rankVal0[w] = current;
19980c16b537SWarner Losh         }
19990c16b537SWarner Losh         for (consumed = minBits; consumed <= memLog - minBits; consumed++)
20000c16b537SWarner Losh         {
20010c16b537SWarner Losh             U32* rankValPtr = rankVal[consumed];
20020c16b537SWarner Losh             for (w = 1; w <= maxW; w++)
20030c16b537SWarner Losh             {
20040c16b537SWarner Losh                 rankValPtr[w] = rankVal0[w] >> consumed;
20050c16b537SWarner Losh             }
20060c16b537SWarner Losh         }
20070c16b537SWarner Losh     }
20080c16b537SWarner Losh 
20090c16b537SWarner Losh     HUF_fillDTableX4(dt, memLog,
20100c16b537SWarner Losh                    sortedSymbol, sizeOfSort,
20110c16b537SWarner Losh                    rankStart0, rankVal, maxW,
20120c16b537SWarner Losh                    tableLog+1);
20130c16b537SWarner Losh 
20140c16b537SWarner Losh     return iSize;
20150c16b537SWarner Losh }
20160c16b537SWarner Losh 
20170c16b537SWarner Losh 
20180c16b537SWarner Losh static U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
20190c16b537SWarner Losh {
20200c16b537SWarner Losh     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
20210c16b537SWarner Losh     memcpy(op, dt+val, 2);
20220c16b537SWarner Losh     BIT_skipBits(DStream, dt[val].nbBits);
20230c16b537SWarner Losh     return dt[val].length;
20240c16b537SWarner Losh }
20250c16b537SWarner Losh 
20260c16b537SWarner Losh static U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
20270c16b537SWarner Losh {
20280c16b537SWarner Losh     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
20290c16b537SWarner Losh     memcpy(op, dt+val, 1);
20300c16b537SWarner Losh     if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
20310c16b537SWarner Losh     else
20320c16b537SWarner Losh     {
20330c16b537SWarner Losh         if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))
20340c16b537SWarner Losh         {
20350c16b537SWarner Losh             BIT_skipBits(DStream, dt[val].nbBits);
20360c16b537SWarner Losh             if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
20370c16b537SWarner 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 */
20380c16b537SWarner Losh         }
20390c16b537SWarner Losh     }
20400c16b537SWarner Losh     return 1;
20410c16b537SWarner Losh }
20420c16b537SWarner Losh 
20430c16b537SWarner Losh 
20440c16b537SWarner Losh #define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
20450c16b537SWarner Losh     ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
20460c16b537SWarner Losh 
20470c16b537SWarner Losh #define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
20480c16b537SWarner Losh     if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \
20490c16b537SWarner Losh         ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
20500c16b537SWarner Losh 
20510c16b537SWarner Losh #define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
20520c16b537SWarner Losh     if (MEM_64bits()) \
20530c16b537SWarner Losh         ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
20540c16b537SWarner Losh 
20550c16b537SWarner Losh static inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)
20560c16b537SWarner Losh {
20570c16b537SWarner Losh     BYTE* const pStart = p;
20580c16b537SWarner Losh 
20590c16b537SWarner Losh     /* up to 8 symbols at a time */
20600c16b537SWarner Losh     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))
20610c16b537SWarner Losh     {
20620c16b537SWarner Losh         HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
20630c16b537SWarner Losh         HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
20640c16b537SWarner Losh         HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
20650c16b537SWarner Losh         HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
20660c16b537SWarner Losh     }
20670c16b537SWarner Losh 
20680c16b537SWarner Losh     /* closer to the end */
20690c16b537SWarner Losh     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))
20700c16b537SWarner Losh         HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
20710c16b537SWarner Losh 
20720c16b537SWarner Losh     while (p <= pEnd-2)
20730c16b537SWarner Losh         HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
20740c16b537SWarner Losh 
20750c16b537SWarner Losh     if (p < pEnd)
20760c16b537SWarner Losh         p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
20770c16b537SWarner Losh 
20780c16b537SWarner Losh     return p-pStart;
20790c16b537SWarner Losh }
20800c16b537SWarner Losh 
20810c16b537SWarner Losh 
20820c16b537SWarner Losh 
20830c16b537SWarner Losh static size_t HUF_decompress4X4_usingDTable(
20840c16b537SWarner Losh           void* dst,  size_t dstSize,
20850c16b537SWarner Losh     const void* cSrc, size_t cSrcSize,
20860c16b537SWarner Losh     const U32* DTable)
20870c16b537SWarner Losh {
20880c16b537SWarner Losh     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
20890c16b537SWarner Losh 
20900c16b537SWarner Losh     {
20910c16b537SWarner Losh         const BYTE* const istart = (const BYTE*) cSrc;
20920c16b537SWarner Losh         BYTE* const ostart = (BYTE*) dst;
20930c16b537SWarner Losh         BYTE* const oend = ostart + dstSize;
20940c16b537SWarner Losh 
20950c16b537SWarner Losh         const void* ptr = DTable;
20960c16b537SWarner Losh         const HUF_DEltX4* const dt = ((const HUF_DEltX4*)ptr) +1;
20970c16b537SWarner Losh         const U32 dtLog = DTable[0];
20980c16b537SWarner Losh         size_t errorCode;
20990c16b537SWarner Losh 
21000c16b537SWarner Losh         /* Init */
21010c16b537SWarner Losh         BIT_DStream_t bitD1;
21020c16b537SWarner Losh         BIT_DStream_t bitD2;
21030c16b537SWarner Losh         BIT_DStream_t bitD3;
21040c16b537SWarner Losh         BIT_DStream_t bitD4;
21050c16b537SWarner Losh         const size_t length1 = MEM_readLE16(istart);
21060c16b537SWarner Losh         const size_t length2 = MEM_readLE16(istart+2);
21070c16b537SWarner Losh         const size_t length3 = MEM_readLE16(istart+4);
21080c16b537SWarner Losh         size_t length4;
21090c16b537SWarner Losh         const BYTE* const istart1 = istart + 6;  /* jumpTable */
21100c16b537SWarner Losh         const BYTE* const istart2 = istart1 + length1;
21110c16b537SWarner Losh         const BYTE* const istart3 = istart2 + length2;
21120c16b537SWarner Losh         const BYTE* const istart4 = istart3 + length3;
21130c16b537SWarner Losh         const size_t segmentSize = (dstSize+3) / 4;
21140c16b537SWarner Losh         BYTE* const opStart2 = ostart + segmentSize;
21150c16b537SWarner Losh         BYTE* const opStart3 = opStart2 + segmentSize;
21160c16b537SWarner Losh         BYTE* const opStart4 = opStart3 + segmentSize;
21170c16b537SWarner Losh         BYTE* op1 = ostart;
21180c16b537SWarner Losh         BYTE* op2 = opStart2;
21190c16b537SWarner Losh         BYTE* op3 = opStart3;
21200c16b537SWarner Losh         BYTE* op4 = opStart4;
21210c16b537SWarner Losh         U32 endSignal;
21220c16b537SWarner Losh 
21230c16b537SWarner Losh         length4 = cSrcSize - (length1 + length2 + length3 + 6);
21240c16b537SWarner Losh         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
21250c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD1, istart1, length1);
21260c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
21270c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD2, istart2, length2);
21280c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
21290c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD3, istart3, length3);
21300c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
21310c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD4, istart4, length4);
21320c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
21330c16b537SWarner Losh 
21340c16b537SWarner Losh         /* 16-32 symbols per loop (4-8 symbols per stream) */
21350c16b537SWarner Losh         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
21360c16b537SWarner Losh         for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )
21370c16b537SWarner Losh         {
21380c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
21390c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
21400c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
21410c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
21420c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
21430c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
21440c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
21450c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
21460c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
21470c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
21480c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
21490c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
21500c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
21510c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
21520c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
21530c16b537SWarner Losh             HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
21540c16b537SWarner Losh 
21550c16b537SWarner Losh             endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
21560c16b537SWarner Losh         }
21570c16b537SWarner Losh 
21580c16b537SWarner Losh         /* check corruption */
21590c16b537SWarner Losh         if (op1 > opStart2) return ERROR(corruption_detected);
21600c16b537SWarner Losh         if (op2 > opStart3) return ERROR(corruption_detected);
21610c16b537SWarner Losh         if (op3 > opStart4) return ERROR(corruption_detected);
21620c16b537SWarner Losh         /* note : op4 supposed already verified within main loop */
21630c16b537SWarner Losh 
21640c16b537SWarner Losh         /* finish bitStreams one by one */
21650c16b537SWarner Losh         HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
21660c16b537SWarner Losh         HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
21670c16b537SWarner Losh         HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
21680c16b537SWarner Losh         HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);
21690c16b537SWarner Losh 
21700c16b537SWarner Losh         /* check */
21710c16b537SWarner Losh         endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
21720c16b537SWarner Losh         if (!endSignal) return ERROR(corruption_detected);
21730c16b537SWarner Losh 
21740c16b537SWarner Losh         /* decoded size */
21750c16b537SWarner Losh         return dstSize;
21760c16b537SWarner Losh     }
21770c16b537SWarner Losh }
21780c16b537SWarner Losh 
21790c16b537SWarner Losh 
21800c16b537SWarner Losh static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
21810c16b537SWarner Losh {
21820c16b537SWarner Losh     HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);
21830c16b537SWarner Losh     const BYTE* ip = (const BYTE*) cSrc;
21840c16b537SWarner Losh 
21850c16b537SWarner Losh     size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);
21860c16b537SWarner Losh     if (HUF_isError(hSize)) return hSize;
21870c16b537SWarner Losh     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
21880c16b537SWarner Losh     ip += hSize;
21890c16b537SWarner Losh     cSrcSize -= hSize;
21900c16b537SWarner Losh 
21910c16b537SWarner Losh     return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
21920c16b537SWarner Losh }
21930c16b537SWarner Losh 
21940c16b537SWarner Losh 
21950c16b537SWarner Losh /**********************************/
21960c16b537SWarner Losh /* quad-symbol decoding           */
21970c16b537SWarner Losh /**********************************/
21980c16b537SWarner Losh typedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6;
21990c16b537SWarner Losh typedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6;
22000c16b537SWarner Losh 
22010c16b537SWarner Losh /* recursive, up to level 3; may benefit from <template>-like strategy to nest each level inline */
22020c16b537SWarner Losh static void HUF_fillDTableX6LevelN(HUF_DDescX6* DDescription, HUF_DSeqX6* DSequence, int sizeLog,
22030c16b537SWarner Losh                            const rankVal_t rankValOrigin, const U32 consumed, const int minWeight, const U32 maxWeight,
22040c16b537SWarner Losh                            const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, const U32* rankStart,
22050c16b537SWarner Losh                            const U32 nbBitsBaseline, HUF_DSeqX6 baseSeq, HUF_DDescX6 DDesc)
22060c16b537SWarner Losh {
22070c16b537SWarner Losh     const int scaleLog = nbBitsBaseline - sizeLog;   /* note : targetLog >= (nbBitsBaseline-1), hence scaleLog <= 1 */
22080c16b537SWarner Losh     const int minBits  = nbBitsBaseline - maxWeight;
22090c16b537SWarner Losh     const U32 level = DDesc.nbBytes;
22100c16b537SWarner Losh     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];
22110c16b537SWarner Losh     U32 symbolStartPos, s;
22120c16b537SWarner Losh 
22130c16b537SWarner Losh     /* local rankVal, will be modified */
22140c16b537SWarner Losh     memcpy(rankVal, rankValOrigin[consumed], sizeof(rankVal));
22150c16b537SWarner Losh 
22160c16b537SWarner Losh     /* fill skipped values */
22170c16b537SWarner Losh     if (minWeight>1)
22180c16b537SWarner Losh     {
22190c16b537SWarner Losh         U32 i;
22200c16b537SWarner Losh         const U32 skipSize = rankVal[minWeight];
22210c16b537SWarner Losh         for (i = 0; i < skipSize; i++)
22220c16b537SWarner Losh         {
22230c16b537SWarner Losh             DSequence[i] = baseSeq;
22240c16b537SWarner Losh             DDescription[i] = DDesc;
22250c16b537SWarner Losh         }
22260c16b537SWarner Losh     }
22270c16b537SWarner Losh 
22280c16b537SWarner Losh     /* fill DTable */
22290c16b537SWarner Losh     DDesc.nbBytes++;
22300c16b537SWarner Losh     symbolStartPos = rankStart[minWeight];
22310c16b537SWarner Losh     for (s=symbolStartPos; s<sortedListSize; s++)
22320c16b537SWarner Losh     {
22330c16b537SWarner Losh         const BYTE symbol = sortedSymbols[s].symbol;
22340c16b537SWarner Losh         const U32  weight = sortedSymbols[s].weight;   /* >= 1 (sorted) */
22350c16b537SWarner Losh         const int  nbBits = nbBitsBaseline - weight;   /* >= 1 (by construction) */
22360c16b537SWarner Losh         const int  totalBits = consumed+nbBits;
22370c16b537SWarner Losh         const U32  start  = rankVal[weight];
22380c16b537SWarner Losh         const U32  length = 1 << (sizeLog-nbBits);
22390c16b537SWarner Losh         baseSeq.byte[level] = symbol;
22400c16b537SWarner Losh         DDesc.nbBits = (BYTE)totalBits;
22410c16b537SWarner Losh 
22420c16b537SWarner Losh         if ((level<3) && (sizeLog-totalBits >= minBits))   /* enough room for another symbol */
22430c16b537SWarner Losh         {
22440c16b537SWarner Losh             int nextMinWeight = totalBits + scaleLog;
22450c16b537SWarner Losh             if (nextMinWeight < 1) nextMinWeight = 1;
22460c16b537SWarner Losh             HUF_fillDTableX6LevelN(DDescription+start, DSequence+start, sizeLog-nbBits,
22470c16b537SWarner Losh                            rankValOrigin, totalBits, nextMinWeight, maxWeight,
22480c16b537SWarner Losh                            sortedSymbols, sortedListSize, rankStart,
22490c16b537SWarner Losh                            nbBitsBaseline, baseSeq, DDesc);   /* recursive (max : level 3) */
22500c16b537SWarner Losh         }
22510c16b537SWarner Losh         else
22520c16b537SWarner Losh         {
22530c16b537SWarner Losh             U32 i;
22540c16b537SWarner Losh             const U32 end = start + length;
22550c16b537SWarner Losh             for (i = start; i < end; i++)
22560c16b537SWarner Losh             {
22570c16b537SWarner Losh                 DDescription[i] = DDesc;
22580c16b537SWarner Losh                 DSequence[i] = baseSeq;
22590c16b537SWarner Losh             }
22600c16b537SWarner Losh         }
22610c16b537SWarner Losh         rankVal[weight] += length;
22620c16b537SWarner Losh     }
22630c16b537SWarner Losh }
22640c16b537SWarner Losh 
22650c16b537SWarner Losh 
22660c16b537SWarner Losh /* note : same preparation as X4 */
22670c16b537SWarner Losh static size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
22680c16b537SWarner Losh {
22690c16b537SWarner Losh     BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];
22700c16b537SWarner Losh     sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];
22710c16b537SWarner Losh     U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };
22720c16b537SWarner Losh     U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };
22730c16b537SWarner Losh     U32* const rankStart = rankStart0+1;
22740c16b537SWarner Losh     U32 tableLog, maxW, sizeOfSort, nbSymbols;
22750c16b537SWarner Losh     rankVal_t rankVal;
22760c16b537SWarner Losh     const U32 memLog = DTable[0];
22770c16b537SWarner Losh     const BYTE* ip = (const BYTE*) src;
22780c16b537SWarner Losh     size_t iSize = ip[0];
22790c16b537SWarner Losh 
22800c16b537SWarner Losh     if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);
22810c16b537SWarner Losh     //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */
22820c16b537SWarner Losh 
22830c16b537SWarner Losh     iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
22840c16b537SWarner Losh     if (HUF_isError(iSize)) return iSize;
22850c16b537SWarner Losh 
22860c16b537SWarner Losh     /* check result */
22870c16b537SWarner Losh     if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable is too small */
22880c16b537SWarner Losh 
22890c16b537SWarner Losh     /* find maxWeight */
22900c16b537SWarner Losh     for (maxW = tableLog; rankStats[maxW]==0; maxW--)
22910c16b537SWarner Losh         { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */
22920c16b537SWarner Losh 
22930c16b537SWarner Losh 
22940c16b537SWarner Losh     /* Get start index of each weight */
22950c16b537SWarner Losh     {
22960c16b537SWarner Losh         U32 w, nextRankStart = 0;
22970c16b537SWarner Losh         for (w=1; w<=maxW; w++)
22980c16b537SWarner Losh         {
22990c16b537SWarner Losh             U32 current = nextRankStart;
23000c16b537SWarner Losh             nextRankStart += rankStats[w];
23010c16b537SWarner Losh             rankStart[w] = current;
23020c16b537SWarner Losh         }
23030c16b537SWarner Losh         rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
23040c16b537SWarner Losh         sizeOfSort = nextRankStart;
23050c16b537SWarner Losh     }
23060c16b537SWarner Losh 
23070c16b537SWarner Losh     /* sort symbols by weight */
23080c16b537SWarner Losh     {
23090c16b537SWarner Losh         U32 s;
23100c16b537SWarner Losh         for (s=0; s<nbSymbols; s++)
23110c16b537SWarner Losh         {
23120c16b537SWarner Losh             U32 w = weightList[s];
23130c16b537SWarner Losh             U32 r = rankStart[w]++;
23140c16b537SWarner Losh             sortedSymbol[r].symbol = (BYTE)s;
23150c16b537SWarner Losh             sortedSymbol[r].weight = (BYTE)w;
23160c16b537SWarner Losh         }
23170c16b537SWarner Losh         rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
23180c16b537SWarner Losh     }
23190c16b537SWarner Losh 
23200c16b537SWarner Losh     /* Build rankVal */
23210c16b537SWarner Losh     {
23220c16b537SWarner Losh         const U32 minBits = tableLog+1 - maxW;
23230c16b537SWarner Losh         U32 nextRankVal = 0;
23240c16b537SWarner Losh         U32 w, consumed;
23250c16b537SWarner Losh         const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */
23260c16b537SWarner Losh         U32* rankVal0 = rankVal[0];
23270c16b537SWarner Losh         for (w=1; w<=maxW; w++)
23280c16b537SWarner Losh         {
23290c16b537SWarner Losh             U32 current = nextRankVal;
23300c16b537SWarner Losh             nextRankVal += rankStats[w] << (w+rescale);
23310c16b537SWarner Losh             rankVal0[w] = current;
23320c16b537SWarner Losh         }
23330c16b537SWarner Losh         for (consumed = minBits; consumed <= memLog - minBits; consumed++)
23340c16b537SWarner Losh         {
23350c16b537SWarner Losh             U32* rankValPtr = rankVal[consumed];
23360c16b537SWarner Losh             for (w = 1; w <= maxW; w++)
23370c16b537SWarner Losh             {
23380c16b537SWarner Losh                 rankValPtr[w] = rankVal0[w] >> consumed;
23390c16b537SWarner Losh             }
23400c16b537SWarner Losh         }
23410c16b537SWarner Losh     }
23420c16b537SWarner Losh 
23430c16b537SWarner Losh 
23440c16b537SWarner Losh     /* fill tables */
23450c16b537SWarner Losh     {
23460c16b537SWarner Losh         void* ptr = DTable+1;
23470c16b537SWarner Losh         HUF_DDescX6* DDescription = (HUF_DDescX6*)(ptr);
23480c16b537SWarner Losh         void* dSeqStart = DTable + 1 + ((size_t)1<<(memLog-1));
23490c16b537SWarner Losh         HUF_DSeqX6* DSequence = (HUF_DSeqX6*)(dSeqStart);
23500c16b537SWarner Losh         HUF_DSeqX6 DSeq;
23510c16b537SWarner Losh         HUF_DDescX6 DDesc;
23520c16b537SWarner Losh         DSeq.sequence = 0;
23530c16b537SWarner Losh         DDesc.nbBits = 0;
23540c16b537SWarner Losh         DDesc.nbBytes = 0;
23550c16b537SWarner Losh         HUF_fillDTableX6LevelN(DDescription, DSequence, memLog,
23560c16b537SWarner Losh                        (const U32 (*)[HUF_ABSOLUTEMAX_TABLELOG + 1])rankVal, 0, 1, maxW,
23570c16b537SWarner Losh                        sortedSymbol, sizeOfSort, rankStart0,
23580c16b537SWarner Losh                        tableLog+1, DSeq, DDesc);
23590c16b537SWarner Losh     }
23600c16b537SWarner Losh 
23610c16b537SWarner Losh     return iSize;
23620c16b537SWarner Losh }
23630c16b537SWarner Losh 
23640c16b537SWarner Losh 
23650c16b537SWarner Losh static U32 HUF_decodeSymbolX6(void* op, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog)
23660c16b537SWarner Losh {
23670c16b537SWarner Losh     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
23680c16b537SWarner Losh     memcpy(op, ds+val, sizeof(HUF_DSeqX6));
23690c16b537SWarner Losh     BIT_skipBits(DStream, dd[val].nbBits);
23700c16b537SWarner Losh     return dd[val].nbBytes;
23710c16b537SWarner Losh }
23720c16b537SWarner Losh 
23730c16b537SWarner Losh static U32 HUF_decodeLastSymbolsX6(void* op, const U32 maxL, BIT_DStream_t* DStream,
23740c16b537SWarner Losh                                   const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog)
23750c16b537SWarner Losh {
23760c16b537SWarner Losh     const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
23770c16b537SWarner Losh     U32 length = dd[val].nbBytes;
23780c16b537SWarner Losh     if (length <= maxL)
23790c16b537SWarner Losh     {
23800c16b537SWarner Losh         memcpy(op, ds+val, length);
23810c16b537SWarner Losh         BIT_skipBits(DStream, dd[val].nbBits);
23820c16b537SWarner Losh         return length;
23830c16b537SWarner Losh     }
23840c16b537SWarner Losh     memcpy(op, ds+val, maxL);
23850c16b537SWarner Losh     if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))
23860c16b537SWarner Losh     {
23870c16b537SWarner Losh         BIT_skipBits(DStream, dd[val].nbBits);
23880c16b537SWarner Losh         if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
23890c16b537SWarner 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 */
23900c16b537SWarner Losh     }
23910c16b537SWarner Losh     return maxL;
23920c16b537SWarner Losh }
23930c16b537SWarner Losh 
23940c16b537SWarner Losh 
23950c16b537SWarner Losh #define HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) \
23960c16b537SWarner Losh     ptr += HUF_decodeSymbolX6(ptr, DStreamPtr, dd, ds, dtLog)
23970c16b537SWarner Losh 
23980c16b537SWarner Losh #define HUF_DECODE_SYMBOLX6_1(ptr, DStreamPtr) \
23990c16b537SWarner Losh     if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \
24000c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr)
24010c16b537SWarner Losh 
24020c16b537SWarner Losh #define HUF_DECODE_SYMBOLX6_2(ptr, DStreamPtr) \
24030c16b537SWarner Losh     if (MEM_64bits()) \
24040c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr)
24050c16b537SWarner Losh 
24060c16b537SWarner Losh static inline size_t HUF_decodeStreamX6(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const U32* DTable, const U32 dtLog)
24070c16b537SWarner Losh {
24080c16b537SWarner Losh     const void* ddPtr = DTable+1;
24090c16b537SWarner Losh     const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr);
24100c16b537SWarner Losh     const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1));
24110c16b537SWarner Losh     const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr);
24120c16b537SWarner Losh     BYTE* const pStart = p;
24130c16b537SWarner Losh 
24140c16b537SWarner Losh     /* up to 16 symbols at a time */
24150c16b537SWarner Losh     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-16))
24160c16b537SWarner Losh     {
24170c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_2(p, bitDPtr);
24180c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_1(p, bitDPtr);
24190c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_2(p, bitDPtr);
24200c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_0(p, bitDPtr);
24210c16b537SWarner Losh     }
24220c16b537SWarner Losh 
24230c16b537SWarner Losh     /* closer to the end, up to 4 symbols at a time */
24240c16b537SWarner Losh     while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))
24250c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_0(p, bitDPtr);
24260c16b537SWarner Losh 
24270c16b537SWarner Losh     while (p <= pEnd-4)
24280c16b537SWarner Losh         HUF_DECODE_SYMBOLX6_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
24290c16b537SWarner Losh 
24300c16b537SWarner Losh     while (p < pEnd)
24310c16b537SWarner Losh         p += HUF_decodeLastSymbolsX6(p, (U32)(pEnd-p), bitDPtr, dd, ds, dtLog);
24320c16b537SWarner Losh 
24330c16b537SWarner Losh     return p-pStart;
24340c16b537SWarner Losh }
24350c16b537SWarner Losh 
24360c16b537SWarner Losh 
24370c16b537SWarner Losh 
24380c16b537SWarner Losh static size_t HUF_decompress4X6_usingDTable(
24390c16b537SWarner Losh           void* dst,  size_t dstSize,
24400c16b537SWarner Losh     const void* cSrc, size_t cSrcSize,
24410c16b537SWarner Losh     const U32* DTable)
24420c16b537SWarner Losh {
24430c16b537SWarner Losh     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
24440c16b537SWarner Losh 
24450c16b537SWarner Losh     {
24460c16b537SWarner Losh         const BYTE* const istart = (const BYTE*) cSrc;
24470c16b537SWarner Losh         BYTE* const ostart = (BYTE*) dst;
24480c16b537SWarner Losh         BYTE* const oend = ostart + dstSize;
24490c16b537SWarner Losh 
24500c16b537SWarner Losh         const U32 dtLog = DTable[0];
24510c16b537SWarner Losh         const void* ddPtr = DTable+1;
24520c16b537SWarner Losh         const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr);
24530c16b537SWarner Losh         const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1));
24540c16b537SWarner Losh         const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr);
24550c16b537SWarner Losh         size_t errorCode;
24560c16b537SWarner Losh 
24570c16b537SWarner Losh         /* Init */
24580c16b537SWarner Losh         BIT_DStream_t bitD1;
24590c16b537SWarner Losh         BIT_DStream_t bitD2;
24600c16b537SWarner Losh         BIT_DStream_t bitD3;
24610c16b537SWarner Losh         BIT_DStream_t bitD4;
24620c16b537SWarner Losh         const size_t length1 = MEM_readLE16(istart);
24630c16b537SWarner Losh         const size_t length2 = MEM_readLE16(istart+2);
24640c16b537SWarner Losh         const size_t length3 = MEM_readLE16(istart+4);
24650c16b537SWarner Losh         size_t length4;
24660c16b537SWarner Losh         const BYTE* const istart1 = istart + 6;  /* jumpTable */
24670c16b537SWarner Losh         const BYTE* const istart2 = istart1 + length1;
24680c16b537SWarner Losh         const BYTE* const istart3 = istart2 + length2;
24690c16b537SWarner Losh         const BYTE* const istart4 = istart3 + length3;
24700c16b537SWarner Losh         const size_t segmentSize = (dstSize+3) / 4;
24710c16b537SWarner Losh         BYTE* const opStart2 = ostart + segmentSize;
24720c16b537SWarner Losh         BYTE* const opStart3 = opStart2 + segmentSize;
24730c16b537SWarner Losh         BYTE* const opStart4 = opStart3 + segmentSize;
24740c16b537SWarner Losh         BYTE* op1 = ostart;
24750c16b537SWarner Losh         BYTE* op2 = opStart2;
24760c16b537SWarner Losh         BYTE* op3 = opStart3;
24770c16b537SWarner Losh         BYTE* op4 = opStart4;
24780c16b537SWarner Losh         U32 endSignal;
24790c16b537SWarner Losh 
24800c16b537SWarner Losh         length4 = cSrcSize - (length1 + length2 + length3 + 6);
24810c16b537SWarner Losh         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
24820c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD1, istart1, length1);
24830c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
24840c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD2, istart2, length2);
24850c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
24860c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD3, istart3, length3);
24870c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
24880c16b537SWarner Losh         errorCode = BIT_initDStream(&bitD4, istart4, length4);
24890c16b537SWarner Losh         if (HUF_isError(errorCode)) return errorCode;
24900c16b537SWarner Losh 
24910c16b537SWarner Losh         /* 16-64 symbols per loop (4-16 symbols per stream) */
24920c16b537SWarner Losh         endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
24930c16b537SWarner Losh         for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; )
24940c16b537SWarner Losh         {
24950c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op1, &bitD1);
24960c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op2, &bitD2);
24970c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op3, &bitD3);
24980c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op4, &bitD4);
24990c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_1(op1, &bitD1);
25000c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_1(op2, &bitD2);
25010c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_1(op3, &bitD3);
25020c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_1(op4, &bitD4);
25030c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op1, &bitD1);
25040c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op2, &bitD2);
25050c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op3, &bitD3);
25060c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_2(op4, &bitD4);
25070c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_0(op1, &bitD1);
25080c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_0(op2, &bitD2);
25090c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_0(op3, &bitD3);
25100c16b537SWarner Losh             HUF_DECODE_SYMBOLX6_0(op4, &bitD4);
25110c16b537SWarner Losh 
25120c16b537SWarner Losh             endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
25130c16b537SWarner Losh         }
25140c16b537SWarner Losh 
25150c16b537SWarner Losh         /* check corruption */
25160c16b537SWarner Losh         if (op1 > opStart2) return ERROR(corruption_detected);
25170c16b537SWarner Losh         if (op2 > opStart3) return ERROR(corruption_detected);
25180c16b537SWarner Losh         if (op3 > opStart4) return ERROR(corruption_detected);
25190c16b537SWarner Losh         /* note : op4 supposed already verified within main loop */
25200c16b537SWarner Losh 
25210c16b537SWarner Losh         /* finish bitStreams one by one */
25220c16b537SWarner Losh         HUF_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog);
25230c16b537SWarner Losh         HUF_decodeStreamX6(op2, &bitD2, opStart3, DTable, dtLog);
25240c16b537SWarner Losh         HUF_decodeStreamX6(op3, &bitD3, opStart4, DTable, dtLog);
25250c16b537SWarner Losh         HUF_decodeStreamX6(op4, &bitD4, oend,     DTable, dtLog);
25260c16b537SWarner Losh 
25270c16b537SWarner Losh         /* check */
25280c16b537SWarner Losh         endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
25290c16b537SWarner Losh         if (!endSignal) return ERROR(corruption_detected);
25300c16b537SWarner Losh 
25310c16b537SWarner Losh         /* decoded size */
25320c16b537SWarner Losh         return dstSize;
25330c16b537SWarner Losh     }
25340c16b537SWarner Losh }
25350c16b537SWarner Losh 
25360c16b537SWarner Losh 
25370c16b537SWarner Losh static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
25380c16b537SWarner Losh {
25390c16b537SWarner Losh     HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG);
25400c16b537SWarner Losh     const BYTE* ip = (const BYTE*) cSrc;
25410c16b537SWarner Losh 
25420c16b537SWarner Losh     size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize);
25430c16b537SWarner Losh     if (HUF_isError(hSize)) return hSize;
25440c16b537SWarner Losh     if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
25450c16b537SWarner Losh     ip += hSize;
25460c16b537SWarner Losh     cSrcSize -= hSize;
25470c16b537SWarner Losh 
25480c16b537SWarner Losh     return HUF_decompress4X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable);
25490c16b537SWarner Losh }
25500c16b537SWarner Losh 
25510c16b537SWarner Losh 
25520c16b537SWarner Losh /**********************************/
25530c16b537SWarner Losh /* Generic decompression selector */
25540c16b537SWarner Losh /**********************************/
25550c16b537SWarner Losh 
25560c16b537SWarner Losh typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
25570c16b537SWarner Losh static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
25580c16b537SWarner Losh {
25590c16b537SWarner Losh     /* single, double, quad */
25600c16b537SWarner Losh     {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */
25610c16b537SWarner Losh     {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */
25620c16b537SWarner Losh     {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */
25630c16b537SWarner Losh     {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */
25640c16b537SWarner Losh     {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */
25650c16b537SWarner Losh     {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */
25660c16b537SWarner Losh     {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */
25670c16b537SWarner Losh     {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */
25680c16b537SWarner Losh     {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */
25690c16b537SWarner Losh     {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */
25700c16b537SWarner Losh     {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */
25710c16b537SWarner Losh     {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */
25720c16b537SWarner Losh     {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */
25730c16b537SWarner Losh     {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */
25740c16b537SWarner Losh     {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */
25750c16b537SWarner Losh     {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */
25760c16b537SWarner Losh };
25770c16b537SWarner Losh 
25780c16b537SWarner Losh typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
25790c16b537SWarner Losh 
25800c16b537SWarner Losh static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
25810c16b537SWarner Losh {
25820c16b537SWarner Losh     static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, HUF_decompress4X6 };
25830c16b537SWarner Losh     /* estimate decompression time */
25840c16b537SWarner Losh     U32 Q;
25850c16b537SWarner Losh     const U32 D256 = (U32)(dstSize >> 8);
25860c16b537SWarner Losh     U32 Dtime[3];
25870c16b537SWarner Losh     U32 algoNb = 0;
25880c16b537SWarner Losh     int n;
25890c16b537SWarner Losh 
25900c16b537SWarner Losh     /* validation checks */
25910c16b537SWarner Losh     if (dstSize == 0) return ERROR(dstSize_tooSmall);
25920c16b537SWarner Losh     if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
25930c16b537SWarner Losh     if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
25940c16b537SWarner Losh     if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
25950c16b537SWarner Losh 
25960c16b537SWarner Losh     /* decoder timing evaluation */
25970c16b537SWarner Losh     Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */
25980c16b537SWarner Losh     for (n=0; n<3; n++)
25990c16b537SWarner Losh         Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);
26000c16b537SWarner Losh 
26010c16b537SWarner Losh     Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */
26020c16b537SWarner Losh 
26030c16b537SWarner Losh     if (Dtime[1] < Dtime[0]) algoNb = 1;
26040c16b537SWarner Losh     if (Dtime[2] < Dtime[algoNb]) algoNb = 2;
26050c16b537SWarner Losh 
26060c16b537SWarner Losh     return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
26070c16b537SWarner Losh 
26080c16b537SWarner Losh     //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */
26090c16b537SWarner Losh     //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */
26100c16b537SWarner Losh     //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */
26110c16b537SWarner Losh }
26120c16b537SWarner Losh /*
26130c16b537SWarner Losh     zstd - standard compression library
26140c16b537SWarner Losh     Copyright (C) 2014-2015, Yann Collet.
26150c16b537SWarner Losh 
26160c16b537SWarner Losh     BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
26170c16b537SWarner Losh 
26180c16b537SWarner Losh     Redistribution and use in source and binary forms, with or without
26190c16b537SWarner Losh     modification, are permitted provided that the following conditions are
26200c16b537SWarner Losh     met:
26210c16b537SWarner Losh     * Redistributions of source code must retain the above copyright
26220c16b537SWarner Losh     notice, this list of conditions and the following disclaimer.
26230c16b537SWarner Losh     * Redistributions in binary form must reproduce the above
26240c16b537SWarner Losh     copyright notice, this list of conditions and the following disclaimer
26250c16b537SWarner Losh     in the documentation and/or other materials provided with the
26260c16b537SWarner Losh     distribution.
26270c16b537SWarner Losh     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26280c16b537SWarner Losh     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26290c16b537SWarner Losh     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26300c16b537SWarner Losh     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26310c16b537SWarner Losh     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26320c16b537SWarner Losh     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26330c16b537SWarner Losh     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26340c16b537SWarner Losh     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26350c16b537SWarner Losh     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26360c16b537SWarner Losh     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26370c16b537SWarner Losh     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26380c16b537SWarner Losh 
26390c16b537SWarner Losh     You can contact the author at :
26400c16b537SWarner Losh     - zstd source repository : https://github.com/Cyan4973/zstd
26410c16b537SWarner Losh     - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
26420c16b537SWarner Losh */
26430c16b537SWarner Losh 
26440c16b537SWarner Losh /* ***************************************************************
26450c16b537SWarner Losh *  Tuning parameters
26460c16b537SWarner Losh *****************************************************************/
26470c16b537SWarner Losh /*!
26480c16b537SWarner Losh *  MEMORY_USAGE :
26490c16b537SWarner Losh *  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
26500c16b537SWarner Losh *  Increasing memory usage improves compression ratio
26510c16b537SWarner Losh *  Reduced memory usage can improve speed, due to cache effect
26520c16b537SWarner Losh */
26530c16b537SWarner Losh #define ZSTD_MEMORY_USAGE 17
26540c16b537SWarner Losh 
26550c16b537SWarner Losh /*!
26560c16b537SWarner Losh  * HEAPMODE :
26570c16b537SWarner Losh  * Select how default compression functions will allocate memory for their hash table,
26580c16b537SWarner Losh  * in memory stack (0, fastest), or in memory heap (1, requires malloc())
26590c16b537SWarner Losh  * Note that compression context is fairly large, as a consequence heap memory is recommended.
26600c16b537SWarner Losh  */
26610c16b537SWarner Losh #ifndef ZSTD_HEAPMODE
26620c16b537SWarner Losh #  define ZSTD_HEAPMODE 1
26630c16b537SWarner Losh #endif /* ZSTD_HEAPMODE */
26640c16b537SWarner Losh 
26650c16b537SWarner Losh /*!
26660c16b537SWarner Losh *  LEGACY_SUPPORT :
26670c16b537SWarner Losh *  decompressor can decode older formats (starting from Zstd 0.1+)
26680c16b537SWarner Losh */
26690c16b537SWarner Losh #ifndef ZSTD_LEGACY_SUPPORT
26700c16b537SWarner Losh #  define ZSTD_LEGACY_SUPPORT 1
26710c16b537SWarner Losh #endif
26720c16b537SWarner Losh 
26730c16b537SWarner Losh 
26740c16b537SWarner Losh /* *******************************************************
26750c16b537SWarner Losh *  Includes
26760c16b537SWarner Losh *********************************************************/
26770c16b537SWarner Losh #include <stdlib.h>      /* calloc */
26780c16b537SWarner Losh #include <string.h>      /* memcpy, memmove */
26790c16b537SWarner Losh #include <stdio.h>       /* debug : printf */
26800c16b537SWarner Losh 
26810c16b537SWarner Losh 
26820c16b537SWarner Losh /* *******************************************************
26830c16b537SWarner Losh *  Compiler specifics
26840c16b537SWarner Losh *********************************************************/
26850c16b537SWarner Losh #ifdef __AVX2__
26860c16b537SWarner Losh #  include <immintrin.h>   /* AVX2 intrinsics */
26870c16b537SWarner Losh #endif
26880c16b537SWarner Losh 
26890c16b537SWarner Losh #ifdef _MSC_VER    /* Visual Studio */
26900c16b537SWarner Losh #  include <intrin.h>                    /* For Visual 2005 */
26910c16b537SWarner Losh #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
26920c16b537SWarner Losh #  pragma warning(disable : 4324)        /* disable: C4324: padded structure */
26930c16b537SWarner Losh #endif
26940c16b537SWarner Losh 
26950c16b537SWarner Losh 
26960c16b537SWarner Losh /* *******************************************************
26970c16b537SWarner Losh *  Constants
26980c16b537SWarner Losh *********************************************************/
26990c16b537SWarner Losh #define HASH_LOG (ZSTD_MEMORY_USAGE - 2)
27000c16b537SWarner Losh #define HASH_TABLESIZE (1 << HASH_LOG)
27010c16b537SWarner Losh #define HASH_MASK (HASH_TABLESIZE - 1)
27020c16b537SWarner Losh 
27030c16b537SWarner Losh #define KNUTH 2654435761
27040c16b537SWarner Losh 
27050c16b537SWarner Losh #define BIT7 128
27060c16b537SWarner Losh #define BIT6  64
27070c16b537SWarner Losh #define BIT5  32
27080c16b537SWarner Losh #define BIT4  16
27090c16b537SWarner Losh #define BIT1   2
27100c16b537SWarner Losh #define BIT0   1
27110c16b537SWarner Losh 
27120c16b537SWarner Losh #define KB *(1 <<10)
27130c16b537SWarner Losh #define MB *(1 <<20)
27140c16b537SWarner Losh #define GB *(1U<<30)
27150c16b537SWarner Losh 
27160c16b537SWarner Losh #define BLOCKSIZE (128 KB)                 /* define, for static allocation */
27170c16b537SWarner Losh #define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
27180c16b537SWarner Losh #define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)
27190c16b537SWarner Losh #define IS_RAW BIT0
27200c16b537SWarner Losh #define IS_RLE BIT1
27210c16b537SWarner Losh 
27220c16b537SWarner Losh #define WORKPLACESIZE (BLOCKSIZE*3)
27230c16b537SWarner Losh #define MINMATCH 4
27240c16b537SWarner Losh #define MLbits   7
27250c16b537SWarner Losh #define LLbits   6
27260c16b537SWarner Losh #define Offbits  5
27270c16b537SWarner Losh #define MaxML  ((1<<MLbits )-1)
27280c16b537SWarner Losh #define MaxLL  ((1<<LLbits )-1)
27290c16b537SWarner Losh #define MaxOff   31
27300c16b537SWarner Losh #define LitFSELog  11
27310c16b537SWarner Losh #define MLFSELog   10
27320c16b537SWarner Losh #define LLFSELog   10
27330c16b537SWarner Losh #define OffFSELog   9
27340c16b537SWarner Losh #define MAX(a,b) ((a)<(b)?(b):(a))
27350c16b537SWarner Losh #define MaxSeq MAX(MaxLL, MaxML)
27360c16b537SWarner Losh 
27370c16b537SWarner Losh #define LITERAL_NOENTROPY 63
27380c16b537SWarner Losh #define COMMAND_NOENTROPY 7   /* to remove */
27390c16b537SWarner Losh 
27402b9c00cbSConrad Meyer #define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)
27412b9c00cbSConrad Meyer 
27420c16b537SWarner Losh static const size_t ZSTD_blockHeaderSize = 3;
27430c16b537SWarner Losh static const size_t ZSTD_frameHeaderSize = 4;
27440c16b537SWarner Losh 
27450c16b537SWarner Losh 
27460c16b537SWarner Losh /* *******************************************************
27470c16b537SWarner Losh *  Memory operations
27480c16b537SWarner Losh **********************************************************/
27490c16b537SWarner Losh static void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
27500c16b537SWarner Losh 
27510c16b537SWarner Losh static void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
27520c16b537SWarner Losh 
27530c16b537SWarner Losh #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
27540c16b537SWarner Losh 
27550c16b537SWarner Losh /*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */
27560c16b537SWarner Losh static void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)
27570c16b537SWarner Losh {
27580c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
27590c16b537SWarner Losh     BYTE* op = (BYTE*)dst;
27600c16b537SWarner Losh     BYTE* const oend = op + length;
27610c16b537SWarner Losh     do COPY8(op, ip) while (op < oend);
27620c16b537SWarner Losh }
27630c16b537SWarner Losh 
27640c16b537SWarner Losh 
27650c16b537SWarner Losh /* **************************************
27660c16b537SWarner Losh *  Local structures
27670c16b537SWarner Losh ****************************************/
27680c16b537SWarner Losh typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
27690c16b537SWarner Losh 
27700c16b537SWarner Losh typedef struct
27710c16b537SWarner Losh {
27720c16b537SWarner Losh     blockType_t blockType;
27730c16b537SWarner Losh     U32 origSize;
27740c16b537SWarner Losh } blockProperties_t;
27750c16b537SWarner Losh 
27760c16b537SWarner Losh typedef struct {
27770c16b537SWarner Losh     void* buffer;
27780c16b537SWarner Losh     U32*  offsetStart;
27790c16b537SWarner Losh     U32*  offset;
27800c16b537SWarner Losh     BYTE* offCodeStart;
27810c16b537SWarner Losh     BYTE* offCode;
27820c16b537SWarner Losh     BYTE* litStart;
27830c16b537SWarner Losh     BYTE* lit;
27840c16b537SWarner Losh     BYTE* litLengthStart;
27850c16b537SWarner Losh     BYTE* litLength;
27860c16b537SWarner Losh     BYTE* matchLengthStart;
27870c16b537SWarner Losh     BYTE* matchLength;
27880c16b537SWarner Losh     BYTE* dumpsStart;
27890c16b537SWarner Losh     BYTE* dumps;
27900c16b537SWarner Losh } seqStore_t;
27910c16b537SWarner Losh 
27920c16b537SWarner Losh 
27930c16b537SWarner Losh /* *************************************
27940c16b537SWarner Losh *  Error Management
27950c16b537SWarner Losh ***************************************/
27960c16b537SWarner Losh /*! ZSTD_isError
27970c16b537SWarner Losh *   tells if a return value is an error code */
27980c16b537SWarner Losh static unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
27990c16b537SWarner Losh 
28000c16b537SWarner Losh 
28010c16b537SWarner Losh 
28020c16b537SWarner Losh /* *************************************************************
28030c16b537SWarner Losh *   Decompression section
28040c16b537SWarner Losh ***************************************************************/
28050c16b537SWarner Losh struct ZSTD_DCtx_s
28060c16b537SWarner Losh {
28070c16b537SWarner Losh     U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
28080c16b537SWarner Losh     U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
28090c16b537SWarner Losh     U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
28100c16b537SWarner Losh     void* previousDstEnd;
28110c16b537SWarner Losh     void* base;
28120c16b537SWarner Losh     size_t expected;
28130c16b537SWarner Losh     blockType_t bType;
28140c16b537SWarner Losh     U32 phase;
28150c16b537SWarner Losh     const BYTE* litPtr;
28160c16b537SWarner Losh     size_t litSize;
28170c16b537SWarner Losh     BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];
28180c16b537SWarner Losh };   /* typedef'd to ZSTD_Dctx within "zstd_static.h" */
28190c16b537SWarner Losh 
28200c16b537SWarner Losh 
28210c16b537SWarner Losh static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
28220c16b537SWarner Losh {
28230c16b537SWarner Losh     const BYTE* const in = (const BYTE* const)src;
28240c16b537SWarner Losh     BYTE headerFlags;
28250c16b537SWarner Losh     U32 cSize;
28260c16b537SWarner Losh 
28270c16b537SWarner Losh     if (srcSize < 3) return ERROR(srcSize_wrong);
28280c16b537SWarner Losh 
28290c16b537SWarner Losh     headerFlags = *in;
28300c16b537SWarner Losh     cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
28310c16b537SWarner Losh 
28320c16b537SWarner Losh     bpPtr->blockType = (blockType_t)(headerFlags >> 6);
28330c16b537SWarner Losh     bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
28340c16b537SWarner Losh 
28350c16b537SWarner Losh     if (bpPtr->blockType == bt_end) return 0;
28360c16b537SWarner Losh     if (bpPtr->blockType == bt_rle) return 1;
28370c16b537SWarner Losh     return cSize;
28380c16b537SWarner Losh }
28390c16b537SWarner Losh 
28400c16b537SWarner Losh static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
28410c16b537SWarner Losh {
28420c16b537SWarner Losh     if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
284337f1f268SConrad Meyer     if (srcSize > 0) {
28440c16b537SWarner Losh         memcpy(dst, src, srcSize);
284537f1f268SConrad Meyer     }
28460c16b537SWarner Losh     return srcSize;
28470c16b537SWarner Losh }
28480c16b537SWarner Losh 
28490c16b537SWarner Losh 
28500c16b537SWarner Losh /** ZSTD_decompressLiterals
28510c16b537SWarner Losh     @return : nb of bytes read from src, or an error code*/
28520c16b537SWarner Losh static size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,
28530c16b537SWarner Losh                                 const void* src, size_t srcSize)
28540c16b537SWarner Losh {
28550c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
28560c16b537SWarner Losh 
28570c16b537SWarner Losh     const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
28580c16b537SWarner Losh     const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
28590c16b537SWarner Losh 
28600c16b537SWarner Losh     if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);
28610c16b537SWarner Losh     if (litCSize + 5 > srcSize) return ERROR(corruption_detected);
28620c16b537SWarner Losh 
28630c16b537SWarner Losh     if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);
28640c16b537SWarner Losh 
28650c16b537SWarner Losh     *maxDstSizePtr = litSize;
28660c16b537SWarner Losh     return litCSize + 5;
28670c16b537SWarner Losh }
28680c16b537SWarner Losh 
28690c16b537SWarner Losh 
28700c16b537SWarner Losh /** ZSTD_decodeLiteralsBlock
28710c16b537SWarner Losh     @return : nb of bytes read from src (< srcSize )*/
28720c16b537SWarner Losh static size_t ZSTD_decodeLiteralsBlock(void* ctx,
28730c16b537SWarner Losh                           const void* src, size_t srcSize)
28740c16b537SWarner Losh {
28750c16b537SWarner Losh     ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;
28760c16b537SWarner Losh     const BYTE* const istart = (const BYTE* const)src;
28770c16b537SWarner Losh 
28780c16b537SWarner Losh     /* any compressed block with literals segment must be at least this size */
28790c16b537SWarner Losh     if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
28800c16b537SWarner Losh 
28810c16b537SWarner Losh     switch(*istart & 3)
28820c16b537SWarner Losh     {
28830c16b537SWarner Losh     default:
28840c16b537SWarner Losh     case 0:
28850c16b537SWarner Losh         {
28860c16b537SWarner Losh             size_t litSize = BLOCKSIZE;
28870c16b537SWarner Losh             const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);
28880c16b537SWarner Losh             dctx->litPtr = dctx->litBuffer;
28890c16b537SWarner Losh             dctx->litSize = litSize;
28900c16b537SWarner Losh             memset(dctx->litBuffer + dctx->litSize, 0, 8);
28910c16b537SWarner Losh             return readSize;   /* works if it's an error too */
28920c16b537SWarner Losh         }
28930c16b537SWarner Losh     case IS_RAW:
28940c16b537SWarner Losh         {
28950c16b537SWarner Losh             const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
28960c16b537SWarner Losh             if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */
28970c16b537SWarner Losh             {
28989cbefe25SConrad Meyer                 if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
28990c16b537SWarner Losh                 if (litSize > srcSize-3) return ERROR(corruption_detected);
29000c16b537SWarner Losh                 memcpy(dctx->litBuffer, istart, litSize);
29010c16b537SWarner Losh                 dctx->litPtr = dctx->litBuffer;
29020c16b537SWarner Losh                 dctx->litSize = litSize;
29030c16b537SWarner Losh                 memset(dctx->litBuffer + dctx->litSize, 0, 8);
29040c16b537SWarner Losh                 return litSize+3;
29050c16b537SWarner Losh             }
29060c16b537SWarner Losh             /* direct reference into compressed stream */
29070c16b537SWarner Losh             dctx->litPtr = istart+3;
29080c16b537SWarner Losh             dctx->litSize = litSize;
29090c16b537SWarner Losh             return litSize+3;
29100c16b537SWarner Losh         }
29110c16b537SWarner Losh     case IS_RLE:
29120c16b537SWarner Losh         {
29130c16b537SWarner Losh             const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
29140c16b537SWarner Losh             if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
29150c16b537SWarner Losh             memset(dctx->litBuffer, istart[3], litSize + 8);
29160c16b537SWarner Losh             dctx->litPtr = dctx->litBuffer;
29170c16b537SWarner Losh             dctx->litSize = litSize;
29180c16b537SWarner Losh             return 4;
29190c16b537SWarner Losh         }
29200c16b537SWarner Losh     }
29210c16b537SWarner Losh }
29220c16b537SWarner Losh 
29230c16b537SWarner Losh 
29240c16b537SWarner Losh static size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
29250c16b537SWarner Losh                          FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
29260c16b537SWarner Losh                          const void* src, size_t srcSize)
29270c16b537SWarner Losh {
29280c16b537SWarner Losh     const BYTE* const istart = (const BYTE* const)src;
29290c16b537SWarner Losh     const BYTE* ip = istart;
29300c16b537SWarner Losh     const BYTE* const iend = istart + srcSize;
29310c16b537SWarner Losh     U32 LLtype, Offtype, MLtype;
29320c16b537SWarner Losh     U32 LLlog, Offlog, MLlog;
29330c16b537SWarner Losh     size_t dumpsLength;
29340c16b537SWarner Losh 
29350c16b537SWarner Losh     /* check */
29360c16b537SWarner Losh     if (srcSize < 5) return ERROR(srcSize_wrong);
29370c16b537SWarner Losh 
29380c16b537SWarner Losh     /* SeqHead */
29390c16b537SWarner Losh     *nbSeq = MEM_readLE16(ip); ip+=2;
29400c16b537SWarner Losh     LLtype  = *ip >> 6;
29410c16b537SWarner Losh     Offtype = (*ip >> 4) & 3;
29420c16b537SWarner Losh     MLtype  = (*ip >> 2) & 3;
29430c16b537SWarner Losh     if (*ip & 2)
29440c16b537SWarner Losh     {
29450c16b537SWarner Losh         dumpsLength  = ip[2];
29460c16b537SWarner Losh         dumpsLength += ip[1] << 8;
29470c16b537SWarner Losh         ip += 3;
29480c16b537SWarner Losh     }
29490c16b537SWarner Losh     else
29500c16b537SWarner Losh     {
29510c16b537SWarner Losh         dumpsLength  = ip[1];
29520c16b537SWarner Losh         dumpsLength += (ip[0] & 1) << 8;
29530c16b537SWarner Losh         ip += 2;
29540c16b537SWarner Losh     }
29550c16b537SWarner Losh     *dumpsPtr = ip;
29560c16b537SWarner Losh     ip += dumpsLength;
29570c16b537SWarner Losh     *dumpsLengthPtr = dumpsLength;
29580c16b537SWarner Losh 
29590c16b537SWarner Losh     /* check */
29600c16b537SWarner Losh     if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
29610c16b537SWarner Losh 
29620c16b537SWarner Losh     /* sequences */
29630c16b537SWarner Losh     {
29640c16b537SWarner Losh         S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */
29650c16b537SWarner Losh         size_t headerSize;
29660c16b537SWarner Losh 
29670c16b537SWarner Losh         /* Build DTables */
29680c16b537SWarner Losh         switch(LLtype)
29690c16b537SWarner Losh         {
29700c16b537SWarner Losh         case bt_rle :
29710c16b537SWarner Losh             LLlog = 0;
29720c16b537SWarner Losh             FSE_buildDTable_rle(DTableLL, *ip++); break;
29730c16b537SWarner Losh         case bt_raw :
29740c16b537SWarner Losh             LLlog = LLbits;
29750c16b537SWarner Losh             FSE_buildDTable_raw(DTableLL, LLbits); break;
29760c16b537SWarner Losh         default :
29770c16b537SWarner Losh             {   U32 max = MaxLL;
29780c16b537SWarner Losh                 headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
29790c16b537SWarner Losh                 if (FSE_isError(headerSize)) return ERROR(GENERIC);
29800c16b537SWarner Losh                 if (LLlog > LLFSELog) return ERROR(corruption_detected);
29810c16b537SWarner Losh                 ip += headerSize;
29820c16b537SWarner Losh                 FSE_buildDTable(DTableLL, norm, max, LLlog);
29830c16b537SWarner Losh         }   }
29840c16b537SWarner Losh 
29850c16b537SWarner Losh         switch(Offtype)
29860c16b537SWarner Losh         {
29870c16b537SWarner Losh         case bt_rle :
29880c16b537SWarner Losh             Offlog = 0;
29890c16b537SWarner Losh             if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : "raw", hence no header, but at least xxLog bits */
29900c16b537SWarner Losh             FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
29910c16b537SWarner Losh             break;
29920c16b537SWarner Losh         case bt_raw :
29930c16b537SWarner Losh             Offlog = Offbits;
29940c16b537SWarner Losh             FSE_buildDTable_raw(DTableOffb, Offbits); break;
29950c16b537SWarner Losh         default :
29960c16b537SWarner Losh             {   U32 max = MaxOff;
29970c16b537SWarner Losh                 headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
29980c16b537SWarner Losh                 if (FSE_isError(headerSize)) return ERROR(GENERIC);
29990c16b537SWarner Losh                 if (Offlog > OffFSELog) return ERROR(corruption_detected);
30000c16b537SWarner Losh                 ip += headerSize;
30010c16b537SWarner Losh                 FSE_buildDTable(DTableOffb, norm, max, Offlog);
30020c16b537SWarner Losh         }   }
30030c16b537SWarner Losh 
30040c16b537SWarner Losh         switch(MLtype)
30050c16b537SWarner Losh         {
30060c16b537SWarner Losh         case bt_rle :
30070c16b537SWarner Losh             MLlog = 0;
30080c16b537SWarner Losh             if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
30090c16b537SWarner Losh             FSE_buildDTable_rle(DTableML, *ip++); break;
30100c16b537SWarner Losh         case bt_raw :
30110c16b537SWarner Losh             MLlog = MLbits;
30120c16b537SWarner Losh             FSE_buildDTable_raw(DTableML, MLbits); break;
30130c16b537SWarner Losh         default :
30140c16b537SWarner Losh             {   U32 max = MaxML;
30150c16b537SWarner Losh                 headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
30160c16b537SWarner Losh                 if (FSE_isError(headerSize)) return ERROR(GENERIC);
30170c16b537SWarner Losh                 if (MLlog > MLFSELog) return ERROR(corruption_detected);
30180c16b537SWarner Losh                 ip += headerSize;
30190c16b537SWarner Losh                 FSE_buildDTable(DTableML, norm, max, MLlog);
30200c16b537SWarner Losh     }   }   }
30210c16b537SWarner Losh 
30220c16b537SWarner Losh     return ip-istart;
30230c16b537SWarner Losh }
30240c16b537SWarner Losh 
30250c16b537SWarner Losh 
30260c16b537SWarner Losh typedef struct {
30270c16b537SWarner Losh     size_t litLength;
30280c16b537SWarner Losh     size_t offset;
30290c16b537SWarner Losh     size_t matchLength;
30300c16b537SWarner Losh } seq_t;
30310c16b537SWarner Losh 
30320c16b537SWarner Losh typedef struct {
30330c16b537SWarner Losh     BIT_DStream_t DStream;
30340c16b537SWarner Losh     FSE_DState_t stateLL;
30350c16b537SWarner Losh     FSE_DState_t stateOffb;
30360c16b537SWarner Losh     FSE_DState_t stateML;
30370c16b537SWarner Losh     size_t prevOffset;
30380c16b537SWarner Losh     const BYTE* dumps;
30390c16b537SWarner Losh     const BYTE* dumpsEnd;
30400c16b537SWarner Losh } seqState_t;
30410c16b537SWarner Losh 
30420c16b537SWarner Losh 
30430c16b537SWarner Losh static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
30440c16b537SWarner Losh {
30450c16b537SWarner Losh     size_t litLength;
30460c16b537SWarner Losh     size_t prevOffset;
30470c16b537SWarner Losh     size_t offset;
30480c16b537SWarner Losh     size_t matchLength;
30490c16b537SWarner Losh     const BYTE* dumps = seqState->dumps;
30500c16b537SWarner Losh     const BYTE* const de = seqState->dumpsEnd;
30510c16b537SWarner Losh 
30520c16b537SWarner Losh     /* Literal length */
30530c16b537SWarner Losh     litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));
30540c16b537SWarner Losh     prevOffset = litLength ? seq->offset : seqState->prevOffset;
30550c16b537SWarner Losh     seqState->prevOffset = seq->offset;
30560c16b537SWarner Losh     if (litLength == MaxLL)
30570c16b537SWarner Losh     {
30584d3f1eafSConrad Meyer         const U32 add = dumps<de ? *dumps++ : 0;
30590c16b537SWarner Losh         if (add < 255) litLength += add;
30604d3f1eafSConrad Meyer         else if (dumps + 3 <= de)
30610c16b537SWarner Losh         {
30624d3f1eafSConrad Meyer             litLength = MEM_readLE24(dumps);
30630c16b537SWarner Losh             dumps += 3;
30640c16b537SWarner Losh         }
30650c16b537SWarner Losh         if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */
30660c16b537SWarner Losh     }
30670c16b537SWarner Losh 
30680c16b537SWarner Losh     /* Offset */
30690c16b537SWarner Losh     {
30700c16b537SWarner Losh         static const size_t offsetPrefix[MaxOff+1] = {  /* note : size_t faster than U32 */
30710c16b537SWarner Losh                 1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,
30720c16b537SWarner Losh                 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
30730c16b537SWarner Losh                 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };
30740c16b537SWarner Losh         U32 offsetCode, nbBits;
30750c16b537SWarner Losh         offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */
30760c16b537SWarner Losh         if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
30770c16b537SWarner Losh         nbBits = offsetCode - 1;
30780c16b537SWarner Losh         if (offsetCode==0) nbBits = 0;   /* cmove */
30790c16b537SWarner Losh         offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);
30800c16b537SWarner Losh         if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
30810c16b537SWarner Losh         if (offsetCode==0) offset = prevOffset;   /* cmove */
30820c16b537SWarner Losh     }
30830c16b537SWarner Losh 
30840c16b537SWarner Losh     /* MatchLength */
30850c16b537SWarner Losh     matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
30860c16b537SWarner Losh     if (matchLength == MaxML)
30870c16b537SWarner Losh     {
30884d3f1eafSConrad Meyer         const U32 add = dumps<de ? *dumps++ : 0;
30890c16b537SWarner Losh         if (add < 255) matchLength += add;
30904d3f1eafSConrad Meyer         else if (dumps + 3 <= de)
30910c16b537SWarner Losh         {
30924d3f1eafSConrad Meyer             matchLength = MEM_readLE24(dumps);
30930c16b537SWarner Losh             dumps += 3;
30940c16b537SWarner Losh         }
30950c16b537SWarner Losh         if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */
30960c16b537SWarner Losh     }
30970c16b537SWarner Losh     matchLength += MINMATCH;
30980c16b537SWarner Losh 
30990c16b537SWarner Losh     /* save result */
31000c16b537SWarner Losh     seq->litLength = litLength;
31010c16b537SWarner Losh     seq->offset = offset;
31020c16b537SWarner Losh     seq->matchLength = matchLength;
31030c16b537SWarner Losh     seqState->dumps = dumps;
31040c16b537SWarner Losh }
31050c16b537SWarner Losh 
31060c16b537SWarner Losh 
31070c16b537SWarner Losh static size_t ZSTD_execSequence(BYTE* op,
31080c16b537SWarner Losh                                 seq_t sequence,
31090c16b537SWarner Losh                                 const BYTE** litPtr, const BYTE* const litLimit,
31100c16b537SWarner Losh                                 BYTE* const base, BYTE* const oend)
31110c16b537SWarner Losh {
31120c16b537SWarner Losh     static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */
31132b9c00cbSConrad Meyer     static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */
31140c16b537SWarner Losh     const BYTE* const ostart = op;
31150c16b537SWarner Losh     BYTE* const oLitEnd = op + sequence.litLength;
31160c16b537SWarner Losh     BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength;   /* risk : address space overflow (32-bits) */
31170c16b537SWarner Losh     BYTE* const oend_8 = oend-8;
31180c16b537SWarner Losh     const BYTE* const litEnd = *litPtr + sequence.litLength;
31190c16b537SWarner Losh 
31200c16b537SWarner Losh     /* checks */
31210c16b537SWarner Losh     if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);   /* last match must start at a minimum distance of 8 from oend */
31220c16b537SWarner Losh     if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */
31230c16b537SWarner Losh     if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */
31240c16b537SWarner Losh 
31250c16b537SWarner Losh     /* copy Literals */
31260c16b537SWarner Losh     ZSTD_wildcopy(op, *litPtr, sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
31270c16b537SWarner Losh     op = oLitEnd;
31280c16b537SWarner Losh     *litPtr = litEnd;   /* update for next sequence */
31290c16b537SWarner Losh 
31300c16b537SWarner Losh     /* copy Match */
31310c16b537SWarner Losh     {
31320c16b537SWarner Losh         const BYTE* match = op - sequence.offset;
31330c16b537SWarner Losh 
31340c16b537SWarner Losh         /* check */
31350c16b537SWarner Losh         if (sequence.offset > (size_t)op) return ERROR(corruption_detected);   /* address space overflow test (this test seems kept by clang optimizer) */
31360c16b537SWarner Losh         //if (match > op) return ERROR(corruption_detected);   /* address space overflow test (is clang optimizer removing this test ?) */
31370c16b537SWarner Losh         if (match < base) return ERROR(corruption_detected);
31380c16b537SWarner Losh 
31390c16b537SWarner Losh         /* close range match, overlap */
31400c16b537SWarner Losh         if (sequence.offset < 8)
31410c16b537SWarner Losh         {
31420c16b537SWarner Losh             const int dec64 = dec64table[sequence.offset];
31430c16b537SWarner Losh             op[0] = match[0];
31440c16b537SWarner Losh             op[1] = match[1];
31450c16b537SWarner Losh             op[2] = match[2];
31460c16b537SWarner Losh             op[3] = match[3];
31470c16b537SWarner Losh             match += dec32table[sequence.offset];
31480c16b537SWarner Losh             ZSTD_copy4(op+4, match);
31490c16b537SWarner Losh             match -= dec64;
31500c16b537SWarner Losh         }
31510c16b537SWarner Losh         else
31520c16b537SWarner Losh         {
31530c16b537SWarner Losh             ZSTD_copy8(op, match);
31540c16b537SWarner Losh         }
31550c16b537SWarner Losh         op += 8; match += 8;
31560c16b537SWarner Losh 
31570c16b537SWarner Losh         if (oMatchEnd > oend-(16-MINMATCH))
31580c16b537SWarner Losh         {
31590c16b537SWarner Losh             if (op < oend_8)
31600c16b537SWarner Losh             {
31610c16b537SWarner Losh                 ZSTD_wildcopy(op, match, oend_8 - op);
31620c16b537SWarner Losh                 match += oend_8 - op;
31630c16b537SWarner Losh                 op = oend_8;
31640c16b537SWarner Losh             }
31650c16b537SWarner Losh             while (op < oMatchEnd) *op++ = *match++;
31660c16b537SWarner Losh         }
31670c16b537SWarner Losh         else
31680c16b537SWarner Losh         {
31690c16b537SWarner Losh             ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */
31700c16b537SWarner Losh         }
31710c16b537SWarner Losh     }
31720c16b537SWarner Losh 
31730c16b537SWarner Losh     return oMatchEnd - ostart;
31740c16b537SWarner Losh }
31750c16b537SWarner Losh 
31760c16b537SWarner Losh static size_t ZSTD_decompressSequences(
31770c16b537SWarner Losh                                void* ctx,
31780c16b537SWarner Losh                                void* dst, size_t maxDstSize,
31790c16b537SWarner Losh                          const void* seqStart, size_t seqSize)
31800c16b537SWarner Losh {
31810c16b537SWarner Losh     ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;
31820c16b537SWarner Losh     const BYTE* ip = (const BYTE*)seqStart;
31830c16b537SWarner Losh     const BYTE* const iend = ip + seqSize;
31840c16b537SWarner Losh     BYTE* const ostart = (BYTE* const)dst;
31850c16b537SWarner Losh     BYTE* op = ostart;
31860c16b537SWarner Losh     BYTE* const oend = ostart + maxDstSize;
31870c16b537SWarner Losh     size_t errorCode, dumpsLength;
31880c16b537SWarner Losh     const BYTE* litPtr = dctx->litPtr;
31890c16b537SWarner Losh     const BYTE* const litEnd = litPtr + dctx->litSize;
31900c16b537SWarner Losh     int nbSeq;
31910c16b537SWarner Losh     const BYTE* dumps;
31920c16b537SWarner Losh     U32* DTableLL = dctx->LLTable;
31930c16b537SWarner Losh     U32* DTableML = dctx->MLTable;
31940c16b537SWarner Losh     U32* DTableOffb = dctx->OffTable;
31950c16b537SWarner Losh     BYTE* const base = (BYTE*) (dctx->base);
31960c16b537SWarner Losh 
31970c16b537SWarner Losh     /* Build Decoding Tables */
31980c16b537SWarner Losh     errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
31990c16b537SWarner Losh                                       DTableLL, DTableML, DTableOffb,
32000c16b537SWarner Losh                                       ip, iend-ip);
32010c16b537SWarner Losh     if (ZSTD_isError(errorCode)) return errorCode;
32020c16b537SWarner Losh     ip += errorCode;
32030c16b537SWarner Losh 
32040c16b537SWarner Losh     /* Regen sequences */
32050c16b537SWarner Losh     {
32060c16b537SWarner Losh         seq_t sequence;
32070c16b537SWarner Losh         seqState_t seqState;
32080c16b537SWarner Losh 
32090c16b537SWarner Losh         memset(&sequence, 0, sizeof(sequence));
32100c16b537SWarner Losh         seqState.dumps = dumps;
32110c16b537SWarner Losh         seqState.dumpsEnd = dumps + dumpsLength;
32120c16b537SWarner Losh         seqState.prevOffset = 1;
32130c16b537SWarner Losh         errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
32140c16b537SWarner Losh         if (ERR_isError(errorCode)) return ERROR(corruption_detected);
32150c16b537SWarner Losh         FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
32160c16b537SWarner Losh         FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
32170c16b537SWarner Losh         FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
32180c16b537SWarner Losh 
32190c16b537SWarner Losh         for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (nbSeq>0) ; )
32200c16b537SWarner Losh         {
32210c16b537SWarner Losh             size_t oneSeqSize;
32220c16b537SWarner Losh             nbSeq--;
32230c16b537SWarner Losh             ZSTD_decodeSequence(&sequence, &seqState);
32240c16b537SWarner Losh             oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);
32250c16b537SWarner Losh             if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
32260c16b537SWarner Losh             op += oneSeqSize;
32270c16b537SWarner Losh         }
32280c16b537SWarner Losh 
32290c16b537SWarner Losh         /* check if reached exact end */
32300c16b537SWarner Losh         if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */
32310c16b537SWarner Losh         if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */
32320c16b537SWarner Losh 
32330c16b537SWarner Losh         /* last literal segment */
32340c16b537SWarner Losh         {
32350c16b537SWarner Losh             size_t lastLLSize = litEnd - litPtr;
32360c16b537SWarner Losh             if (litPtr > litEnd) return ERROR(corruption_detected);
32370c16b537SWarner Losh             if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
323837f1f268SConrad Meyer             if (lastLLSize > 0) {
32390c16b537SWarner Losh                 if (op != litPtr) memmove(op, litPtr, lastLLSize);
32400c16b537SWarner Losh                 op += lastLLSize;
32410c16b537SWarner Losh             }
32420c16b537SWarner Losh         }
324337f1f268SConrad Meyer     }
32440c16b537SWarner Losh 
32450c16b537SWarner Losh     return op-ostart;
32460c16b537SWarner Losh }
32470c16b537SWarner Losh 
32480c16b537SWarner Losh 
32490c16b537SWarner Losh static size_t ZSTD_decompressBlock(
32500c16b537SWarner Losh                             void* ctx,
32510c16b537SWarner Losh                             void* dst, size_t maxDstSize,
32520c16b537SWarner Losh                       const void* src, size_t srcSize)
32530c16b537SWarner Losh {
32540c16b537SWarner Losh     /* blockType == blockCompressed */
32550c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
32560c16b537SWarner Losh 
32570c16b537SWarner Losh     /* Decode literals sub-block */
32580c16b537SWarner Losh     size_t litCSize = ZSTD_decodeLiteralsBlock(ctx, src, srcSize);
32590c16b537SWarner Losh     if (ZSTD_isError(litCSize)) return litCSize;
32600c16b537SWarner Losh     ip += litCSize;
32610c16b537SWarner Losh     srcSize -= litCSize;
32620c16b537SWarner Losh 
32630c16b537SWarner Losh     return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize);
32640c16b537SWarner Losh }
32650c16b537SWarner Losh 
32660c16b537SWarner Losh 
32670c16b537SWarner Losh static size_t ZSTD_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
32680c16b537SWarner Losh {
32690c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
32700c16b537SWarner Losh     const BYTE* iend = ip + srcSize;
32710c16b537SWarner Losh     BYTE* const ostart = (BYTE* const)dst;
32720c16b537SWarner Losh     BYTE* op = ostart;
32730c16b537SWarner Losh     BYTE* const oend = ostart + maxDstSize;
32740c16b537SWarner Losh     size_t remainingSize = srcSize;
32750c16b537SWarner Losh     U32 magicNumber;
32760c16b537SWarner Losh     blockProperties_t blockProperties;
32770c16b537SWarner Losh 
32780c16b537SWarner Losh     /* Frame Header */
32790c16b537SWarner Losh     if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
32800c16b537SWarner Losh     magicNumber = MEM_readLE32(src);
32810c16b537SWarner Losh     if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
32820c16b537SWarner Losh     ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
32830c16b537SWarner Losh 
32840c16b537SWarner Losh     /* Loop on each block */
32850c16b537SWarner Losh     while (1)
32860c16b537SWarner Losh     {
32870c16b537SWarner Losh         size_t decodedSize=0;
32880c16b537SWarner Losh         size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
32890c16b537SWarner Losh         if (ZSTD_isError(cBlockSize)) return cBlockSize;
32900c16b537SWarner Losh 
32910c16b537SWarner Losh         ip += ZSTD_blockHeaderSize;
32920c16b537SWarner Losh         remainingSize -= ZSTD_blockHeaderSize;
32930c16b537SWarner Losh         if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
32940c16b537SWarner Losh 
32950c16b537SWarner Losh         switch(blockProperties.blockType)
32960c16b537SWarner Losh         {
32970c16b537SWarner Losh         case bt_compressed:
32980c16b537SWarner Losh             decodedSize = ZSTD_decompressBlock(ctx, op, oend-op, ip, cBlockSize);
32990c16b537SWarner Losh             break;
33000c16b537SWarner Losh         case bt_raw :
33010c16b537SWarner Losh             decodedSize = ZSTD_copyUncompressedBlock(op, oend-op, ip, cBlockSize);
33020c16b537SWarner Losh             break;
33030c16b537SWarner Losh         case bt_rle :
33040c16b537SWarner Losh             return ERROR(GENERIC);   /* not yet supported */
33050c16b537SWarner Losh             break;
33060c16b537SWarner Losh         case bt_end :
33070c16b537SWarner Losh             /* end of frame */
33080c16b537SWarner Losh             if (remainingSize) return ERROR(srcSize_wrong);
33090c16b537SWarner Losh             break;
33100c16b537SWarner Losh         default:
33110c16b537SWarner Losh             return ERROR(GENERIC);   /* impossible */
33120c16b537SWarner Losh         }
33130c16b537SWarner Losh         if (cBlockSize == 0) break;   /* bt_end */
33140c16b537SWarner Losh 
33150c16b537SWarner Losh         if (ZSTD_isError(decodedSize)) return decodedSize;
33160c16b537SWarner Losh         op += decodedSize;
33170c16b537SWarner Losh         ip += cBlockSize;
33180c16b537SWarner Losh         remainingSize -= cBlockSize;
33190c16b537SWarner Losh     }
33200c16b537SWarner Losh 
33210c16b537SWarner Losh     return op-ostart;
33220c16b537SWarner Losh }
33230c16b537SWarner Losh 
33240c16b537SWarner Losh static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
33250c16b537SWarner Losh {
33260c16b537SWarner Losh     ZSTD_DCtx ctx;
33270c16b537SWarner Losh     ctx.base = dst;
33280c16b537SWarner Losh     return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
33290c16b537SWarner Losh }
33300c16b537SWarner Losh 
33312b9c00cbSConrad Meyer /* ZSTD_errorFrameSizeInfoLegacy() :
33322b9c00cbSConrad Meyer    assumes `cSize` and `dBound` are _not_ NULL */
33332b9c00cbSConrad Meyer static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
33340c16b537SWarner Losh {
33352b9c00cbSConrad Meyer     *cSize = ret;
33362b9c00cbSConrad Meyer     *dBound = ZSTD_CONTENTSIZE_ERROR;
33372b9c00cbSConrad Meyer }
33380c16b537SWarner Losh 
33392b9c00cbSConrad Meyer void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
33402b9c00cbSConrad Meyer {
33410c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
33420c16b537SWarner Losh     size_t remainingSize = srcSize;
33432b9c00cbSConrad Meyer     size_t nbBlocks = 0;
33440c16b537SWarner Losh     U32 magicNumber;
33450c16b537SWarner Losh     blockProperties_t blockProperties;
33460c16b537SWarner Losh 
33470c16b537SWarner Losh     /* Frame Header */
33482b9c00cbSConrad Meyer     if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
33492b9c00cbSConrad Meyer         ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
33502b9c00cbSConrad Meyer         return;
33512b9c00cbSConrad Meyer     }
33520c16b537SWarner Losh     magicNumber = MEM_readLE32(src);
33532b9c00cbSConrad Meyer     if (magicNumber != ZSTD_magicNumber) {
33542b9c00cbSConrad Meyer         ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
33552b9c00cbSConrad Meyer         return;
33562b9c00cbSConrad Meyer     }
33570c16b537SWarner Losh     ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
33580c16b537SWarner Losh 
33590c16b537SWarner Losh     /* Loop on each block */
33600c16b537SWarner Losh     while (1)
33610c16b537SWarner Losh     {
33620c16b537SWarner Losh         size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
33632b9c00cbSConrad Meyer         if (ZSTD_isError(cBlockSize)) {
33642b9c00cbSConrad Meyer             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);
33652b9c00cbSConrad Meyer             return;
33662b9c00cbSConrad Meyer         }
33670c16b537SWarner Losh 
33680c16b537SWarner Losh         ip += ZSTD_blockHeaderSize;
33690c16b537SWarner Losh         remainingSize -= ZSTD_blockHeaderSize;
33702b9c00cbSConrad Meyer         if (cBlockSize > remainingSize) {
33712b9c00cbSConrad Meyer             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
33722b9c00cbSConrad Meyer             return;
33732b9c00cbSConrad Meyer         }
33740c16b537SWarner Losh 
33750c16b537SWarner Losh         if (cBlockSize == 0) break;   /* bt_end */
33760c16b537SWarner Losh 
33770c16b537SWarner Losh         ip += cBlockSize;
33780c16b537SWarner Losh         remainingSize -= cBlockSize;
33792b9c00cbSConrad Meyer         nbBlocks++;
33800c16b537SWarner Losh     }
33810c16b537SWarner Losh 
33822b9c00cbSConrad Meyer     *cSize = ip - (const BYTE*)src;
33832b9c00cbSConrad Meyer     *dBound = nbBlocks * BLOCKSIZE;
33840c16b537SWarner Losh }
33850c16b537SWarner Losh 
33860c16b537SWarner Losh /*******************************
33870c16b537SWarner Losh *  Streaming Decompression API
33880c16b537SWarner Losh *******************************/
33890c16b537SWarner Losh 
33900c16b537SWarner Losh static size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)
33910c16b537SWarner Losh {
33920c16b537SWarner Losh     dctx->expected = ZSTD_frameHeaderSize;
33930c16b537SWarner Losh     dctx->phase = 0;
33940c16b537SWarner Losh     dctx->previousDstEnd = NULL;
33950c16b537SWarner Losh     dctx->base = NULL;
33960c16b537SWarner Losh     return 0;
33970c16b537SWarner Losh }
33980c16b537SWarner Losh 
33990c16b537SWarner Losh static ZSTD_DCtx* ZSTD_createDCtx(void)
34000c16b537SWarner Losh {
34010c16b537SWarner Losh     ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));
34020c16b537SWarner Losh     if (dctx==NULL) return NULL;
34030c16b537SWarner Losh     ZSTD_resetDCtx(dctx);
34040c16b537SWarner Losh     return dctx;
34050c16b537SWarner Losh }
34060c16b537SWarner Losh 
34070c16b537SWarner Losh static size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
34080c16b537SWarner Losh {
34090c16b537SWarner Losh     free(dctx);
34100c16b537SWarner Losh     return 0;
34110c16b537SWarner Losh }
34120c16b537SWarner Losh 
34130c16b537SWarner Losh static size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)
34140c16b537SWarner Losh {
34150c16b537SWarner Losh     return dctx->expected;
34160c16b537SWarner Losh }
34170c16b537SWarner Losh 
34180c16b537SWarner Losh static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
34190c16b537SWarner Losh {
34200c16b537SWarner Losh     /* Sanity check */
34210c16b537SWarner Losh     if (srcSize != ctx->expected) return ERROR(srcSize_wrong);
34220c16b537SWarner Losh     if (dst != ctx->previousDstEnd)  /* not contiguous */
34230c16b537SWarner Losh         ctx->base = dst;
34240c16b537SWarner Losh 
34250c16b537SWarner Losh     /* Decompress : frame header */
34260c16b537SWarner Losh     if (ctx->phase == 0)
34270c16b537SWarner Losh     {
34280c16b537SWarner Losh         /* Check frame magic header */
34290c16b537SWarner Losh         U32 magicNumber = MEM_readLE32(src);
34300c16b537SWarner Losh         if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
34310c16b537SWarner Losh         ctx->phase = 1;
34320c16b537SWarner Losh         ctx->expected = ZSTD_blockHeaderSize;
34330c16b537SWarner Losh         return 0;
34340c16b537SWarner Losh     }
34350c16b537SWarner Losh 
34360c16b537SWarner Losh     /* Decompress : block header */
34370c16b537SWarner Losh     if (ctx->phase == 1)
34380c16b537SWarner Losh     {
34390c16b537SWarner Losh         blockProperties_t bp;
34400c16b537SWarner Losh         size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
34410c16b537SWarner Losh         if (ZSTD_isError(blockSize)) return blockSize;
34420c16b537SWarner Losh         if (bp.blockType == bt_end)
34430c16b537SWarner Losh         {
34440c16b537SWarner Losh             ctx->expected = 0;
34450c16b537SWarner Losh             ctx->phase = 0;
34460c16b537SWarner Losh         }
34470c16b537SWarner Losh         else
34480c16b537SWarner Losh         {
34490c16b537SWarner Losh             ctx->expected = blockSize;
34500c16b537SWarner Losh             ctx->bType = bp.blockType;
34510c16b537SWarner Losh             ctx->phase = 2;
34520c16b537SWarner Losh         }
34530c16b537SWarner Losh 
34540c16b537SWarner Losh         return 0;
34550c16b537SWarner Losh     }
34560c16b537SWarner Losh 
34570c16b537SWarner Losh     /* Decompress : block content */
34580c16b537SWarner Losh     {
34590c16b537SWarner Losh         size_t rSize;
34600c16b537SWarner Losh         switch(ctx->bType)
34610c16b537SWarner Losh         {
34620c16b537SWarner Losh         case bt_compressed:
34630c16b537SWarner Losh             rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);
34640c16b537SWarner Losh             break;
34650c16b537SWarner Losh         case bt_raw :
34660c16b537SWarner Losh             rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);
34670c16b537SWarner Losh             break;
34680c16b537SWarner Losh         case bt_rle :
34690c16b537SWarner Losh             return ERROR(GENERIC);   /* not yet handled */
34700c16b537SWarner Losh             break;
34710c16b537SWarner Losh         case bt_end :   /* should never happen (filtered at phase 1) */
34720c16b537SWarner Losh             rSize = 0;
34730c16b537SWarner Losh             break;
34740c16b537SWarner Losh         default:
34750c16b537SWarner Losh             return ERROR(GENERIC);
34760c16b537SWarner Losh         }
34770c16b537SWarner Losh         ctx->phase = 1;
34780c16b537SWarner Losh         ctx->expected = ZSTD_blockHeaderSize;
34790c16b537SWarner Losh         ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);
34800c16b537SWarner Losh         return rSize;
34810c16b537SWarner Losh     }
34820c16b537SWarner Losh 
34830c16b537SWarner Losh }
34840c16b537SWarner Losh 
34850c16b537SWarner Losh 
34860c16b537SWarner Losh /* wrapper layer */
34870c16b537SWarner Losh 
34880c16b537SWarner Losh unsigned ZSTDv02_isError(size_t code)
34890c16b537SWarner Losh {
34900c16b537SWarner Losh     return ZSTD_isError(code);
34910c16b537SWarner Losh }
34920c16b537SWarner Losh 
34930c16b537SWarner Losh size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
34940c16b537SWarner Losh                      const void* src, size_t compressedSize)
34950c16b537SWarner Losh {
34960c16b537SWarner Losh     return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
34970c16b537SWarner Losh }
34980c16b537SWarner Losh 
34990c16b537SWarner Losh ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
35000c16b537SWarner Losh {
35010c16b537SWarner Losh     return (ZSTDv02_Dctx*)ZSTD_createDCtx();
35020c16b537SWarner Losh }
35030c16b537SWarner Losh 
35040c16b537SWarner Losh size_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx)
35050c16b537SWarner Losh {
35060c16b537SWarner Losh     return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
35070c16b537SWarner Losh }
35080c16b537SWarner Losh 
35090c16b537SWarner Losh size_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx)
35100c16b537SWarner Losh {
35110c16b537SWarner Losh     return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
35120c16b537SWarner Losh }
35130c16b537SWarner Losh 
35140c16b537SWarner Losh size_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx)
35150c16b537SWarner Losh {
35160c16b537SWarner Losh     return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
35170c16b537SWarner Losh }
35180c16b537SWarner Losh 
35190c16b537SWarner Losh size_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
35200c16b537SWarner Losh {
35210c16b537SWarner Losh     return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
35220c16b537SWarner Losh }
3523