xref: /freebsd/sys/contrib/zstd/lib/legacy/zstd_v01.c (revision 5ff13fbc199bdf5f0572845351c68ee5ca828e71)
10c16b537SWarner Losh /*
2*5ff13fbcSAllan Jude  * Copyright (c) Yann Collet, Facebook, Inc.
30c16b537SWarner Losh  * All rights reserved.
40c16b537SWarner Losh  *
50c16b537SWarner Losh  * This source code is licensed under both the BSD-style license (found in the
60c16b537SWarner Losh  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
70c16b537SWarner Losh  * in the COPYING file in the root directory of this source tree).
80c16b537SWarner Losh  * You may select, at your option, one of the above-listed licenses.
90c16b537SWarner Losh  */
100c16b537SWarner Losh 
110c16b537SWarner Losh 
120c16b537SWarner Losh /******************************************
130c16b537SWarner Losh *  Includes
140c16b537SWarner Losh ******************************************/
150c16b537SWarner Losh #include <stddef.h>    /* size_t, ptrdiff_t */
160c16b537SWarner Losh #include "zstd_v01.h"
1737f1f268SConrad Meyer #include "../common/error_private.h"
180c16b537SWarner Losh 
190c16b537SWarner Losh 
200c16b537SWarner Losh /******************************************
210c16b537SWarner Losh *  Static allocation
220c16b537SWarner Losh ******************************************/
230c16b537SWarner Losh /* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */
240c16b537SWarner Losh #define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))
250c16b537SWarner Losh 
260c16b537SWarner Losh /* You can statically allocate Huff0 DTable as a table of unsigned short using below macro */
270c16b537SWarner Losh #define HUF_DTABLE_SIZE_U16(maxTableLog)   (1 + (1<<maxTableLog))
280c16b537SWarner Losh #define HUF_CREATE_STATIC_DTABLE(DTable, maxTableLog) \
290c16b537SWarner Losh         unsigned short DTable[HUF_DTABLE_SIZE_U16(maxTableLog)] = { maxTableLog }
300c16b537SWarner Losh 
310c16b537SWarner Losh 
320c16b537SWarner Losh /******************************************
330c16b537SWarner Losh *  Error Management
340c16b537SWarner Losh ******************************************/
350c16b537SWarner Losh #define FSE_LIST_ERRORS(ITEM) \
360c16b537SWarner Losh         ITEM(FSE_OK_NoError) ITEM(FSE_ERROR_GENERIC) \
370c16b537SWarner Losh         ITEM(FSE_ERROR_tableLog_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooSmall) \
380c16b537SWarner Losh         ITEM(FSE_ERROR_dstSize_tooSmall) ITEM(FSE_ERROR_srcSize_wrong)\
390c16b537SWarner Losh         ITEM(FSE_ERROR_corruptionDetected) \
400c16b537SWarner Losh         ITEM(FSE_ERROR_maxCode)
410c16b537SWarner Losh 
420c16b537SWarner Losh #define FSE_GENERATE_ENUM(ENUM) ENUM,
430c16b537SWarner Losh typedef enum { FSE_LIST_ERRORS(FSE_GENERATE_ENUM) } FSE_errorCodes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */
440c16b537SWarner Losh 
450c16b537SWarner Losh 
460c16b537SWarner Losh /******************************************
470c16b537SWarner Losh *  FSE symbol compression API
480c16b537SWarner Losh ******************************************/
490c16b537SWarner Losh /*
500c16b537SWarner Losh    This API consists of small unitary functions, which highly benefit from being inlined.
510c16b537SWarner Losh    You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary.
520c16b537SWarner Losh    Visual seems to do it automatically.
530c16b537SWarner Losh    For gcc or clang, you'll need to add -flto flag at compilation and linking stages.
540c16b537SWarner Losh    If none of these solutions is applicable, include "fse.c" directly.
550c16b537SWarner Losh */
560c16b537SWarner Losh 
570c16b537SWarner Losh typedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */
580c16b537SWarner Losh typedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */
590c16b537SWarner Losh 
600c16b537SWarner Losh typedef struct
610c16b537SWarner Losh {
620c16b537SWarner Losh     size_t bitContainer;
630c16b537SWarner Losh     int    bitPos;
640c16b537SWarner Losh     char*  startPtr;
650c16b537SWarner Losh     char*  ptr;
660c16b537SWarner Losh     char*  endPtr;
670c16b537SWarner Losh } FSE_CStream_t;
680c16b537SWarner Losh 
690c16b537SWarner Losh typedef struct
700c16b537SWarner Losh {
710c16b537SWarner Losh     ptrdiff_t   value;
720c16b537SWarner Losh     const void* stateTable;
730c16b537SWarner Losh     const void* symbolTT;
740c16b537SWarner Losh     unsigned    stateLog;
750c16b537SWarner Losh } FSE_CState_t;
760c16b537SWarner Losh 
770c16b537SWarner Losh typedef struct
780c16b537SWarner Losh {
790c16b537SWarner Losh     size_t   bitContainer;
800c16b537SWarner Losh     unsigned bitsConsumed;
810c16b537SWarner Losh     const char* ptr;
820c16b537SWarner Losh     const char* start;
830c16b537SWarner Losh } FSE_DStream_t;
840c16b537SWarner Losh 
850c16b537SWarner Losh typedef struct
860c16b537SWarner Losh {
870c16b537SWarner Losh     size_t      state;
880c16b537SWarner Losh     const void* table;   /* precise table may vary, depending on U16 */
890c16b537SWarner Losh } FSE_DState_t;
900c16b537SWarner Losh 
910c16b537SWarner Losh typedef enum { FSE_DStream_unfinished = 0,
920c16b537SWarner Losh                FSE_DStream_endOfBuffer = 1,
930c16b537SWarner Losh                FSE_DStream_completed = 2,
940c16b537SWarner Losh                FSE_DStream_tooFar = 3 } FSE_DStream_status;  /* result of FSE_reloadDStream() */
950c16b537SWarner Losh                /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... ?! */
960c16b537SWarner Losh 
970c16b537SWarner Losh 
980c16b537SWarner Losh /****************************************************************
990c16b537SWarner Losh *  Tuning parameters
1000c16b537SWarner Losh ****************************************************************/
1010c16b537SWarner Losh /* MEMORY_USAGE :
1020c16b537SWarner Losh *  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
1030c16b537SWarner Losh *  Increasing memory usage improves compression ratio
1040c16b537SWarner Losh *  Reduced memory usage can improve speed, due to cache effect
1050c16b537SWarner Losh *  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
1060c16b537SWarner Losh #define FSE_MAX_MEMORY_USAGE 14
1070c16b537SWarner Losh #define FSE_DEFAULT_MEMORY_USAGE 13
1080c16b537SWarner Losh 
1090c16b537SWarner Losh /* FSE_MAX_SYMBOL_VALUE :
1100c16b537SWarner Losh *  Maximum symbol value authorized.
1110c16b537SWarner Losh *  Required for proper stack allocation */
1120c16b537SWarner Losh #define FSE_MAX_SYMBOL_VALUE 255
1130c16b537SWarner Losh 
1140c16b537SWarner Losh 
1150c16b537SWarner Losh /****************************************************************
1160c16b537SWarner Losh *  template functions type & suffix
1170c16b537SWarner Losh ****************************************************************/
1180c16b537SWarner Losh #define FSE_FUNCTION_TYPE BYTE
1190c16b537SWarner Losh #define FSE_FUNCTION_EXTENSION
1200c16b537SWarner Losh 
1210c16b537SWarner Losh 
1220c16b537SWarner Losh /****************************************************************
1230c16b537SWarner Losh *  Byte symbol type
1240c16b537SWarner Losh ****************************************************************/
1250c16b537SWarner Losh typedef struct
1260c16b537SWarner Losh {
1270c16b537SWarner Losh     unsigned short newState;
1280c16b537SWarner Losh     unsigned char  symbol;
1290c16b537SWarner Losh     unsigned char  nbBits;
1300c16b537SWarner Losh } FSE_decode_t;   /* size == U32 */
1310c16b537SWarner Losh 
1320c16b537SWarner Losh 
1330c16b537SWarner Losh 
1340c16b537SWarner Losh /****************************************************************
1350c16b537SWarner Losh *  Compiler specifics
1360c16b537SWarner Losh ****************************************************************/
1370c16b537SWarner Losh #ifdef _MSC_VER    /* Visual Studio */
1380c16b537SWarner Losh #  define FORCE_INLINE static __forceinline
1390c16b537SWarner Losh #  include <intrin.h>                    /* For Visual 2005 */
1400c16b537SWarner Losh #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
1410c16b537SWarner Losh #  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */
1420c16b537SWarner Losh #else
1430c16b537SWarner Losh #  define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
1440c16b537SWarner Losh #  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
1450c16b537SWarner Losh #    ifdef __GNUC__
1460c16b537SWarner Losh #      define FORCE_INLINE static inline __attribute__((always_inline))
1470c16b537SWarner Losh #    else
1480c16b537SWarner Losh #      define FORCE_INLINE static inline
1490c16b537SWarner Losh #    endif
1500c16b537SWarner Losh #  else
1510c16b537SWarner Losh #    define FORCE_INLINE static
1520c16b537SWarner Losh #  endif /* __STDC_VERSION__ */
1530c16b537SWarner Losh #endif
1540c16b537SWarner Losh 
1550c16b537SWarner Losh 
1560c16b537SWarner Losh /****************************************************************
1570c16b537SWarner Losh *  Includes
1580c16b537SWarner Losh ****************************************************************/
1590c16b537SWarner Losh #include <stdlib.h>     /* malloc, free, qsort */
1600c16b537SWarner Losh #include <string.h>     /* memcpy, memset */
1610c16b537SWarner Losh #include <stdio.h>      /* printf (debug) */
1620c16b537SWarner Losh 
1630c16b537SWarner Losh 
1640c16b537SWarner Losh #ifndef MEM_ACCESS_MODULE
1650c16b537SWarner Losh #define MEM_ACCESS_MODULE
1660c16b537SWarner Losh /****************************************************************
1670c16b537SWarner Losh *  Basic Types
1680c16b537SWarner Losh *****************************************************************/
1690c16b537SWarner Losh #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
1700c16b537SWarner Losh # include <stdint.h>
1710c16b537SWarner Losh typedef  uint8_t BYTE;
1720c16b537SWarner Losh typedef uint16_t U16;
1730c16b537SWarner Losh typedef  int16_t S16;
1740c16b537SWarner Losh typedef uint32_t U32;
1750c16b537SWarner Losh typedef  int32_t S32;
1760c16b537SWarner Losh typedef uint64_t U64;
1770c16b537SWarner Losh typedef  int64_t S64;
1780c16b537SWarner Losh #else
1790c16b537SWarner Losh typedef unsigned char       BYTE;
1800c16b537SWarner Losh typedef unsigned short      U16;
1810c16b537SWarner Losh typedef   signed short      S16;
1820c16b537SWarner Losh typedef unsigned int        U32;
1830c16b537SWarner Losh typedef   signed int        S32;
1840c16b537SWarner Losh typedef unsigned long long  U64;
1850c16b537SWarner Losh typedef   signed long long  S64;
1860c16b537SWarner Losh #endif
1870c16b537SWarner Losh 
1880c16b537SWarner Losh #endif   /* MEM_ACCESS_MODULE */
1890c16b537SWarner Losh 
1900c16b537SWarner Losh /****************************************************************
1910c16b537SWarner Losh *  Memory I/O
1920c16b537SWarner Losh *****************************************************************/
1930c16b537SWarner Losh /* FSE_FORCE_MEMORY_ACCESS
1940c16b537SWarner Losh  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
1950c16b537SWarner Losh  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
1960c16b537SWarner Losh  * The below switch allow to select different access method for improved performance.
1970c16b537SWarner Losh  * Method 0 (default) : use `memcpy()`. Safe and portable.
1980c16b537SWarner Losh  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
1990c16b537SWarner Losh  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
2000c16b537SWarner Losh  * Method 2 : direct access. This method is portable but violate C standard.
2010c16b537SWarner Losh  *            It can generate buggy code on targets generating assembly depending on alignment.
2020c16b537SWarner Losh  *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
2030c16b537SWarner Losh  * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
2040c16b537SWarner Losh  * Prefer these methods in priority order (0 > 1 > 2)
2050c16b537SWarner Losh  */
2060c16b537SWarner Losh #ifndef FSE_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
207*5ff13fbcSAllan Jude #  if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
2080c16b537SWarner Losh #    define FSE_FORCE_MEMORY_ACCESS 1
2090c16b537SWarner Losh #  endif
2100c16b537SWarner Losh #endif
2110c16b537SWarner Losh 
2120c16b537SWarner Losh 
FSE_32bits(void)2130c16b537SWarner Losh static unsigned FSE_32bits(void)
2140c16b537SWarner Losh {
2150c16b537SWarner Losh     return sizeof(void*)==4;
2160c16b537SWarner Losh }
2170c16b537SWarner Losh 
FSE_isLittleEndian(void)2180c16b537SWarner Losh static unsigned FSE_isLittleEndian(void)
2190c16b537SWarner Losh {
2200c16b537SWarner Losh     const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
2210c16b537SWarner Losh     return one.c[0];
2220c16b537SWarner Losh }
2230c16b537SWarner Losh 
2240c16b537SWarner Losh #if defined(FSE_FORCE_MEMORY_ACCESS) && (FSE_FORCE_MEMORY_ACCESS==2)
2250c16b537SWarner Losh 
FSE_read16(const void * memPtr)2260c16b537SWarner Losh static U16 FSE_read16(const void* memPtr) { return *(const U16*) memPtr; }
FSE_read32(const void * memPtr)2270c16b537SWarner Losh static U32 FSE_read32(const void* memPtr) { return *(const U32*) memPtr; }
FSE_read64(const void * memPtr)2280c16b537SWarner Losh static U64 FSE_read64(const void* memPtr) { return *(const U64*) memPtr; }
2290c16b537SWarner Losh 
2300c16b537SWarner Losh #elif defined(FSE_FORCE_MEMORY_ACCESS) && (FSE_FORCE_MEMORY_ACCESS==1)
2310c16b537SWarner Losh 
2320c16b537SWarner Losh /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
2330c16b537SWarner Losh /* currently only defined for gcc and icc */
2340c16b537SWarner Losh typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
2350c16b537SWarner Losh 
FSE_read16(const void * ptr)2360c16b537SWarner Losh static U16 FSE_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
FSE_read32(const void * ptr)2370c16b537SWarner Losh static U32 FSE_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
FSE_read64(const void * ptr)2380c16b537SWarner Losh static U64 FSE_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
2390c16b537SWarner Losh 
2400c16b537SWarner Losh #else
2410c16b537SWarner Losh 
FSE_read16(const void * memPtr)2420c16b537SWarner Losh static U16 FSE_read16(const void* memPtr)
2430c16b537SWarner Losh {
2440c16b537SWarner Losh     U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
2450c16b537SWarner Losh }
2460c16b537SWarner Losh 
FSE_read32(const void * memPtr)2470c16b537SWarner Losh static U32 FSE_read32(const void* memPtr)
2480c16b537SWarner Losh {
2490c16b537SWarner Losh     U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
2500c16b537SWarner Losh }
2510c16b537SWarner Losh 
FSE_read64(const void * memPtr)2520c16b537SWarner Losh static U64 FSE_read64(const void* memPtr)
2530c16b537SWarner Losh {
2540c16b537SWarner Losh     U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
2550c16b537SWarner Losh }
2560c16b537SWarner Losh 
25737f1f268SConrad Meyer #endif /* FSE_FORCE_MEMORY_ACCESS */
2580c16b537SWarner Losh 
FSE_readLE16(const void * memPtr)2590c16b537SWarner Losh static U16 FSE_readLE16(const void* memPtr)
2600c16b537SWarner Losh {
2610c16b537SWarner Losh     if (FSE_isLittleEndian())
2620c16b537SWarner Losh         return FSE_read16(memPtr);
2630c16b537SWarner Losh     else
2640c16b537SWarner Losh     {
2650c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
2660c16b537SWarner Losh         return (U16)(p[0] + (p[1]<<8));
2670c16b537SWarner Losh     }
2680c16b537SWarner Losh }
2690c16b537SWarner Losh 
FSE_readLE32(const void * memPtr)2700c16b537SWarner Losh static U32 FSE_readLE32(const void* memPtr)
2710c16b537SWarner Losh {
2720c16b537SWarner Losh     if (FSE_isLittleEndian())
2730c16b537SWarner Losh         return FSE_read32(memPtr);
2740c16b537SWarner Losh     else
2750c16b537SWarner Losh     {
2760c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
2770c16b537SWarner Losh         return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));
2780c16b537SWarner Losh     }
2790c16b537SWarner Losh }
2800c16b537SWarner Losh 
2810c16b537SWarner Losh 
FSE_readLE64(const void * memPtr)2820c16b537SWarner Losh static U64 FSE_readLE64(const void* memPtr)
2830c16b537SWarner Losh {
2840c16b537SWarner Losh     if (FSE_isLittleEndian())
2850c16b537SWarner Losh         return FSE_read64(memPtr);
2860c16b537SWarner Losh     else
2870c16b537SWarner Losh     {
2880c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
2890c16b537SWarner Losh         return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)
2900c16b537SWarner Losh                      + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));
2910c16b537SWarner Losh     }
2920c16b537SWarner Losh }
2930c16b537SWarner Losh 
FSE_readLEST(const void * memPtr)2940c16b537SWarner Losh static size_t FSE_readLEST(const void* memPtr)
2950c16b537SWarner Losh {
2960c16b537SWarner Losh     if (FSE_32bits())
2970c16b537SWarner Losh         return (size_t)FSE_readLE32(memPtr);
2980c16b537SWarner Losh     else
2990c16b537SWarner Losh         return (size_t)FSE_readLE64(memPtr);
3000c16b537SWarner Losh }
3010c16b537SWarner Losh 
3020c16b537SWarner Losh 
3030c16b537SWarner Losh 
3040c16b537SWarner Losh /****************************************************************
3050c16b537SWarner Losh *  Constants
3060c16b537SWarner Losh *****************************************************************/
3070c16b537SWarner Losh #define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)
3080c16b537SWarner Losh #define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
3090c16b537SWarner Losh #define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
3100c16b537SWarner Losh #define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
3110c16b537SWarner Losh #define FSE_MIN_TABLELOG 5
3120c16b537SWarner Losh 
3130c16b537SWarner Losh #define FSE_TABLELOG_ABSOLUTE_MAX 15
3140c16b537SWarner Losh #if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
3150c16b537SWarner Losh #error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
3160c16b537SWarner Losh #endif
3170c16b537SWarner Losh 
3180c16b537SWarner Losh 
3190c16b537SWarner Losh /****************************************************************
3200c16b537SWarner Losh *  Error Management
3210c16b537SWarner Losh ****************************************************************/
3220c16b537SWarner Losh #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
3230c16b537SWarner Losh 
3240c16b537SWarner Losh 
3250c16b537SWarner Losh /****************************************************************
3260c16b537SWarner Losh *  Complex types
3270c16b537SWarner Losh ****************************************************************/
3280c16b537SWarner Losh typedef struct
3290c16b537SWarner Losh {
3300c16b537SWarner Losh     int deltaFindState;
3310c16b537SWarner Losh     U32 deltaNbBits;
3320c16b537SWarner Losh } FSE_symbolCompressionTransform; /* total 8 bytes */
3330c16b537SWarner Losh 
3340c16b537SWarner Losh typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
3350c16b537SWarner Losh 
3360c16b537SWarner Losh /****************************************************************
3370c16b537SWarner Losh *  Internal functions
3380c16b537SWarner Losh ****************************************************************/
FSE_highbit32(U32 val)339052d3c12SConrad Meyer FORCE_INLINE unsigned FSE_highbit32 (U32 val)
3400c16b537SWarner Losh {
3410c16b537SWarner Losh #   if defined(_MSC_VER)   /* Visual */
3420c16b537SWarner Losh     unsigned long r;
343*5ff13fbcSAllan Jude     return _BitScanReverse(&r, val) ? (unsigned)r : 0;
3440c16b537SWarner Losh #   elif defined(__GNUC__) && (GCC_VERSION >= 304)   /* GCC Intrinsic */
3459cbefe25SConrad Meyer     return __builtin_clz (val) ^ 31;
3460c16b537SWarner Losh #   else   /* Software version */
3470c16b537SWarner 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 };
3480c16b537SWarner Losh     U32 v = val;
3490c16b537SWarner Losh     unsigned r;
3500c16b537SWarner Losh     v |= v >> 1;
3510c16b537SWarner Losh     v |= v >> 2;
3520c16b537SWarner Losh     v |= v >> 4;
3530c16b537SWarner Losh     v |= v >> 8;
3540c16b537SWarner Losh     v |= v >> 16;
3550c16b537SWarner Losh     r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
3560c16b537SWarner Losh     return r;
3570c16b537SWarner Losh #   endif
3580c16b537SWarner Losh }
3590c16b537SWarner Losh 
3600c16b537SWarner Losh 
3610c16b537SWarner Losh /****************************************************************
3620c16b537SWarner Losh *  Templates
3630c16b537SWarner Losh ****************************************************************/
3640c16b537SWarner Losh /*
3650c16b537SWarner Losh   designed to be included
3660c16b537SWarner Losh   for type-specific functions (template emulation in C)
3670c16b537SWarner Losh   Objective is to write these functions only once, for improved maintenance
3680c16b537SWarner Losh */
3690c16b537SWarner Losh 
3700c16b537SWarner Losh /* safety checks */
3710c16b537SWarner Losh #ifndef FSE_FUNCTION_EXTENSION
3720c16b537SWarner Losh #  error "FSE_FUNCTION_EXTENSION must be defined"
3730c16b537SWarner Losh #endif
3740c16b537SWarner Losh #ifndef FSE_FUNCTION_TYPE
3750c16b537SWarner Losh #  error "FSE_FUNCTION_TYPE must be defined"
3760c16b537SWarner Losh #endif
3770c16b537SWarner Losh 
3780c16b537SWarner Losh /* Function names */
3790c16b537SWarner Losh #define FSE_CAT(X,Y) X##Y
3800c16b537SWarner Losh #define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
3810c16b537SWarner Losh #define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
3820c16b537SWarner Losh 
3830c16b537SWarner Losh 
3840c16b537SWarner Losh 
FSE_tableStep(U32 tableSize)3850c16b537SWarner Losh static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }
3860c16b537SWarner Losh 
3870c16b537SWarner Losh #define FSE_DECODE_TYPE FSE_decode_t
3880c16b537SWarner Losh 
3890c16b537SWarner Losh 
3900c16b537SWarner Losh typedef struct {
3910c16b537SWarner Losh     U16 tableLog;
3920c16b537SWarner Losh     U16 fastMode;
3930c16b537SWarner Losh } FSE_DTableHeader;   /* sizeof U32 */
3940c16b537SWarner Losh 
FSE_buildDTable(FSE_DTable * dt,const short * normalizedCounter,unsigned maxSymbolValue,unsigned tableLog)3950c16b537SWarner Losh static size_t FSE_buildDTable
3960c16b537SWarner Losh (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
3970c16b537SWarner Losh {
3980c16b537SWarner Losh     void* ptr = dt;
3990c16b537SWarner Losh     FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
4000c16b537SWarner Losh     FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)(ptr) + 1;   /* because dt is unsigned, 32-bits aligned on 32-bits */
4010c16b537SWarner Losh     const U32 tableSize = 1 << tableLog;
4020c16b537SWarner Losh     const U32 tableMask = tableSize-1;
4030c16b537SWarner Losh     const U32 step = FSE_tableStep(tableSize);
4040c16b537SWarner Losh     U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];
4050c16b537SWarner Losh     U32 position = 0;
4060c16b537SWarner Losh     U32 highThreshold = tableSize-1;
4070c16b537SWarner Losh     const S16 largeLimit= (S16)(1 << (tableLog-1));
4080c16b537SWarner Losh     U32 noLarge = 1;
4090c16b537SWarner Losh     U32 s;
4100c16b537SWarner Losh 
4110c16b537SWarner Losh     /* Sanity Checks */
4120c16b537SWarner Losh     if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return (size_t)-FSE_ERROR_maxSymbolValue_tooLarge;
4130c16b537SWarner Losh     if (tableLog > FSE_MAX_TABLELOG) return (size_t)-FSE_ERROR_tableLog_tooLarge;
4140c16b537SWarner Losh 
4150c16b537SWarner Losh     /* Init, lay down lowprob symbols */
4160c16b537SWarner Losh     DTableH[0].tableLog = (U16)tableLog;
4170c16b537SWarner Losh     for (s=0; s<=maxSymbolValue; s++)
4180c16b537SWarner Losh     {
4190c16b537SWarner Losh         if (normalizedCounter[s]==-1)
4200c16b537SWarner Losh         {
4210c16b537SWarner Losh             tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
4220c16b537SWarner Losh             symbolNext[s] = 1;
4230c16b537SWarner Losh         }
4240c16b537SWarner Losh         else
4250c16b537SWarner Losh         {
4260c16b537SWarner Losh             if (normalizedCounter[s] >= largeLimit) noLarge=0;
4270c16b537SWarner Losh             symbolNext[s] = normalizedCounter[s];
4280c16b537SWarner Losh         }
4290c16b537SWarner Losh     }
4300c16b537SWarner Losh 
4310c16b537SWarner Losh     /* Spread symbols */
4320c16b537SWarner Losh     for (s=0; s<=maxSymbolValue; s++)
4330c16b537SWarner Losh     {
4340c16b537SWarner Losh         int i;
4350c16b537SWarner Losh         for (i=0; i<normalizedCounter[s]; i++)
4360c16b537SWarner Losh         {
4370c16b537SWarner Losh             tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
4380c16b537SWarner Losh             position = (position + step) & tableMask;
4390c16b537SWarner Losh             while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */
4400c16b537SWarner Losh         }
4410c16b537SWarner Losh     }
4420c16b537SWarner Losh 
4430c16b537SWarner Losh     if (position!=0) return (size_t)-FSE_ERROR_GENERIC;   /* position must reach all cells once, otherwise normalizedCounter is incorrect */
4440c16b537SWarner Losh 
4450c16b537SWarner Losh     /* Build Decoding table */
4460c16b537SWarner Losh     {
4470c16b537SWarner Losh         U32 i;
4480c16b537SWarner Losh         for (i=0; i<tableSize; i++)
4490c16b537SWarner Losh         {
4500c16b537SWarner Losh             FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);
4510c16b537SWarner Losh             U16 nextState = symbolNext[symbol]++;
4520c16b537SWarner Losh             tableDecode[i].nbBits = (BYTE) (tableLog - FSE_highbit32 ((U32)nextState) );
4530c16b537SWarner Losh             tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);
4540c16b537SWarner Losh         }
4550c16b537SWarner Losh     }
4560c16b537SWarner Losh 
4570c16b537SWarner Losh     DTableH->fastMode = (U16)noLarge;
4580c16b537SWarner Losh     return 0;
4590c16b537SWarner Losh }
4600c16b537SWarner Losh 
4610c16b537SWarner Losh 
4620c16b537SWarner Losh /******************************************
4630c16b537SWarner Losh *  FSE byte symbol
4640c16b537SWarner Losh ******************************************/
4650c16b537SWarner Losh #ifndef FSE_COMMONDEFS_ONLY
4660c16b537SWarner Losh 
FSE_isError(size_t code)4670c16b537SWarner Losh static unsigned FSE_isError(size_t code) { return (code > (size_t)(-FSE_ERROR_maxCode)); }
4680c16b537SWarner Losh 
FSE_abs(short a)4690c16b537SWarner Losh static short FSE_abs(short a)
4700c16b537SWarner Losh {
4710c16b537SWarner Losh     return a<0? -a : a;
4720c16b537SWarner Losh }
4730c16b537SWarner Losh 
4740c16b537SWarner Losh 
4750c16b537SWarner Losh /****************************************************************
4760c16b537SWarner Losh *  Header bitstream management
4770c16b537SWarner Losh ****************************************************************/
FSE_readNCount(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize)4780c16b537SWarner Losh static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
4790c16b537SWarner Losh                  const void* headerBuffer, size_t hbSize)
4800c16b537SWarner Losh {
4810c16b537SWarner Losh     const BYTE* const istart = (const BYTE*) headerBuffer;
4820c16b537SWarner Losh     const BYTE* const iend = istart + hbSize;
4830c16b537SWarner Losh     const BYTE* ip = istart;
4840c16b537SWarner Losh     int nbBits;
4850c16b537SWarner Losh     int remaining;
4860c16b537SWarner Losh     int threshold;
4870c16b537SWarner Losh     U32 bitStream;
4880c16b537SWarner Losh     int bitCount;
4890c16b537SWarner Losh     unsigned charnum = 0;
4900c16b537SWarner Losh     int previous0 = 0;
4910c16b537SWarner Losh 
4920c16b537SWarner Losh     if (hbSize < 4) return (size_t)-FSE_ERROR_srcSize_wrong;
4930c16b537SWarner Losh     bitStream = FSE_readLE32(ip);
4940c16b537SWarner Losh     nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */
4950c16b537SWarner Losh     if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return (size_t)-FSE_ERROR_tableLog_tooLarge;
4960c16b537SWarner Losh     bitStream >>= 4;
4970c16b537SWarner Losh     bitCount = 4;
4980c16b537SWarner Losh     *tableLogPtr = nbBits;
4990c16b537SWarner Losh     remaining = (1<<nbBits)+1;
5000c16b537SWarner Losh     threshold = 1<<nbBits;
5010c16b537SWarner Losh     nbBits++;
5020c16b537SWarner Losh 
5030c16b537SWarner Losh     while ((remaining>1) && (charnum<=*maxSVPtr))
5040c16b537SWarner Losh     {
5050c16b537SWarner Losh         if (previous0)
5060c16b537SWarner Losh         {
5070c16b537SWarner Losh             unsigned n0 = charnum;
5080c16b537SWarner Losh             while ((bitStream & 0xFFFF) == 0xFFFF)
5090c16b537SWarner Losh             {
5100c16b537SWarner Losh                 n0+=24;
5110c16b537SWarner Losh                 if (ip < iend-5)
5120c16b537SWarner Losh                 {
5130c16b537SWarner Losh                     ip+=2;
5140c16b537SWarner Losh                     bitStream = FSE_readLE32(ip) >> bitCount;
5150c16b537SWarner Losh                 }
5160c16b537SWarner Losh                 else
5170c16b537SWarner Losh                 {
5180c16b537SWarner Losh                     bitStream >>= 16;
5190c16b537SWarner Losh                     bitCount+=16;
5200c16b537SWarner Losh                 }
5210c16b537SWarner Losh             }
5220c16b537SWarner Losh             while ((bitStream & 3) == 3)
5230c16b537SWarner Losh             {
5240c16b537SWarner Losh                 n0+=3;
5250c16b537SWarner Losh                 bitStream>>=2;
5260c16b537SWarner Losh                 bitCount+=2;
5270c16b537SWarner Losh             }
5280c16b537SWarner Losh             n0 += bitStream & 3;
5290c16b537SWarner Losh             bitCount += 2;
5300c16b537SWarner Losh             if (n0 > *maxSVPtr) return (size_t)-FSE_ERROR_maxSymbolValue_tooSmall;
5310c16b537SWarner Losh             while (charnum < n0) normalizedCounter[charnum++] = 0;
5320c16b537SWarner Losh             if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))
5330c16b537SWarner Losh             {
5340c16b537SWarner Losh                 ip += bitCount>>3;
5350c16b537SWarner Losh                 bitCount &= 7;
5360c16b537SWarner Losh                 bitStream = FSE_readLE32(ip) >> bitCount;
5370c16b537SWarner Losh             }
5380c16b537SWarner Losh             else
5390c16b537SWarner Losh                 bitStream >>= 2;
5400c16b537SWarner Losh         }
5410c16b537SWarner Losh         {
5420c16b537SWarner Losh             const short max = (short)((2*threshold-1)-remaining);
5430c16b537SWarner Losh             short count;
5440c16b537SWarner Losh 
5450c16b537SWarner Losh             if ((bitStream & (threshold-1)) < (U32)max)
5460c16b537SWarner Losh             {
5470c16b537SWarner Losh                 count = (short)(bitStream & (threshold-1));
5480c16b537SWarner Losh                 bitCount   += nbBits-1;
5490c16b537SWarner Losh             }
5500c16b537SWarner Losh             else
5510c16b537SWarner Losh             {
5520c16b537SWarner Losh                 count = (short)(bitStream & (2*threshold-1));
5530c16b537SWarner Losh                 if (count >= threshold) count -= max;
5540c16b537SWarner Losh                 bitCount   += nbBits;
5550c16b537SWarner Losh             }
5560c16b537SWarner Losh 
5570c16b537SWarner Losh             count--;   /* extra accuracy */
5580c16b537SWarner Losh             remaining -= FSE_abs(count);
5590c16b537SWarner Losh             normalizedCounter[charnum++] = count;
5600c16b537SWarner Losh             previous0 = !count;
5610c16b537SWarner Losh             while (remaining < threshold)
5620c16b537SWarner Losh             {
5630c16b537SWarner Losh                 nbBits--;
5640c16b537SWarner Losh                 threshold >>= 1;
5650c16b537SWarner Losh             }
5660c16b537SWarner Losh 
5670c16b537SWarner Losh             {
5680c16b537SWarner Losh                 if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))
5690c16b537SWarner Losh                 {
5700c16b537SWarner Losh                     ip += bitCount>>3;
5710c16b537SWarner Losh                     bitCount &= 7;
5720c16b537SWarner Losh                 }
5730c16b537SWarner Losh                 else
5740c16b537SWarner Losh                 {
5750c16b537SWarner Losh                     bitCount -= (int)(8 * (iend - 4 - ip));
5760c16b537SWarner Losh                     ip = iend - 4;
5770c16b537SWarner Losh                 }
5780c16b537SWarner Losh                 bitStream = FSE_readLE32(ip) >> (bitCount & 31);
5790c16b537SWarner Losh             }
5800c16b537SWarner Losh         }
5810c16b537SWarner Losh     }
5820c16b537SWarner Losh     if (remaining != 1) return (size_t)-FSE_ERROR_GENERIC;
5830c16b537SWarner Losh     *maxSVPtr = charnum-1;
5840c16b537SWarner Losh 
5850c16b537SWarner Losh     ip += (bitCount+7)>>3;
5860c16b537SWarner Losh     if ((size_t)(ip-istart) > hbSize) return (size_t)-FSE_ERROR_srcSize_wrong;
5870c16b537SWarner Losh     return ip-istart;
5880c16b537SWarner Losh }
5890c16b537SWarner Losh 
5900c16b537SWarner Losh 
5910c16b537SWarner Losh /*********************************************************
5920c16b537SWarner Losh *  Decompression (Byte symbols)
5930c16b537SWarner Losh *********************************************************/
FSE_buildDTable_rle(FSE_DTable * dt,BYTE symbolValue)5940c16b537SWarner Losh static size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
5950c16b537SWarner Losh {
5960c16b537SWarner Losh     void* ptr = dt;
5970c16b537SWarner Losh     FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
5980c16b537SWarner Losh     FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */
5990c16b537SWarner Losh 
6000c16b537SWarner Losh     DTableH->tableLog = 0;
6010c16b537SWarner Losh     DTableH->fastMode = 0;
6020c16b537SWarner Losh 
6030c16b537SWarner Losh     cell->newState = 0;
6040c16b537SWarner Losh     cell->symbol = symbolValue;
6050c16b537SWarner Losh     cell->nbBits = 0;
6060c16b537SWarner Losh 
6070c16b537SWarner Losh     return 0;
6080c16b537SWarner Losh }
6090c16b537SWarner Losh 
6100c16b537SWarner Losh 
FSE_buildDTable_raw(FSE_DTable * dt,unsigned nbBits)6110c16b537SWarner Losh static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
6120c16b537SWarner Losh {
6130c16b537SWarner Losh     void* ptr = dt;
6140c16b537SWarner Losh     FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
6150c16b537SWarner Losh     FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */
6160c16b537SWarner Losh     const unsigned tableSize = 1 << nbBits;
6170c16b537SWarner Losh     const unsigned tableMask = tableSize - 1;
6180c16b537SWarner Losh     const unsigned maxSymbolValue = tableMask;
6190c16b537SWarner Losh     unsigned s;
6200c16b537SWarner Losh 
6210c16b537SWarner Losh     /* Sanity checks */
6220c16b537SWarner Losh     if (nbBits < 1) return (size_t)-FSE_ERROR_GENERIC;             /* min size */
6230c16b537SWarner Losh 
6240c16b537SWarner Losh     /* Build Decoding Table */
6250c16b537SWarner Losh     DTableH->tableLog = (U16)nbBits;
6260c16b537SWarner Losh     DTableH->fastMode = 1;
6270c16b537SWarner Losh     for (s=0; s<=maxSymbolValue; s++)
6280c16b537SWarner Losh     {
6290c16b537SWarner Losh         dinfo[s].newState = 0;
6300c16b537SWarner Losh         dinfo[s].symbol = (BYTE)s;
6310c16b537SWarner Losh         dinfo[s].nbBits = (BYTE)nbBits;
6320c16b537SWarner Losh     }
6330c16b537SWarner Losh 
6340c16b537SWarner Losh     return 0;
6350c16b537SWarner Losh }
6360c16b537SWarner Losh 
6370c16b537SWarner Losh 
6380c16b537SWarner Losh /* FSE_initDStream
6390c16b537SWarner Losh  * Initialize a FSE_DStream_t.
6400c16b537SWarner Losh  * srcBuffer must point at the beginning of an FSE block.
6410c16b537SWarner Losh  * The function result is the size of the FSE_block (== srcSize).
6420c16b537SWarner Losh  * If srcSize is too small, the function will return an errorCode;
6430c16b537SWarner Losh  */
FSE_initDStream(FSE_DStream_t * bitD,const void * srcBuffer,size_t srcSize)6440c16b537SWarner Losh static size_t FSE_initDStream(FSE_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
6450c16b537SWarner Losh {
6460c16b537SWarner Losh     if (srcSize < 1) return (size_t)-FSE_ERROR_srcSize_wrong;
6470c16b537SWarner Losh 
6480c16b537SWarner Losh     if (srcSize >=  sizeof(size_t))
6490c16b537SWarner Losh     {
6500c16b537SWarner Losh         U32 contain32;
6510c16b537SWarner Losh         bitD->start = (const char*)srcBuffer;
6520c16b537SWarner Losh         bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);
6530c16b537SWarner Losh         bitD->bitContainer = FSE_readLEST(bitD->ptr);
6540c16b537SWarner Losh         contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
6550c16b537SWarner Losh         if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC;   /* stop bit not present */
6560c16b537SWarner Losh         bitD->bitsConsumed = 8 - FSE_highbit32(contain32);
6570c16b537SWarner Losh     }
6580c16b537SWarner Losh     else
6590c16b537SWarner Losh     {
6600c16b537SWarner Losh         U32 contain32;
6610c16b537SWarner Losh         bitD->start = (const char*)srcBuffer;
6620c16b537SWarner Losh         bitD->ptr   = bitD->start;
6630c16b537SWarner Losh         bitD->bitContainer = *(const BYTE*)(bitD->start);
6640c16b537SWarner Losh         switch(srcSize)
6650c16b537SWarner Losh         {
6660c16b537SWarner Losh             case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);
6670f743729SConrad Meyer                     /* fallthrough */
6680c16b537SWarner Losh             case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);
6690f743729SConrad Meyer                     /* fallthrough */
6700c16b537SWarner Losh             case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);
6710f743729SConrad Meyer                     /* fallthrough */
6720c16b537SWarner Losh             case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;
6730f743729SConrad Meyer                     /* fallthrough */
6740c16b537SWarner Losh             case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;
6750f743729SConrad Meyer                     /* fallthrough */
6760c16b537SWarner Losh             case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;
6770f743729SConrad Meyer                     /* fallthrough */
6780c16b537SWarner Losh             default:;
6790c16b537SWarner Losh         }
6800c16b537SWarner Losh         contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
6810c16b537SWarner Losh         if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC;   /* stop bit not present */
6820c16b537SWarner Losh         bitD->bitsConsumed = 8 - FSE_highbit32(contain32);
6830c16b537SWarner Losh         bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;
6840c16b537SWarner Losh     }
6850c16b537SWarner Losh 
6860c16b537SWarner Losh     return srcSize;
6870c16b537SWarner Losh }
6880c16b537SWarner Losh 
6890c16b537SWarner Losh 
6900c16b537SWarner Losh /*!FSE_lookBits
6910c16b537SWarner Losh  * Provides next n bits from the bitContainer.
6920c16b537SWarner Losh  * bitContainer is not modified (bits are still present for next read/look)
6930c16b537SWarner Losh  * On 32-bits, maxNbBits==25
6940c16b537SWarner Losh  * On 64-bits, maxNbBits==57
6950c16b537SWarner Losh  * return : value extracted.
6960c16b537SWarner Losh  */
FSE_lookBits(FSE_DStream_t * bitD,U32 nbBits)6970c16b537SWarner Losh static size_t FSE_lookBits(FSE_DStream_t* bitD, U32 nbBits)
6980c16b537SWarner Losh {
6990c16b537SWarner Losh     const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
7000c16b537SWarner Losh     return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
7010c16b537SWarner Losh }
7020c16b537SWarner Losh 
FSE_lookBitsFast(FSE_DStream_t * bitD,U32 nbBits)7030c16b537SWarner Losh static size_t FSE_lookBitsFast(FSE_DStream_t* bitD, U32 nbBits)   /* only if nbBits >= 1 !! */
7040c16b537SWarner Losh {
7050c16b537SWarner Losh     const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
7060c16b537SWarner Losh     return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
7070c16b537SWarner Losh }
7080c16b537SWarner Losh 
FSE_skipBits(FSE_DStream_t * bitD,U32 nbBits)7090c16b537SWarner Losh static void FSE_skipBits(FSE_DStream_t* bitD, U32 nbBits)
7100c16b537SWarner Losh {
7110c16b537SWarner Losh     bitD->bitsConsumed += nbBits;
7120c16b537SWarner Losh }
7130c16b537SWarner Losh 
7140c16b537SWarner Losh 
7150c16b537SWarner Losh /*!FSE_readBits
7160c16b537SWarner Losh  * Read next n bits from the bitContainer.
7170c16b537SWarner Losh  * On 32-bits, don't read more than maxNbBits==25
7180c16b537SWarner Losh  * On 64-bits, don't read more than maxNbBits==57
7190c16b537SWarner Losh  * Use the fast variant *only* if n >= 1.
7200c16b537SWarner Losh  * return : value extracted.
7210c16b537SWarner Losh  */
FSE_readBits(FSE_DStream_t * bitD,U32 nbBits)7220c16b537SWarner Losh static size_t FSE_readBits(FSE_DStream_t* bitD, U32 nbBits)
7230c16b537SWarner Losh {
7240c16b537SWarner Losh     size_t value = FSE_lookBits(bitD, nbBits);
7250c16b537SWarner Losh     FSE_skipBits(bitD, nbBits);
7260c16b537SWarner Losh     return value;
7270c16b537SWarner Losh }
7280c16b537SWarner Losh 
FSE_readBitsFast(FSE_DStream_t * bitD,U32 nbBits)7290c16b537SWarner Losh static size_t FSE_readBitsFast(FSE_DStream_t* bitD, U32 nbBits)   /* only if nbBits >= 1 !! */
7300c16b537SWarner Losh {
7310c16b537SWarner Losh     size_t value = FSE_lookBitsFast(bitD, nbBits);
7320c16b537SWarner Losh     FSE_skipBits(bitD, nbBits);
7330c16b537SWarner Losh     return value;
7340c16b537SWarner Losh }
7350c16b537SWarner Losh 
FSE_reloadDStream(FSE_DStream_t * bitD)7360c16b537SWarner Losh static unsigned FSE_reloadDStream(FSE_DStream_t* bitD)
7370c16b537SWarner Losh {
7380c16b537SWarner Losh     if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */
7390c16b537SWarner Losh         return FSE_DStream_tooFar;
7400c16b537SWarner Losh 
7410c16b537SWarner Losh     if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
7420c16b537SWarner Losh     {
7430c16b537SWarner Losh         bitD->ptr -= bitD->bitsConsumed >> 3;
7440c16b537SWarner Losh         bitD->bitsConsumed &= 7;
7450c16b537SWarner Losh         bitD->bitContainer = FSE_readLEST(bitD->ptr);
7460c16b537SWarner Losh         return FSE_DStream_unfinished;
7470c16b537SWarner Losh     }
7480c16b537SWarner Losh     if (bitD->ptr == bitD->start)
7490c16b537SWarner Losh     {
7500c16b537SWarner Losh         if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return FSE_DStream_endOfBuffer;
7510c16b537SWarner Losh         return FSE_DStream_completed;
7520c16b537SWarner Losh     }
7530c16b537SWarner Losh     {
7540c16b537SWarner Losh         U32 nbBytes = bitD->bitsConsumed >> 3;
7550c16b537SWarner Losh         U32 result = FSE_DStream_unfinished;
7560c16b537SWarner Losh         if (bitD->ptr - nbBytes < bitD->start)
7570c16b537SWarner Losh         {
7580c16b537SWarner Losh             nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */
7590c16b537SWarner Losh             result = FSE_DStream_endOfBuffer;
7600c16b537SWarner Losh         }
7610c16b537SWarner Losh         bitD->ptr -= nbBytes;
7620c16b537SWarner Losh         bitD->bitsConsumed -= nbBytes*8;
7630c16b537SWarner Losh         bitD->bitContainer = FSE_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */
7640c16b537SWarner Losh         return result;
7650c16b537SWarner Losh     }
7660c16b537SWarner Losh }
7670c16b537SWarner Losh 
7680c16b537SWarner Losh 
FSE_initDState(FSE_DState_t * DStatePtr,FSE_DStream_t * bitD,const FSE_DTable * dt)7690c16b537SWarner Losh static void FSE_initDState(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD, const FSE_DTable* dt)
7700c16b537SWarner Losh {
7710c16b537SWarner Losh     const void* ptr = dt;
7720c16b537SWarner Losh     const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
7730c16b537SWarner Losh     DStatePtr->state = FSE_readBits(bitD, DTableH->tableLog);
7740c16b537SWarner Losh     FSE_reloadDStream(bitD);
7750c16b537SWarner Losh     DStatePtr->table = dt + 1;
7760c16b537SWarner Losh }
7770c16b537SWarner Losh 
FSE_decodeSymbol(FSE_DState_t * DStatePtr,FSE_DStream_t * bitD)7780c16b537SWarner Losh static BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD)
7790c16b537SWarner Losh {
7800c16b537SWarner Losh     const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
7810c16b537SWarner Losh     const U32  nbBits = DInfo.nbBits;
7820c16b537SWarner Losh     BYTE symbol = DInfo.symbol;
7830c16b537SWarner Losh     size_t lowBits = FSE_readBits(bitD, nbBits);
7840c16b537SWarner Losh 
7850c16b537SWarner Losh     DStatePtr->state = DInfo.newState + lowBits;
7860c16b537SWarner Losh     return symbol;
7870c16b537SWarner Losh }
7880c16b537SWarner Losh 
FSE_decodeSymbolFast(FSE_DState_t * DStatePtr,FSE_DStream_t * bitD)7890c16b537SWarner Losh static BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD)
7900c16b537SWarner Losh {
7910c16b537SWarner Losh     const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
7920c16b537SWarner Losh     const U32 nbBits = DInfo.nbBits;
7930c16b537SWarner Losh     BYTE symbol = DInfo.symbol;
7940c16b537SWarner Losh     size_t lowBits = FSE_readBitsFast(bitD, nbBits);
7950c16b537SWarner Losh 
7960c16b537SWarner Losh     DStatePtr->state = DInfo.newState + lowBits;
7970c16b537SWarner Losh     return symbol;
7980c16b537SWarner Losh }
7990c16b537SWarner Losh 
8000c16b537SWarner Losh /* FSE_endOfDStream
8010c16b537SWarner Losh    Tells if bitD has reached end of bitStream or not */
8020c16b537SWarner Losh 
FSE_endOfDStream(const FSE_DStream_t * bitD)8030c16b537SWarner Losh static unsigned FSE_endOfDStream(const FSE_DStream_t* bitD)
8040c16b537SWarner Losh {
8050c16b537SWarner Losh     return ((bitD->ptr == bitD->start) && (bitD->bitsConsumed == sizeof(bitD->bitContainer)*8));
8060c16b537SWarner Losh }
8070c16b537SWarner Losh 
FSE_endOfDState(const FSE_DState_t * DStatePtr)8080c16b537SWarner Losh static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
8090c16b537SWarner Losh {
8100c16b537SWarner Losh     return DStatePtr->state == 0;
8110c16b537SWarner Losh }
8120c16b537SWarner Losh 
8130c16b537SWarner Losh 
FSE_decompress_usingDTable_generic(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const FSE_DTable * dt,const unsigned fast)8140c16b537SWarner Losh FORCE_INLINE size_t FSE_decompress_usingDTable_generic(
8150c16b537SWarner Losh           void* dst, size_t maxDstSize,
8160c16b537SWarner Losh     const void* cSrc, size_t cSrcSize,
8170c16b537SWarner Losh     const FSE_DTable* dt, const unsigned fast)
8180c16b537SWarner Losh {
8190c16b537SWarner Losh     BYTE* const ostart = (BYTE*) dst;
8200c16b537SWarner Losh     BYTE* op = ostart;
8210c16b537SWarner Losh     BYTE* const omax = op + maxDstSize;
8220c16b537SWarner Losh     BYTE* const olimit = omax-3;
8230c16b537SWarner Losh 
8240c16b537SWarner Losh     FSE_DStream_t bitD;
8250c16b537SWarner Losh     FSE_DState_t state1;
8260c16b537SWarner Losh     FSE_DState_t state2;
8270c16b537SWarner Losh     size_t errorCode;
8280c16b537SWarner Losh 
8290c16b537SWarner Losh     /* Init */
8300c16b537SWarner Losh     errorCode = FSE_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */
8310c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
8320c16b537SWarner Losh 
8330c16b537SWarner Losh     FSE_initDState(&state1, &bitD, dt);
8340c16b537SWarner Losh     FSE_initDState(&state2, &bitD, dt);
8350c16b537SWarner Losh 
8360c16b537SWarner Losh #define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
8370c16b537SWarner Losh 
8380c16b537SWarner Losh     /* 4 symbols per loop */
8390c16b537SWarner Losh     for ( ; (FSE_reloadDStream(&bitD)==FSE_DStream_unfinished) && (op<olimit) ; op+=4)
8400c16b537SWarner Losh     {
8410c16b537SWarner Losh         op[0] = FSE_GETSYMBOL(&state1);
8420c16b537SWarner Losh 
8430c16b537SWarner Losh         if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
8440c16b537SWarner Losh             FSE_reloadDStream(&bitD);
8450c16b537SWarner Losh 
8460c16b537SWarner Losh         op[1] = FSE_GETSYMBOL(&state2);
8470c16b537SWarner Losh 
8480c16b537SWarner Losh         if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
8490c16b537SWarner Losh             { if (FSE_reloadDStream(&bitD) > FSE_DStream_unfinished) { op+=2; break; } }
8500c16b537SWarner Losh 
8510c16b537SWarner Losh         op[2] = FSE_GETSYMBOL(&state1);
8520c16b537SWarner Losh 
8530c16b537SWarner Losh         if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
8540c16b537SWarner Losh             FSE_reloadDStream(&bitD);
8550c16b537SWarner Losh 
8560c16b537SWarner Losh         op[3] = FSE_GETSYMBOL(&state2);
8570c16b537SWarner Losh     }
8580c16b537SWarner Losh 
8590c16b537SWarner Losh     /* tail */
8600c16b537SWarner Losh     /* note : FSE_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly FSE_DStream_completed */
8610c16b537SWarner Losh     while (1)
8620c16b537SWarner Losh     {
8630c16b537SWarner Losh         if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )
8640c16b537SWarner Losh             break;
8650c16b537SWarner Losh 
8660c16b537SWarner Losh         *op++ = FSE_GETSYMBOL(&state1);
8670c16b537SWarner Losh 
8680c16b537SWarner Losh         if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )
8690c16b537SWarner Losh             break;
8700c16b537SWarner Losh 
8710c16b537SWarner Losh         *op++ = FSE_GETSYMBOL(&state2);
8720c16b537SWarner Losh     }
8730c16b537SWarner Losh 
8740c16b537SWarner Losh     /* end ? */
8750c16b537SWarner Losh     if (FSE_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))
8760c16b537SWarner Losh         return op-ostart;
8770c16b537SWarner Losh 
8780c16b537SWarner Losh     if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */
8790c16b537SWarner Losh 
8800c16b537SWarner Losh     return (size_t)-FSE_ERROR_corruptionDetected;
8810c16b537SWarner Losh }
8820c16b537SWarner Losh 
8830c16b537SWarner Losh 
FSE_decompress_usingDTable(void * dst,size_t originalSize,const void * cSrc,size_t cSrcSize,const FSE_DTable * dt)8840c16b537SWarner Losh static size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
8850c16b537SWarner Losh                             const void* cSrc, size_t cSrcSize,
8860c16b537SWarner Losh                             const FSE_DTable* dt)
8870c16b537SWarner Losh {
8880c16b537SWarner Losh     FSE_DTableHeader DTableH;
8890c16b537SWarner Losh     memcpy(&DTableH, dt, sizeof(DTableH));   /* memcpy() into local variable, to avoid strict aliasing warning */
8900c16b537SWarner Losh 
8910c16b537SWarner Losh     /* select fast mode (static) */
8920c16b537SWarner Losh     if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
8930c16b537SWarner Losh     return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
8940c16b537SWarner Losh }
8950c16b537SWarner Losh 
8960c16b537SWarner Losh 
FSE_decompress(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize)8970c16b537SWarner Losh static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
8980c16b537SWarner Losh {
8990c16b537SWarner Losh     const BYTE* const istart = (const BYTE*)cSrc;
9000c16b537SWarner Losh     const BYTE* ip = istart;
9010c16b537SWarner Losh     short counting[FSE_MAX_SYMBOL_VALUE+1];
9020c16b537SWarner Losh     DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */
9030c16b537SWarner Losh     unsigned tableLog;
9040c16b537SWarner Losh     unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
9050c16b537SWarner Losh     size_t errorCode;
9060c16b537SWarner Losh 
9070c16b537SWarner Losh     if (cSrcSize<2) return (size_t)-FSE_ERROR_srcSize_wrong;   /* too small input size */
9080c16b537SWarner Losh 
9090c16b537SWarner Losh     /* normal FSE decoding mode */
9100c16b537SWarner Losh     errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
9110c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
9120c16b537SWarner Losh     if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;   /* too small input size */
9130c16b537SWarner Losh     ip += errorCode;
9140c16b537SWarner Losh     cSrcSize -= errorCode;
9150c16b537SWarner Losh 
9160c16b537SWarner Losh     errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);
9170c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
9180c16b537SWarner Losh 
9190c16b537SWarner Losh     /* always return, even if it is an error code */
9200c16b537SWarner Losh     return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);
9210c16b537SWarner Losh }
9220c16b537SWarner Losh 
9230c16b537SWarner Losh 
9240c16b537SWarner Losh 
9250c16b537SWarner Losh /* *******************************************************
9260c16b537SWarner Losh *  Huff0 : Huffman block compression
9270c16b537SWarner Losh *********************************************************/
9280c16b537SWarner Losh #define HUF_MAX_SYMBOL_VALUE 255
9290c16b537SWarner Losh #define HUF_DEFAULT_TABLELOG  12       /* used by default, when not specified */
9300c16b537SWarner Losh #define HUF_MAX_TABLELOG  12           /* max possible tableLog; for allocation purpose; can be modified */
9310c16b537SWarner Losh #define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
9320c16b537SWarner Losh #if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)
9330c16b537SWarner Losh #  error "HUF_MAX_TABLELOG is too large !"
9340c16b537SWarner Losh #endif
9350c16b537SWarner Losh 
9360c16b537SWarner Losh typedef struct HUF_CElt_s {
9370c16b537SWarner Losh   U16  val;
9380c16b537SWarner Losh   BYTE nbBits;
9390c16b537SWarner Losh } HUF_CElt ;
9400c16b537SWarner Losh 
9410c16b537SWarner Losh typedef struct nodeElt_s {
9420c16b537SWarner Losh     U32 count;
9430c16b537SWarner Losh     U16 parent;
9440c16b537SWarner Losh     BYTE byte;
9450c16b537SWarner Losh     BYTE nbBits;
9460c16b537SWarner Losh } nodeElt;
9470c16b537SWarner Losh 
9480c16b537SWarner Losh 
9490c16b537SWarner Losh /* *******************************************************
9500c16b537SWarner Losh *  Huff0 : Huffman block decompression
9510c16b537SWarner Losh *********************************************************/
9520c16b537SWarner Losh typedef struct {
9530c16b537SWarner Losh     BYTE byte;
9540c16b537SWarner Losh     BYTE nbBits;
9550c16b537SWarner Losh } HUF_DElt;
9560c16b537SWarner Losh 
HUF_readDTable(U16 * DTable,const void * src,size_t srcSize)9570c16b537SWarner Losh static size_t HUF_readDTable (U16* DTable, const void* src, size_t srcSize)
9580c16b537SWarner Losh {
9590c16b537SWarner Losh     BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];
9600c16b537SWarner Losh     U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];  /* large enough for values from 0 to 16 */
9610c16b537SWarner Losh     U32 weightTotal;
9620c16b537SWarner Losh     U32 maxBits;
9630c16b537SWarner Losh     const BYTE* ip = (const BYTE*) src;
9640c16b537SWarner Losh     size_t iSize;
9650c16b537SWarner Losh     size_t oSize;
9660c16b537SWarner Losh     U32 n;
9670c16b537SWarner Losh     U32 nextRankStart;
9680c16b537SWarner Losh     void* ptr = DTable+1;
9690c16b537SWarner Losh     HUF_DElt* const dt = (HUF_DElt*)ptr;
9700c16b537SWarner Losh 
9710c16b537SWarner Losh     if (!srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
9720c16b537SWarner Losh     iSize = ip[0];
9730c16b537SWarner Losh 
9740c16b537SWarner Losh     FSE_STATIC_ASSERT(sizeof(HUF_DElt) == sizeof(U16));   /* if compilation fails here, assertion is false */
9750c16b537SWarner Losh     //memset(huffWeight, 0, sizeof(huffWeight));   /* should not be necessary, but some analyzer complain ... */
9760c16b537SWarner Losh     if (iSize >= 128)  /* special header */
9770c16b537SWarner Losh     {
9780c16b537SWarner Losh         if (iSize >= (242))   /* RLE */
9790c16b537SWarner Losh         {
9800c16b537SWarner Losh             static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
9810c16b537SWarner Losh             oSize = l[iSize-242];
9820c16b537SWarner Losh             memset(huffWeight, 1, sizeof(huffWeight));
9830c16b537SWarner Losh             iSize = 0;
9840c16b537SWarner Losh         }
9850c16b537SWarner Losh         else   /* Incompressible */
9860c16b537SWarner Losh         {
9870c16b537SWarner Losh             oSize = iSize - 127;
9880c16b537SWarner Losh             iSize = ((oSize+1)/2);
9890c16b537SWarner Losh             if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
9900c16b537SWarner Losh             ip += 1;
9910c16b537SWarner Losh             for (n=0; n<oSize; n+=2)
9920c16b537SWarner Losh             {
9930c16b537SWarner Losh                 huffWeight[n]   = ip[n/2] >> 4;
9940c16b537SWarner Losh                 huffWeight[n+1] = ip[n/2] & 15;
9950c16b537SWarner Losh             }
9960c16b537SWarner Losh         }
9970c16b537SWarner Losh     }
9980c16b537SWarner Losh     else  /* header compressed with FSE (normal case) */
9990c16b537SWarner Losh     {
10000c16b537SWarner Losh         if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
10010c16b537SWarner Losh         oSize = FSE_decompress(huffWeight, HUF_MAX_SYMBOL_VALUE, ip+1, iSize);   /* max 255 values decoded, last one is implied */
10020c16b537SWarner Losh         if (FSE_isError(oSize)) return oSize;
10030c16b537SWarner Losh     }
10040c16b537SWarner Losh 
10050c16b537SWarner Losh     /* collect weight stats */
10060c16b537SWarner Losh     memset(rankVal, 0, sizeof(rankVal));
10070c16b537SWarner Losh     weightTotal = 0;
10080c16b537SWarner Losh     for (n=0; n<oSize; n++)
10090c16b537SWarner Losh     {
10100c16b537SWarner Losh         if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return (size_t)-FSE_ERROR_corruptionDetected;
10110c16b537SWarner Losh         rankVal[huffWeight[n]]++;
10120c16b537SWarner Losh         weightTotal += (1 << huffWeight[n]) >> 1;
10130c16b537SWarner Losh     }
10140c16b537SWarner Losh     if (weightTotal == 0) return (size_t)-FSE_ERROR_corruptionDetected;
10150c16b537SWarner Losh 
10160c16b537SWarner Losh     /* get last non-null symbol weight (implied, total must be 2^n) */
10170c16b537SWarner Losh     maxBits = FSE_highbit32(weightTotal) + 1;
10180c16b537SWarner Losh     if (maxBits > DTable[0]) return (size_t)-FSE_ERROR_tableLog_tooLarge;   /* DTable is too small */
10190c16b537SWarner Losh     DTable[0] = (U16)maxBits;
10200c16b537SWarner Losh     {
10210c16b537SWarner Losh         U32 total = 1 << maxBits;
10220c16b537SWarner Losh         U32 rest = total - weightTotal;
10230c16b537SWarner Losh         U32 verif = 1 << FSE_highbit32(rest);
10240c16b537SWarner Losh         U32 lastWeight = FSE_highbit32(rest) + 1;
10250c16b537SWarner Losh         if (verif != rest) return (size_t)-FSE_ERROR_corruptionDetected;    /* last value must be a clean power of 2 */
10260c16b537SWarner Losh         huffWeight[oSize] = (BYTE)lastWeight;
10270c16b537SWarner Losh         rankVal[lastWeight]++;
10280c16b537SWarner Losh     }
10290c16b537SWarner Losh 
10300c16b537SWarner Losh     /* check tree construction validity */
10310c16b537SWarner Losh     if ((rankVal[1] < 2) || (rankVal[1] & 1)) return (size_t)-FSE_ERROR_corruptionDetected;   /* by construction : at least 2 elts of rank 1, must be even */
10320c16b537SWarner Losh 
10330c16b537SWarner Losh     /* Prepare ranks */
10340c16b537SWarner Losh     nextRankStart = 0;
10350c16b537SWarner Losh     for (n=1; n<=maxBits; n++)
10360c16b537SWarner Losh     {
10370c16b537SWarner Losh         U32 current = nextRankStart;
10380c16b537SWarner Losh         nextRankStart += (rankVal[n] << (n-1));
10390c16b537SWarner Losh         rankVal[n] = current;
10400c16b537SWarner Losh     }
10410c16b537SWarner Losh 
10420c16b537SWarner Losh     /* fill DTable */
10430c16b537SWarner Losh     for (n=0; n<=oSize; n++)
10440c16b537SWarner Losh     {
10450c16b537SWarner Losh         const U32 w = huffWeight[n];
10460c16b537SWarner Losh         const U32 length = (1 << w) >> 1;
10470c16b537SWarner Losh         U32 i;
10480c16b537SWarner Losh         HUF_DElt D;
10490c16b537SWarner Losh         D.byte = (BYTE)n; D.nbBits = (BYTE)(maxBits + 1 - w);
10500c16b537SWarner Losh         for (i = rankVal[w]; i < rankVal[w] + length; i++)
10510c16b537SWarner Losh             dt[i] = D;
10520c16b537SWarner Losh         rankVal[w] += length;
10530c16b537SWarner Losh     }
10540c16b537SWarner Losh 
10550c16b537SWarner Losh     return iSize+1;
10560c16b537SWarner Losh }
10570c16b537SWarner Losh 
10580c16b537SWarner Losh 
HUF_decodeSymbol(FSE_DStream_t * Dstream,const HUF_DElt * dt,const U32 dtLog)10590c16b537SWarner Losh static BYTE HUF_decodeSymbol(FSE_DStream_t* Dstream, const HUF_DElt* dt, const U32 dtLog)
10600c16b537SWarner Losh {
10610c16b537SWarner Losh         const size_t val = FSE_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
10620c16b537SWarner Losh         const BYTE c = dt[val].byte;
10630c16b537SWarner Losh         FSE_skipBits(Dstream, dt[val].nbBits);
10640c16b537SWarner Losh         return c;
10650c16b537SWarner Losh }
10660c16b537SWarner Losh 
HUF_decompress_usingDTable(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize,const U16 * DTable)10670c16b537SWarner Losh static size_t HUF_decompress_usingDTable(   /* -3% slower when non static */
10680c16b537SWarner Losh           void* dst, size_t maxDstSize,
10690c16b537SWarner Losh     const void* cSrc, size_t cSrcSize,
10700c16b537SWarner Losh     const U16* DTable)
10710c16b537SWarner Losh {
10724d3f1eafSConrad Meyer     if (cSrcSize < 6) return (size_t)-FSE_ERROR_srcSize_wrong;
10734d3f1eafSConrad Meyer     {
10740c16b537SWarner Losh         BYTE* const ostart = (BYTE*) dst;
10750c16b537SWarner Losh         BYTE* op = ostart;
10760c16b537SWarner Losh         BYTE* const omax = op + maxDstSize;
107737f1f268SConrad Meyer         BYTE* const olimit = maxDstSize < 15 ? op : omax-15;
10780c16b537SWarner Losh 
10790c16b537SWarner Losh         const void* ptr = DTable;
10800c16b537SWarner Losh         const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1;
10810c16b537SWarner Losh         const U32 dtLog = DTable[0];
10820c16b537SWarner Losh         size_t errorCode;
10830c16b537SWarner Losh         U32 reloadStatus;
10840c16b537SWarner Losh 
10850c16b537SWarner Losh         /* Init */
10860c16b537SWarner Losh 
10870c16b537SWarner Losh         const U16* jumpTable = (const U16*)cSrc;
10880c16b537SWarner Losh         const size_t length1 = FSE_readLE16(jumpTable);
10890c16b537SWarner Losh         const size_t length2 = FSE_readLE16(jumpTable+1);
10900c16b537SWarner Losh         const size_t length3 = FSE_readLE16(jumpTable+2);
109137f1f268SConrad Meyer         const size_t length4 = cSrcSize - 6 - length1 - length2 - length3;   /* check coherency !! */
10920c16b537SWarner Losh         const char* const start1 = (const char*)(cSrc) + 6;
10930c16b537SWarner Losh         const char* const start2 = start1 + length1;
10940c16b537SWarner Losh         const char* const start3 = start2 + length2;
10950c16b537SWarner Losh         const char* const start4 = start3 + length3;
10960c16b537SWarner Losh         FSE_DStream_t bitD1, bitD2, bitD3, bitD4;
10970c16b537SWarner Losh 
10980c16b537SWarner Losh         if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
10990c16b537SWarner Losh 
11000c16b537SWarner Losh         errorCode = FSE_initDStream(&bitD1, start1, length1);
11010c16b537SWarner Losh         if (FSE_isError(errorCode)) return errorCode;
11020c16b537SWarner Losh         errorCode = FSE_initDStream(&bitD2, start2, length2);
11030c16b537SWarner Losh         if (FSE_isError(errorCode)) return errorCode;
11040c16b537SWarner Losh         errorCode = FSE_initDStream(&bitD3, start3, length3);
11050c16b537SWarner Losh         if (FSE_isError(errorCode)) return errorCode;
11060c16b537SWarner Losh         errorCode = FSE_initDStream(&bitD4, start4, length4);
11070c16b537SWarner Losh         if (FSE_isError(errorCode)) return errorCode;
11080c16b537SWarner Losh 
11090c16b537SWarner Losh         reloadStatus=FSE_reloadDStream(&bitD2);
11100c16b537SWarner Losh 
11110c16b537SWarner Losh         /* 16 symbols per loop */
11120c16b537SWarner Losh         for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit);  /* D2-3-4 are supposed to be synchronized and finish together */
11130c16b537SWarner Losh             op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1))
11140c16b537SWarner Losh         {
11150c16b537SWarner Losh     #define HUF_DECODE_SYMBOL_0(n, Dstream) \
11160c16b537SWarner Losh             op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog);
11170c16b537SWarner Losh 
11180c16b537SWarner Losh     #define HUF_DECODE_SYMBOL_1(n, Dstream) \
11190c16b537SWarner Losh             op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \
11200c16b537SWarner Losh             if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream)
11210c16b537SWarner Losh 
11220c16b537SWarner Losh     #define HUF_DECODE_SYMBOL_2(n, Dstream) \
11230c16b537SWarner Losh             op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \
11240c16b537SWarner Losh             if (FSE_32bits()) FSE_reloadDStream(&Dstream)
11250c16b537SWarner Losh 
11260c16b537SWarner Losh             HUF_DECODE_SYMBOL_1( 0, bitD1);
11270c16b537SWarner Losh             HUF_DECODE_SYMBOL_1( 1, bitD2);
11280c16b537SWarner Losh             HUF_DECODE_SYMBOL_1( 2, bitD3);
11290c16b537SWarner Losh             HUF_DECODE_SYMBOL_1( 3, bitD4);
11300c16b537SWarner Losh             HUF_DECODE_SYMBOL_2( 4, bitD1);
11310c16b537SWarner Losh             HUF_DECODE_SYMBOL_2( 5, bitD2);
11320c16b537SWarner Losh             HUF_DECODE_SYMBOL_2( 6, bitD3);
11330c16b537SWarner Losh             HUF_DECODE_SYMBOL_2( 7, bitD4);
11340c16b537SWarner Losh             HUF_DECODE_SYMBOL_1( 8, bitD1);
11350c16b537SWarner Losh             HUF_DECODE_SYMBOL_1( 9, bitD2);
11360c16b537SWarner Losh             HUF_DECODE_SYMBOL_1(10, bitD3);
11370c16b537SWarner Losh             HUF_DECODE_SYMBOL_1(11, bitD4);
11380c16b537SWarner Losh             HUF_DECODE_SYMBOL_0(12, bitD1);
11390c16b537SWarner Losh             HUF_DECODE_SYMBOL_0(13, bitD2);
11400c16b537SWarner Losh             HUF_DECODE_SYMBOL_0(14, bitD3);
11410c16b537SWarner Losh             HUF_DECODE_SYMBOL_0(15, bitD4);
11420c16b537SWarner Losh         }
11430c16b537SWarner Losh 
11440c16b537SWarner Losh         if (reloadStatus!=FSE_DStream_completed)   /* not complete : some bitStream might be FSE_DStream_unfinished */
11450c16b537SWarner Losh             return (size_t)-FSE_ERROR_corruptionDetected;
11460c16b537SWarner Losh 
11470c16b537SWarner Losh         /* tail */
11480c16b537SWarner Losh         {
114937f1f268SConrad Meyer             /* bitTail = bitD1; */   /* *much* slower : -20% !??! */
11500c16b537SWarner Losh             FSE_DStream_t bitTail;
11510c16b537SWarner Losh             bitTail.ptr = bitD1.ptr;
11520c16b537SWarner Losh             bitTail.bitsConsumed = bitD1.bitsConsumed;
115337f1f268SConrad Meyer             bitTail.bitContainer = bitD1.bitContainer;   /* required in case of FSE_DStream_endOfBuffer */
11540c16b537SWarner Losh             bitTail.start = start1;
11550c16b537SWarner Losh             for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++)
11560c16b537SWarner Losh             {
11570c16b537SWarner Losh                 HUF_DECODE_SYMBOL_0(0, bitTail);
11580c16b537SWarner Losh             }
11590c16b537SWarner Losh 
11600c16b537SWarner Losh             if (FSE_endOfDStream(&bitTail))
11610c16b537SWarner Losh                 return op-ostart;
11620c16b537SWarner Losh         }
11630c16b537SWarner Losh 
11640c16b537SWarner Losh         if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */
11650c16b537SWarner Losh 
11660c16b537SWarner Losh         return (size_t)-FSE_ERROR_corruptionDetected;
11670c16b537SWarner Losh     }
11684d3f1eafSConrad Meyer }
11690c16b537SWarner Losh 
11700c16b537SWarner Losh 
HUF_decompress(void * dst,size_t maxDstSize,const void * cSrc,size_t cSrcSize)11710c16b537SWarner Losh static size_t HUF_decompress (void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
11720c16b537SWarner Losh {
11730c16b537SWarner Losh     HUF_CREATE_STATIC_DTABLE(DTable, HUF_MAX_TABLELOG);
11740c16b537SWarner Losh     const BYTE* ip = (const BYTE*) cSrc;
11750c16b537SWarner Losh     size_t errorCode;
11760c16b537SWarner Losh 
11770c16b537SWarner Losh     errorCode = HUF_readDTable (DTable, cSrc, cSrcSize);
11780c16b537SWarner Losh     if (FSE_isError(errorCode)) return errorCode;
11790c16b537SWarner Losh     if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;
11800c16b537SWarner Losh     ip += errorCode;
11810c16b537SWarner Losh     cSrcSize -= errorCode;
11820c16b537SWarner Losh 
11830c16b537SWarner Losh     return HUF_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, DTable);
11840c16b537SWarner Losh }
11850c16b537SWarner Losh 
11860c16b537SWarner Losh 
11870c16b537SWarner Losh #endif   /* FSE_COMMONDEFS_ONLY */
11880c16b537SWarner Losh 
11890c16b537SWarner Losh /*
11900c16b537SWarner Losh     zstd - standard compression library
11910c16b537SWarner Losh     Copyright (C) 2014-2015, Yann Collet.
11920c16b537SWarner Losh 
11930c16b537SWarner Losh     BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
11940c16b537SWarner Losh 
11950c16b537SWarner Losh     Redistribution and use in source and binary forms, with or without
11960c16b537SWarner Losh     modification, are permitted provided that the following conditions are
11970c16b537SWarner Losh     met:
11980c16b537SWarner Losh     * Redistributions of source code must retain the above copyright
11990c16b537SWarner Losh     notice, this list of conditions and the following disclaimer.
12000c16b537SWarner Losh     * Redistributions in binary form must reproduce the above
12010c16b537SWarner Losh     copyright notice, this list of conditions and the following disclaimer
12020c16b537SWarner Losh     in the documentation and/or other materials provided with the
12030c16b537SWarner Losh     distribution.
12040c16b537SWarner Losh     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12050c16b537SWarner Losh     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12060c16b537SWarner Losh     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12070c16b537SWarner Losh     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12080c16b537SWarner Losh     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
12090c16b537SWarner Losh     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
12100c16b537SWarner Losh     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12110c16b537SWarner Losh     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12120c16b537SWarner Losh     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12130c16b537SWarner Losh     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
12140c16b537SWarner Losh     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12150c16b537SWarner Losh 
12160c16b537SWarner Losh     You can contact the author at :
12170c16b537SWarner Losh     - zstd source repository : https://github.com/Cyan4973/zstd
12180c16b537SWarner Losh     - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
12190c16b537SWarner Losh */
12200c16b537SWarner Losh 
12210c16b537SWarner Losh /****************************************************************
12220c16b537SWarner Losh *  Tuning parameters
12230c16b537SWarner Losh *****************************************************************/
12240c16b537SWarner Losh /* MEMORY_USAGE :
12250c16b537SWarner Losh *  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
12260c16b537SWarner Losh *  Increasing memory usage improves compression ratio
12270c16b537SWarner Losh *  Reduced memory usage can improve speed, due to cache effect */
12280c16b537SWarner Losh #define ZSTD_MEMORY_USAGE 17
12290c16b537SWarner Losh 
12300c16b537SWarner Losh 
12310c16b537SWarner Losh /**************************************
12320c16b537SWarner Losh    CPU Feature Detection
12330c16b537SWarner Losh **************************************/
12340c16b537SWarner Losh /*
12350c16b537SWarner Losh  * Automated efficient unaligned memory access detection
12360c16b537SWarner Losh  * Based on known hardware architectures
12370c16b537SWarner Losh  * This list will be updated thanks to feedbacks
12380c16b537SWarner Losh  */
12390c16b537SWarner Losh #if defined(CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS) \
12400c16b537SWarner Losh     || defined(__ARM_FEATURE_UNALIGNED) \
12410c16b537SWarner Losh     || defined(__i386__) || defined(__x86_64__) \
12420c16b537SWarner Losh     || defined(_M_IX86) || defined(_M_X64) \
12430c16b537SWarner Losh     || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_8__) \
12440c16b537SWarner Losh     || (defined(_M_ARM) && (_M_ARM >= 7))
12450c16b537SWarner Losh #  define ZSTD_UNALIGNED_ACCESS 1
12460c16b537SWarner Losh #else
12470c16b537SWarner Losh #  define ZSTD_UNALIGNED_ACCESS 0
12480c16b537SWarner Losh #endif
12490c16b537SWarner Losh 
12500c16b537SWarner Losh 
12510c16b537SWarner Losh /********************************************************
12520c16b537SWarner Losh *  Includes
12530c16b537SWarner Losh *********************************************************/
12540c16b537SWarner Losh #include <stdlib.h>      /* calloc */
12550c16b537SWarner Losh #include <string.h>      /* memcpy, memmove */
12560c16b537SWarner Losh #include <stdio.h>       /* debug : printf */
12570c16b537SWarner Losh 
12580c16b537SWarner Losh 
12590c16b537SWarner Losh /********************************************************
12600c16b537SWarner Losh *  Compiler specifics
12610c16b537SWarner Losh *********************************************************/
12620c16b537SWarner Losh #ifdef __AVX2__
12630c16b537SWarner Losh #  include <immintrin.h>   /* AVX2 intrinsics */
12640c16b537SWarner Losh #endif
12650c16b537SWarner Losh 
12660c16b537SWarner Losh #ifdef _MSC_VER    /* Visual Studio */
12670c16b537SWarner Losh #  include <intrin.h>                    /* For Visual 2005 */
12680c16b537SWarner Losh #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
12690c16b537SWarner Losh #  pragma warning(disable : 4324)        /* disable: C4324: padded structure */
12700c16b537SWarner Losh #endif
12710c16b537SWarner Losh 
12720c16b537SWarner Losh 
12730c16b537SWarner Losh #ifndef MEM_ACCESS_MODULE
12740c16b537SWarner Losh #define MEM_ACCESS_MODULE
12750c16b537SWarner Losh /********************************************************
12760c16b537SWarner Losh *  Basic Types
12770c16b537SWarner Losh *********************************************************/
12780c16b537SWarner Losh #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
1279f7cd7fe5SConrad Meyer # if defined(_AIX)
1280f7cd7fe5SConrad Meyer #  include <inttypes.h>
1281f7cd7fe5SConrad Meyer # else
1282f7cd7fe5SConrad Meyer #  include <stdint.h> /* intptr_t */
1283f7cd7fe5SConrad Meyer # endif
12840c16b537SWarner Losh typedef  uint8_t BYTE;
12850c16b537SWarner Losh typedef uint16_t U16;
12860c16b537SWarner Losh typedef  int16_t S16;
12870c16b537SWarner Losh typedef uint32_t U32;
12880c16b537SWarner Losh typedef  int32_t S32;
12890c16b537SWarner Losh typedef uint64_t U64;
12900c16b537SWarner Losh #else
12910c16b537SWarner Losh typedef unsigned char       BYTE;
12920c16b537SWarner Losh typedef unsigned short      U16;
12930c16b537SWarner Losh typedef   signed short      S16;
12940c16b537SWarner Losh typedef unsigned int        U32;
12950c16b537SWarner Losh typedef   signed int        S32;
12960c16b537SWarner Losh typedef unsigned long long  U64;
12970c16b537SWarner Losh #endif
12980c16b537SWarner Losh 
12990c16b537SWarner Losh #endif   /* MEM_ACCESS_MODULE */
13000c16b537SWarner Losh 
13010c16b537SWarner Losh 
13020c16b537SWarner Losh /********************************************************
13030c16b537SWarner Losh *  Constants
13040c16b537SWarner Losh *********************************************************/
13050c16b537SWarner Losh static const U32 ZSTD_magicNumber = 0xFD2FB51E;   /* 3rd version : seqNb header */
13060c16b537SWarner Losh 
13070c16b537SWarner Losh #define HASH_LOG (ZSTD_MEMORY_USAGE - 2)
13080c16b537SWarner Losh #define HASH_TABLESIZE (1 << HASH_LOG)
13090c16b537SWarner Losh #define HASH_MASK (HASH_TABLESIZE - 1)
13100c16b537SWarner Losh 
13110c16b537SWarner Losh #define KNUTH 2654435761
13120c16b537SWarner Losh 
13130c16b537SWarner Losh #define BIT7 128
13140c16b537SWarner Losh #define BIT6  64
13150c16b537SWarner Losh #define BIT5  32
13160c16b537SWarner Losh #define BIT4  16
13170c16b537SWarner Losh 
13180c16b537SWarner Losh #define KB *(1 <<10)
13190c16b537SWarner Losh #define MB *(1 <<20)
13200c16b537SWarner Losh #define GB *(1U<<30)
13210c16b537SWarner Losh 
13220c16b537SWarner Losh #define BLOCKSIZE (128 KB)                 /* define, for static allocation */
13230c16b537SWarner Losh 
13240c16b537SWarner Losh #define WORKPLACESIZE (BLOCKSIZE*3)
13250c16b537SWarner Losh #define MINMATCH 4
13260c16b537SWarner Losh #define MLbits   7
13270c16b537SWarner Losh #define LLbits   6
13280c16b537SWarner Losh #define Offbits  5
13290c16b537SWarner Losh #define MaxML  ((1<<MLbits )-1)
13300c16b537SWarner Losh #define MaxLL  ((1<<LLbits )-1)
13310c16b537SWarner Losh #define MaxOff ((1<<Offbits)-1)
13320c16b537SWarner Losh #define LitFSELog  11
13330c16b537SWarner Losh #define MLFSELog   10
13340c16b537SWarner Losh #define LLFSELog   10
13350c16b537SWarner Losh #define OffFSELog   9
13360c16b537SWarner Losh #define MAX(a,b) ((a)<(b)?(b):(a))
13370c16b537SWarner Losh #define MaxSeq MAX(MaxLL, MaxML)
13380c16b537SWarner Losh 
13390c16b537SWarner Losh #define LITERAL_NOENTROPY 63
13400c16b537SWarner Losh #define COMMAND_NOENTROPY 7   /* to remove */
13410c16b537SWarner Losh 
13422b9c00cbSConrad Meyer #define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)
13432b9c00cbSConrad Meyer 
13440c16b537SWarner Losh static const size_t ZSTD_blockHeaderSize = 3;
13450c16b537SWarner Losh static const size_t ZSTD_frameHeaderSize = 4;
13460c16b537SWarner Losh 
13470c16b537SWarner Losh 
13480c16b537SWarner Losh /********************************************************
13490c16b537SWarner Losh *  Memory operations
13500c16b537SWarner Losh *********************************************************/
ZSTD_32bits(void)13510c16b537SWarner Losh static unsigned ZSTD_32bits(void) { return sizeof(void*)==4; }
13520c16b537SWarner Losh 
ZSTD_isLittleEndian(void)13530c16b537SWarner Losh static unsigned ZSTD_isLittleEndian(void)
13540c16b537SWarner Losh {
13550c16b537SWarner Losh     const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
13560c16b537SWarner Losh     return one.c[0];
13570c16b537SWarner Losh }
13580c16b537SWarner Losh 
ZSTD_read16(const void * p)13590c16b537SWarner Losh static U16    ZSTD_read16(const void* p) { U16 r; memcpy(&r, p, sizeof(r)); return r; }
13600c16b537SWarner Losh 
ZSTD_copy4(void * dst,const void * src)13610c16b537SWarner Losh static void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
13620c16b537SWarner Losh 
ZSTD_copy8(void * dst,const void * src)13630c16b537SWarner Losh static void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
13640c16b537SWarner Losh 
13650c16b537SWarner Losh #define COPY8(d,s)    { ZSTD_copy8(d,s); d+=8; s+=8; }
13660c16b537SWarner Losh 
ZSTD_wildcopy(void * dst,const void * src,ptrdiff_t length)13670c16b537SWarner Losh static void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)
13680c16b537SWarner Losh {
13690c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
13700c16b537SWarner Losh     BYTE* op = (BYTE*)dst;
13710c16b537SWarner Losh     BYTE* const oend = op + length;
13720c16b537SWarner Losh     while (op < oend) COPY8(op, ip);
13730c16b537SWarner Losh }
13740c16b537SWarner Losh 
ZSTD_readLE16(const void * memPtr)13750c16b537SWarner Losh static U16 ZSTD_readLE16(const void* memPtr)
13760c16b537SWarner Losh {
13770c16b537SWarner Losh     if (ZSTD_isLittleEndian()) return ZSTD_read16(memPtr);
13780c16b537SWarner Losh     else
13790c16b537SWarner Losh     {
13800c16b537SWarner Losh         const BYTE* p = (const BYTE*)memPtr;
13810c16b537SWarner Losh         return (U16)((U16)p[0] + ((U16)p[1]<<8));
13820c16b537SWarner Losh     }
13830c16b537SWarner Losh }
13840c16b537SWarner Losh 
ZSTD_readLE24(const void * memPtr)13854d3f1eafSConrad Meyer static U32 ZSTD_readLE24(const void* memPtr)
13860c16b537SWarner Losh {
13874d3f1eafSConrad Meyer     return ZSTD_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
13880c16b537SWarner Losh }
13890c16b537SWarner Losh 
ZSTD_readBE32(const void * memPtr)13900c16b537SWarner Losh static U32 ZSTD_readBE32(const void* memPtr)
13910c16b537SWarner Losh {
13920c16b537SWarner Losh     const BYTE* p = (const BYTE*)memPtr;
13930c16b537SWarner Losh     return (U32)(((U32)p[0]<<24) + ((U32)p[1]<<16) + ((U32)p[2]<<8) + ((U32)p[3]<<0));
13940c16b537SWarner Losh }
13950c16b537SWarner Losh 
13960c16b537SWarner Losh 
13970c16b537SWarner Losh /**************************************
13980c16b537SWarner Losh *  Local structures
13990c16b537SWarner Losh ***************************************/
14000c16b537SWarner Losh typedef struct ZSTD_Cctx_s ZSTD_Cctx;
14010c16b537SWarner Losh 
14020c16b537SWarner Losh typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
14030c16b537SWarner Losh 
14040c16b537SWarner Losh typedef struct
14050c16b537SWarner Losh {
14060c16b537SWarner Losh     blockType_t blockType;
14070c16b537SWarner Losh     U32 origSize;
14080c16b537SWarner Losh } blockProperties_t;
14090c16b537SWarner Losh 
14100c16b537SWarner Losh typedef struct {
14110c16b537SWarner Losh     void* buffer;
14120c16b537SWarner Losh     U32*  offsetStart;
14130c16b537SWarner Losh     U32*  offset;
14140c16b537SWarner Losh     BYTE* offCodeStart;
14150c16b537SWarner Losh     BYTE* offCode;
14160c16b537SWarner Losh     BYTE* litStart;
14170c16b537SWarner Losh     BYTE* lit;
14180c16b537SWarner Losh     BYTE* litLengthStart;
14190c16b537SWarner Losh     BYTE* litLength;
14200c16b537SWarner Losh     BYTE* matchLengthStart;
14210c16b537SWarner Losh     BYTE* matchLength;
14220c16b537SWarner Losh     BYTE* dumpsStart;
14230c16b537SWarner Losh     BYTE* dumps;
14240c16b537SWarner Losh } seqStore_t;
14250c16b537SWarner Losh 
14260c16b537SWarner Losh 
14270c16b537SWarner Losh typedef struct ZSTD_Cctx_s
14280c16b537SWarner Losh {
14290c16b537SWarner Losh     const BYTE* base;
14300c16b537SWarner Losh     U32 current;
14310c16b537SWarner Losh     U32 nextUpdate;
14320c16b537SWarner Losh     seqStore_t seqStore;
14330c16b537SWarner Losh #ifdef __AVX2__
14340c16b537SWarner Losh     __m256i hashTable[HASH_TABLESIZE>>3];
14350c16b537SWarner Losh #else
14360c16b537SWarner Losh     U32 hashTable[HASH_TABLESIZE];
14370c16b537SWarner Losh #endif
14380c16b537SWarner Losh     BYTE buffer[WORKPLACESIZE];
14390c16b537SWarner Losh } cctxi_t;
14400c16b537SWarner Losh 
14410c16b537SWarner Losh 
14420c16b537SWarner Losh 
14430c16b537SWarner Losh 
14440c16b537SWarner Losh /**************************************
14450c16b537SWarner Losh *  Error Management
14460c16b537SWarner Losh **************************************/
14470c16b537SWarner Losh /* published entry point */
ZSTDv01_isError(size_t code)14480c16b537SWarner Losh unsigned ZSTDv01_isError(size_t code) { return ERR_isError(code); }
14490c16b537SWarner Losh 
14500c16b537SWarner Losh 
14510c16b537SWarner Losh /**************************************
14520c16b537SWarner Losh *  Tool functions
14530c16b537SWarner Losh **************************************/
14540c16b537SWarner Losh #define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */
14550c16b537SWarner Losh #define ZSTD_VERSION_MINOR    1    /* for new (non-breaking) interface capabilities */
14560c16b537SWarner Losh #define ZSTD_VERSION_RELEASE  3    /* for tweaks, bug-fixes, or development */
14570c16b537SWarner Losh #define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
14580c16b537SWarner Losh 
14590c16b537SWarner Losh /**************************************************************
14600c16b537SWarner Losh *   Decompression code
14610c16b537SWarner Losh **************************************************************/
14620c16b537SWarner Losh 
ZSTDv01_getcBlockSize(const void * src,size_t srcSize,blockProperties_t * bpPtr)14630f743729SConrad Meyer static size_t ZSTDv01_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
14640c16b537SWarner Losh {
14650c16b537SWarner Losh     const BYTE* const in = (const BYTE* const)src;
14660c16b537SWarner Losh     BYTE headerFlags;
14670c16b537SWarner Losh     U32 cSize;
14680c16b537SWarner Losh 
14690c16b537SWarner Losh     if (srcSize < 3) return ERROR(srcSize_wrong);
14700c16b537SWarner Losh 
14710c16b537SWarner Losh     headerFlags = *in;
14720c16b537SWarner Losh     cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
14730c16b537SWarner Losh 
14740c16b537SWarner Losh     bpPtr->blockType = (blockType_t)(headerFlags >> 6);
14750c16b537SWarner Losh     bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
14760c16b537SWarner Losh 
14770c16b537SWarner Losh     if (bpPtr->blockType == bt_end) return 0;
14780c16b537SWarner Losh     if (bpPtr->blockType == bt_rle) return 1;
14790c16b537SWarner Losh     return cSize;
14800c16b537SWarner Losh }
14810c16b537SWarner Losh 
14820c16b537SWarner Losh 
ZSTD_copyUncompressedBlock(void * dst,size_t maxDstSize,const void * src,size_t srcSize)14830c16b537SWarner Losh static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
14840c16b537SWarner Losh {
14850c16b537SWarner Losh     if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
148637f1f268SConrad Meyer     if (srcSize > 0) {
14870c16b537SWarner Losh         memcpy(dst, src, srcSize);
148837f1f268SConrad Meyer     }
14890c16b537SWarner Losh     return srcSize;
14900c16b537SWarner Losh }
14910c16b537SWarner Losh 
14920c16b537SWarner Losh 
ZSTD_decompressLiterals(void * ctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)14930c16b537SWarner Losh static size_t ZSTD_decompressLiterals(void* ctx,
14940c16b537SWarner Losh                                       void* dst, size_t maxDstSize,
14950c16b537SWarner Losh                                 const void* src, size_t srcSize)
14960c16b537SWarner Losh {
14970c16b537SWarner Losh     BYTE* op = (BYTE*)dst;
14980c16b537SWarner Losh     BYTE* const oend = op + maxDstSize;
14990c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
15000c16b537SWarner Losh     size_t errorCode;
15010c16b537SWarner Losh     size_t litSize;
15020c16b537SWarner Losh 
15030c16b537SWarner Losh     /* check : minimum 2, for litSize, +1, for content */
15040c16b537SWarner Losh     if (srcSize <= 3) return ERROR(corruption_detected);
15050c16b537SWarner Losh 
15060c16b537SWarner Losh     litSize = ip[1] + (ip[0]<<8);
150737f1f268SConrad Meyer     litSize += ((ip[-3] >> 3) & 7) << 16;   /* mmmmh.... */
15080c16b537SWarner Losh     op = oend - litSize;
15090c16b537SWarner Losh 
15100c16b537SWarner Losh     (void)ctx;
15110c16b537SWarner Losh     if (litSize > maxDstSize) return ERROR(dstSize_tooSmall);
15120c16b537SWarner Losh     errorCode = HUF_decompress(op, litSize, ip+2, srcSize-2);
15130c16b537SWarner Losh     if (FSE_isError(errorCode)) return ERROR(GENERIC);
15140c16b537SWarner Losh     return litSize;
15150c16b537SWarner Losh }
15160c16b537SWarner Losh 
15170c16b537SWarner Losh 
ZSTDv01_decodeLiteralsBlock(void * ctx,void * dst,size_t maxDstSize,const BYTE ** litStart,size_t * litSize,const void * src,size_t srcSize)15180f743729SConrad Meyer static size_t ZSTDv01_decodeLiteralsBlock(void* ctx,
15190c16b537SWarner Losh                                 void* dst, size_t maxDstSize,
15200c16b537SWarner Losh                           const BYTE** litStart, size_t* litSize,
15210c16b537SWarner Losh                           const void* src, size_t srcSize)
15220c16b537SWarner Losh {
15230c16b537SWarner Losh     const BYTE* const istart = (const BYTE* const)src;
15240c16b537SWarner Losh     const BYTE* ip = istart;
15250c16b537SWarner Losh     BYTE* const ostart = (BYTE* const)dst;
15260c16b537SWarner Losh     BYTE* const oend = ostart + maxDstSize;
15270c16b537SWarner Losh     blockProperties_t litbp;
15280c16b537SWarner Losh 
15290c16b537SWarner Losh     size_t litcSize = ZSTDv01_getcBlockSize(src, srcSize, &litbp);
15300c16b537SWarner Losh     if (ZSTDv01_isError(litcSize)) return litcSize;
15310c16b537SWarner Losh     if (litcSize > srcSize - ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
15320c16b537SWarner Losh     ip += ZSTD_blockHeaderSize;
15330c16b537SWarner Losh 
15340c16b537SWarner Losh     switch(litbp.blockType)
15350c16b537SWarner Losh     {
15360c16b537SWarner Losh     case bt_raw:
15370c16b537SWarner Losh         *litStart = ip;
15380c16b537SWarner Losh         ip += litcSize;
15390c16b537SWarner Losh         *litSize = litcSize;
15400c16b537SWarner Losh         break;
15410c16b537SWarner Losh     case bt_rle:
15420c16b537SWarner Losh         {
15430c16b537SWarner Losh             size_t rleSize = litbp.origSize;
15440c16b537SWarner Losh             if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall);
15450c16b537SWarner Losh             if (!srcSize) return ERROR(srcSize_wrong);
154637f1f268SConrad Meyer             if (rleSize > 0) {
15470c16b537SWarner Losh                 memset(oend - rleSize, *ip, rleSize);
154837f1f268SConrad Meyer             }
15490c16b537SWarner Losh             *litStart = oend - rleSize;
15500c16b537SWarner Losh             *litSize = rleSize;
15510c16b537SWarner Losh             ip++;
15520c16b537SWarner Losh             break;
15530c16b537SWarner Losh         }
15540c16b537SWarner Losh     case bt_compressed:
15550c16b537SWarner Losh         {
15560c16b537SWarner Losh             size_t decodedLitSize = ZSTD_decompressLiterals(ctx, dst, maxDstSize, ip, litcSize);
15570c16b537SWarner Losh             if (ZSTDv01_isError(decodedLitSize)) return decodedLitSize;
15580c16b537SWarner Losh             *litStart = oend - decodedLitSize;
15590c16b537SWarner Losh             *litSize = decodedLitSize;
15600c16b537SWarner Losh             ip += litcSize;
15610c16b537SWarner Losh             break;
15620c16b537SWarner Losh         }
15630c16b537SWarner Losh     case bt_end:
15640c16b537SWarner Losh     default:
15650c16b537SWarner Losh         return ERROR(GENERIC);
15660c16b537SWarner Losh     }
15670c16b537SWarner Losh 
15680c16b537SWarner Losh     return ip-istart;
15690c16b537SWarner Losh }
15700c16b537SWarner Losh 
15710c16b537SWarner Losh 
ZSTDv01_decodeSeqHeaders(int * nbSeq,const BYTE ** dumpsPtr,size_t * dumpsLengthPtr,FSE_DTable * DTableLL,FSE_DTable * DTableML,FSE_DTable * DTableOffb,const void * src,size_t srcSize)15720f743729SConrad Meyer static size_t ZSTDv01_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
15730c16b537SWarner Losh                          FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
15740c16b537SWarner Losh                          const void* src, size_t srcSize)
15750c16b537SWarner Losh {
15760c16b537SWarner Losh     const BYTE* const istart = (const BYTE* const)src;
15770c16b537SWarner Losh     const BYTE* ip = istart;
15780c16b537SWarner Losh     const BYTE* const iend = istart + srcSize;
15790c16b537SWarner Losh     U32 LLtype, Offtype, MLtype;
15800c16b537SWarner Losh     U32 LLlog, Offlog, MLlog;
15810c16b537SWarner Losh     size_t dumpsLength;
15820c16b537SWarner Losh 
15830c16b537SWarner Losh     /* check */
15840c16b537SWarner Losh     if (srcSize < 5) return ERROR(srcSize_wrong);
15850c16b537SWarner Losh 
15860c16b537SWarner Losh     /* SeqHead */
15870c16b537SWarner Losh     *nbSeq = ZSTD_readLE16(ip); ip+=2;
15880c16b537SWarner Losh     LLtype  = *ip >> 6;
15890c16b537SWarner Losh     Offtype = (*ip >> 4) & 3;
15900c16b537SWarner Losh     MLtype  = (*ip >> 2) & 3;
15910c16b537SWarner Losh     if (*ip & 2)
15920c16b537SWarner Losh     {
15930c16b537SWarner Losh         dumpsLength  = ip[2];
15940c16b537SWarner Losh         dumpsLength += ip[1] << 8;
15950c16b537SWarner Losh         ip += 3;
15960c16b537SWarner Losh     }
15970c16b537SWarner Losh     else
15980c16b537SWarner Losh     {
15990c16b537SWarner Losh         dumpsLength  = ip[1];
16000c16b537SWarner Losh         dumpsLength += (ip[0] & 1) << 8;
16010c16b537SWarner Losh         ip += 2;
16020c16b537SWarner Losh     }
16030c16b537SWarner Losh     *dumpsPtr = ip;
16040c16b537SWarner Losh     ip += dumpsLength;
16050c16b537SWarner Losh     *dumpsLengthPtr = dumpsLength;
16060c16b537SWarner Losh 
16070c16b537SWarner Losh     /* check */
16080c16b537SWarner Losh     if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
16090c16b537SWarner Losh 
16100c16b537SWarner Losh     /* sequences */
16110c16b537SWarner Losh     {
16120c16b537SWarner Losh         S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */
16130c16b537SWarner Losh         size_t headerSize;
16140c16b537SWarner Losh 
16150c16b537SWarner Losh         /* Build DTables */
16160c16b537SWarner Losh         switch(LLtype)
16170c16b537SWarner Losh         {
16180c16b537SWarner Losh         case bt_rle :
16190c16b537SWarner Losh             LLlog = 0;
16200c16b537SWarner Losh             FSE_buildDTable_rle(DTableLL, *ip++); break;
16210c16b537SWarner Losh         case bt_raw :
16220c16b537SWarner Losh             LLlog = LLbits;
16230c16b537SWarner Losh             FSE_buildDTable_raw(DTableLL, LLbits); break;
16240c16b537SWarner Losh         default :
16250c16b537SWarner Losh             {   U32 max = MaxLL;
16260c16b537SWarner Losh                 headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
16270c16b537SWarner Losh                 if (FSE_isError(headerSize)) return ERROR(GENERIC);
16280c16b537SWarner Losh                 if (LLlog > LLFSELog) return ERROR(corruption_detected);
16290c16b537SWarner Losh                 ip += headerSize;
16300c16b537SWarner Losh                 FSE_buildDTable(DTableLL, norm, max, LLlog);
16310c16b537SWarner Losh         }   }
16320c16b537SWarner Losh 
16330c16b537SWarner Losh         switch(Offtype)
16340c16b537SWarner Losh         {
16350c16b537SWarner Losh         case bt_rle :
16360c16b537SWarner Losh             Offlog = 0;
16370c16b537SWarner Losh             if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
16380c16b537SWarner Losh             FSE_buildDTable_rle(DTableOffb, *ip++); break;
16390c16b537SWarner Losh         case bt_raw :
16400c16b537SWarner Losh             Offlog = Offbits;
16410c16b537SWarner Losh             FSE_buildDTable_raw(DTableOffb, Offbits); break;
16420c16b537SWarner Losh         default :
16430c16b537SWarner Losh             {   U32 max = MaxOff;
16440c16b537SWarner Losh                 headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
16450c16b537SWarner Losh                 if (FSE_isError(headerSize)) return ERROR(GENERIC);
16460c16b537SWarner Losh                 if (Offlog > OffFSELog) return ERROR(corruption_detected);
16470c16b537SWarner Losh                 ip += headerSize;
16480c16b537SWarner Losh                 FSE_buildDTable(DTableOffb, norm, max, Offlog);
16490c16b537SWarner Losh         }   }
16500c16b537SWarner Losh 
16510c16b537SWarner Losh         switch(MLtype)
16520c16b537SWarner Losh         {
16530c16b537SWarner Losh         case bt_rle :
16540c16b537SWarner Losh             MLlog = 0;
16550c16b537SWarner Losh             if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
16560c16b537SWarner Losh             FSE_buildDTable_rle(DTableML, *ip++); break;
16570c16b537SWarner Losh         case bt_raw :
16580c16b537SWarner Losh             MLlog = MLbits;
16590c16b537SWarner Losh             FSE_buildDTable_raw(DTableML, MLbits); break;
16600c16b537SWarner Losh         default :
16610c16b537SWarner Losh             {   U32 max = MaxML;
16620c16b537SWarner Losh                 headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
16630c16b537SWarner Losh                 if (FSE_isError(headerSize)) return ERROR(GENERIC);
16640c16b537SWarner Losh                 if (MLlog > MLFSELog) return ERROR(corruption_detected);
16650c16b537SWarner Losh                 ip += headerSize;
16660c16b537SWarner Losh                 FSE_buildDTable(DTableML, norm, max, MLlog);
16670c16b537SWarner Losh     }   }   }
16680c16b537SWarner Losh 
16690c16b537SWarner Losh     return ip-istart;
16700c16b537SWarner Losh }
16710c16b537SWarner Losh 
16720c16b537SWarner Losh 
16730c16b537SWarner Losh typedef struct {
16740c16b537SWarner Losh     size_t litLength;
16750c16b537SWarner Losh     size_t offset;
16760c16b537SWarner Losh     size_t matchLength;
16770c16b537SWarner Losh } seq_t;
16780c16b537SWarner Losh 
16790c16b537SWarner Losh typedef struct {
16800c16b537SWarner Losh     FSE_DStream_t DStream;
16810c16b537SWarner Losh     FSE_DState_t stateLL;
16820c16b537SWarner Losh     FSE_DState_t stateOffb;
16830c16b537SWarner Losh     FSE_DState_t stateML;
16840c16b537SWarner Losh     size_t prevOffset;
16850c16b537SWarner Losh     const BYTE* dumps;
16860c16b537SWarner Losh     const BYTE* dumpsEnd;
16870c16b537SWarner Losh } seqState_t;
16880c16b537SWarner Losh 
16890c16b537SWarner Losh 
ZSTD_decodeSequence(seq_t * seq,seqState_t * seqState)16900c16b537SWarner Losh static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
16910c16b537SWarner Losh {
16920c16b537SWarner Losh     size_t litLength;
16930c16b537SWarner Losh     size_t prevOffset;
16940c16b537SWarner Losh     size_t offset;
16950c16b537SWarner Losh     size_t matchLength;
16960c16b537SWarner Losh     const BYTE* dumps = seqState->dumps;
16970c16b537SWarner Losh     const BYTE* const de = seqState->dumpsEnd;
16980c16b537SWarner Losh 
16990c16b537SWarner Losh     /* Literal length */
17000c16b537SWarner Losh     litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));
17010c16b537SWarner Losh     prevOffset = litLength ? seq->offset : seqState->prevOffset;
17020c16b537SWarner Losh     seqState->prevOffset = seq->offset;
17030c16b537SWarner Losh     if (litLength == MaxLL)
17040c16b537SWarner Losh     {
17054d3f1eafSConrad Meyer         const U32 add = dumps<de ? *dumps++ : 0;
17060c16b537SWarner Losh         if (add < 255) litLength += add;
17070c16b537SWarner Losh         else
17080c16b537SWarner Losh         {
17090c16b537SWarner Losh             if (dumps<=(de-3))
17100c16b537SWarner Losh             {
17114d3f1eafSConrad Meyer                 litLength = ZSTD_readLE24(dumps);
17120c16b537SWarner Losh                 dumps += 3;
17130c16b537SWarner Losh             }
17140c16b537SWarner Losh         }
17150c16b537SWarner Losh     }
17160c16b537SWarner Losh 
17170c16b537SWarner Losh     /* Offset */
17180c16b537SWarner Losh     {
17190c16b537SWarner Losh         U32 offsetCode, nbBits;
17200c16b537SWarner Losh         offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));
17210c16b537SWarner Losh         if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream));
17220c16b537SWarner Losh         nbBits = offsetCode - 1;
17230c16b537SWarner Losh         if (offsetCode==0) nbBits = 0;   /* cmove */
17240c16b537SWarner Losh         offset = ((size_t)1 << (nbBits & ((sizeof(offset)*8)-1))) + FSE_readBits(&(seqState->DStream), nbBits);
17250c16b537SWarner Losh         if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream));
17260c16b537SWarner Losh         if (offsetCode==0) offset = prevOffset;
17270c16b537SWarner Losh     }
17280c16b537SWarner Losh 
17290c16b537SWarner Losh     /* MatchLength */
17300c16b537SWarner Losh     matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
17310c16b537SWarner Losh     if (matchLength == MaxML)
17320c16b537SWarner Losh     {
17334d3f1eafSConrad Meyer         const U32 add = dumps<de ? *dumps++ : 0;
17340c16b537SWarner Losh         if (add < 255) matchLength += add;
17350c16b537SWarner Losh         else
17360c16b537SWarner Losh         {
17370c16b537SWarner Losh             if (dumps<=(de-3))
17380c16b537SWarner Losh             {
17394d3f1eafSConrad Meyer                 matchLength = ZSTD_readLE24(dumps);
17400c16b537SWarner Losh                 dumps += 3;
17410c16b537SWarner Losh             }
17420c16b537SWarner Losh         }
17430c16b537SWarner Losh     }
17440c16b537SWarner Losh     matchLength += MINMATCH;
17450c16b537SWarner Losh 
17460c16b537SWarner Losh     /* save result */
17470c16b537SWarner Losh     seq->litLength = litLength;
17480c16b537SWarner Losh     seq->offset = offset;
17490c16b537SWarner Losh     seq->matchLength = matchLength;
17500c16b537SWarner Losh     seqState->dumps = dumps;
17510c16b537SWarner Losh }
17520c16b537SWarner Losh 
17530c16b537SWarner Losh 
ZSTD_execSequence(BYTE * op,seq_t sequence,const BYTE ** litPtr,const BYTE * const litLimit,BYTE * const base,BYTE * const oend)17540c16b537SWarner Losh static size_t ZSTD_execSequence(BYTE* op,
17550c16b537SWarner Losh                                 seq_t sequence,
17560c16b537SWarner Losh                                 const BYTE** litPtr, const BYTE* const litLimit,
17570c16b537SWarner Losh                                 BYTE* const base, BYTE* const oend)
17580c16b537SWarner Losh {
17590c16b537SWarner Losh     static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */
17602b9c00cbSConrad Meyer     static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */
17610c16b537SWarner Losh     const BYTE* const ostart = op;
17620c16b537SWarner Losh     const size_t litLength = sequence.litLength;
17630c16b537SWarner Losh     BYTE* const endMatch = op + litLength + sequence.matchLength;    /* risk : address space overflow (32-bits) */
17640c16b537SWarner Losh     const BYTE* const litEnd = *litPtr + litLength;
17650c16b537SWarner Losh 
17660c16b537SWarner Losh     /* check */
17670c16b537SWarner Losh     if (endMatch > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */
17680c16b537SWarner Losh     if (litEnd > litLimit) return ERROR(corruption_detected);
17690c16b537SWarner Losh     if (sequence.matchLength > (size_t)(*litPtr-op))  return ERROR(dstSize_tooSmall);    /* overwrite literal segment */
17700c16b537SWarner Losh 
17710c16b537SWarner Losh     /* copy Literals */
17720c16b537SWarner Losh     if (((size_t)(*litPtr - op) < 8) || ((size_t)(oend-litEnd) < 8) || (op+litLength > oend-8))
17730c16b537SWarner Losh         memmove(op, *litPtr, litLength);   /* overwrite risk */
17740c16b537SWarner Losh     else
17750c16b537SWarner Losh         ZSTD_wildcopy(op, *litPtr, litLength);
17760c16b537SWarner Losh     op += litLength;
17770c16b537SWarner Losh     *litPtr = litEnd;   /* update for next sequence */
17780c16b537SWarner Losh 
17790c16b537SWarner Losh     /* check : last match must be at a minimum distance of 8 from end of dest buffer */
17800c16b537SWarner Losh     if (oend-op < 8) return ERROR(dstSize_tooSmall);
17810c16b537SWarner Losh 
17820c16b537SWarner Losh     /* copy Match */
17830c16b537SWarner Losh     {
17840c16b537SWarner Losh         const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12);
17850c16b537SWarner Losh         const BYTE* match = op - sequence.offset;            /* possible underflow at op - offset ? */
17860c16b537SWarner Losh         size_t qutt = 12;
17870c16b537SWarner Losh         U64 saved[2];
17880c16b537SWarner Losh 
17890c16b537SWarner Losh         /* check */
17900c16b537SWarner Losh         if (match < base) return ERROR(corruption_detected);
17910c16b537SWarner Losh         if (sequence.offset > (size_t)base) return ERROR(corruption_detected);
17920c16b537SWarner Losh 
17930c16b537SWarner Losh         /* save beginning of literal sequence, in case of write overlap */
17940c16b537SWarner Losh         if (overlapRisk)
17950c16b537SWarner Losh         {
17960c16b537SWarner Losh             if ((endMatch + qutt) > oend) qutt = oend-endMatch;
17970c16b537SWarner Losh             memcpy(saved, endMatch, qutt);
17980c16b537SWarner Losh         }
17990c16b537SWarner Losh 
18000c16b537SWarner Losh         if (sequence.offset < 8)
18010c16b537SWarner Losh         {
18020c16b537SWarner Losh             const int dec64 = dec64table[sequence.offset];
18030c16b537SWarner Losh             op[0] = match[0];
18040c16b537SWarner Losh             op[1] = match[1];
18050c16b537SWarner Losh             op[2] = match[2];
18060c16b537SWarner Losh             op[3] = match[3];
18070c16b537SWarner Losh             match += dec32table[sequence.offset];
18080c16b537SWarner Losh             ZSTD_copy4(op+4, match);
18090c16b537SWarner Losh             match -= dec64;
18100c16b537SWarner Losh         } else { ZSTD_copy8(op, match); }
18110c16b537SWarner Losh         op += 8; match += 8;
18120c16b537SWarner Losh 
18130c16b537SWarner Losh         if (endMatch > oend-(16-MINMATCH))
18140c16b537SWarner Losh         {
18150c16b537SWarner Losh             if (op < oend-8)
18160c16b537SWarner Losh             {
18170c16b537SWarner Losh                 ZSTD_wildcopy(op, match, (oend-8) - op);
18180c16b537SWarner Losh                 match += (oend-8) - op;
18190c16b537SWarner Losh                 op = oend-8;
18200c16b537SWarner Losh             }
18210c16b537SWarner Losh             while (op<endMatch) *op++ = *match++;
18220c16b537SWarner Losh         }
18230c16b537SWarner Losh         else
18240c16b537SWarner Losh             ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */
18250c16b537SWarner Losh 
18260c16b537SWarner Losh         /* restore, in case of overlap */
18270c16b537SWarner Losh         if (overlapRisk) memcpy(endMatch, saved, qutt);
18280c16b537SWarner Losh     }
18290c16b537SWarner Losh 
18300c16b537SWarner Losh     return endMatch-ostart;
18310c16b537SWarner Losh }
18320c16b537SWarner Losh 
18330c16b537SWarner Losh typedef struct ZSTDv01_Dctx_s
18340c16b537SWarner Losh {
18350c16b537SWarner Losh     U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
18360c16b537SWarner Losh     U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
18370c16b537SWarner Losh     U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
18380c16b537SWarner Losh     void* previousDstEnd;
18390c16b537SWarner Losh     void* base;
18400c16b537SWarner Losh     size_t expected;
18410c16b537SWarner Losh     blockType_t bType;
18420c16b537SWarner Losh     U32 phase;
18430c16b537SWarner Losh } dctx_t;
18440c16b537SWarner Losh 
18450c16b537SWarner Losh 
ZSTD_decompressSequences(void * ctx,void * dst,size_t maxDstSize,const void * seqStart,size_t seqSize,const BYTE * litStart,size_t litSize)18460c16b537SWarner Losh static size_t ZSTD_decompressSequences(
18470c16b537SWarner Losh                                void* ctx,
18480c16b537SWarner Losh                                void* dst, size_t maxDstSize,
18490c16b537SWarner Losh                          const void* seqStart, size_t seqSize,
18500c16b537SWarner Losh                          const BYTE* litStart, size_t litSize)
18510c16b537SWarner Losh {
18520c16b537SWarner Losh     dctx_t* dctx = (dctx_t*)ctx;
18530c16b537SWarner Losh     const BYTE* ip = (const BYTE*)seqStart;
18540c16b537SWarner Losh     const BYTE* const iend = ip + seqSize;
18550c16b537SWarner Losh     BYTE* const ostart = (BYTE* const)dst;
18560c16b537SWarner Losh     BYTE* op = ostart;
18570c16b537SWarner Losh     BYTE* const oend = ostart + maxDstSize;
18580c16b537SWarner Losh     size_t errorCode, dumpsLength;
18590c16b537SWarner Losh     const BYTE* litPtr = litStart;
18600c16b537SWarner Losh     const BYTE* const litEnd = litStart + litSize;
18610c16b537SWarner Losh     int nbSeq;
18620c16b537SWarner Losh     const BYTE* dumps;
18630c16b537SWarner Losh     U32* DTableLL = dctx->LLTable;
18640c16b537SWarner Losh     U32* DTableML = dctx->MLTable;
18650c16b537SWarner Losh     U32* DTableOffb = dctx->OffTable;
18660c16b537SWarner Losh     BYTE* const base = (BYTE*) (dctx->base);
18670c16b537SWarner Losh 
18680c16b537SWarner Losh     /* Build Decoding Tables */
18690c16b537SWarner Losh     errorCode = ZSTDv01_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
18700c16b537SWarner Losh                                       DTableLL, DTableML, DTableOffb,
18710c16b537SWarner Losh                                       ip, iend-ip);
18720c16b537SWarner Losh     if (ZSTDv01_isError(errorCode)) return errorCode;
18730c16b537SWarner Losh     ip += errorCode;
18740c16b537SWarner Losh 
18750c16b537SWarner Losh     /* Regen sequences */
18760c16b537SWarner Losh     {
18770c16b537SWarner Losh         seq_t sequence;
18780c16b537SWarner Losh         seqState_t seqState;
18790c16b537SWarner Losh 
18800c16b537SWarner Losh         memset(&sequence, 0, sizeof(sequence));
18810c16b537SWarner Losh         seqState.dumps = dumps;
18820c16b537SWarner Losh         seqState.dumpsEnd = dumps + dumpsLength;
18830c16b537SWarner Losh         seqState.prevOffset = 1;
18840c16b537SWarner Losh         errorCode = FSE_initDStream(&(seqState.DStream), ip, iend-ip);
18850c16b537SWarner Losh         if (FSE_isError(errorCode)) return ERROR(corruption_detected);
18860c16b537SWarner Losh         FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
18870c16b537SWarner Losh         FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
18880c16b537SWarner Losh         FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
18890c16b537SWarner Losh 
18900c16b537SWarner Losh         for ( ; (FSE_reloadDStream(&(seqState.DStream)) <= FSE_DStream_completed) && (nbSeq>0) ; )
18910c16b537SWarner Losh         {
18920c16b537SWarner Losh             size_t oneSeqSize;
18930c16b537SWarner Losh             nbSeq--;
18940c16b537SWarner Losh             ZSTD_decodeSequence(&sequence, &seqState);
18950c16b537SWarner Losh             oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);
18960c16b537SWarner Losh             if (ZSTDv01_isError(oneSeqSize)) return oneSeqSize;
18970c16b537SWarner Losh             op += oneSeqSize;
18980c16b537SWarner Losh         }
18990c16b537SWarner Losh 
19000c16b537SWarner Losh         /* check if reached exact end */
19010c16b537SWarner Losh         if ( !FSE_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */
19020c16b537SWarner Losh         if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */
19030c16b537SWarner Losh 
19040c16b537SWarner Losh         /* last literal segment */
19050c16b537SWarner Losh         {
19060c16b537SWarner Losh             size_t lastLLSize = litEnd - litPtr;
19070c16b537SWarner Losh             if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
190837f1f268SConrad Meyer             if (lastLLSize > 0) {
19090c16b537SWarner Losh                 if (op != litPtr) memmove(op, litPtr, lastLLSize);
19100c16b537SWarner Losh                 op += lastLLSize;
19110c16b537SWarner Losh             }
19120c16b537SWarner Losh         }
191337f1f268SConrad Meyer     }
19140c16b537SWarner Losh 
19150c16b537SWarner Losh     return op-ostart;
19160c16b537SWarner Losh }
19170c16b537SWarner Losh 
19180c16b537SWarner Losh 
ZSTD_decompressBlock(void * ctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)19190c16b537SWarner Losh static size_t ZSTD_decompressBlock(
19200c16b537SWarner Losh                             void* ctx,
19210c16b537SWarner Losh                             void* dst, size_t maxDstSize,
19220c16b537SWarner Losh                       const void* src, size_t srcSize)
19230c16b537SWarner Losh {
19240c16b537SWarner Losh     /* blockType == blockCompressed, srcSize is trusted */
19250c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
19260c16b537SWarner Losh     const BYTE* litPtr = NULL;
19270c16b537SWarner Losh     size_t litSize = 0;
19280c16b537SWarner Losh     size_t errorCode;
19290c16b537SWarner Losh 
19300c16b537SWarner Losh     /* Decode literals sub-block */
19310c16b537SWarner Losh     errorCode = ZSTDv01_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize);
19320c16b537SWarner Losh     if (ZSTDv01_isError(errorCode)) return errorCode;
19330c16b537SWarner Losh     ip += errorCode;
19340c16b537SWarner Losh     srcSize -= errorCode;
19350c16b537SWarner Losh 
19360c16b537SWarner Losh     return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize, litPtr, litSize);
19370c16b537SWarner Losh }
19380c16b537SWarner Losh 
19390c16b537SWarner Losh 
ZSTDv01_decompressDCtx(void * ctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)19400c16b537SWarner Losh size_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
19410c16b537SWarner Losh {
19420c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
19430c16b537SWarner Losh     const BYTE* iend = ip + srcSize;
19440c16b537SWarner Losh     BYTE* const ostart = (BYTE* const)dst;
19450c16b537SWarner Losh     BYTE* op = ostart;
19460c16b537SWarner Losh     BYTE* const oend = ostart + maxDstSize;
19470c16b537SWarner Losh     size_t remainingSize = srcSize;
19480c16b537SWarner Losh     U32 magicNumber;
19490c16b537SWarner Losh     size_t errorCode=0;
19500c16b537SWarner Losh     blockProperties_t blockProperties;
19510c16b537SWarner Losh 
19520c16b537SWarner Losh     /* Frame Header */
19530c16b537SWarner Losh     if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
19540c16b537SWarner Losh     magicNumber = ZSTD_readBE32(src);
19550c16b537SWarner Losh     if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
19560c16b537SWarner Losh     ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
19570c16b537SWarner Losh 
19580c16b537SWarner Losh     /* Loop on each block */
19590c16b537SWarner Losh     while (1)
19600c16b537SWarner Losh     {
19610c16b537SWarner Losh         size_t blockSize = ZSTDv01_getcBlockSize(ip, iend-ip, &blockProperties);
19620c16b537SWarner Losh         if (ZSTDv01_isError(blockSize)) return blockSize;
19630c16b537SWarner Losh 
19640c16b537SWarner Losh         ip += ZSTD_blockHeaderSize;
19650c16b537SWarner Losh         remainingSize -= ZSTD_blockHeaderSize;
19660c16b537SWarner Losh         if (blockSize > remainingSize) return ERROR(srcSize_wrong);
19670c16b537SWarner Losh 
19680c16b537SWarner Losh         switch(blockProperties.blockType)
19690c16b537SWarner Losh         {
19700c16b537SWarner Losh         case bt_compressed:
19710c16b537SWarner Losh             errorCode = ZSTD_decompressBlock(ctx, op, oend-op, ip, blockSize);
19720c16b537SWarner Losh             break;
19730c16b537SWarner Losh         case bt_raw :
19740c16b537SWarner Losh             errorCode = ZSTD_copyUncompressedBlock(op, oend-op, ip, blockSize);
19750c16b537SWarner Losh             break;
19760c16b537SWarner Losh         case bt_rle :
19770c16b537SWarner Losh             return ERROR(GENERIC);   /* not yet supported */
19780c16b537SWarner Losh             break;
19790c16b537SWarner Losh         case bt_end :
19800c16b537SWarner Losh             /* end of frame */
19810c16b537SWarner Losh             if (remainingSize) return ERROR(srcSize_wrong);
19820c16b537SWarner Losh             break;
19830c16b537SWarner Losh         default:
19840c16b537SWarner Losh             return ERROR(GENERIC);
19850c16b537SWarner Losh         }
19860c16b537SWarner Losh         if (blockSize == 0) break;   /* bt_end */
19870c16b537SWarner Losh 
19880c16b537SWarner Losh         if (ZSTDv01_isError(errorCode)) return errorCode;
19890c16b537SWarner Losh         op += errorCode;
19900c16b537SWarner Losh         ip += blockSize;
19910c16b537SWarner Losh         remainingSize -= blockSize;
19920c16b537SWarner Losh     }
19930c16b537SWarner Losh 
19940c16b537SWarner Losh     return op-ostart;
19950c16b537SWarner Losh }
19960c16b537SWarner Losh 
ZSTDv01_decompress(void * dst,size_t maxDstSize,const void * src,size_t srcSize)19970c16b537SWarner Losh size_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
19980c16b537SWarner Losh {
19990c16b537SWarner Losh     dctx_t ctx;
20000c16b537SWarner Losh     ctx.base = dst;
20010c16b537SWarner Losh     return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);
20020c16b537SWarner Losh }
20030c16b537SWarner Losh 
20042b9c00cbSConrad Meyer /* ZSTD_errorFrameSizeInfoLegacy() :
20052b9c00cbSConrad Meyer    assumes `cSize` and `dBound` are _not_ NULL */
ZSTD_errorFrameSizeInfoLegacy(size_t * cSize,unsigned long long * dBound,size_t ret)20062b9c00cbSConrad Meyer static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)
20072b9c00cbSConrad Meyer {
20082b9c00cbSConrad Meyer     *cSize = ret;
20092b9c00cbSConrad Meyer     *dBound = ZSTD_CONTENTSIZE_ERROR;
20102b9c00cbSConrad Meyer }
20112b9c00cbSConrad Meyer 
ZSTDv01_findFrameSizeInfoLegacy(const void * src,size_t srcSize,size_t * cSize,unsigned long long * dBound)20122b9c00cbSConrad Meyer void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)
20130c16b537SWarner Losh {
20140c16b537SWarner Losh     const BYTE* ip = (const BYTE*)src;
20150c16b537SWarner Losh     size_t remainingSize = srcSize;
20162b9c00cbSConrad Meyer     size_t nbBlocks = 0;
20170c16b537SWarner Losh     U32 magicNumber;
20180c16b537SWarner Losh     blockProperties_t blockProperties;
20190c16b537SWarner Losh 
20200c16b537SWarner Losh     /* Frame Header */
20212b9c00cbSConrad Meyer     if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {
20222b9c00cbSConrad Meyer         ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
20232b9c00cbSConrad Meyer         return;
20242b9c00cbSConrad Meyer     }
20250c16b537SWarner Losh     magicNumber = ZSTD_readBE32(src);
20262b9c00cbSConrad Meyer     if (magicNumber != ZSTD_magicNumber) {
20272b9c00cbSConrad Meyer         ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));
20282b9c00cbSConrad Meyer         return;
20292b9c00cbSConrad Meyer     }
20300c16b537SWarner Losh     ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;
20310c16b537SWarner Losh 
20320c16b537SWarner Losh     /* Loop on each block */
20330c16b537SWarner Losh     while (1)
20340c16b537SWarner Losh     {
20350c16b537SWarner Losh         size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);
20362b9c00cbSConrad Meyer         if (ZSTDv01_isError(blockSize)) {
20372b9c00cbSConrad Meyer             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize);
20382b9c00cbSConrad Meyer             return;
20392b9c00cbSConrad Meyer         }
20400c16b537SWarner Losh 
20410c16b537SWarner Losh         ip += ZSTD_blockHeaderSize;
20420c16b537SWarner Losh         remainingSize -= ZSTD_blockHeaderSize;
20432b9c00cbSConrad Meyer         if (blockSize > remainingSize) {
20442b9c00cbSConrad Meyer             ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));
20452b9c00cbSConrad Meyer             return;
20462b9c00cbSConrad Meyer         }
20470c16b537SWarner Losh 
20480c16b537SWarner Losh         if (blockSize == 0) break;   /* bt_end */
20490c16b537SWarner Losh 
20500c16b537SWarner Losh         ip += blockSize;
20510c16b537SWarner Losh         remainingSize -= blockSize;
20522b9c00cbSConrad Meyer         nbBlocks++;
20530c16b537SWarner Losh     }
20540c16b537SWarner Losh 
20552b9c00cbSConrad Meyer     *cSize = ip - (const BYTE*)src;
20562b9c00cbSConrad Meyer     *dBound = nbBlocks * BLOCKSIZE;
20570c16b537SWarner Losh }
20580c16b537SWarner Losh 
20590c16b537SWarner Losh /*******************************
20600c16b537SWarner Losh *  Streaming Decompression API
20610c16b537SWarner Losh *******************************/
20620c16b537SWarner Losh 
ZSTDv01_resetDCtx(ZSTDv01_Dctx * dctx)20630c16b537SWarner Losh size_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx)
20640c16b537SWarner Losh {
20650c16b537SWarner Losh     dctx->expected = ZSTD_frameHeaderSize;
20660c16b537SWarner Losh     dctx->phase = 0;
20670c16b537SWarner Losh     dctx->previousDstEnd = NULL;
20680c16b537SWarner Losh     dctx->base = NULL;
20690c16b537SWarner Losh     return 0;
20700c16b537SWarner Losh }
20710c16b537SWarner Losh 
ZSTDv01_createDCtx(void)20720c16b537SWarner Losh ZSTDv01_Dctx* ZSTDv01_createDCtx(void)
20730c16b537SWarner Losh {
20740c16b537SWarner Losh     ZSTDv01_Dctx* dctx = (ZSTDv01_Dctx*)malloc(sizeof(ZSTDv01_Dctx));
20750c16b537SWarner Losh     if (dctx==NULL) return NULL;
20760c16b537SWarner Losh     ZSTDv01_resetDCtx(dctx);
20770c16b537SWarner Losh     return dctx;
20780c16b537SWarner Losh }
20790c16b537SWarner Losh 
ZSTDv01_freeDCtx(ZSTDv01_Dctx * dctx)20800c16b537SWarner Losh size_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx)
20810c16b537SWarner Losh {
20820c16b537SWarner Losh     free(dctx);
20830c16b537SWarner Losh     return 0;
20840c16b537SWarner Losh }
20850c16b537SWarner Losh 
ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx * dctx)20860c16b537SWarner Losh size_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx)
20870c16b537SWarner Losh {
20880c16b537SWarner Losh     return ((dctx_t*)dctx)->expected;
20890c16b537SWarner Losh }
20900c16b537SWarner Losh 
ZSTDv01_decompressContinue(ZSTDv01_Dctx * dctx,void * dst,size_t maxDstSize,const void * src,size_t srcSize)20910c16b537SWarner Losh size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
20920c16b537SWarner Losh {
20930c16b537SWarner Losh     dctx_t* ctx = (dctx_t*)dctx;
20940c16b537SWarner Losh 
20950c16b537SWarner Losh     /* Sanity check */
20960c16b537SWarner Losh     if (srcSize != ctx->expected) return ERROR(srcSize_wrong);
20970c16b537SWarner Losh     if (dst != ctx->previousDstEnd)  /* not contiguous */
20980c16b537SWarner Losh         ctx->base = dst;
20990c16b537SWarner Losh 
21000c16b537SWarner Losh     /* Decompress : frame header */
21010c16b537SWarner Losh     if (ctx->phase == 0)
21020c16b537SWarner Losh     {
21030c16b537SWarner Losh         /* Check frame magic header */
21040c16b537SWarner Losh         U32 magicNumber = ZSTD_readBE32(src);
21050c16b537SWarner Losh         if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);
21060c16b537SWarner Losh         ctx->phase = 1;
21070c16b537SWarner Losh         ctx->expected = ZSTD_blockHeaderSize;
21080c16b537SWarner Losh         return 0;
21090c16b537SWarner Losh     }
21100c16b537SWarner Losh 
21110c16b537SWarner Losh     /* Decompress : block header */
21120c16b537SWarner Losh     if (ctx->phase == 1)
21130c16b537SWarner Losh     {
21140c16b537SWarner Losh         blockProperties_t bp;
21150c16b537SWarner Losh         size_t blockSize = ZSTDv01_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
21160c16b537SWarner Losh         if (ZSTDv01_isError(blockSize)) return blockSize;
21170c16b537SWarner Losh         if (bp.blockType == bt_end)
21180c16b537SWarner Losh         {
21190c16b537SWarner Losh             ctx->expected = 0;
21200c16b537SWarner Losh             ctx->phase = 0;
21210c16b537SWarner Losh         }
21220c16b537SWarner Losh         else
21230c16b537SWarner Losh         {
21240c16b537SWarner Losh             ctx->expected = blockSize;
21250c16b537SWarner Losh             ctx->bType = bp.blockType;
21260c16b537SWarner Losh             ctx->phase = 2;
21270c16b537SWarner Losh         }
21280c16b537SWarner Losh 
21290c16b537SWarner Losh         return 0;
21300c16b537SWarner Losh     }
21310c16b537SWarner Losh 
21320c16b537SWarner Losh     /* Decompress : block content */
21330c16b537SWarner Losh     {
21340c16b537SWarner Losh         size_t rSize;
21350c16b537SWarner Losh         switch(ctx->bType)
21360c16b537SWarner Losh         {
21370c16b537SWarner Losh         case bt_compressed:
21380c16b537SWarner Losh             rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);
21390c16b537SWarner Losh             break;
21400c16b537SWarner Losh         case bt_raw :
21410c16b537SWarner Losh             rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);
21420c16b537SWarner Losh             break;
21430c16b537SWarner Losh         case bt_rle :
21440c16b537SWarner Losh             return ERROR(GENERIC);   /* not yet handled */
21450c16b537SWarner Losh             break;
21460c16b537SWarner Losh         case bt_end :   /* should never happen (filtered at phase 1) */
21470c16b537SWarner Losh             rSize = 0;
21480c16b537SWarner Losh             break;
21490c16b537SWarner Losh         default:
21500c16b537SWarner Losh             return ERROR(GENERIC);
21510c16b537SWarner Losh         }
21520c16b537SWarner Losh         ctx->phase = 1;
21530c16b537SWarner Losh         ctx->expected = ZSTD_blockHeaderSize;
21540c16b537SWarner Losh         ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);
21550c16b537SWarner Losh         return rSize;
21560c16b537SWarner Losh     }
21570c16b537SWarner Losh 
21580c16b537SWarner Losh }
2159